chore: add claw smoke runtime sample
This commit is contained in:
20
.env.server.example
Normal file
20
.env.server.example
Normal file
@@ -0,0 +1,20 @@
|
||||
BOSS_AUTH_VERIFICATION_MODE=fixed
|
||||
BOSS_AUTH_FIXED_CODE=000000
|
||||
BOSS_STATE_FILE=/opt/boss/data/boss-state.json
|
||||
|
||||
# 切到真实邮件验证码时,改成:
|
||||
# BOSS_AUTH_VERIFICATION_MODE=email
|
||||
# BOSS_AUTH_FIXED_CODE=
|
||||
|
||||
BOSS_MAIL_DOMAIN=boss.hyzq.net
|
||||
BOSS_MAIL_FROM_ADDRESS=verify@boss.hyzq.net
|
||||
BOSS_MAIL_FROM_NAME=Boss Verify
|
||||
BOSS_SENDMAIL_PATH=/usr/sbin/sendmail
|
||||
|
||||
# 可选:启用 ClawBackendAdapter(默认关闭)
|
||||
# BOSS_CLAW_ENABLED=true
|
||||
# BOSS_CLAW_COMMAND=node
|
||||
# BOSS_CLAW_ARGS=scripts/claw-runtime-smoke.mjs
|
||||
# BOSS_CLAW_WORKDIR=/opt/boss
|
||||
# BOSS_CLAW_TIMEOUT_MS=45000
|
||||
# BOSS_CLAW_DEFAULT_MODEL=gpt-5.4
|
||||
@@ -59,6 +59,7 @@
|
||||
- 当前 Boss 已新增 `src/lib/execution/` 执行底座抽象层;当前生产主链仍然沿用 `local-agent -> codex exec resume`,只是执行责任已开始通过 `ExecutionBackend / PromptAssembler / PermissionPolicy / RemoteRuntimeAdapter / OrchestrationBackend` 默认实现收束
|
||||
- 当前 `claw-code` 已以最小 `ClawBackendAdapter` 形式接入执行底座,但默认关闭;只有在显式配置 `BOSS_CLAW_*` 并在 `master-agent` 当前对话里显式选择 `claw-runtime` 时才会参与执行候选
|
||||
- 当前 `oh-my-codex` 仍未正式接入生产执行链;当前状态是 orchestration-ready,后续将通过独立 adapter 接入
|
||||
- 当前仓库已自带一个本地 smoke runtime:`scripts/claw-runtime-smoke.mjs`。在还没有真实 `claw-code` 可执行文件时,可以先用它验证 `ClawBackendAdapter -> backendOverride -> 异步回流` 整条链
|
||||
- `GET http://127.0.0.1:4317/api/v1/skills` 正常,已返回本机扫描到的 Codex Skill
|
||||
- `POST http://127.0.0.1:4317/api/v1/heartbeat` 正常,且会顺带触发 `thread-context` 上报
|
||||
- `launchd` 已加载:`~/Library/LaunchAgents/com.hyzq.boss.local-agent.plist`
|
||||
|
||||
@@ -178,6 +178,7 @@
|
||||
- 已在生产代码中被 `boss-master-agent.ts`、`local-agent/server.mjs` 和 `master-agent task complete route` 使用
|
||||
- 当前仍服务 Boss 自身执行链
|
||||
- 当前已最小接入 `ClawBackendAdapter`,但默认关闭,仅在显式配置和显式选择时参与执行
|
||||
- 当前仓库自带 `scripts/claw-runtime-smoke.mjs` 作为兼容 JSON 协议的 smoke runtime,可用于本地和服务器验证 `ClawBackendAdapter`
|
||||
- 当前尚未接入 `oh-my-codex`
|
||||
|
||||
### 3.2 认证相关
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
- 当前执行底座抽象层已落地在 `src/lib/execution/`,并已补齐 `ExecutionBackend / PromptAssembler / PermissionPolicy / RemoteRuntimeAdapter / OrchestrationBackend` 默认实现
|
||||
- 当前生产主链仍然沿用 `local-agent -> codex exec resume -> /api/v1/master-agent/tasks/[taskId]/complete`,执行底座重构以“先抽象、不改行为”为准
|
||||
- 当前 `claw-code` 已以最小 `ClawBackendAdapter` 形式接入执行底座,但默认关闭;只有显式配置 `BOSS_CLAW_*` 并在 `master-agent` 当前对话中选择 `claw-runtime` 时才会参与执行候选
|
||||
- 当前仓库已自带 `scripts/claw-runtime-smoke.mjs` 作为本地 smoke runtime;在没有真实 `claw-code` 可执行文件时,可先用 `BOSS_CLAW_COMMAND=node` 与 `BOSS_CLAW_ARGS=scripts/claw-runtime-smoke.mjs` 验证整条链
|
||||
- 当前 `oh-my-codex` 还未正式接入生产链,只是已经具备 orchestration adapter-ready 的 contract 基础
|
||||
|
||||
本地已知运行方式:
|
||||
|
||||
62
scripts/claw-runtime-smoke.mjs
Normal file
62
scripts/claw-runtime-smoke.mjs
Normal file
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
function writeJson(payload) {
|
||||
process.stdout.write(`${JSON.stringify(payload)}\n`);
|
||||
}
|
||||
|
||||
async function readStdin() {
|
||||
const chunks = [];
|
||||
for await (const chunk of process.stdin) {
|
||||
chunks.push(typeof chunk === "string" ? chunk : chunk.toString("utf8"));
|
||||
}
|
||||
return chunks.join("").trim();
|
||||
}
|
||||
|
||||
function normalizePayload(raw) {
|
||||
try {
|
||||
const parsed = JSON.parse(raw);
|
||||
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
||||
return {
|
||||
ok: false,
|
||||
error: "INVALID_CLAW_PAYLOAD: expected object",
|
||||
};
|
||||
}
|
||||
return {
|
||||
ok: true,
|
||||
payload: parsed,
|
||||
};
|
||||
} catch {
|
||||
return {
|
||||
ok: false,
|
||||
error: "INVALID_CLAW_PAYLOAD: invalid json",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const raw = await readStdin();
|
||||
const normalized = normalizePayload(raw);
|
||||
|
||||
if (!normalized.ok) {
|
||||
writeJson({
|
||||
status: "failed",
|
||||
error: normalized.error,
|
||||
});
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const payload = normalized.payload;
|
||||
const requestKind = typeof payload.requestKind === "string" ? payload.requestKind : "unknown";
|
||||
const model = typeof payload.model === "string" && payload.model.trim() ? payload.model.trim() : "default";
|
||||
const reasoningEffort =
|
||||
typeof payload.reasoningEffort === "string" && payload.reasoningEffort.trim()
|
||||
? payload.reasoningEffort.trim()
|
||||
: "default";
|
||||
const executionPrompt =
|
||||
typeof payload.executionPrompt === "string" && payload.executionPrompt.trim()
|
||||
? payload.executionPrompt.trim()
|
||||
: "链路正常";
|
||||
|
||||
writeJson({
|
||||
status: "completed",
|
||||
output: `Claw smoke completed: ${executionPrompt} (kind=${requestKind}, model=${model}, reasoning=${reasoningEffort})`,
|
||||
});
|
||||
61
tests/claw-runtime-smoke-script.test.ts
Normal file
61
tests/claw-runtime-smoke-script.test.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import path from "node:path";
|
||||
import { spawn } from "node:child_process";
|
||||
|
||||
function runSmoke(payload: unknown) {
|
||||
return new Promise<{
|
||||
exitCode: number | null;
|
||||
stdout: string;
|
||||
stderr: string;
|
||||
}>((resolve, reject) => {
|
||||
const scriptPath = path.resolve("scripts/claw-runtime-smoke.mjs");
|
||||
const child = spawn(process.execPath, [scriptPath], {
|
||||
cwd: "/Users/kris/code/boss",
|
||||
stdio: ["pipe", "pipe", "pipe"],
|
||||
});
|
||||
|
||||
let stdout = "";
|
||||
let stderr = "";
|
||||
child.stdout.setEncoding("utf8");
|
||||
child.stderr.setEncoding("utf8");
|
||||
child.stdout.on("data", (chunk) => {
|
||||
stdout += chunk;
|
||||
});
|
||||
child.stderr.on("data", (chunk) => {
|
||||
stderr += chunk;
|
||||
});
|
||||
child.on("error", reject);
|
||||
child.on("close", (exitCode) => {
|
||||
resolve({ exitCode, stdout, stderr });
|
||||
});
|
||||
|
||||
child.stdin.write(JSON.stringify(payload));
|
||||
child.stdin.end();
|
||||
});
|
||||
}
|
||||
|
||||
test("claw runtime smoke script emits completed JSON for valid payload", async () => {
|
||||
const result = await runSmoke({
|
||||
requestKind: "master_agent_reply",
|
||||
executionPrompt: "请回复链路正常",
|
||||
model: "gpt-5.4",
|
||||
reasoningEffort: "medium",
|
||||
});
|
||||
|
||||
assert.equal(result.exitCode, 0);
|
||||
assert.equal(result.stderr, "");
|
||||
const parsed = JSON.parse(result.stdout);
|
||||
assert.equal(parsed.status, "completed");
|
||||
assert.match(parsed.output, /链路正常/);
|
||||
assert.match(parsed.output, /gpt-5\.4/);
|
||||
});
|
||||
|
||||
test("claw runtime smoke script emits failed JSON for invalid payload", async () => {
|
||||
const result = await runSmoke("not-an-object");
|
||||
|
||||
assert.equal(result.exitCode, 0);
|
||||
const parsed = JSON.parse(result.stdout);
|
||||
assert.equal(parsed.status, "failed");
|
||||
assert.match(parsed.error, /INVALID_CLAW_PAYLOAD/);
|
||||
});
|
||||
Reference in New Issue
Block a user