@nowcrew/daemon 0.6.65 → 0.6.66
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/agent-ability/materializer.js +1 -20
- package/dist/agent-ability/resolver.js +10 -7
- package/dist/agent-ability/runtime.js +0 -3
- package/dist/automatic-install-target.js +10 -15
- package/dist/computer-cli.js +1 -10
- package/dist/computer-service.js +1 -41
- package/dist/config.js +0 -44
- package/dist/daemon-migration-controller.js +18 -16
- package/dist/execution-runner.js +1 -3
- package/dist/local-execution-prompt.js +9 -14
- package/dist/local-executor.js +3 -56
- package/dist/machine-info.js +2 -3
- package/dist/main.js +0 -83
- package/dist/managed-service-lifecycle.js +2 -47
- package/dist/managed-service-startup.js +0 -2
- package/dist/profile-layout.js +4 -10
- package/dist/project-skills/controller.js +0 -2
- package/dist/prompt.js +1 -19
- package/dist/runner.js +0 -3
- package/dist/runtimes/codex-app-server-runner.js +14 -54
- package/dist/runtimes/codex-contract.js +5 -20
- package/dist/runtimes/codex.js +0 -4
- package/dist/serve.js +3 -68
- package/dist/supervised-runtime.js +0 -3
- package/dist/workspace.js +1 -24
- package/package.json +9 -10
- package/dist/local-memory/index-budget.js +0 -74
- package/dist/local-memory/pending.js +0 -111
- package/dist/local-memory/runtime.js +0 -87
- package/dist/local-memory/types.js +0 -1
- package/dist/local-memory/write.js +0 -448
- package/dist/runtimes/codex-command-safety.js +0 -75
- package/dist/runtimes/codex-turn-retry.js +0 -69
- package/dist/storage-config.js +0 -175
- package/dist/storage-control.js +0 -193
- package/dist/storage-copy.js +0 -609
- package/dist/storage-credential-guard.js +0 -21
- package/dist/storage-doctor.js +0 -228
- package/dist/storage-identity.js +0 -29
- package/dist/storage-layout.js +0 -143
- package/dist/storage-manifest.js +0 -855
- package/dist/storage-migration-controller.js +0 -417
- package/dist/storage-migration-manifest.js +0 -105
- package/dist/storage-migration-policy.js +0 -100
- package/dist/storage-runtime-controller.js +0 -339
- package/dist/storage-runtime-readiness.js +0 -184
- package/dist/storage-runtime.js +0 -39
- package/dist/storage-safe-fs.js +0 -302
- package/dist/storage-serve-adapter.js +0 -65
- package/dist/storage-status-delivery.js +0 -209
- package/dist/storage-status-replay.js +0 -125
- package/dist/storage-target-confirmation.js +0 -129
- package/dist/storage-worker-command.js +0 -27
- package/dist/storage-worker-executor.js +0 -384
- package/dist/storage-worker-handoff.js +0 -151
- package/dist/storage-worker-operation.js +0 -284
- package/dist/storage-worker-status.js +0 -105
|
@@ -249,23 +249,6 @@ const verifyCache = async (agentsRoot, ability) => {
|
|
|
249
249
|
};
|
|
250
250
|
const layerRelativePath = (path, layer) => path.startsWith(`${layer}/`) ? path.slice(layer.length + 1) : path;
|
|
251
251
|
const readManagedCatalog = async (trainingRoot) => JSON.parse(await readFile(join(trainingRoot, "ACTIVE_RELEASE.json"), "utf8"));
|
|
252
|
-
const projectedSkillExists = async (trainingRoot, name) => {
|
|
253
|
-
const root = join(trainingRoot, "skills", safeAbilityName(name));
|
|
254
|
-
if (!await isRealDirectory(root))
|
|
255
|
-
return false;
|
|
256
|
-
const direct = await lstat(join(root, "SKILL.md")).catch(() => null);
|
|
257
|
-
if (direct?.isFile() && !direct.isSymbolicLink())
|
|
258
|
-
return true;
|
|
259
|
-
for (const entry of await readdir(root, { withFileTypes: true })) {
|
|
260
|
-
if (!entry.isDirectory())
|
|
261
|
-
continue;
|
|
262
|
-
const skill = await lstat(join(root, entry.name, "SKILL.md")).catch(() => null);
|
|
263
|
-
if (skill?.isFile() && !skill.isSymbolicLink())
|
|
264
|
-
return true;
|
|
265
|
-
}
|
|
266
|
-
return false;
|
|
267
|
-
};
|
|
268
|
-
const projectedSkillsComplete = async (trainingRoot, skills) => (await Promise.all(skills.map((skill) => projectedSkillExists(trainingRoot, skill.name)))).every(Boolean);
|
|
269
252
|
const trainingSwitchJournalPath = (agentRoot) => join(agentRoot, ".training-switch.json");
|
|
270
253
|
const trainingRollbackRoot = (agentRoot) => join(agentRoot, ".training-rollback");
|
|
271
254
|
const trainingDiscardRoot = (agentRoot) => join(agentRoot, ".training-discard");
|
|
@@ -439,7 +422,6 @@ const activeTrainingRoot = async (agentsRoot, handle, ability) => {
|
|
|
439
422
|
&& catalog.releaseId === ability.releaseId
|
|
440
423
|
&& catalog.rootCommit === ability.rootCommit
|
|
441
424
|
&& catalog.artifactDigest === ability.artifactDigest
|
|
442
|
-
&& await projectedSkillsComplete(trainingRoot, ability.skills)
|
|
443
425
|
? trainingRoot
|
|
444
426
|
: null;
|
|
445
427
|
};
|
|
@@ -481,8 +463,7 @@ const materializeWorkspaceTraining = async (agentsRoot, handle, ability) => {
|
|
|
481
463
|
}
|
|
482
464
|
if (previousCatalog.releaseId === ability.releaseId
|
|
483
465
|
&& previousCatalog.artifactDigest === ability.artifactDigest
|
|
484
|
-
&& previousCatalog.projectionDigest === projectionDigest
|
|
485
|
-
&& await projectedSkillsComplete(trainingRoot, ability.skills))
|
|
466
|
+
&& previousCatalog.projectionDigest === projectionDigest)
|
|
486
467
|
return trainingRoot;
|
|
487
468
|
}
|
|
488
469
|
await mkdir(agentRoot, { recursive: true });
|
|
@@ -9,8 +9,8 @@ import { abilityWorkspaceProjectionPath, DaemonAbilityLockSchema, DaemonAbilityM
|
|
|
9
9
|
import { PROJECT_MANIFEST_SOURCE_PATH, ProjectDependencyManifestSchema, } from "../project-dependency-manifest.js";
|
|
10
10
|
const runFile = promisify(execFile);
|
|
11
11
|
const MAX_FILES = 5_000;
|
|
12
|
-
const
|
|
13
|
-
const
|
|
12
|
+
export const AGENT_ABILITY_MAX_TOTAL_BYTES = 200 * 1024 * 1024;
|
|
13
|
+
export const AGENT_ABILITY_MAX_FILE_BYTES = 100 * 1024 * 1024;
|
|
14
14
|
const MAX_INSTRUCTIONS_BYTES = 96 * 1024;
|
|
15
15
|
const MAX_MEMORY_BYTES = 64 * 1024;
|
|
16
16
|
const AUTHORING_ONLY_ROOTS = new Set([".claude"]);
|
|
@@ -114,10 +114,11 @@ export const collectAbilityFiles = async (root) => {
|
|
|
114
114
|
if (info.isDirectory())
|
|
115
115
|
await visit(absolute);
|
|
116
116
|
else if (info.isFile()) {
|
|
117
|
-
if (info.size >
|
|
117
|
+
if (info.size > AGENT_ABILITY_MAX_FILE_BYTES) {
|
|
118
118
|
throw new Error(`ability_file_size_exceeded:${relative(root, absolute)}`);
|
|
119
|
+
}
|
|
119
120
|
totalBytes += info.size;
|
|
120
|
-
if (totalBytes >
|
|
121
|
+
if (totalBytes > AGENT_ABILITY_MAX_TOTAL_BYTES)
|
|
121
122
|
throw new Error("ability_total_size_exceeded");
|
|
122
123
|
if (files.length >= MAX_FILES)
|
|
123
124
|
throw new Error("ability_file_count_exceeded");
|
|
@@ -251,7 +252,7 @@ export const validateAbilityDependencyDeclarations = (manifest, lock) => {
|
|
|
251
252
|
throw new Error("ability_lock_has_undeclared_dependency");
|
|
252
253
|
}
|
|
253
254
|
};
|
|
254
|
-
const
|
|
255
|
+
export const scanAbilityFiles = (files, manifest) => {
|
|
255
256
|
const findings = [];
|
|
256
257
|
const secrets = [
|
|
257
258
|
/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/u,
|
|
@@ -259,7 +260,9 @@ const scan = (files, manifest) => {
|
|
|
259
260
|
/\bAK(?:ID|IA)[A-Z0-9]{12,}\b/u,
|
|
260
261
|
];
|
|
261
262
|
const executable = new Set([".exe", ".dll", ".dylib", ".so", ".bin", ".class", ".jar"]);
|
|
262
|
-
const allowedBinaryDocuments = new Set([
|
|
263
|
+
const allowedBinaryDocuments = new Set([
|
|
264
|
+
".pdf", ".png", ".jpg", ".jpeg", ".gif", ".webp", ".xlsx", ".xls", ".docx", ".pptx", ".ttf", ".otf",
|
|
265
|
+
]);
|
|
263
266
|
for (const file of files) {
|
|
264
267
|
let text;
|
|
265
268
|
try {
|
|
@@ -382,7 +385,7 @@ export async function resolveAbilityRelease(agentsRoot, command) {
|
|
|
382
385
|
}
|
|
383
386
|
const externalPaths = await verifyExternalDependencies(cacheRoot, resolved.root, lock);
|
|
384
387
|
files = await collectAbilityFiles(resolved.root);
|
|
385
|
-
const security =
|
|
388
|
+
const security = scanAbilityFiles(files, manifest);
|
|
386
389
|
const kinds = new Set(lock.assets.map((asset) => asset.kind));
|
|
387
390
|
const memory = [];
|
|
388
391
|
for (const [layer, mounts] of [["release-policy", manifest.spec.memory.policy], ["release-seed", manifest.spec.memory.seeds]]) {
|
|
@@ -32,9 +32,6 @@ export function createAgentAbilityRuntime(agentsRoot, options = {}) {
|
|
|
32
32
|
else if (type === "agent:ability:resolve") {
|
|
33
33
|
result = await controller.handle(input);
|
|
34
34
|
}
|
|
35
|
-
else if (options.isAdmissionClosed?.() === true) {
|
|
36
|
-
result = { ok: false, error: "storage_migration_quiescing" };
|
|
37
|
-
}
|
|
38
35
|
else {
|
|
39
36
|
const parsed = AbilityApplyCommandSchema.safeParse(input);
|
|
40
37
|
if (!parsed.success)
|
|
@@ -3,12 +3,12 @@ import { profileLayout, validateLocalInstanceName } from "./profile-layout.js";
|
|
|
3
3
|
const PROFILE_NAME = /^[a-z0-9][a-z0-9_-]{0,47}$/;
|
|
4
4
|
const KNOWN_TARGETS = {
|
|
5
5
|
"nowwork-in.nowcoder.com": {
|
|
6
|
-
|
|
6
|
+
profile: "in",
|
|
7
7
|
daemonDirectory: "daemon",
|
|
8
8
|
agentsDirectory: "agents",
|
|
9
9
|
},
|
|
10
10
|
"nowwork-dev.nowcoder.com": {
|
|
11
|
-
|
|
11
|
+
profile: "dev",
|
|
12
12
|
daemonDirectory: "daemon-dev",
|
|
13
13
|
agentsDirectory: "agents-dev",
|
|
14
14
|
},
|
|
@@ -42,37 +42,32 @@ function requireCustomProfile(hostname, value) {
|
|
|
42
42
|
if (!PROFILE_NAME.test(value)) {
|
|
43
43
|
throw new Error("Invalid custom profile; expected a lowercase name of 1-48 letters, digits, '_' or '-'");
|
|
44
44
|
}
|
|
45
|
-
if (value === "in" || value === "dev"
|
|
45
|
+
if (value === "in" || value === "dev") {
|
|
46
46
|
throw new Error(`Profile '${value}' is reserved for a known NowWork hostname`);
|
|
47
47
|
}
|
|
48
48
|
return value;
|
|
49
49
|
}
|
|
50
50
|
function knownTargetForProfile(environment, requestedProfile, input, parsed) {
|
|
51
51
|
const paths = input.platform === "win32" ? win32 : posix;
|
|
52
|
-
|
|
53
|
-
// uses the canonical environment token (production, never in).
|
|
54
|
-
const legacyProfile = environment === "production" ? "in" : environment;
|
|
52
|
+
const legacyProfile = environment;
|
|
55
53
|
if (requestedProfile === undefined || requestedProfile === legacyProfile) {
|
|
56
54
|
return Object.freeze({
|
|
57
55
|
kind: "known",
|
|
58
56
|
profile: legacyProfile,
|
|
59
57
|
serverUrl: normalizedServerUrl(parsed),
|
|
60
|
-
daemonHome: paths.join(input.userHome, ".crew", environment === "
|
|
61
|
-
agentsRoot: paths.join(input.userHome, ".crew", environment === "
|
|
58
|
+
daemonHome: paths.join(input.userHome, ".crew", environment === "in" ? "daemon" : "daemon-dev"),
|
|
59
|
+
agentsRoot: paths.join(input.userHome, ".crew", environment === "in" ? "agents" : "agents-dev"),
|
|
62
60
|
npmPrefix: paths.join(input.userHome, ".crew", "daemon-runtimes", legacyProfile),
|
|
63
61
|
});
|
|
64
62
|
}
|
|
65
63
|
if (requestedProfile === "in" || requestedProfile === "dev") {
|
|
66
|
-
throw new Error(`Server hostname '${new URL(input.serverUrl).hostname}' requires profile '${
|
|
64
|
+
throw new Error(`Server hostname '${new URL(input.serverUrl).hostname}' requires profile '${legacyProfile}'`);
|
|
67
65
|
}
|
|
68
66
|
const prefix = `nw-${environment}-`;
|
|
69
|
-
|
|
70
|
-
if (!requestedProfile.startsWith(prefix) && !requestedProfile.startsWith(legacyPrefix)) {
|
|
67
|
+
if (!requestedProfile.startsWith(prefix)) {
|
|
71
68
|
throw new Error(`Server hostname '${new URL(input.serverUrl).hostname}' requires profile '${prefix}<local-name>'`);
|
|
72
69
|
}
|
|
73
|
-
const localInstanceName = validateLocalInstanceName(requestedProfile.
|
|
74
|
-
? requestedProfile.slice(prefix.length)
|
|
75
|
-
: requestedProfile.slice(legacyPrefix.length));
|
|
70
|
+
const localInstanceName = validateLocalInstanceName(requestedProfile.slice(prefix.length));
|
|
76
71
|
const layout = profileLayout({
|
|
77
72
|
environment,
|
|
78
73
|
localInstanceName,
|
|
@@ -96,7 +91,7 @@ export function resolveAutomaticInstallTarget(input) {
|
|
|
96
91
|
const paths = input.platform === "win32" ? win32 : posix;
|
|
97
92
|
const known = KNOWN_TARGETS[hostname];
|
|
98
93
|
if (known !== undefined) {
|
|
99
|
-
return knownTargetForProfile(known.
|
|
94
|
+
return knownTargetForProfile(known.profile, input.requestedProfile, input, parsed);
|
|
100
95
|
}
|
|
101
96
|
const profile = requireCustomProfile(hostname, input.requestedProfile);
|
|
102
97
|
return Object.freeze({
|
package/dist/computer-cli.js
CHANGED
|
@@ -82,14 +82,6 @@ function translatedError(error, td) {
|
|
|
82
82
|
}
|
|
83
83
|
return td(error.message);
|
|
84
84
|
}
|
|
85
|
-
function storageServiceEnvironment(env) {
|
|
86
|
-
return {
|
|
87
|
-
...(env.NOWWORK_HOME === undefined ? {} : { NOWWORK_HOME: env.NOWWORK_HOME }),
|
|
88
|
-
...(env.NOWWORK_ENV_TAG === undefined ? {} : { NOWWORK_ENV_TAG: env.NOWWORK_ENV_TAG }),
|
|
89
|
-
...(env.NOWWORK_STORAGE_POLICY_PATH === undefined
|
|
90
|
-
? {} : { NOWWORK_STORAGE_POLICY_PATH: env.NOWWORK_STORAGE_POLICY_PATH }),
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
85
|
export async function runComputerCommand(argv, overrides = {}) {
|
|
94
86
|
const command = argv[0];
|
|
95
87
|
if (!command || !COMPUTER_COMMANDS.has(command))
|
|
@@ -210,7 +202,6 @@ export async function runComputerCommand(argv, overrides = {}) {
|
|
|
210
202
|
...deps,
|
|
211
203
|
profile: restartProfile.name,
|
|
212
204
|
profileHome: home,
|
|
213
|
-
environment: storageServiceEnvironment(deps.env),
|
|
214
205
|
})
|
|
215
206
|
: null;
|
|
216
207
|
if (spec && restartProfile) {
|
|
@@ -281,7 +272,7 @@ export async function runComputerCommand(argv, overrides = {}) {
|
|
|
281
272
|
throw new Error(td("Service lifecycle requires the built daemon entry (.js), not a TypeScript development entry"));
|
|
282
273
|
}
|
|
283
274
|
const spec = buildServiceSpec({
|
|
284
|
-
...deps, profile: name, profileHome: home,
|
|
275
|
+
...deps, profile: name, profileHome: home,
|
|
285
276
|
});
|
|
286
277
|
const installation = daemonGlobalInstallation(deps.entryPath, deps.platform);
|
|
287
278
|
const managedRecord = installation !== null && spec.platform !== "win32"
|
package/dist/computer-service.js
CHANGED
|
@@ -53,7 +53,6 @@ export function windowsCommandArg(value) {
|
|
|
53
53
|
}
|
|
54
54
|
export function buildServiceSpec(input) {
|
|
55
55
|
const { platform, profile, userHome } = input;
|
|
56
|
-
const environment = input.environment ?? process.env;
|
|
57
56
|
if (platform !== "darwin" && platform !== "linux" && platform !== "win32") {
|
|
58
57
|
throw new Error(`Computer services are not supported on platform '${platform}'`);
|
|
59
58
|
}
|
|
@@ -73,16 +72,6 @@ export function buildServiceSpec(input) {
|
|
|
73
72
|
throw new Error("Cannot install launchd service without a numeric uid");
|
|
74
73
|
const id = `com.nowcrew.daemon.${profile}${identitySuffix}`;
|
|
75
74
|
const args = daemonCommand.map((arg) => ` <string>${xml(arg)}</string>`).join("\n");
|
|
76
|
-
const environmentEntries = [
|
|
77
|
-
["NOWWORK_HOME", environment.NOWWORK_HOME],
|
|
78
|
-
["NOWWORK_ENV_TAG", environment.NOWWORK_ENV_TAG],
|
|
79
|
-
["NOWWORK_STORAGE_POLICY_PATH", environment.NOWWORK_STORAGE_POLICY_PATH],
|
|
80
|
-
].flatMap(([key, value]) => value === undefined
|
|
81
|
-
? []
|
|
82
|
-
: [` <key>${key}</key><string>${xml(assertSingleLine(value, key))}</string>`]);
|
|
83
|
-
const environmentBlock = environmentEntries.length === 0
|
|
84
|
-
? ""
|
|
85
|
-
: ` <key>EnvironmentVariables</key>\n <dict>\n${environmentEntries.join("\n")}\n </dict>\n`;
|
|
86
75
|
return {
|
|
87
76
|
platform,
|
|
88
77
|
profile,
|
|
@@ -90,7 +79,7 @@ export function buildServiceSpec(input) {
|
|
|
90
79
|
descriptorPath: resolve(userHome, "Library", "LaunchAgents", `${id}.plist`),
|
|
91
80
|
daemonCommand,
|
|
92
81
|
managerDomain: `gui/${input.uid}`,
|
|
93
|
-
descriptor: `<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n<plist version="1.0">\n<dict>\n <key>Label</key><string>${xml(id)}</string>\n <key>ProgramArguments</key>\n <array>\n${args}\n </array>\n
|
|
82
|
+
descriptor: `<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n<plist version="1.0">\n<dict>\n <key>Label</key><string>${xml(id)}</string>\n <key>ProgramArguments</key>\n <array>\n${args}\n </array>\n <key>KeepAlive</key><true/>\n <key>ProcessType</key><string>Background</string>\n</dict>\n</plist>\n`,
|
|
94
83
|
};
|
|
95
84
|
}
|
|
96
85
|
if (platform === "linux") {
|
|
@@ -277,35 +266,6 @@ export async function installService(spec, runner = systemCommandRunner) {
|
|
|
277
266
|
throw error;
|
|
278
267
|
}
|
|
279
268
|
}
|
|
280
|
-
export async function replaceInstalledServiceDescriptor(spec, previousDescriptor, runner = systemCommandRunner) {
|
|
281
|
-
if (spec.platform === "win32" || spec.descriptorPath === null || spec.descriptor === null) {
|
|
282
|
-
throw new Error("Installed service descriptor replacement requires launchd or systemd");
|
|
283
|
-
}
|
|
284
|
-
const current = await readServiceDescriptor(spec);
|
|
285
|
-
if (current !== previousDescriptor) {
|
|
286
|
-
throw new Error(`Installed descriptor for '${spec.id}' changed before replacement`);
|
|
287
|
-
}
|
|
288
|
-
const status = await serviceStatus(spec, runner);
|
|
289
|
-
if (!status.installed)
|
|
290
|
-
throw new Error(`Service '${spec.id}' is not installed`);
|
|
291
|
-
if (status.running || status.loaded)
|
|
292
|
-
await serviceAction(spec, "stop", runner);
|
|
293
|
-
try {
|
|
294
|
-
await writePrivateAtomic(spec.descriptorPath, spec.descriptor);
|
|
295
|
-
if (spec.platform === "linux") {
|
|
296
|
-
await checked(runner, "systemctl", ["--user", "daemon-reload"], "systemd reload");
|
|
297
|
-
await checked(runner, "systemctl", ["--user", "enable", spec.id], "systemd enable");
|
|
298
|
-
}
|
|
299
|
-
if (status.running)
|
|
300
|
-
await serviceAction(spec, "start", runner);
|
|
301
|
-
}
|
|
302
|
-
catch (error) {
|
|
303
|
-
await writePrivateAtomic(spec.descriptorPath, previousDescriptor).catch(() => undefined);
|
|
304
|
-
if (status.running)
|
|
305
|
-
await serviceAction(spec, "start", runner).catch(() => undefined);
|
|
306
|
-
throw error;
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
269
|
export async function ensureServiceEnabled(spec, runner = systemCommandRunner) {
|
|
310
270
|
if (spec.platform === "linux") {
|
|
311
271
|
if (spec.descriptorPath === null || !await pathExists(spec.descriptorPath)) {
|
package/dist/config.js
CHANGED
|
@@ -59,40 +59,6 @@ function defaultCliPath() {
|
|
|
59
59
|
return resolve(here, "../../cli/dist/main.js");
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
-
// 临时 dev 验收名单。测试完成后删除此常量,恢复未配置时默认关闭的行为。
|
|
63
|
-
const TEMP_LOCAL_MEMORY_V2_TEST_HANDLES = [
|
|
64
|
-
"memory-v2-test-a",
|
|
65
|
-
"memory-v2-test-b",
|
|
66
|
-
"memory-v2-test-c",
|
|
67
|
-
];
|
|
68
|
-
function isTemporaryDevServer(serverUrl) {
|
|
69
|
-
try {
|
|
70
|
-
const hostname = new URL(serverUrl).hostname.toLowerCase();
|
|
71
|
-
return hostname === "localhost"
|
|
72
|
-
|| hostname === "127.0.0.1"
|
|
73
|
-
|| hostname === "::1"
|
|
74
|
-
|| hostname === "nowwork-dev.nowcoder.com";
|
|
75
|
-
}
|
|
76
|
-
catch {
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
function localMemoryV2Handles(env, serverUrl) {
|
|
81
|
-
const configured = env.CREW_LOCAL_MEMORY_V2_HANDLES;
|
|
82
|
-
if (configured === undefined) {
|
|
83
|
-
return isTemporaryDevServer(serverUrl)
|
|
84
|
-
? new Set(TEMP_LOCAL_MEMORY_V2_TEST_HANDLES)
|
|
85
|
-
: new Set();
|
|
86
|
-
}
|
|
87
|
-
const raw = configured.trim();
|
|
88
|
-
if (raw === "")
|
|
89
|
-
return new Set();
|
|
90
|
-
const handles = raw.split(",").map((value) => value.trim()).filter(Boolean);
|
|
91
|
-
if (handles.some((handle) => !/^[A-Za-z0-9][A-Za-z0-9._-]*$/u.test(handle))) {
|
|
92
|
-
throw new ConfigError("CREW_LOCAL_MEMORY_V2_HANDLES contains an invalid agent handle");
|
|
93
|
-
}
|
|
94
|
-
return new Set(handles);
|
|
95
|
-
}
|
|
96
62
|
export const DEFAULT_SERVER_URL = "http://127.0.0.1:3001";
|
|
97
63
|
function codexHomeModeEnv(env) {
|
|
98
64
|
const value = env.CREW_CODEX_HOME_MODE;
|
|
@@ -102,14 +68,6 @@ function codexHomeModeEnv(env) {
|
|
|
102
68
|
return "private";
|
|
103
69
|
throw new ConfigError("CREW_CODEX_HOME_MODE must be shared or private");
|
|
104
70
|
}
|
|
105
|
-
function codexCollaborationToolsEnv(env) {
|
|
106
|
-
const value = (env.CREW_CODEX_COLLABORATION_TOOLS ?? "").trim().toLowerCase();
|
|
107
|
-
if (value === "" || value === "0" || value === "false" || value === "off")
|
|
108
|
-
return false;
|
|
109
|
-
if (value === "1" || value === "true" || value === "on")
|
|
110
|
-
return true;
|
|
111
|
-
throw new ConfigError("CREW_CODEX_COLLABORATION_TOOLS must be one of 1/true/on/0/false/off");
|
|
112
|
-
}
|
|
113
71
|
export function loadConfig(env = process.env) {
|
|
114
72
|
const serverUrl = (env.CREW_SERVER_URL ?? DEFAULT_SERVER_URL).replace(/\/+$/, "");
|
|
115
73
|
const machineToken = env.CREW_MACHINE_TOKEN ?? "";
|
|
@@ -141,7 +99,6 @@ export function loadConfig(env = process.env) {
|
|
|
141
99
|
cliPath: env.CREW_CLI_PATH ?? defaultCliPath(),
|
|
142
100
|
runtimeBin: env.CREW_RUNTIME ?? "claude",
|
|
143
101
|
codexHomeMode: codexHomeModeEnv(env),
|
|
144
|
-
codexCollaborationTools: codexCollaborationToolsEnv(env),
|
|
145
102
|
dangerous: env.CREW_RUNTIME_SAFE !== "1", // 默认开启 (headless agent 在自有 workspace 内运行)
|
|
146
103
|
resume: env.CREW_RESUME !== "off" && env.CREW_RESUME !== "0", // 默认开启;一键回退现状用 CREW_RESUME=off
|
|
147
104
|
resumeWarmMs: env.CREW_RESUME_WARM_MS != null ? Number(env.CREW_RESUME_WARM_MS) : 3_600_000, // 默认 1h
|
|
@@ -151,7 +108,6 @@ export function loadConfig(env = process.env) {
|
|
|
151
108
|
sessionMaxTurns: env.CREW_SESSION_MAX_TURNS != null ? Number(env.CREW_SESSION_MAX_TURNS) : 30,
|
|
152
109
|
productName: env.CREW_PRODUCT_NAME ?? "nowwork",
|
|
153
110
|
agentMemory: loadAgentMemoryConfig(env),
|
|
154
|
-
localMemoryV2Handles: localMemoryV2Handles(env, serverUrl),
|
|
155
111
|
executionLimits,
|
|
156
112
|
};
|
|
157
113
|
}
|
|
@@ -10,7 +10,6 @@ import { buildServiceSpec, captureExactService, serviceStatus, systemCommandRunn
|
|
|
10
10
|
import { readManagedServiceRegistry } from "./managed-service-registry.js";
|
|
11
11
|
import { uninstallManagedService } from "./managed-service-lifecycle.js";
|
|
12
12
|
import { resolveAutomaticInstallTarget } from "./automatic-install-target.js";
|
|
13
|
-
import { buildStorageMigrationMappings, createSafeServiceManifest, CredentialMaterialError, } from "./storage-migration-manifest.js";
|
|
14
13
|
const MigrationMessageSchema = z.object({
|
|
15
14
|
type: z.literal("daemon:migrate"),
|
|
16
15
|
migrationId: z.string().uuid(),
|
|
@@ -48,30 +47,33 @@ async function hashedFiles(root, directory = root) {
|
|
|
48
47
|
return files;
|
|
49
48
|
}
|
|
50
49
|
async function backupAndCopy(input, id, targetHome, targetAgents, service) {
|
|
51
|
-
// Validate and project service identity before creating any backup bytes. A descriptor containing
|
|
52
|
-
// a token must stop the migration before it can be copied into the local backup root.
|
|
53
|
-
const safeService = createSafeServiceManifest({
|
|
54
|
-
spec: service.spec,
|
|
55
|
-
snapshot: service.snapshot,
|
|
56
|
-
managedRecord: service.managedRecord,
|
|
57
|
-
});
|
|
58
50
|
const backup = migrationBackupRoot(input, id);
|
|
59
51
|
await mkdir(backup, { recursive: true, mode: 0o700 });
|
|
60
52
|
await cp(input.currentDaemonHome, resolve(backup, "daemon-home"), { recursive: true, force: false });
|
|
61
53
|
await cp(input.currentAgentsRoot, resolve(backup, "agents-root"), { recursive: true, force: false });
|
|
62
54
|
await cp(input.currentDaemonHome, targetHome, { recursive: true, force: false });
|
|
63
55
|
await cp(input.currentAgentsRoot, targetAgents, { recursive: true, force: false });
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
56
|
+
const files = [
|
|
57
|
+
...(await hashedFiles(resolve(backup, "daemon-home"))).map((file) => ({ ...file, path: `daemon-home/${file.path}` })),
|
|
58
|
+
...(await hashedFiles(resolve(backup, "agents-root"))).map((file) => ({ ...file, path: `agents-root/${file.path}` })),
|
|
59
|
+
];
|
|
67
60
|
await writeFile(resolve(backup, "manifest.json"), `${JSON.stringify({
|
|
68
|
-
version:
|
|
61
|
+
version: 1,
|
|
69
62
|
migrationId: id,
|
|
70
63
|
profile: input.profileName,
|
|
71
64
|
daemonHome: input.currentDaemonHome,
|
|
72
65
|
agentsRoot: input.currentAgentsRoot,
|
|
73
|
-
service:
|
|
74
|
-
|
|
66
|
+
service: {
|
|
67
|
+
id: service.spec.id,
|
|
68
|
+
platform: service.spec.platform,
|
|
69
|
+
descriptorPath: service.spec.descriptorPath,
|
|
70
|
+
descriptor: service.spec.descriptor,
|
|
71
|
+
daemonCommand: service.spec.daemonCommand,
|
|
72
|
+
installed: service.snapshot.installed,
|
|
73
|
+
running: service.snapshot.running,
|
|
74
|
+
managedRecord: service.managedRecord,
|
|
75
|
+
},
|
|
76
|
+
files,
|
|
75
77
|
}, null, 2)}\n`, { mode: 0o600 });
|
|
76
78
|
return backup;
|
|
77
79
|
}
|
|
@@ -145,7 +147,7 @@ export function createDaemonMigrationController(input) {
|
|
|
145
147
|
}
|
|
146
148
|
}
|
|
147
149
|
catch (error) {
|
|
148
|
-
sendFailure(message.migrationId,
|
|
150
|
+
sendFailure(message.migrationId, "target_conflict", error);
|
|
149
151
|
return;
|
|
150
152
|
}
|
|
151
153
|
input.sendStatus({ type: "daemon:migration-status", migrationId: message.migrationId, status: "backing_up" });
|
|
@@ -156,7 +158,7 @@ export function createDaemonMigrationController(input) {
|
|
|
156
158
|
}
|
|
157
159
|
catch (error) {
|
|
158
160
|
await Promise.allSettled([rm(targetPath, { recursive: true, force: true }), rm(targetAgents, { recursive: true, force: true })]);
|
|
159
|
-
sendFailure(message.migrationId,
|
|
161
|
+
sendFailure(message.migrationId, "backup_failed", error);
|
|
160
162
|
return;
|
|
161
163
|
}
|
|
162
164
|
const install = input.install ?? installDaemonAutomatically;
|
package/dist/execution-runner.js
CHANGED
|
@@ -775,7 +775,7 @@ export async function runExecution(config, input, dependencies) {
|
|
|
775
775
|
const baseSystemPromptBudget = spec.agent.abilityRelease === undefined
|
|
776
776
|
? systemPromptBudget
|
|
777
777
|
: Math.max(0, Math.min(systemPromptBudget, Math.max(32 * 1024, systemPromptBudget - 168 * 1024)));
|
|
778
|
-
const systemPromptWithLocalFacts = withLocalExecutionFacts(spec.instructions.systemPrompt, baseSystemPromptBudget
|
|
778
|
+
const systemPromptWithLocalFacts = withLocalExecutionFacts(spec.instructions.systemPrompt, baseSystemPromptBudget);
|
|
779
779
|
const boundedSystemPrompt = (context) => appendAgentMemoryContext(typeof systemPromptWithLocalFacts === "string"
|
|
780
780
|
? systemPromptWithLocalFacts
|
|
781
781
|
: systemPromptWithLocalFacts(context), recalledMemory, baseSystemPromptBudget);
|
|
@@ -801,7 +801,6 @@ export async function runExecution(config, input, dependencies) {
|
|
|
801
801
|
name: spec.runtime.name,
|
|
802
802
|
...(spec.runtime.model === undefined ? {} : { model: spec.runtime.model }),
|
|
803
803
|
...(spec.runtime.reasoning === undefined ? {} : { reasoning: spec.runtime.reasoning }),
|
|
804
|
-
codexCollaborationTools: config.codexCollaborationTools,
|
|
805
804
|
},
|
|
806
805
|
effectivePermission: permission,
|
|
807
806
|
captureFinal: spec.reporting.captureFinal,
|
|
@@ -827,7 +826,6 @@ export async function runExecution(config, input, dependencies) {
|
|
|
827
826
|
softTokens: config.sessionSoftTokens,
|
|
828
827
|
maxTurns: config.sessionMaxTurns,
|
|
829
828
|
},
|
|
830
|
-
localMemoryV2Enabled: config.localMemoryV2Handles?.has(spec.agent.handle) === true,
|
|
831
829
|
};
|
|
832
830
|
const result = await Promise.race([
|
|
833
831
|
execute(localInput, callbacks, localDependencies),
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* server 提示词是权威部分,绝不裁剪;项目工作区提示词是绑定执行的强制部分,放不下就直接失败;
|
|
5
5
|
* 只有本机事实(CREW_HOME / work-log / MEMORY 注入)是可选增强,按整段丢弃或按字节截断。
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
7
|
+
import { buildRuntimeWorkspacePrompt, capMemoryForInject, capWorkLogForInject, } from "./prompt.js";
|
|
8
8
|
export function truncateUtf8(value, maxBytes) {
|
|
9
9
|
if (maxBytes <= 0)
|
|
10
10
|
return "";
|
|
@@ -30,11 +30,10 @@ function takeCompletePromptSections(sections, maxBytes) {
|
|
|
30
30
|
}, { value: "", bytes: 0, full: true }).value;
|
|
31
31
|
}
|
|
32
32
|
/** v1 server instructions opt in to daemon-owned paths and bounded local workspace context. */
|
|
33
|
-
export function withLocalExecutionFacts(serverPrompt, maxBytes
|
|
33
|
+
export function withLocalExecutionFacts(serverPrompt, maxBytes) {
|
|
34
34
|
return ({ workspace, resuming, projectContext }) => {
|
|
35
35
|
const memory = capMemoryForInject(workspace.memory);
|
|
36
36
|
const workLog = resuming ? "" : capWorkLogForInject(workspace.workLog);
|
|
37
|
-
const collaborationPrompt = options.collaborationTools === true ? buildCollaborationToolsPrompt() : "";
|
|
38
37
|
const mandatoryWorkspacePrompt = buildRuntimeWorkspacePrompt(projectContext);
|
|
39
38
|
const localFactSections = [`\n\n## Local execution facts
|
|
40
39
|
- $CREW_HOME: ${workspace.dir}
|
|
@@ -42,21 +41,17 @@ export function withLocalExecutionFacts(serverPrompt, maxBytes, options = {}) {
|
|
|
42
41
|
...(memory ? [`\n\n## Injected MEMORY.md (bounded local context)\n${memory}`] : []),
|
|
43
42
|
...(workLog ? [`\n\n## Injected work-log (bounded local context)\n${workLog}`] : []),
|
|
44
43
|
];
|
|
45
|
-
const
|
|
46
|
-
const collaborationBytes = Buffer.byteLength(collaborationPrompt, "utf8");
|
|
47
|
-
const mandatoryBytes = Buffer.byteLength(mandatoryWorkspacePrompt, "utf8");
|
|
48
|
-
const requiredBytes = serverPromptBytes + collaborationBytes + mandatoryBytes;
|
|
49
|
-
// 必需预算与 projectContext 无关:协作段落永远参与;无协作时与旧实现逐字节等价。
|
|
50
|
-
if (collaborationPrompt !== "" && requiredBytes > maxBytes) {
|
|
51
|
-
throw new Error("collaboration_tools_prompt_budget_exceeded");
|
|
52
|
-
}
|
|
44
|
+
const localFacts = localFactSections.join("");
|
|
53
45
|
if (mandatoryWorkspacePrompt !== "") {
|
|
46
|
+
const serverPromptBytes = Buffer.byteLength(serverPrompt, "utf8");
|
|
47
|
+
const mandatoryBytes = Buffer.byteLength(mandatoryWorkspacePrompt, "utf8");
|
|
48
|
+
const requiredBytes = serverPromptBytes + mandatoryBytes;
|
|
54
49
|
if (requiredBytes > maxBytes)
|
|
55
50
|
throw new Error("project_workspace_prompt_budget_exceeded");
|
|
56
51
|
const optionalFacts = takeCompletePromptSections(localFactSections, maxBytes - requiredBytes);
|
|
57
|
-
return `${serverPrompt}${
|
|
52
|
+
return `${serverPrompt}${optionalFacts}${mandatoryWorkspacePrompt}`;
|
|
58
53
|
}
|
|
59
|
-
const remaining = maxBytes -
|
|
60
|
-
return `${serverPrompt}${
|
|
54
|
+
const remaining = maxBytes - Buffer.byteLength(serverPrompt, "utf8");
|
|
55
|
+
return `${serverPrompt}${truncateUtf8(localFacts, remaining)}`;
|
|
61
56
|
};
|
|
62
57
|
}
|
package/dist/local-executor.js
CHANGED
|
@@ -31,7 +31,6 @@ import { diffMemoryPruneNotes, evaluateMemoryPrunePostcondition, inspectMemoryPr
|
|
|
31
31
|
import { createLocalMemoryTelemetry, logLocalMemoryContextPrepareFailure, logLocalMemoryDiagnosticsFailure, } from "./local-memory-telemetry.js";
|
|
32
32
|
import { CodexStartupStageParser } from "./codex-startup-stage.js";
|
|
33
33
|
import { formatRuntimeStartupError } from "./runtime-startup-error.js";
|
|
34
|
-
import { commitLocalMemoryResultAfterExit, initializeLocalMemoryV2ForWorkspace, isLocalMemoryV2Eligible, localMemoryResultPath as makeLocalMemoryResultPath, renderLocalMemoryResultInstructions, } from "./local-memory/runtime.js";
|
|
35
34
|
function memoryPruneFileFactFields(fileFacts) {
|
|
36
35
|
const fields = {};
|
|
37
36
|
for (const [label, fact] of Object.entries(fileFacts)) {
|
|
@@ -78,7 +77,6 @@ const RUNTIME_RUNNING_CALLBACK_TIMEOUT_MS = 30_000;
|
|
|
78
77
|
const MEMORY_PRUNE_DIAGNOSTICS_TIMEOUT_MS = 2_000;
|
|
79
78
|
const LOCAL_MEMORY_DIAGNOSTICS_TIMEOUT_MS = 250;
|
|
80
79
|
const CLAUDE_INSTRUCTION_WARNING = "claude_additional_directory_instructions_unverified";
|
|
81
|
-
const CODEX_COLLABORATION_EXEC_WARNING = "codex_collaboration_disabled_on_exec";
|
|
82
80
|
const ENV_KEY_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
83
81
|
const RESERVED_ENV = new Set([
|
|
84
82
|
"PATH",
|
|
@@ -279,7 +277,6 @@ async function executeLocalUnlocked(input, callbacks, dependencies) {
|
|
|
279
277
|
}, "workspace_prepare", error);
|
|
280
278
|
throw error;
|
|
281
279
|
}
|
|
282
|
-
const localMemoryV2Initialized = await initializeLocalMemoryV2ForWorkspace(workspace, input.localMemoryV2Enabled === true);
|
|
283
280
|
let materialized = null;
|
|
284
281
|
let knownAttachmentDirectory = null;
|
|
285
282
|
const startupReservationState = { current: null };
|
|
@@ -289,7 +286,6 @@ async function executeLocalUnlocked(input, callbacks, dependencies) {
|
|
|
289
286
|
let memoryPruneFailurePhase = "diagnostics_before";
|
|
290
287
|
let memoryPruneBeforeSnapshot = null;
|
|
291
288
|
let memoryPruneSharedWriteKey = null;
|
|
292
|
-
let localMemoryResultPath = null;
|
|
293
289
|
let executionWorkspace = workspace;
|
|
294
290
|
let localMemoryTelemetry = null;
|
|
295
291
|
const inheritedEnv = { ...process.env };
|
|
@@ -375,6 +371,7 @@ async function executeLocalUnlocked(input, callbacks, dependencies) {
|
|
|
375
371
|
nearBudget,
|
|
376
372
|
...(input.projectContext === undefined ? {} : { projectContext: input.projectContext }),
|
|
377
373
|
};
|
|
374
|
+
const systemPrompt = resolvePrompt(input.systemPrompt, promptContext);
|
|
378
375
|
if (input.attachments && input.attachments.length > 0) {
|
|
379
376
|
if (dependencies.cancellation?.isRequested())
|
|
380
377
|
throw new RuntimeCancelledError();
|
|
@@ -408,29 +405,6 @@ async function executeLocalUnlocked(input, callbacks, dependencies) {
|
|
|
408
405
|
const attachmentPlan = routeRuntimeAttachments(runtime.name, materialized?.attachments ?? []);
|
|
409
406
|
const wakePrompt = `${resolvePrompt(input.wakePrompt, promptContext)}${attachmentPlan.promptSuffix}`;
|
|
410
407
|
memoryPruneTraceId = parseMemoryPruneTraceId(wakePrompt);
|
|
411
|
-
if (input.localMemoryV2Enabled === true && memoryPruneTraceId !== null
|
|
412
|
-
&& isLocalMemoryV2Eligible({
|
|
413
|
-
enabledForHandle: true,
|
|
414
|
-
agentHomePreexisted: workspace.agentHomePreexisted === true,
|
|
415
|
-
memorySeedCreated: executionWorkspace.memorySeedCreated === true && (localMemoryV2Initialized || workspace.localMemoryV2Initialized !== false),
|
|
416
|
-
localMemoryV2Initialized,
|
|
417
|
-
memoryPrune: true,
|
|
418
|
-
})) {
|
|
419
|
-
localMemoryResultPath = makeLocalMemoryResultPath(executionWorkspace.runDir, input.executionId);
|
|
420
|
-
}
|
|
421
|
-
const baseSystemPrompt = resolvePrompt(input.systemPrompt, promptContext);
|
|
422
|
-
const structuredMemoryInstructions = localMemoryResultPath === null
|
|
423
|
-
? null
|
|
424
|
-
: renderLocalMemoryResultInstructions(localMemoryResultPath);
|
|
425
|
-
const structuredPromptFits = structuredMemoryInstructions === null
|
|
426
|
-
|| input.maxSystemPromptBytes === undefined
|
|
427
|
-
|| Buffer.byteLength(baseSystemPrompt, "utf8") + Buffer.byteLength(structuredMemoryInstructions, "utf8")
|
|
428
|
-
<= input.maxSystemPromptBytes;
|
|
429
|
-
if (!structuredPromptFits)
|
|
430
|
-
localMemoryResultPath = null;
|
|
431
|
-
const systemPrompt = localMemoryResultPath === null
|
|
432
|
-
? baseSystemPrompt
|
|
433
|
-
: `${baseSystemPrompt}${structuredMemoryInstructions ?? ""}`;
|
|
434
408
|
try {
|
|
435
409
|
localMemoryTelemetry = createLocalMemoryTelemetry({
|
|
436
410
|
executionId: input.executionId,
|
|
@@ -539,13 +513,7 @@ async function executeLocalUnlocked(input, callbacks, dependencies) {
|
|
|
539
513
|
ability_release_id: input.abilityRelease?.releaseId,
|
|
540
514
|
ability_root_commit: input.abilityRelease?.rootCommit,
|
|
541
515
|
});
|
|
542
|
-
const
|
|
543
|
-
const launchRuntime = dependencies.launchRuntime ?? (async (launchReq) => {
|
|
544
|
-
if (launchReq.runtime === "codex" && launchReq.codexCollaborationTools === true) {
|
|
545
|
-
warn(CODEX_COLLABORATION_EXEC_WARNING);
|
|
546
|
-
}
|
|
547
|
-
return launchLegacyRuntime(launchReq);
|
|
548
|
-
});
|
|
516
|
+
const launchRuntime = dependencies.launchRuntime ?? launchLegacyRuntime;
|
|
549
517
|
if (dependencies.cancellation?.isRequested())
|
|
550
518
|
throw new RuntimeCancelledError();
|
|
551
519
|
let activeProjectSkillRuntimeRoot;
|
|
@@ -614,7 +582,7 @@ async function executeLocalUnlocked(input, callbacks, dependencies) {
|
|
|
614
582
|
}
|
|
615
583
|
else {
|
|
616
584
|
runtimeEnv = withoutClaudeInstructionFlag(childEnv);
|
|
617
|
-
|
|
585
|
+
(dependencies.warnRuntime ?? warnRuntimeLocally)(CLAUDE_INSTRUCTION_WARNING);
|
|
618
586
|
callbacks.onConsole?.({
|
|
619
587
|
stream: "system",
|
|
620
588
|
text: `[runtime-warning] ${CLAUDE_INSTRUCTION_WARNING}`,
|
|
@@ -638,9 +606,6 @@ async function executeLocalUnlocked(input, callbacks, dependencies) {
|
|
|
638
606
|
...(launchReasoning === undefined ? {} : { reasoning: launchReasoning }),
|
|
639
607
|
...(launchSessionId === null ? {} : { sessionId: launchSessionId }),
|
|
640
608
|
resume: resuming,
|
|
641
|
-
...(runtime.codexCollaborationTools === undefined
|
|
642
|
-
? {}
|
|
643
|
-
: { codexCollaborationTools: runtime.codexCollaborationTools }),
|
|
644
609
|
...(attachmentPlan.nativeImagePaths.length > 0
|
|
645
610
|
? { imagePaths: attachmentPlan.nativeImagePaths }
|
|
646
611
|
: {}),
|
|
@@ -927,24 +892,6 @@ async function executeLocalUnlocked(input, callbacks, dependencies) {
|
|
|
927
892
|
const { exitCode, spawnError, terminationSignal } = runtimeExit;
|
|
928
893
|
localMemoryTelemetry?.markRuntimeExited(exitCode);
|
|
929
894
|
memoryPruneRuntimeExitCode = exitCode;
|
|
930
|
-
if (localMemoryResultPath !== null) {
|
|
931
|
-
const committed = await commitLocalMemoryResultAfterExit({
|
|
932
|
-
resultPath: localMemoryResultPath,
|
|
933
|
-
agentDir: executionWorkspace.dir,
|
|
934
|
-
executionId: input.executionId,
|
|
935
|
-
pruneTraceId: memoryPruneTraceId,
|
|
936
|
-
exitCode,
|
|
937
|
-
});
|
|
938
|
-
if (committed.status === "failed") {
|
|
939
|
-
dslog("local_memory.commit_failed", "结构化本地记忆候选未落地,保留结果文件", {
|
|
940
|
-
level: "WARN",
|
|
941
|
-
execution_id: input.executionId,
|
|
942
|
-
agent_handle: input.handle,
|
|
943
|
-
error_code: committed.error,
|
|
944
|
-
result_path: localMemoryResultPath,
|
|
945
|
-
});
|
|
946
|
-
}
|
|
947
|
-
}
|
|
948
895
|
const errorTail = [
|
|
949
896
|
stderrTail.trim(),
|
|
950
897
|
spawnError === undefined
|
package/dist/machine-info.js
CHANGED
|
@@ -191,11 +191,10 @@ export async function collectMachineHello(agentsRoot, executionLimits, runtimePl
|
|
|
191
191
|
profileName: dependencies.profileName,
|
|
192
192
|
daemonHome: dependencies.daemonHome ?? daemonHome(),
|
|
193
193
|
agentsRoot,
|
|
194
|
-
...(dependencies.profileName.match(/^nw-(?:
|
|
194
|
+
...(dependencies.profileName.match(/^nw-(?:in|dev)-([a-z0-9][a-z0-9_-]{0,39})$/u)?.[1] === undefined
|
|
195
195
|
? {}
|
|
196
|
-
: { localInstanceName: dependencies.profileName.match(/^nw-(?:
|
|
196
|
+
: { localInstanceName: dependencies.profileName.match(/^nw-(?:in|dev)-([a-z0-9][a-z0-9_-]{0,39})$/u)[1] }),
|
|
197
197
|
}),
|
|
198
|
-
...(dependencies.storageIdentity ?? {}),
|
|
199
198
|
...(backend.supported ? {
|
|
200
199
|
executionProtocol: EXECUTION_PROTOCOL,
|
|
201
200
|
executionLimits: Object.freeze({
|