@nowcrew/daemon 0.6.95-beta.1 → 0.6.95
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/computer-main.js +0 -0
- package/dist/list-models.js +31 -6
- package/dist/local-executor.js +2 -7
- package/dist/main.js +0 -0
- package/dist/normalize.js +10 -9
- package/dist/runtimes/pi-runner.js +36 -10
- package/dist/runtimes/pi.js +1 -1
- package/package.json +9 -8
package/dist/computer-main.js
CHANGED
|
File without changes
|
package/dist/list-models.js
CHANGED
|
@@ -182,10 +182,35 @@ export function parseOpencodeModels(stdout) {
|
|
|
182
182
|
}
|
|
183
183
|
return models;
|
|
184
184
|
}
|
|
185
|
-
function parsePiModels(stdout) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
185
|
+
export function parsePiModels(stdout) {
|
|
186
|
+
const reasoning = ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
187
|
+
const models = [];
|
|
188
|
+
const seen = new Set();
|
|
189
|
+
for (const rawLine of stdout.split(/\r?\n/)) {
|
|
190
|
+
const line = rawLine.trim();
|
|
191
|
+
if (line.length === 0 || line.toLowerCase().startsWith("warning"))
|
|
192
|
+
continue;
|
|
193
|
+
const columns = line.split(/\s+/);
|
|
194
|
+
const [provider, model, context, maxOutput, thinking, images] = columns;
|
|
195
|
+
if (provider === "provider" && model === "model"
|
|
196
|
+
|| !provider || !model
|
|
197
|
+
|| !/^\d+(?:\.\d+)?[KMG]$/i.test(context ?? "")
|
|
198
|
+
|| !/^\d+(?:\.\d+)?[KMG]$/i.test(maxOutput ?? "")
|
|
199
|
+
|| !/^(?:yes|no)$/i.test(thinking ?? "")
|
|
200
|
+
|| !/^(?:yes|no)$/i.test(images ?? ""))
|
|
201
|
+
continue;
|
|
202
|
+
const id = `${provider}/${model}`;
|
|
203
|
+
if (seen.has(id))
|
|
204
|
+
continue;
|
|
205
|
+
seen.add(id);
|
|
206
|
+
models.push({
|
|
207
|
+
id,
|
|
208
|
+
label: id,
|
|
209
|
+
...(thinking?.toLowerCase() === "yes" ? { reasoning } : {}),
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
// `pi --list-models` does not identify the configured default model, and its
|
|
213
|
+
// output order is not a default-model contract. Leave default unset so the
|
|
214
|
+
// UI does not infer capabilities from an unrelated first row.
|
|
215
|
+
return models;
|
|
191
216
|
}
|
package/dist/local-executor.js
CHANGED
|
@@ -14,7 +14,7 @@ import { spawnKimi } from "./runtimes/kimi.js";
|
|
|
14
14
|
import { applyDeepSeekHarnessMachineEnv, applyProviderEnv, providerFingerprint, } from "./provider-env.js";
|
|
15
15
|
import { deliverCloudReports, prepareCloudReportExecution } from "./cloud-report-uploader.js";
|
|
16
16
|
import { reportDeliveryContext } from "./cloud-report-receipt.js";
|
|
17
|
-
import { extractFinalText, extractRunMeta, normalizeEvent, parseLine, } from "./normalize.js";
|
|
17
|
+
import { extractFinalText, isIncrementalTextEvent, extractRunMeta, normalizeEvent, parseLine, } from "./normalize.js";
|
|
18
18
|
import { readSession, writeSession, pickResumeId, isNearBudget } from "./session.js";
|
|
19
19
|
import { NativeThreadContext, isolateMaintenanceSession } from "./native-thread-context.js";
|
|
20
20
|
import { prepareThreadDelivery } from "./thread-input-delivery.js";
|
|
@@ -811,12 +811,7 @@ async function executeLocalUnlocked(input, callbacks, dependencies) {
|
|
|
811
811
|
}
|
|
812
812
|
const extracted = extractFinalText(event);
|
|
813
813
|
if (extracted) {
|
|
814
|
-
|
|
815
|
-
&& "type" in event && (event.type === "kimi.acp.text_delta"
|
|
816
|
-
|| event.type === "hermes.acp.text_delta"
|
|
817
|
-
|| event.type === "deepseek-harness.acp.text_delta"
|
|
818
|
-
|| event.type === "opencode.text_delta");
|
|
819
|
-
finalText = incremental ? `${finalText ?? ""}${extracted}` : extracted;
|
|
814
|
+
finalText = isIncrementalTextEvent(event) ? `${finalText ?? ""}${extracted}` : extracted;
|
|
820
815
|
}
|
|
821
816
|
for (const text of decodeExternalOutputEvent(runtime.name, event, externalOutput)) {
|
|
822
817
|
callbacks.onExternalOutput?.(text);
|
package/dist/main.js
CHANGED
|
File without changes
|
package/dist/normalize.js
CHANGED
|
@@ -32,13 +32,17 @@ export function classifyCommand(command) {
|
|
|
32
32
|
return { kind: "crew", label: "crew 命令", detail: c };
|
|
33
33
|
return { kind: "tool", label: "执行命令", detail: c };
|
|
34
34
|
}
|
|
35
|
-
/**
|
|
35
|
+
/** 提取和汇总共用同一份增量事件判定,避免新增 runtime 时漏掉拼接。 */
|
|
36
|
+
export function isIncrementalTextEvent(event) {
|
|
37
|
+
const e = (event ?? {});
|
|
38
|
+
return e.type === "kimi.acp.text_delta" || e.type === "hermes.acp.text_delta"
|
|
39
|
+
|| e.type === "deepseek-harness.acp.text_delta" || e.type === "opencode.text_delta"
|
|
40
|
+
|| e.type === "pi.text_delta";
|
|
41
|
+
}
|
|
42
|
+
/** 提取可交付文本;增量事件须拼接,完整消息保留最后一个非空值。 */
|
|
36
43
|
export function extractFinalText(event) {
|
|
37
44
|
const e = (event ?? {});
|
|
38
|
-
if ((e
|
|
39
|
-
|| e.type === "deepseek-harness.acp.text_delta"
|
|
40
|
-
|| e.type === "opencode.text_delta"
|
|
41
|
-
|| e.type === "pi.text_delta") && e.text)
|
|
45
|
+
if (isIncrementalTextEvent(e) && e.text)
|
|
42
46
|
return e.text;
|
|
43
47
|
if (e.type === "result" && !e.is_error && e.result?.trim())
|
|
44
48
|
return e.result.trim();
|
|
@@ -69,10 +73,7 @@ export function normalizeEvent(event) {
|
|
|
69
73
|
const plan = boundedCodexPlan(e.plan);
|
|
70
74
|
return plan === null ? [] : [{ kind: "tool", label: "计划更新", detail: codexPlanText(plan) }];
|
|
71
75
|
}
|
|
72
|
-
if ((e
|
|
73
|
-
|| e.type === "deepseek-harness.acp.text_delta"
|
|
74
|
-
|| e.type === "opencode.text_delta"
|
|
75
|
-
|| e.type === "pi.text_delta") && e.text?.trim()) {
|
|
76
|
+
if (isIncrementalTextEvent(e) && e.text?.trim()) {
|
|
76
77
|
return [{ kind: "text", label: "思考/说明", detail: e.text }];
|
|
77
78
|
}
|
|
78
79
|
if (e.type === "kimi.acp.tool_call" || e.type === "hermes.acp.tool_call"
|
|
@@ -4,22 +4,48 @@ import { parseArgs } from "node:util";
|
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
5
5
|
import spawn from "cross-spawn";
|
|
6
6
|
import { augmentedPath } from "../runtime-path.js";
|
|
7
|
+
import { prepareThreadDelivery } from "../thread-input-delivery.js";
|
|
7
8
|
import { buildPiArgs, createPiEventDecoder } from "./pi.js";
|
|
8
9
|
async function readInput() { process.stdin.setEncoding("utf8"); let text = ""; for await (const chunk of process.stdin)
|
|
9
10
|
text += String(chunk); return JSON.parse(text); }
|
|
10
11
|
async function emit(event) { if (process.stdout.write(`${JSON.stringify(event)}\n`))
|
|
11
12
|
return; await once(process.stdout, "drain"); }
|
|
12
|
-
export async function runPi(bin) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
export async function runPi(bin) {
|
|
14
|
+
const input = await readInput();
|
|
15
|
+
// Pi 不持久化原生会话,每轮都须在启动模型前补齐当前线程快照。
|
|
16
|
+
const delivery = await prepareThreadDelivery({
|
|
17
|
+
env: process.env, resumed: false, sessionId: "unverified-cold-pi", wakePrompt: input.wakePrompt,
|
|
18
|
+
});
|
|
19
|
+
const child = spawn(bin, buildPiArgs({ ...input, wakePrompt: delivery.prompt }), {
|
|
20
|
+
cwd: process.cwd(), env: { ...process.env, PATH: augmentedPath(), PWD: process.cwd() },
|
|
21
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
22
|
+
});
|
|
23
|
+
if (!child.stdin || !child.stdout || !child.stderr)
|
|
24
|
+
throw new Error("Pi process did not expose stdio");
|
|
25
|
+
child.stderr.pipe(process.stderr, { end: false });
|
|
26
|
+
const exit = once(child, "close");
|
|
27
|
+
let inputError;
|
|
28
|
+
child.stdin.on("error", error => { inputError = error; });
|
|
29
|
+
// Pi print 模式读取 stdin;完整线程历史不能塞进受长度限制的 argv。
|
|
30
|
+
child.stdin.end(delivery.prompt);
|
|
31
|
+
const decoder = createPiEventDecoder();
|
|
32
|
+
for await (const line of createInterface({ input: child.stdout })) {
|
|
33
|
+
try {
|
|
34
|
+
for (const event of decoder.push(JSON.parse(line)))
|
|
35
|
+
await emit(event);
|
|
36
|
+
}
|
|
37
|
+
catch { }
|
|
17
38
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
39
|
+
const [code, signal] = await exit;
|
|
40
|
+
if (inputError)
|
|
41
|
+
throw new Error(`Pi prompt delivery failed: ${inputError.message}`);
|
|
42
|
+
const result = decoder.finish();
|
|
43
|
+
if (!result.ok) {
|
|
44
|
+
process.stderr.write(`${result.error}\n`);
|
|
45
|
+
return 1;
|
|
46
|
+
}
|
|
47
|
+
return code === 0 ? 0 : (code ?? (signal ? 128 : 1));
|
|
48
|
+
}
|
|
23
49
|
const { values } = parseArgs({ args: process.argv.slice(2), options: { bin: { type: "string" } } });
|
|
24
50
|
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
25
51
|
if (!values.bin)
|
package/dist/runtimes/pi.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export function buildPiArgs(options) { return ["--mode", "json", "--print", "--no-session", "--system-prompt", options.systemPrompt, ...(options.model ? ["--model", options.model] : []), ...(options.reasoning && options.reasoning !== "default" ? ["--thinking", options.reasoning] : [])
|
|
1
|
+
export function buildPiArgs(options) { return ["--mode", "json", "--print", "--no-session", "--system-prompt", options.systemPrompt, ...(options.model ? ["--model", options.model] : []), ...(options.reasoning && options.reasoning !== "default" ? ["--thinking", options.reasoning] : [])]; }
|
|
2
2
|
export function createPiEventDecoder() { let sessionId = null; let finalText = ""; let error = null; let sawTurnEnd = false; let usage; return { push(raw) { const e = (raw ?? {}); const out = []; if (e.type === "session" && typeof e.id === "string") {
|
|
3
3
|
sessionId = e.id;
|
|
4
4
|
out.push({ type: "thread.started", thread_id: e.id });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nowcrew/daemon",
|
|
3
|
-
"version": "0.6.95
|
|
3
|
+
"version": "0.6.95",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "crew daemon — 运行在用户机器:拉起/管理 agent 进程,注入 crew CLI,归一化 runtime 事件",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -18,6 +18,13 @@
|
|
|
18
18
|
"publishConfig": {
|
|
19
19
|
"access": "public"
|
|
20
20
|
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"daemon": "pnpm --filter @nowcrew/cli build && tsx src/main.ts",
|
|
23
|
+
"build": "tsc -p tsconfig.json",
|
|
24
|
+
"prepublishOnly": "pnpm build && node ../scripts/daemon-release-artifact.mjs --strict-registry",
|
|
25
|
+
"test": "vitest run",
|
|
26
|
+
"typecheck": "tsc --noEmit"
|
|
27
|
+
},
|
|
21
28
|
"dependencies": {
|
|
22
29
|
"@agentclientprotocol/sdk": "1.2.1",
|
|
23
30
|
"@nowcrew/cli": "0.4.17",
|
|
@@ -39,11 +46,5 @@
|
|
|
39
46
|
"tsx": "^4.19.0",
|
|
40
47
|
"typescript": "^5.6.0",
|
|
41
48
|
"vitest": "^2.1.0"
|
|
42
|
-
},
|
|
43
|
-
"scripts": {
|
|
44
|
-
"daemon": "pnpm --filter @nowcrew/cli build && tsx src/main.ts",
|
|
45
|
-
"build": "tsc -p tsconfig.json",
|
|
46
|
-
"test": "vitest run",
|
|
47
|
-
"typecheck": "tsc --noEmit"
|
|
48
49
|
}
|
|
49
|
-
}
|
|
50
|
+
}
|