@nowcrew/daemon 0.6.79 → 0.6.80-beta.1

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.
Files changed (37) hide show
  1. package/dist/agent-ability/resolver.js +7 -10
  2. package/dist/execution-protocol.js +0 -1
  3. package/dist/execution-runner.js +3 -9
  4. package/dist/local-execution-prompt.js +2 -3
  5. package/dist/local-executor.js +35 -59
  6. package/dist/machine-info.js +0 -3
  7. package/dist/main.js +0 -0
  8. package/dist/package-manager-env.js +75 -0
  9. package/dist/provider-env.js +3 -21
  10. package/dist/runner.js +1 -1
  11. package/dist/runtime-env.js +21 -0
  12. package/dist/runtimes/codex-app-server-runner.js +1 -9
  13. package/dist/runtimes/codex-deepseek-config.js +7 -17
  14. package/dist/runtimes/codex.js +0 -3
  15. package/dist/supervised-runtime.js +0 -1
  16. package/dist/workspace.js +10 -13
  17. package/package.json +10 -9
  18. package/dist/project-skills/capability.js +0 -109
  19. package/dist/project-skills/controller-convergence.js +0 -57
  20. package/dist/project-skills/projection-set-switch.js +0 -419
  21. package/dist/project-skills/projection-state-domain.js +0 -170
  22. package/dist/project-skills/projection-state-store.js +0 -842
  23. package/dist/project-skills/projection-state-transaction.js +0 -322
  24. package/dist/project-skills/projection-state.js +0 -3
  25. package/dist/project-skills/runtime-root-bootstrap.js +0 -53
  26. package/dist/project-skills/runtime-root-domain.js +0 -268
  27. package/dist/project-skills/runtime-root-gc.js +0 -293
  28. package/dist/project-skills/runtime-root-lease-artifact.js +0 -46
  29. package/dist/project-skills/runtime-root-leases.js +0 -487
  30. package/dist/project-skills/runtime-root-source-identity.js +0 -60
  31. package/dist/project-skills/runtime-root-startup.js +0 -50
  32. package/dist/project-skills/runtime-root-state-artifact-domain.js +0 -143
  33. package/dist/project-skills/runtime-root-state-index.js +0 -356
  34. package/dist/project-skills/runtime-root-store.js +0 -722
  35. package/dist/project-skills/serve-capability.js +0 -28
  36. package/dist/project-skills/serve-startup.js +0 -60
  37. package/dist/self-training-workspace.js +0 -15
@@ -10,8 +10,8 @@ import { PROJECT_MANIFEST_SOURCE_PATH, ProjectDependencyManifestSchema, } from "
10
10
  import { normalizeRepositoryIdentity } from "../repository-identity.js";
11
11
  const runFile = promisify(execFile);
12
12
  const MAX_FILES = 5_000;
13
- export const AGENT_ABILITY_MAX_TOTAL_BYTES = 200 * 1024 * 1024;
14
- export const AGENT_ABILITY_MAX_FILE_BYTES = 100 * 1024 * 1024;
13
+ const MAX_TOTAL_BYTES = 25 * 1024 * 1024;
14
+ const MAX_FILE_BYTES = 2 * 1024 * 1024;
15
15
  const MAX_INSTRUCTIONS_BYTES = 96 * 1024;
16
16
  const MAX_MEMORY_BYTES = 64 * 1024;
17
17
  const AUTHORING_ONLY_ROOTS = new Set([".claude"]);
@@ -125,11 +125,10 @@ export const collectAbilityFiles = async (root) => {
125
125
  if (info.isDirectory())
126
126
  await visit(absolute);
127
127
  else if (info.isFile()) {
128
- if (info.size > AGENT_ABILITY_MAX_FILE_BYTES) {
128
+ if (info.size > MAX_FILE_BYTES)
129
129
  throw new Error(`ability_file_size_exceeded:${relative(root, absolute)}`);
130
- }
131
130
  totalBytes += info.size;
132
- if (totalBytes > AGENT_ABILITY_MAX_TOTAL_BYTES)
131
+ if (totalBytes > MAX_TOTAL_BYTES)
133
132
  throw new Error("ability_total_size_exceeded");
134
133
  if (files.length >= MAX_FILES)
135
134
  throw new Error("ability_file_count_exceeded");
@@ -263,7 +262,7 @@ export const validateAbilityDependencyDeclarations = (manifest, lock) => {
263
262
  throw new Error("ability_lock_has_undeclared_dependency");
264
263
  }
265
264
  };
266
- export const scanAbilityFiles = (files, manifest) => {
265
+ const scan = (files, manifest) => {
267
266
  const findings = [];
268
267
  const secrets = [
269
268
  /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/u,
@@ -271,9 +270,7 @@ export const scanAbilityFiles = (files, manifest) => {
271
270
  /\bAK(?:ID|IA)[A-Z0-9]{12,}\b/u,
272
271
  ];
273
272
  const executable = new Set([".exe", ".dll", ".dylib", ".so", ".bin", ".class", ".jar"]);
274
- const allowedBinaryDocuments = new Set([
275
- ".pdf", ".png", ".jpg", ".jpeg", ".gif", ".webp", ".xlsx", ".xls", ".docx", ".pptx", ".ttf", ".otf",
276
- ]);
273
+ const allowedBinaryDocuments = new Set([".pdf", ".png", ".jpg", ".jpeg", ".gif", ".webp", ".xlsx", ".xls", ".docx", ".pptx"]);
277
274
  for (const file of files) {
278
275
  let text;
279
276
  try {
@@ -399,7 +396,7 @@ export async function resolveAbilityRelease(agentsRoot, command) {
399
396
  }
400
397
  const externalPaths = await verifyExternalDependencies(cacheRoot, resolved.root, lock);
401
398
  files = await collectAbilityFiles(resolved.root);
402
- const security = scanAbilityFiles(files, manifest);
399
+ const security = scan(files, manifest);
403
400
  const kinds = new Set(lock.assets.map((asset) => asset.kind));
404
401
  const memory = [];
405
402
  for (const [layer, mounts] of [["release-policy", manifest.spec.memory.policy], ["release-seed", manifest.spec.memory.seeds]]) {
@@ -200,7 +200,6 @@ export const ExecutionStartSchema = z.object({
200
200
  language: z.enum(["zh", "en"]),
201
201
  systemPrompt: z.string(),
202
202
  wakePrompt: z.string(),
203
- maintenancePurpose: z.literal("self_training").optional(),
204
203
  }).strict(),
205
204
  runtime: z.object({
206
205
  name: RuntimeSchema,
@@ -567,9 +567,8 @@ export async function runExecution(config, input, dependencies) {
567
567
  projectContext = await cancellable(resolveProjectContext(projectSnapshot, projectWorkspaceRegistry), dependencies.cancellation);
568
568
  sessionContextFingerprint = projectSessionContextFingerprint(spec.runtime.name, projectSnapshot);
569
569
  }
570
- const selfTraining = spec.instructions.maintenancePurpose === "self_training";
571
570
  let recalledMemory = "";
572
- if (!selfTraining && spec.agent.memoryEnabled === true && dependencies.agentMemory !== undefined) {
571
+ if (spec.agent.memoryEnabled === true && dependencies.agentMemory !== undefined) {
573
572
  try {
574
573
  recalledMemory = await cancellable(dependencies.agentMemory.recall(spec.agent.handle, spec.instructions.wakePrompt, spec.executionId, spec.agent.memoryAgentId ?? null), dependencies.cancellation);
575
574
  }
@@ -828,10 +827,7 @@ export async function runExecution(config, input, dependencies) {
828
827
  const baseSystemPromptBudget = spec.agent.abilityRelease === undefined
829
828
  ? systemPromptBudget
830
829
  : Math.max(0, Math.min(systemPromptBudget, Math.max(32 * 1024, systemPromptBudget - 168 * 1024)));
831
- const systemPromptWithLocalFacts = withLocalExecutionFacts(spec.instructions.systemPrompt, baseSystemPromptBudget, {
832
- ...(selfTraining ? { isolateLocalMemory: true } : {}),
833
- collaborationTools: config.codexCollaborationTools && spec.runtime.name === "codex",
834
- });
830
+ const systemPromptWithLocalFacts = withLocalExecutionFacts(spec.instructions.systemPrompt, baseSystemPromptBudget, { collaborationTools: config.codexCollaborationTools && spec.runtime.name === "codex" });
835
831
  const boundedSystemPrompt = (context) => appendAgentMemoryContext(typeof systemPromptWithLocalFacts === "string"
836
832
  ? systemPromptWithLocalFacts
837
833
  : systemPromptWithLocalFacts(context), recalledMemory, baseSystemPromptBudget);
@@ -880,13 +876,12 @@ export async function runExecution(config, input, dependencies) {
880
876
  } : {}),
881
877
  },
882
878
  session: {
883
- enabled: selfTraining ? false : config.resume,
879
+ enabled: config.resume,
884
880
  warmMs: config.resumeWarmMs,
885
881
  budgetTokens: config.sessionBudgetTokens,
886
882
  softTokens: config.sessionSoftTokens,
887
883
  maxTurns: config.sessionMaxTurns,
888
884
  },
889
- ...(selfTraining ? { maintenancePurpose: "self_training" } : {}),
890
885
  localMemoryV2Enabled: config.localMemoryV2Handles?.has(spec.agent.handle) === true,
891
886
  };
892
887
  const result = await Promise.race([
@@ -1053,7 +1048,6 @@ export async function runExecution(config, input, dependencies) {
1053
1048
  }
1054
1049
  await dependencies.journal.complete(spec.executionId, completion);
1055
1050
  if (completion.outcome === "succeeded"
1056
- && spec.instructions.maintenancePurpose !== "self_training"
1057
1051
  && spec.agent.memoryEnabled === true
1058
1052
  && memoryCaptureFinalText !== null
1059
1053
  && dependencies.agentMemory !== undefined) {
@@ -47,13 +47,12 @@ function takeCompletePromptSections(sections, maxBytes) {
47
47
  /** v1 server instructions opt in to daemon-owned paths and bounded local workspace context. */
48
48
  export function withLocalExecutionFacts(serverPrompt, maxBytes, options = {}) {
49
49
  return ({ workspace, resuming, projectContext, trainingProjectContext }) => {
50
- const memory = options.isolateLocalMemory ? "" : capMemoryForInject(workspace.memory);
50
+ const memory = capMemoryForInject(workspace.memory);
51
51
  const workLog = resuming ? "" : capWorkLogForInject(workspace.workLog);
52
52
  const collaborationPrompt = options.collaborationTools === true ? buildCollaborationToolsPrompt() : "";
53
53
  const mandatoryWorkspacePrompt = `${buildRuntimeWorkspacePrompt(projectContext)}${buildTrainingGitProjectPrompt(trainingProjectContext)}`;
54
- const crewHome = options.isolateLocalMemory ? workspace.runDir : workspace.dir;
55
54
  const localFactSections = [`\n\n## Local execution facts
56
- - $CREW_HOME: ${crewHome}
55
+ - $CREW_HOME: ${workspace.dir}
57
56
  - $CREW_TASK_LOG: ${workspace.workLogPath}`,
58
57
  ...(memory ? [`\n\n## Injected MEMORY.md (bounded local context)\n${memory}`] : []),
59
58
  ...(workLog ? [`\n\n## Injected work-log (bounded local context)\n${workLog}`] : []),
@@ -1,7 +1,6 @@
1
1
  import { createInterface } from "node:readline";
2
2
  import { readFile, rm, writeFile } from "node:fs/promises";
3
3
  import { delimiter, join } from "node:path";
4
- import { cleanupSelfTrainingRunDir } from "./self-training-workspace.js";
5
4
  import { prepareWorkspace, rotateAgentSession, safeKey, } from "./workspace.js";
6
5
  import { CLAUDE_ADDITIONAL_DIRECTORY_INSTRUCTIONS_ENV, isClaudeAdditionalDirectoryInstructionsSupported, probeClaudeVersion, spawnClaude, } from "./runtimes/claude.js";
7
6
  import { spawnCodex } from "./runtimes/codex.js";
@@ -9,7 +8,7 @@ import { DEEPSEEK_CODEX_MODEL, DEEPSEEK_CODEX_REASONING_LEVELS, materializeDeepS
9
8
  import { materializeDefaultCodexHome } from "./runtimes/codex-home.js";
10
9
  import { materializePrivateCodexHome } from "./codex-home-launch.js";
11
10
  import { spawnKimi, KIMI_EFFORT_LEVELS } from "./runtimes/kimi.js";
12
- import { applyDeepSeekHarnessMachineEnv, applyProviderEnv, providerFingerprint, sanitizeEnvVars, } from "./provider-env.js";
11
+ import { applyDeepSeekHarnessMachineEnv, applyProviderEnv, providerFingerprint, } from "./provider-env.js";
13
12
  import { augmentedPath } from "./runtime-path.js";
14
13
  import { extractFinalText, extractRunMeta, normalizeEvent, parseLine, } from "./normalize.js";
15
14
  import { readSession, writeSession, pickResumeId, isNearBudget } from "./session.js";
@@ -33,6 +32,8 @@ import { diffMemoryPruneNotes, evaluateMemoryPrunePostcondition, inspectMemoryPr
33
32
  import { createLocalMemoryTelemetry, logLocalMemoryContextPrepareFailure, logLocalMemoryDiagnosticsFailure, } from "./local-memory-telemetry.js";
34
33
  import { CodexStartupStageParser } from "./codex-startup-stage.js";
35
34
  import { formatRuntimeStartupError } from "./runtime-startup-error.js";
35
+ import { machinePackageManagerEnv, packageManagerEnvFacts } from "./package-manager-env.js";
36
+ import { sanitizeEnvVars } from "./runtime-env.js";
36
37
  import { commitLocalMemoryResultAfterExit, initializeLocalMemoryV2ForWorkspace, isLocalMemoryV2Eligible, localMemoryResultPath as makeLocalMemoryResultPath, renderLocalMemoryResultInstructions, } from "./local-memory/runtime.js";
37
38
  export class RuntimeRunningCallbackTimeoutError extends Error {
38
39
  constructor(runtime, timeoutMs) {
@@ -50,15 +51,6 @@ const MEMORY_PRUNE_DIAGNOSTICS_TIMEOUT_MS = 2_000;
50
51
  const LOCAL_MEMORY_DIAGNOSTICS_TIMEOUT_MS = 250;
51
52
  const CLAUDE_INSTRUCTION_WARNING = "claude_additional_directory_instructions_unverified";
52
53
  const CODEX_COLLABORATION_EXEC_WARNING = "codex_collaboration_disabled_on_exec";
53
- const ENV_KEY_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
54
- const RESERVED_ENV = new Set([
55
- "PATH",
56
- "XDG_CONFIG_HOME",
57
- "XDG_DATA_HOME",
58
- "XDG_CACHE_HOME",
59
- "GH_CONFIG_DIR",
60
- "CLOUDSDK_CONFIG",
61
- ]);
62
54
  function withoutClaudeInstructionFlag(env) {
63
55
  if (!(CLAUDE_ADDITIONAL_DIRECTORY_INSTRUCTIONS_ENV in env))
64
56
  return env;
@@ -119,7 +111,6 @@ async function launchLegacyRuntime(request) {
119
111
  effectivePermission: request.effectivePermission,
120
112
  ...(request.model === undefined ? {} : { model: request.model }),
121
113
  ...(request.reasoning === undefined ? {} : { reasoning: request.reasoning }),
122
- ...(request.networkAccess === undefined ? {} : { networkAccess: request.networkAccess }),
123
114
  };
124
115
  if (request.runtime === "claude") {
125
116
  const additionalDirectories = request.claudeAdditionalDirectories
@@ -209,7 +200,6 @@ export async function executeLocal(input, callbacks = {}, dependencies = {}) {
209
200
  async function executeLocalUnlocked(input, callbacks, dependencies) {
210
201
  const providerConfig = input.launch.providerConfig ?? {};
211
202
  const { runtime } = input;
212
- const isolatedMaintenance = input.maintenancePurpose === "self_training";
213
203
  const isDeepSeekCodex = runtime.name === "codex" && providerConfig.provider === "deepseek";
214
204
  const currentModel = isDeepSeekCodex ? DEEPSEEK_CODEX_MODEL : runtime.model ?? null;
215
205
  const launchModel = isDeepSeekCodex ? DEEPSEEK_CODEX_MODEL : runtime.model;
@@ -234,7 +224,6 @@ async function executeLocalUnlocked(input, callbacks, dependencies) {
234
224
  ? {}
235
225
  : { sessionContextFingerprint: input.sessionContextFingerprint }),
236
226
  ...(input.launch.description ? { description: input.launch.description } : {}),
237
- ...(isolatedMaintenance ? { skipLocalMemory: true } : {}),
238
227
  }), dependencies.cancellation);
239
228
  }
240
229
  catch (error) {
@@ -265,23 +254,12 @@ async function executeLocalUnlocked(input, callbacks, dependencies) {
265
254
  }
266
255
  const sourceCodexHome = inheritedEnv.CODEX_HOME
267
256
  ?? (inheritedEnv.HOME === undefined ? undefined : join(inheritedEnv.HOME, ".codex"));
268
- let materializedDeepSeekHome;
269
257
  try {
270
258
  if (isDeepSeekCodex && !providerConfig.providerApiKey) {
271
259
  throw new Error("DeepSeek API key is not configured for this Agent");
272
260
  }
273
261
  if (isDeepSeekCodex) {
274
- const providerBaseUrl = providerConfig.providerBaseUrl
275
- ? new URL(providerConfig.providerBaseUrl, input.launch.serverUrl).toString()
276
- : undefined;
277
- const materialize = dependencies.materializeDeepSeekCodexHome ?? materializeDeepSeekCodexHome;
278
- const materializeOptions = {
279
- ...(providerBaseUrl === undefined ? {} : { baseUrl: providerBaseUrl }),
280
- ...(isolatedMaintenance ? { selfTraining: true } : {}),
281
- };
282
- materializedDeepSeekHome = await awaitWithCancellation(providerBaseUrl === undefined && !isolatedMaintenance
283
- ? materialize(workspace.homeDir)
284
- : materialize(workspace.homeDir, materializeOptions), dependencies.cancellation);
262
+ await awaitWithCancellation((dependencies.materializeDeepSeekCodexHome ?? materializeDeepSeekCodexHome)(workspace.homeDir), dependencies.cancellation);
285
263
  }
286
264
  const supportsNativeResume = runtime.name === "claude"
287
265
  || (dependencies.launchRuntime !== undefined && runtimeCapability(runtime.name).nativeResume);
@@ -409,30 +387,29 @@ async function executeLocalUnlocked(input, callbacks, dependencies) {
409
387
  const systemPrompt = localMemoryResultPath === null
410
388
  ? baseSystemPrompt
411
389
  : `${baseSystemPrompt}${structuredMemoryInstructions ?? ""}`;
412
- if (!isolatedMaintenance)
413
- try {
414
- localMemoryTelemetry = createLocalMemoryTelemetry({
415
- executionId: input.executionId,
416
- agentHandle: input.handle,
417
- ...(input.taskKey === undefined ? {} : { taskKey: input.taskKey }),
418
- runtime: runtime.name,
419
- stableProtocolRuntime: dependencies.launchRuntime !== undefined,
420
- agentDir: executionWorkspace.dir,
421
- runDir: executionWorkspace.runDir,
422
- isMemoryPrune: memoryPruneTraceId !== null,
423
- diagnosticsTimeoutMs: dependencies.localMemoryDiagnosticsTimeoutMs
424
- ?? LOCAL_MEMORY_DIAGNOSTICS_TIMEOUT_MS,
425
- });
426
- await localMemoryTelemetry.captureBefore();
427
- }
428
- catch (error) {
429
- localMemoryTelemetry = null;
430
- logLocalMemoryDiagnosticsFailure({
431
- executionId: input.executionId,
432
- agentHandle: input.handle,
433
- ...(input.taskKey === undefined ? {} : { taskKey: input.taskKey }),
434
- }, "initialize", error);
435
- }
390
+ try {
391
+ localMemoryTelemetry = createLocalMemoryTelemetry({
392
+ executionId: input.executionId,
393
+ agentHandle: input.handle,
394
+ ...(input.taskKey === undefined ? {} : { taskKey: input.taskKey }),
395
+ runtime: runtime.name,
396
+ stableProtocolRuntime: dependencies.launchRuntime !== undefined,
397
+ agentDir: executionWorkspace.dir,
398
+ runDir: executionWorkspace.runDir,
399
+ isMemoryPrune: memoryPruneTraceId !== null,
400
+ diagnosticsTimeoutMs: dependencies.localMemoryDiagnosticsTimeoutMs
401
+ ?? LOCAL_MEMORY_DIAGNOSTICS_TIMEOUT_MS,
402
+ });
403
+ await localMemoryTelemetry.captureBefore();
404
+ }
405
+ catch (error) {
406
+ localMemoryTelemetry = null;
407
+ logLocalMemoryDiagnosticsFailure({
408
+ executionId: input.executionId,
409
+ agentHandle: input.handle,
410
+ ...(input.taskKey === undefined ? {} : { taskKey: input.taskKey }),
411
+ }, "initialize", error);
412
+ }
436
413
  if (memoryPruneTraceId !== null) {
437
414
  memoryPruneSharedWriteKey = JSON.stringify([input.launch.agentsRoot, input.handle]);
438
415
  const activePruneCount = (activeMemoryPrunes.get(memoryPruneSharedWriteKey) ?? 0) + 1;
@@ -466,16 +443,18 @@ async function executeLocalUnlocked(input, callbacks, dependencies) {
466
443
  }
467
444
  }
468
445
  memoryPruneFailurePhase = "runtime_prepare";
469
- const crewHome = isolatedMaintenance ? executionWorkspace.runDir : workspace.dir;
470
446
  const baseEnv = {
471
447
  ...inheritedEnv,
472
448
  ...sanitizeEnvVars(providerConfig.envVars),
449
+ ...(input.trainingProjectContext === undefined
450
+ ? {}
451
+ : machinePackageManagerEnv(inheritedEnv)),
473
452
  ...input.launch.systemEnv,
474
453
  PATH: `${workspace.crewDir}${delimiter}${augmentedPath()}`,
475
454
  CREW_SERVER_URL: input.launch.serverUrl,
476
455
  CREW_TOKEN: input.launch.token,
477
456
  CREW_CHANNEL: input.channelId,
478
- CREW_HOME: crewHome,
457
+ CREW_HOME: workspace.dir,
479
458
  // Keep the daemon-selected storage root authoritative for runtimes.
480
459
  // In profile-backed NowWork sessions the daemon config may differ from
481
460
  // the daemon process environment, so inheriting CREW_AGENTS_ROOT is not
@@ -485,7 +464,7 @@ async function executeLocalUnlocked(input, callbacks, dependencies) {
485
464
  ...(input.launch.qaReportRoot === undefined ? {} : { QA_REPORT_HUB: input.launch.qaReportRoot }),
486
465
  // Expose only the training root; ability-specific workspace layout stays
487
466
  // owned by the training package rather than the NowWork daemon.
488
- QA_RUNTIME_ROOT: join(crewHome, "training"),
467
+ QA_RUNTIME_ROOT: join(workspace.dir, "training"),
489
468
  CREW_TASK_DIR: executionWorkspace.runDir,
490
469
  CREW_TASK_LOG: executionWorkspace.workLogPath,
491
470
  ...(input.wakeMessageId ? { CREW_WAKE_MESSAGE_ID: input.wakeMessageId } : {}),
@@ -501,7 +480,7 @@ async function executeLocalUnlocked(input, callbacks, dependencies) {
501
480
  };
502
481
  const providerEnv = applyProviderEnv(baseEnv, runtime.name, input.launch.codexHomeMode === undefined
503
482
  ? providerConfig
504
- : { ...providerConfig, codexHomeMode: input.launch.codexHomeMode }, workspace.homeDir, materializedDeepSeekHome);
483
+ : { ...providerConfig, codexHomeMode: input.launch.codexHomeMode }, workspace.homeDir);
505
484
  const childEnv = runtime.name === "deepseek-harness"
506
485
  ? applyDeepSeekHarnessMachineEnv(providerEnv, inheritedEnv)
507
486
  : providerEnv;
@@ -512,7 +491,8 @@ async function executeLocalUnlocked(input, callbacks, dependencies) {
512
491
  qa_runtime_root: childEnv.QA_RUNTIME_ROOT ?? null,
513
492
  qa_runtime_root_present: childEnv.QA_RUNTIME_ROOT !== undefined,
514
493
  inherited_qa_runtime_root_present: inheritedEnv.QA_RUNTIME_ROOT !== undefined,
515
- training_root: join(crewHome, "training"),
494
+ ...packageManagerEnvFacts(childEnv),
495
+ training_root: join(workspace.dir, "training"),
516
496
  project_context_present: input.projectContext !== undefined,
517
497
  project_ids: JSON.stringify(input.projectContext === undefined
518
498
  ? []
@@ -644,7 +624,6 @@ async function executeLocalUnlocked(input, callbacks, dependencies) {
644
624
  ...(input.projectContext === undefined ? {} : {
645
625
  projectContext: input.projectContext,
646
626
  }),
647
- ...(isolatedMaintenance && runtime.name === "codex" ? { networkAccess: true } : {}),
648
627
  ...(input.projectContext === undefined && workspaceRoots.length === 0
649
628
  ? {}
650
629
  : { workspaceRoots: Object.freeze(workspaceRoots) }),
@@ -1128,8 +1107,5 @@ async function executeLocalUnlocked(input, callbacks, dependencies) {
1128
1107
  const detail = error instanceof Error ? error.message : String(error);
1129
1108
  process.stderr.write(`[execution] failed to remove prompt ${workspace.systemPromptPath}: ${detail}\n`);
1130
1109
  }
1131
- if (isolatedMaintenance) {
1132
- await cleanupSelfTrainingRunDir(join(workspace.dir, "tasks"), executionWorkspace.runDir);
1133
- }
1134
1110
  }
1135
1111
  }
@@ -25,9 +25,7 @@ export { executableRuntimes } from "./runtime-capabilities.js";
25
25
  const execFileP = promisify(execFile);
26
26
  export const PROJECT_WORKSPACES_CAPABILITY = "project_workspaces_v1";
27
27
  export const TRAINING_PROJECT_DEPENDENCIES_CAPABILITY = "training_project_dependencies_v1";
28
- export const SELF_TRAINING_EXECUTION_CAPABILITY = "self_training_execution_v1";
29
28
  export const EXECUTION_LARGE_ATTACHMENTS_CAPABILITY = "execution_attachments_300m_v1";
30
- export const PROJECT_SKILL_PROJECTION_CAPABILITY = "project_skill_projection_v2";
31
29
  export const NATIVE_PROJECT_WORKSPACE_READINESS = Object.freeze({
32
30
  resolverReady: true,
33
31
  nativeRuntimeAdaptersReady: true,
@@ -44,7 +42,6 @@ export const DAEMON_CAPABILITIES = Object.freeze([
44
42
  "execution_machine_queue_v1",
45
43
  "execution_agent_memory_policy_v1",
46
44
  "execution_agent_memory_mapping_v1",
47
- SELF_TRAINING_EXECUTION_CAPABILITY,
48
45
  "project_skills_v1",
49
46
  "project_skill_projection_v2",
50
47
  PROJECT_WORKSPACES_CAPABILITY,
package/dist/main.js CHANGED
File without changes
@@ -0,0 +1,75 @@
1
+ import { readFileSync } from "node:fs";
2
+ function nonEmpty(value) {
3
+ const normalized = value?.trim();
4
+ return normalized === undefined || normalized === "" ? undefined : normalized;
5
+ }
6
+ function registryUrl(value) {
7
+ const normalized = nonEmpty(value);
8
+ if (normalized === undefined)
9
+ return undefined;
10
+ try {
11
+ const protocol = new URL(normalized).protocol;
12
+ return protocol === "http:" || protocol === "https:" ? normalized : undefined;
13
+ }
14
+ catch {
15
+ return undefined;
16
+ }
17
+ }
18
+ function configuredPath(env) {
19
+ const explicit = env.CREW_PACKAGE_MANAGER_USERCONFIG?.trim();
20
+ if (explicit !== undefined && explicit !== "")
21
+ return explicit;
22
+ return undefined;
23
+ }
24
+ function registryFromNpmrc(path) {
25
+ if (path === undefined)
26
+ return undefined;
27
+ try {
28
+ const line = readFileSync(path, "utf8")
29
+ .split(/\r?\n/u)
30
+ .find((entry) => /^\s*registry\s*=/u.test(entry));
31
+ return registryUrl(line?.replace(/^\s*registry\s*=\s*/u, ""));
32
+ }
33
+ catch {
34
+ return undefined;
35
+ }
36
+ }
37
+ function npmrcHasAuth(path) {
38
+ if (path === undefined)
39
+ return false;
40
+ try {
41
+ return /^\s*(?:(?:\/\/[^=\s]+:)?_(?:auth|authToken|password))\s*=/imu.test(readFileSync(path, "utf8"));
42
+ }
43
+ catch {
44
+ return false;
45
+ }
46
+ }
47
+ /**
48
+ * Keep machine-owned npm credentials available for explicitly authorized
49
+ * training dependency installs. The daemon must opt in with
50
+ * CREW_PACKAGE_MANAGER_USERCONFIG; Agent env cannot reach this path.
51
+ */
52
+ export function machinePackageManagerEnv(env = process.env) {
53
+ const npmUserConfig = configuredPath(env);
54
+ const yarnRegistry = npmUserConfig === undefined
55
+ ? undefined
56
+ : registryUrl(env.YARN_REGISTRY) ?? registryFromNpmrc(npmUserConfig);
57
+ const entries = npmUserConfig === undefined
58
+ ? []
59
+ : [["NPM_CONFIG_USERCONFIG", npmUserConfig]];
60
+ const alwaysAuth = npmrcHasAuth(npmUserConfig) ? "true" : undefined;
61
+ return Object.fromEntries(yarnRegistry === undefined && alwaysAuth === undefined
62
+ ? entries
63
+ : [
64
+ ...entries,
65
+ ...(yarnRegistry === undefined ? [] : [["YARN_REGISTRY", yarnRegistry]]),
66
+ ...(alwaysAuth === undefined ? [] : [["NPM_CONFIG_ALWAYS_AUTH", alwaysAuth]]),
67
+ ]);
68
+ }
69
+ export function packageManagerEnvFacts(env) {
70
+ return {
71
+ npm_userconfig_present: Boolean(env.NPM_CONFIG_USERCONFIG?.trim()),
72
+ yarn_registry_present: Boolean(env.YARN_REGISTRY?.trim()),
73
+ npm_always_auth_present: Boolean(env.NPM_CONFIG_ALWAYS_AUTH?.trim()),
74
+ };
75
+ }
@@ -11,24 +11,6 @@
11
11
  import { join } from "node:path";
12
12
  import { DEEPSEEK_CODEX_KEY_ENV, deepSeekCodexHome, } from "./runtimes/codex-deepseek-config.js";
13
13
  import { DEEPSEEK_HARNESS_CONFIG_ENV } from "./runtimes/deepseek-harness.js";
14
- const ENV_KEY_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
15
- const RESERVED_ENV = new Set([
16
- "PATH",
17
- "XDG_CONFIG_HOME",
18
- "XDG_DATA_HOME",
19
- "XDG_CACHE_HOME",
20
- "GH_CONFIG_DIR",
21
- "CLOUDSDK_CONFIG",
22
- ]);
23
- /** Keep user-provided variables away from daemon-owned runtime and credential fields. */
24
- export function sanitizeEnvVars(raw) {
25
- if (!raw)
26
- return {};
27
- return Object.fromEntries(Object.entries(raw).filter(([key, value]) => typeof value === "string"
28
- && ENV_KEY_RE.test(key)
29
- && !key.toUpperCase().startsWith("CREW_")
30
- && !RESERVED_ENV.has(key.toUpperCase())));
31
- }
32
14
  /** custom 模式下必须从继承 env 中剔除的全局路由/凭证变量(避免与注入值叠加或抢优先级)。 */
33
15
  const CONFLICTING_ENV = [
34
16
  "ANTHROPIC_BASE_URL",
@@ -57,12 +39,12 @@ const CONFLICTING_CODEX_ENV = [
57
39
  DEEPSEEK_CODEX_KEY_ENV,
58
40
  ];
59
41
  /** 返回叠加了 provider 隔离的新 env(不改入参);不支持的 runtime/provider 组合原样返回。 */
60
- export function applyProviderEnv(base, runtime, cfg, homeDir, deepSeekHomeOverride) {
42
+ export function applyProviderEnv(base, runtime, cfg, homeDir) {
61
43
  if (runtime === "codex" && cfg.provider === "deepseek") {
62
44
  const env = { ...base };
63
45
  for (const key of CONFLICTING_CODEX_ENV)
64
46
  delete env[key];
65
- env.CODEX_HOME = deepSeekHomeOverride ?? deepSeekCodexHome(homeDir);
47
+ env.CODEX_HOME = deepSeekCodexHome(homeDir);
66
48
  if (cfg.providerApiKey)
67
49
  env[DEEPSEEK_CODEX_KEY_ENV] = cfg.providerApiKey;
68
50
  return env;
@@ -118,7 +100,7 @@ export function applyDeepSeekHarnessMachineEnv(base, machineEnv) {
118
100
  */
119
101
  export function providerFingerprint(runtime, cfg) {
120
102
  if (runtime === "codex" && cfg.provider === "deepseek") {
121
- return `deepseek|${cfg.providerBaseUrl ?? "default"}|${cfg.providerApiKey ? "key" : "nokey"}`;
103
+ return `deepseek|${cfg.providerApiKey ? "key" : "nokey"}`;
122
104
  }
123
105
  if (runtime !== "claude" || cfg.provider !== "custom")
124
106
  return null;
package/dist/runner.js CHANGED
@@ -12,7 +12,7 @@ import { readBoundImDecisionFile, resetBoundImDecisionFile } from "./bound-im-de
12
12
  import { launchSupervisedRuntime } from "./supervised-runtime.js";
13
13
  import { awaitWithCancellation, } from "./runtime-cancellation.js";
14
14
  export { awaitExit, exitActivity } from "./local-executor.js";
15
- export { sanitizeEnvVars } from "./provider-env.js";
15
+ export { sanitizeEnvVars } from "./runtime-env.js";
16
16
  const ICON = {
17
17
  init: "🟢", text: "💬", reading: "📖", sending: "📨", checking: "🔎",
18
18
  claiming: "📌", crew: "⚙️", tool: "🛠️", tool_result: "↩️", done: "✅", error: "❌",
@@ -0,0 +1,21 @@
1
+ const ENV_KEY_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
2
+ export const RESERVED_ENV = new Set([
3
+ "PATH",
4
+ "XDG_CONFIG_HOME",
5
+ "XDG_DATA_HOME",
6
+ "XDG_CACHE_HOME",
7
+ "GH_CONFIG_DIR",
8
+ "CLOUDSDK_CONFIG",
9
+ "NPM_CONFIG_USERCONFIG",
10
+ "YARN_REGISTRY",
11
+ "NPM_CONFIG_ALWAYS_AUTH",
12
+ ]);
13
+ /** 用户自定义环境只能补充普通变量,不能覆盖 daemon 维护的运行时契约。 */
14
+ export function sanitizeEnvVars(raw) {
15
+ if (!raw)
16
+ return {};
17
+ return Object.fromEntries(Object.entries(raw).filter(([key, value]) => typeof value === "string"
18
+ && ENV_KEY_RE.test(key)
19
+ && !key.toUpperCase().startsWith("CREW_")
20
+ && !RESERVED_ENV.has(key.toUpperCase())));
21
+ }
@@ -21,14 +21,9 @@ const RunnerInputSchema = z.object({
21
21
  cwd: z.string().min(1).optional(),
22
22
  workspaceRoots: z.array(z.string().min(1)).optional(),
23
23
  skillRoots: z.array(z.string().min(1)).optional(),
24
- networkAccess: z.boolean().optional(),
25
24
  codexCollaborationTools: z.boolean().optional(),
26
25
  resume: z.boolean(),
27
- }).strict().superRefine((input, ctx) => {
28
- if (input.networkAccess === true && input.effectivePermission !== "workspace_write") {
29
- ctx.addIssue({ code: "custom", message: "network_access_requires_workspace_write" });
30
- }
31
- });
26
+ }).strict();
32
27
  const RPC_TIMEOUT_MS = 30_000;
33
28
  const INITIALIZE_RPC_TIMEOUT_MS = 60_000;
34
29
  const ERROR_MESSAGE_CAP = 2_000;
@@ -618,9 +613,6 @@ async function runCodexAppServerAttempt(bin, input, attempt, initializeTimeoutMs
618
613
  ...(input.reasoning === undefined || input.reasoning === "default"
619
614
  ? {}
620
615
  : { effort: input.reasoning }),
621
- ...(input.networkAccess === true ? {
622
- sandboxPolicy: { type: "workspaceWrite", networkAccess: true },
623
- } : {}),
624
616
  });
625
617
  logStage(activeStage, "ok", attempt, stageStartedAt);
626
618
  turnId = started.turn.id;
@@ -7,20 +7,10 @@ export const DEEPSEEK_CODEX_BASE_URL = "https://api.deepseek.com/";
7
7
  export const DEEPSEEK_CODEX_KEY_ENV = "NOWCREW_DEEPSEEK_API_KEY";
8
8
  export const DEEPSEEK_CODEX_REASONING_LEVELS = ["low", "high", "max"];
9
9
  const PRIVATE_CODEX_HOME = ".codex-deepseek";
10
- const SELF_TRAINING_PRIVATE_CODEX_HOME = ".codex-deepseek-self-training";
11
- export function deepSeekCodexHome(homeDir, selfTraining = false) {
12
- return resolve(homeDir, selfTraining ? SELF_TRAINING_PRIVATE_CODEX_HOME : PRIVATE_CODEX_HOME);
10
+ export function deepSeekCodexHome(homeDir) {
11
+ return resolve(homeDir, PRIVATE_CODEX_HOME);
13
12
  }
14
- function normalizedBaseUrl(value) {
15
- const url = new URL(value);
16
- if (url.protocol !== "http:" && url.protocol !== "https:") {
17
- throw new Error("DeepSeek provider base URL must use HTTP(S)");
18
- }
19
- if (!url.pathname.endsWith("/"))
20
- url.pathname = `${url.pathname}/`;
21
- return url.toString();
22
- }
23
- export function renderDeepSeekConfig(codexHome, baseUrl = DEEPSEEK_CODEX_BASE_URL) {
13
+ export function renderDeepSeekConfig(codexHome) {
24
14
  const catalogPath = join(codexHome, "models.json");
25
15
  return [
26
16
  `model = ${JSON.stringify(DEEPSEEK_CODEX_MODEL)}`,
@@ -30,7 +20,7 @@ export function renderDeepSeekConfig(codexHome, baseUrl = DEEPSEEK_CODEX_BASE_UR
30
20
  "",
31
21
  "[model_providers.deepseek]",
32
22
  'name = "deepseek"',
33
- `base_url = ${JSON.stringify(normalizedBaseUrl(baseUrl))}`,
23
+ `base_url = ${JSON.stringify(DEEPSEEK_CODEX_BASE_URL)}`,
34
24
  'wire_api = "responses"',
35
25
  `env_key = ${JSON.stringify(DEEPSEEK_CODEX_KEY_ENV)}`,
36
26
  "",
@@ -50,11 +40,11 @@ async function writePrivateAtomic(path, content) {
50
40
  await rm(temporary, { force: true });
51
41
  }
52
42
  }
53
- export async function materializeDeepSeekCodexHome(homeDir, options = {}) {
54
- const codexHome = deepSeekCodexHome(homeDir, options.selfTraining === true);
43
+ export async function materializeDeepSeekCodexHome(homeDir) {
44
+ const codexHome = deepSeekCodexHome(homeDir);
55
45
  await mkdir(codexHome, { recursive: true, mode: 0o700 });
56
46
  await chmod(codexHome, 0o700);
57
47
  await writePrivateAtomic(join(codexHome, "models.json"), DEEPSEEK_CODEX_CATALOG);
58
- await writePrivateAtomic(join(codexHome, "config.toml"), renderDeepSeekConfig(codexHome, options.baseUrl));
48
+ await writePrivateAtomic(join(codexHome, "config.toml"), renderDeepSeekConfig(codexHome));
59
49
  return codexHome;
60
50
  }
@@ -36,9 +36,6 @@ export function buildCodexArgs(input) {
36
36
  else if (input.effectivePermission === "full_access" || (input.effectivePermission === undefined && input.dangerous)) {
37
37
  args.push("--dangerously-bypass-approvals-and-sandbox");
38
38
  }
39
- if (input.effectivePermission === "workspace_write" && input.networkAccess === true) {
40
- args.push("-c", "sandbox_workspace_write.network_access=true");
41
- }
42
39
  for (const imagePath of input.imagePaths ?? [])
43
40
  args.push("--image", imagePath);
44
41
  // `-` instructs codex exec to read the prompt from stdin. Keeping the complete prompt out of argv
@@ -46,7 +46,6 @@ export function supervisorLaunch(request) {
46
46
  effectivePermission: request.effectivePermission,
47
47
  ...(request.model === undefined ? {} : { model: request.model }),
48
48
  ...(request.reasoning === undefined ? {} : { reasoning: request.reasoning }),
49
- ...(request.networkAccess === undefined ? {} : { networkAccess: request.networkAccess }),
50
49
  ...(request.sessionId === undefined ? {} : { sessionId: request.sessionId }),
51
50
  ...(request.imagePaths === undefined ? {} : { imagePaths: request.imagePaths }),
52
51
  ...(request.agentRoot === undefined ? {} : {
package/dist/workspace.js CHANGED
@@ -59,13 +59,12 @@ export async function prepareWorkspace(input) {
59
59
  const crewDir = join(dir, ".crew");
60
60
  await mkdir(crewDir, { recursive: true });
61
61
  // 预先创建明细目录,让收尾流程可以按功能创建 notes/<topic>.md。
62
- if (!input.skipLocalMemory)
63
- await mkdir(join(dir, "notes"), { recursive: true });
62
+ await mkdir(join(dir, "notes"), { recursive: true });
64
63
  // MEMORY.md:首次创建"持久身份 + 知识索引"骨架,之后由 agent 自己维护
65
64
  const memoryPath = join(dir, "MEMORY.md");
66
- const memorySeedCreated = !input.skipLocalMemory && !(await exists(memoryPath));
65
+ const memorySeedCreated = !(await exists(memoryPath));
67
66
  const localMemoryV2Initialized = await hasLocalMemoryV2Marker(dir);
68
- if (!input.skipLocalMemory && memorySeedCreated) {
67
+ if (memorySeedCreated) {
69
68
  try {
70
69
  await writeFile(memoryPath, memorySeed(input.handle, input.description), "utf8");
71
70
  }
@@ -74,15 +73,13 @@ export async function prepareWorkspace(input) {
74
73
  throw error;
75
74
  }
76
75
  }
77
- let memory = "";
78
- if (!input.skipLocalMemory) {
79
- try {
80
- memory = await readFile(memoryPath, "utf8");
81
- }
82
- catch (error) {
83
- logMemoryPrepareFailure(input, "memory_read", error);
84
- throw error;
85
- }
76
+ let memory;
77
+ try {
78
+ memory = await readFile(memoryPath, "utf8");
79
+ }
80
+ catch (error) {
81
+ logMemoryPrepareFailure(input, "memory_read", error);
82
+ throw error;
86
83
  }
87
84
  // 系统提示词按 execution 隔离;省略 identity 的兼容调用每次使用随机路径。
88
85
  const promptDir = join(crewDir, "prompts");