@nowcrew/daemon 0.6.77-beta.5 → 0.6.77-beta.7
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/config.js +28 -8
- package/dist/execution-runner.js +3 -2
- package/dist/local-executor.js +5 -0
- package/dist/main.js +0 -0
- package/dist/project-skills/runtime-root-bootstrap.js +6 -0
- package/dist/project-skills/runtime-root-startup.js +2 -1
- package/dist/project-skills/serve-startup.js +23 -0
- package/dist/runner.js +2 -1
- package/dist/serve.js +2 -4
- package/package.json +10 -9
package/dist/config.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** daemon 配置:从 env 读取,解析 crew CLI 路径 (注入给 agent 的 wrapper 用)。 */
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
|
-
import { dirname, join, resolve } from "node:path";
|
|
3
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
5
|
import { createRequire } from "node:module";
|
|
6
6
|
import { detectDaemonLang, translateDaemon } from "./i18n.js";
|
|
@@ -28,6 +28,23 @@ export const MIN_EXECUTION_EVENT_BYTES = 512;
|
|
|
28
28
|
export const MAX_EXECUTION_TIMEOUT_MS = 2_147_483_647;
|
|
29
29
|
export class ConfigError extends Error {
|
|
30
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Resolve the shared workspace repository root from the daemon's agent root.
|
|
33
|
+
*
|
|
34
|
+
* Standard NowWork storage keeps `agent-items`, `daemon`, `repos`, and the QA
|
|
35
|
+
* report hub as siblings. Legacy/standalone profiles may still point at an
|
|
36
|
+
* arbitrary agents directory, for which the historical `<agentsRoot>/repos`
|
|
37
|
+
* layout remains the compatible fallback.
|
|
38
|
+
*/
|
|
39
|
+
export function resolveReposRoot(agentsRoot, configured) {
|
|
40
|
+
const explicit = configured?.trim();
|
|
41
|
+
if (explicit)
|
|
42
|
+
return resolve(explicit);
|
|
43
|
+
const resolvedAgentsRoot = resolve(agentsRoot);
|
|
44
|
+
return basename(resolvedAgentsRoot) === "agent-items"
|
|
45
|
+
? join(dirname(resolvedAgentsRoot), "repos")
|
|
46
|
+
: join(resolvedAgentsRoot, "repos");
|
|
47
|
+
}
|
|
31
48
|
function positiveIntegerEnv(env, field, fallback) {
|
|
32
49
|
const raw = env[field];
|
|
33
50
|
const value = raw === undefined ? fallback : Number(raw);
|
|
@@ -59,11 +76,11 @@ function defaultCliPath() {
|
|
|
59
76
|
return resolve(here, "../../cli/dist/main.js");
|
|
60
77
|
}
|
|
61
78
|
}
|
|
62
|
-
// 临时 dev
|
|
79
|
+
// 临时 dev 验收名单。这里必须填写 Server 生成的 Agent handle,而不是显示名称或频道 ID。
|
|
80
|
+
// 测试完成后删除此常量,恢复未配置时默认关闭的行为。
|
|
63
81
|
const TEMP_LOCAL_MEMORY_V2_TEST_HANDLES = [
|
|
64
|
-
"memory-v2-test-a
|
|
65
|
-
"memory-v2-test-b
|
|
66
|
-
"memory-v2-test-c",
|
|
82
|
+
"94533bf3-b5b7-4a1e-9c41-6a1ab0a0e1ea", // memory-v2-test-a
|
|
83
|
+
"967ab9ce-724c-4f22-a664-2f855cd798af", // memory-v2-test-b
|
|
67
84
|
];
|
|
68
85
|
function isTemporaryDevServer(serverUrl) {
|
|
69
86
|
try {
|
|
@@ -136,16 +153,19 @@ export function loadConfig(env = process.env) {
|
|
|
136
153
|
});
|
|
137
154
|
const agentsRoot = resolveAgentsRoot(env.CREW_AGENTS_ROOT, homedir());
|
|
138
155
|
const configuredReposRoot = env.NOWWORK_REPOS_ROOT?.trim();
|
|
139
|
-
const reposRoot =
|
|
156
|
+
const reposRoot = resolveReposRoot(agentsRoot, configuredReposRoot);
|
|
140
157
|
const configuredQaReportRoot = env.QA_REPORT_HUB?.trim();
|
|
158
|
+
const defaultQaReportRoot = configuredReposRoot
|
|
159
|
+
? join(dirname(reposRoot), "qa-report-server-v2")
|
|
160
|
+
: join(dirname(agentsRoot), "qa-report-server-v2");
|
|
141
161
|
return {
|
|
142
162
|
serverUrl,
|
|
143
163
|
machineToken,
|
|
144
164
|
agentsRoot,
|
|
145
|
-
|
|
165
|
+
reposRoot,
|
|
146
166
|
qaReportRoot: configuredQaReportRoot
|
|
147
167
|
? resolve(configuredQaReportRoot)
|
|
148
|
-
:
|
|
168
|
+
: defaultQaReportRoot,
|
|
149
169
|
cliPath: env.CREW_CLI_PATH ?? defaultCliPath(),
|
|
150
170
|
runtimeBin: env.CREW_RUNTIME ?? "claude",
|
|
151
171
|
codexHomeMode: codexHomeModeEnv(env),
|
package/dist/execution-runner.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { dirname, join, resolve } from "node:path";
|
|
3
|
+
import { resolveReposRoot } from "./config.js";
|
|
3
4
|
import { DaemonToServerExecutionFrameSchema, ExecutionCompletedSchema, ExecutionRejectedSchema, ExecutionStartSchema, } from "./execution-protocol.js";
|
|
4
5
|
import { JournalConflictError } from "./execution-journal.js";
|
|
5
6
|
import { boundExecutionFrame } from "./execution-event-limit.js";
|
|
@@ -524,7 +525,7 @@ export async function runExecution(config, input, dependencies) {
|
|
|
524
525
|
if (dependencies.abilityRelease !== undefined) {
|
|
525
526
|
await cancellable(dependencies.abilityRelease.apply(config.agentsRoot, spec.agent.handle, spec.agent.abilityRelease), dependencies.cancellation);
|
|
526
527
|
}
|
|
527
|
-
const reposRoot =
|
|
528
|
+
const reposRoot = resolveReposRoot(config.agentsRoot, config.reposRoot);
|
|
528
529
|
const preparedProjectDependencies = await cancellable(dependencies.projectDependencies.prepare({
|
|
529
530
|
trainingRoot: join(config.agentsRoot, spec.agent.handle, "training"),
|
|
530
531
|
reposRoot,
|
|
@@ -863,7 +864,7 @@ export async function runExecution(config, input, dependencies) {
|
|
|
863
864
|
token: credential.token,
|
|
864
865
|
agentId: credential.agentId,
|
|
865
866
|
agentsRoot: config.agentsRoot,
|
|
866
|
-
|
|
867
|
+
reposRoot: resolveReposRoot(config.agentsRoot, config.reposRoot),
|
|
867
868
|
...(config.qaReportRoot === undefined ? {} : { qaReportRoot: config.qaReportRoot }),
|
|
868
869
|
cliPath: config.cliPath,
|
|
869
870
|
providerConfig,
|
package/dist/local-executor.js
CHANGED
|
@@ -466,6 +466,11 @@ async function executeLocalUnlocked(input, callbacks, dependencies) {
|
|
|
466
466
|
CREW_TOKEN: input.launch.token,
|
|
467
467
|
CREW_CHANNEL: input.channelId,
|
|
468
468
|
CREW_HOME: workspace.dir,
|
|
469
|
+
// Keep the daemon-selected storage root authoritative for runtimes.
|
|
470
|
+
// In profile-backed NowWork sessions the daemon config may differ from
|
|
471
|
+
// the daemon process environment, so inheriting CREW_AGENTS_ROOT is not
|
|
472
|
+
// sufficient for QA/project diagnostics.
|
|
473
|
+
CREW_AGENTS_ROOT: input.launch.agentsRoot,
|
|
469
474
|
...(input.launch.reposRoot === undefined ? {} : { NOWWORK_REPOS_ROOT: input.launch.reposRoot }),
|
|
470
475
|
...(input.launch.qaReportRoot === undefined ? {} : { QA_REPORT_HUB: input.launch.qaReportRoot }),
|
|
471
476
|
// Expose only the training root; ability-specific workspace layout stays
|
package/dist/main.js
CHANGED
|
File without changes
|
|
@@ -16,12 +16,18 @@ export async function initializeAfterProjectSkillLeaseProtection(input) {
|
|
|
16
16
|
/**
|
|
17
17
|
* Runs only after execution-journal restart reconciliation has settled. A lease without a terminal
|
|
18
18
|
* journal fact remains durable and prevents the caller from marking Project Skill v2 ready.
|
|
19
|
+
*
|
|
20
|
+
* 重连时本进程仍在跑的 execution 合法持有 lease(`liveExecutionIds`):既不释放,也不算 unresolved。
|
|
21
|
+
* 否则一次网络抖动就会让 daemon 在整条连接上摘掉 Project Skills 能力(incident: 2026-09-02,
|
|
22
|
+
* 绑定项目的 Agent 全部 execution_spec_incompatible)。
|
|
19
23
|
*/
|
|
20
24
|
export async function recoverProjectSkillRuntimeRoots(input) {
|
|
21
25
|
for (const agentRoot of input.agentRoots) {
|
|
22
26
|
await input.roots.recover(agentRoot);
|
|
23
27
|
let unresolvedLease = false;
|
|
24
28
|
await input.leases.recover(agentRoot, async (executionId) => {
|
|
29
|
+
if (input.liveExecutionIds?.has(executionId))
|
|
30
|
+
return false;
|
|
25
31
|
const entry = await input.journal.get(executionId);
|
|
26
32
|
const releasable = entry?.state === "completed" || entry?.state === "interrupted";
|
|
27
33
|
if (!releasable)
|
|
@@ -22,13 +22,14 @@ export function createProjectSkillRuntimeRootStartup() {
|
|
|
22
22
|
leases,
|
|
23
23
|
initialize,
|
|
24
24
|
}),
|
|
25
|
-
recover: async (agentsRoot, journal, protectedExecutionIds) => {
|
|
25
|
+
recover: async (agentsRoot, journal, protectedExecutionIds, liveExecutionIds) => {
|
|
26
26
|
await recoverProjectSkillRuntimeRoots({
|
|
27
27
|
agentRoots: await agentRoots(agentsRoot),
|
|
28
28
|
journal,
|
|
29
29
|
roots,
|
|
30
30
|
leases,
|
|
31
31
|
gc,
|
|
32
|
+
...(liveExecutionIds === undefined ? {} : { liveExecutionIds }),
|
|
32
33
|
currentRootId: async (agentRoot) => (await readAppliedProjectSkillManifest(agentRoot))?.rootId ?? null,
|
|
33
34
|
afterLeaseRecovery: async () => {
|
|
34
35
|
const remaining = await initializeAfterProjectSkillLeaseProtection({
|
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
import { createExecutionJournal } from "../execution-journal.js";
|
|
2
2
|
import { reconcileExecutionJournal } from "../execution-recovery.js";
|
|
3
3
|
import { dslog, flushSlog } from "../slog.js";
|
|
4
|
+
/**
|
|
5
|
+
* 每次连接 preflight 的 Runtime root / lease 恢复。重连时本进程仍在跑的 execution 合法持有 lease,
|
|
6
|
+
* 必须当作存活而非孤儿;失败也必须留痕,否则整条连接静默摘掉 Project Skills 能力
|
|
7
|
+
* (incident: 2026-09-02,绑定项目的 Agent 全部 execution_spec_incompatible)。
|
|
8
|
+
*/
|
|
9
|
+
export function createProjectSkillReconnectRecovery(startup, agentsRoot, journal, protectedExecutionIds, liveExecutionIds) {
|
|
10
|
+
return async () => {
|
|
11
|
+
const live = liveExecutionIds();
|
|
12
|
+
try {
|
|
13
|
+
await startup.recover(agentsRoot, journal(), protectedExecutionIds, live);
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
dslog("project_skills.preflight_recovery_failed", "Project Skill runtime root 恢复失败,本连接不宣告 Project Skills 能力", {
|
|
18
|
+
level: "ERROR",
|
|
19
|
+
error_code: error.code ?? "unknown",
|
|
20
|
+
error_message: error.message,
|
|
21
|
+
live_execution_count: live.size,
|
|
22
|
+
});
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
4
27
|
export async function initializeProjectSkillProtectedExecutionJournal(input) {
|
|
5
28
|
return input.startup.initializeAfterLeaseProtection(input.config.agentsRoot, async (snapshot) => {
|
|
6
29
|
input.protectedExecutionIds.clear();
|
package/dist/runner.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** Legacy agent orchestration around the business-neutral local executor. */
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
+
import { resolveReposRoot } from "./config.js";
|
|
4
5
|
import { mintAgentToken } from "./token.js";
|
|
5
6
|
import { buildSystemPrompt, buildWakePrompt, capMemoryForInject, capWorkLogForInject } from "./prompt.js";
|
|
6
7
|
import { deliverScheduledReport, } from "./scheduled-report.js";
|
|
@@ -84,7 +85,7 @@ export async function runAgent(config, input, onActivity = defaultPrint, onConso
|
|
|
84
85
|
token: credential.token,
|
|
85
86
|
agentId: credential.agentId,
|
|
86
87
|
agentsRoot: config.agentsRoot,
|
|
87
|
-
|
|
88
|
+
reposRoot: resolveReposRoot(config.agentsRoot, config.reposRoot),
|
|
88
89
|
...(config.qaReportRoot === undefined ? {} : { qaReportRoot: config.qaReportRoot }),
|
|
89
90
|
cliPath: config.cliPath,
|
|
90
91
|
providerConfig,
|
package/dist/serve.js
CHANGED
|
@@ -42,7 +42,7 @@ import { PROJECT_SKILLS_CAPABILITY } from "./project-skills/types.js";
|
|
|
42
42
|
import { createAgentProjectionCoordinator } from "./project-skills/agent-projection-coordinator.js";
|
|
43
43
|
import { createProjectSkillRuntimeRootStartup, } from "./project-skills/runtime-root-startup.js";
|
|
44
44
|
import { createProjectSkillControllerReadiness, withProjectSkillCapabilityStatus } from "./project-skills/capability.js";
|
|
45
|
-
import { initializeProjectSkillProtectedExecutionJournal } from "./project-skills/serve-startup.js";
|
|
45
|
+
import { createProjectSkillReconnectRecovery, initializeProjectSkillProtectedExecutionJournal } from "./project-skills/serve-startup.js";
|
|
46
46
|
import { createProjectSkillConnectionCapabilityProvider, createProjectSkillMachineHelloPublisher } from "./project-skills/serve-capability.js";
|
|
47
47
|
import { createAgentAbilityRuntime } from "./agent-ability/runtime.js";
|
|
48
48
|
import { createProjectSkillsReconciler, } from "./project-skills/reconciler.js";
|
|
@@ -215,9 +215,7 @@ export function serve(config, opts = {}) {
|
|
|
215
215
|
additionalCapabilities: () => managedDaemonCapabilities(updateEligibility),
|
|
216
216
|
probeRuntimeRootStorePrimitive: projectSkillRuntimeRootStartup.probeNativePublicationPrimitiveReadiness,
|
|
217
217
|
initializeController: projectSkillControllerReadiness.ensure,
|
|
218
|
-
recoverRuntimeRootsAndLeases:
|
|
219
|
-
.recover(config.agentsRoot, executionJournal, protectedExecutionIds)
|
|
220
|
-
.then(() => true, () => false),
|
|
218
|
+
recoverRuntimeRootsAndLeases: createProjectSkillReconnectRecovery(projectSkillRuntimeRootStartup, config.agentsRoot, () => executionJournal, protectedExecutionIds, () => new Set(executionRuns.keys())),
|
|
221
219
|
applyReadiness: projectSkillControllerReadiness.applyPreflight,
|
|
222
220
|
});
|
|
223
221
|
const safeExecutionSend = (frame) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nowcrew/daemon",
|
|
3
|
-
"version": "0.6.77-beta.
|
|
3
|
+
"version": "0.6.77-beta.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "crew daemon — 运行在用户机器:拉起/管理 agent 进程,注入 crew CLI,归一化 runtime 事件",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -16,6 +16,14 @@
|
|
|
16
16
|
"publishConfig": {
|
|
17
17
|
"access": "public"
|
|
18
18
|
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"daemon": "pnpm --filter @nowcrew/cli build && tsx src/main.ts",
|
|
21
|
+
"build": "tsc -p tsconfig.json",
|
|
22
|
+
"codex-home:migrate": "tsx src/runtimes/codex-home-migration-cli.ts",
|
|
23
|
+
"prepublishOnly": "pnpm build && node ../scripts/daemon-release-artifact.mjs --strict-registry",
|
|
24
|
+
"test": "vitest run",
|
|
25
|
+
"typecheck": "tsc --noEmit"
|
|
26
|
+
},
|
|
19
27
|
"dependencies": {
|
|
20
28
|
"@agentclientprotocol/sdk": "1.2.1",
|
|
21
29
|
"@nowcrew/cli": "0.4.13",
|
|
@@ -36,12 +44,5 @@
|
|
|
36
44
|
"tsx": "^4.19.0",
|
|
37
45
|
"typescript": "^5.6.0",
|
|
38
46
|
"vitest": "^2.1.0"
|
|
39
|
-
},
|
|
40
|
-
"scripts": {
|
|
41
|
-
"daemon": "pnpm --filter @nowcrew/cli build && tsx src/main.ts",
|
|
42
|
-
"build": "tsc -p tsconfig.json",
|
|
43
|
-
"codex-home:migrate": "tsx src/runtimes/codex-home-migration-cli.ts",
|
|
44
|
-
"test": "vitest run",
|
|
45
|
-
"typecheck": "tsc --noEmit"
|
|
46
47
|
}
|
|
47
|
-
}
|
|
48
|
+
}
|