@nowcrew/daemon 0.6.68 → 0.6.70
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 +30 -1
- package/dist/agent-ability/resolver.js +27 -16
- package/dist/agent-ability/runtime.js +3 -0
- package/dist/agent-ability/types.js +6 -11
- package/dist/automatic-install-target.js +15 -10
- package/dist/background-job.js +50 -0
- package/dist/computer-cli.js +10 -1
- package/dist/computer-service.js +41 -1
- package/dist/config.js +44 -0
- package/dist/console-formatter.js +76 -1
- package/dist/console.js +23 -4
- package/dist/daemon-migration-controller.js +16 -18
- package/dist/execution-protocol.js +0 -1
- package/dist/execution-runner.js +60 -11
- package/dist/i18n.js +2 -0
- package/dist/local-execution-prompt.js +32 -13
- package/dist/local-executor.js +107 -55
- package/dist/local-memory/index-budget.js +74 -0
- package/dist/local-memory/pending.js +111 -0
- package/dist/local-memory/runtime.js +87 -0
- package/dist/local-memory/types.js +1 -0
- package/dist/local-memory/write.js +448 -0
- package/dist/machine-info.js +3 -4
- package/dist/main.js +83 -0
- package/dist/managed-service-lifecycle.js +47 -2
- package/dist/managed-service-startup.js +2 -0
- package/dist/profile-layout.js +10 -4
- package/dist/project-dependencies.js +139 -124
- package/dist/project-dependency-lock.js +87 -0
- package/dist/project-dependency-manifest.js +2 -12
- package/dist/project-registry-wiring.js +1 -4
- package/dist/project-skills/controller.js +2 -0
- package/dist/project-skills/runtime-launch.js +10 -7
- package/dist/prompt.js +19 -1
- package/dist/provider-env.js +3 -21
- package/dist/repository-identity.js +45 -0
- package/dist/runner.js +4 -2
- package/dist/runtimes/codex-app-server-runner.js +55 -23
- package/dist/runtimes/codex-command-safety.js +75 -0
- package/dist/runtimes/codex-contract.js +20 -5
- package/dist/runtimes/codex-deepseek-config.js +7 -17
- package/dist/runtimes/codex-turn-retry.js +69 -0
- package/dist/runtimes/codex.js +4 -3
- package/dist/serve.js +68 -3
- package/dist/storage-config.js +175 -0
- package/dist/storage-control.js +193 -0
- package/dist/storage-copy.js +628 -0
- package/dist/storage-credential-guard.js +21 -0
- package/dist/storage-doctor.js +228 -0
- package/dist/storage-identity.js +29 -0
- package/dist/storage-layout.js +143 -0
- package/dist/storage-manifest.js +855 -0
- package/dist/storage-migration-controller.js +420 -0
- package/dist/storage-migration-manifest.js +105 -0
- package/dist/storage-migration-policy.js +100 -0
- package/dist/storage-runtime-controller.js +339 -0
- package/dist/storage-runtime-readiness.js +184 -0
- package/dist/storage-runtime.js +39 -0
- package/dist/storage-safe-fs.js +302 -0
- package/dist/storage-serve-adapter.js +65 -0
- package/dist/storage-status-delivery.js +209 -0
- package/dist/storage-status-replay.js +125 -0
- package/dist/storage-target-confirmation.js +129 -0
- package/dist/storage-worker-command.js +37 -0
- package/dist/storage-worker-executor.js +430 -0
- package/dist/storage-worker-handoff.js +151 -0
- package/dist/storage-worker-operation.js +284 -0
- package/dist/storage-worker-status.js +259 -0
- package/dist/supervised-runtime.js +3 -1
- package/dist/workspace.js +34 -14
- package/package.json +1 -1
- package/dist/self-training-workspace.js +0 -15
package/dist/console.js
CHANGED
|
@@ -17,7 +17,7 @@ import { buildFilePreview, buildSnippetDiff } from "./console-payload.js";
|
|
|
17
17
|
import { parseUnifiedDiff } from "./unified-diff.js";
|
|
18
18
|
import { buildJsonResult } from "./json-result.js";
|
|
19
19
|
import { buildCollapsedResult } from "./console-collapse.js";
|
|
20
|
-
import { boundedCodexPlan
|
|
20
|
+
import { boundedCodexPlan } from "./runtimes/codex-contract.js";
|
|
21
21
|
/** 单条工具返回正文上限(超出截断并标注),避免单条把终端/DB 撑爆。 */
|
|
22
22
|
export const TOOL_RESULT_CAP = 4000;
|
|
23
23
|
/** 工具输入摘要上限(标题行那一段)。 */
|
|
@@ -69,6 +69,12 @@ function summarizeToolInput(name, input) {
|
|
|
69
69
|
.join(", ");
|
|
70
70
|
return `⏺ ${name}(${clip(head.replace(/\s+/g, " "), TOOL_INPUT_CAP)})`;
|
|
71
71
|
}
|
|
72
|
+
/** codex 计划步骤状态(pending/inProgress/completed) → ConsoleTodo 状态(pending/in_progress/completed)。 */
|
|
73
|
+
const CODEX_PLAN_STATUS_MAP = {
|
|
74
|
+
pending: "pending",
|
|
75
|
+
inProgress: "in_progress",
|
|
76
|
+
completed: "completed",
|
|
77
|
+
};
|
|
72
78
|
const TODO_STATUSES = new Set(["pending", "in_progress", "completed"]);
|
|
73
79
|
/** claude TodoWrite 的 todos 数组归一为 ConsoleTodo[](脏数据条目丢弃)。 */
|
|
74
80
|
function normalizeTodos(raw) {
|
|
@@ -236,7 +242,13 @@ function codexItemChunks(item, td) {
|
|
|
236
242
|
if (!todos.length)
|
|
237
243
|
return [];
|
|
238
244
|
const done = todos.filter((t) => t.status === "completed").length;
|
|
239
|
-
|
|
245
|
+
// codex 对同一份 plan 的多次更新复用同一个 item.id,透传给下游做合并键;无 id 时不伪造。
|
|
246
|
+
const listId = typeof item.id === "string" && item.id ? item.id : undefined;
|
|
247
|
+
return [{
|
|
248
|
+
stream: "tool",
|
|
249
|
+
text: `⏺ Todos(${done}/${todos.length})`,
|
|
250
|
+
payload: { kind: "todos", todos, ...(listId ? { listId } : {}) },
|
|
251
|
+
}];
|
|
240
252
|
}
|
|
241
253
|
if (item.type === "web_search" && item.query?.trim()) {
|
|
242
254
|
return [{ stream: "tool", text: `⏺ WebSearch(${clip(item.query.trim(), TOOL_INPUT_CAP)})` }];
|
|
@@ -276,10 +288,17 @@ export function toConsoleLines(event) {
|
|
|
276
288
|
}
|
|
277
289
|
if (e.type === "turn.plan.updated") {
|
|
278
290
|
const plan = boundedCodexPlan(e.plan);
|
|
279
|
-
|
|
291
|
+
if (plan === null)
|
|
292
|
+
return [];
|
|
293
|
+
const todos = plan.map(({ step, status }) => ({
|
|
294
|
+
text: step,
|
|
295
|
+
status: CODEX_PLAN_STATUS_MAP[status],
|
|
296
|
+
}));
|
|
297
|
+
const listId = typeof e.turn_id === "string" && e.turn_id ? e.turn_id : "codex-plan";
|
|
298
|
+
return [{
|
|
280
299
|
stream: "tool",
|
|
281
300
|
text: `⏺ ${td("Plan updated")} (${plan.length})`,
|
|
282
|
-
payload: { kind: "
|
|
301
|
+
payload: { kind: "todos", todos, listId },
|
|
283
302
|
}];
|
|
284
303
|
}
|
|
285
304
|
if (e.type === "item.completed" && e.item) {
|
|
@@ -10,6 +10,7 @@ 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";
|
|
13
14
|
const MigrationMessageSchema = z.object({
|
|
14
15
|
type: z.literal("daemon:migrate"),
|
|
15
16
|
migrationId: z.string().uuid(),
|
|
@@ -47,33 +48,30 @@ async function hashedFiles(root, directory = root) {
|
|
|
47
48
|
return files;
|
|
48
49
|
}
|
|
49
50
|
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
|
+
});
|
|
50
58
|
const backup = migrationBackupRoot(input, id);
|
|
51
59
|
await mkdir(backup, { recursive: true, mode: 0o700 });
|
|
52
60
|
await cp(input.currentDaemonHome, resolve(backup, "daemon-home"), { recursive: true, force: false });
|
|
53
61
|
await cp(input.currentAgentsRoot, resolve(backup, "agents-root"), { recursive: true, force: false });
|
|
54
62
|
await cp(input.currentDaemonHome, targetHome, { recursive: true, force: false });
|
|
55
63
|
await cp(input.currentAgentsRoot, targetAgents, { recursive: true, force: false });
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
];
|
|
64
|
+
const daemonFiles = await hashedFiles(resolve(backup, "daemon-home"));
|
|
65
|
+
const agentFiles = await hashedFiles(resolve(backup, "agents-root"));
|
|
66
|
+
const mappings = buildStorageMigrationMappings({ daemonFiles, agentFiles });
|
|
60
67
|
await writeFile(resolve(backup, "manifest.json"), `${JSON.stringify({
|
|
61
|
-
version:
|
|
68
|
+
version: 2,
|
|
62
69
|
migrationId: id,
|
|
63
70
|
profile: input.profileName,
|
|
64
71
|
daemonHome: input.currentDaemonHome,
|
|
65
72
|
agentsRoot: input.currentAgentsRoot,
|
|
66
|
-
service:
|
|
67
|
-
|
|
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,
|
|
73
|
+
service: safeService,
|
|
74
|
+
mappings,
|
|
77
75
|
}, null, 2)}\n`, { mode: 0o600 });
|
|
78
76
|
return backup;
|
|
79
77
|
}
|
|
@@ -147,7 +145,7 @@ export function createDaemonMigrationController(input) {
|
|
|
147
145
|
}
|
|
148
146
|
}
|
|
149
147
|
catch (error) {
|
|
150
|
-
sendFailure(message.migrationId, "target_conflict", error);
|
|
148
|
+
sendFailure(message.migrationId, error instanceof CredentialMaterialError ? "credential_material" : "target_conflict", error);
|
|
151
149
|
return;
|
|
152
150
|
}
|
|
153
151
|
input.sendStatus({ type: "daemon:migration-status", migrationId: message.migrationId, status: "backing_up" });
|
|
@@ -158,7 +156,7 @@ export function createDaemonMigrationController(input) {
|
|
|
158
156
|
}
|
|
159
157
|
catch (error) {
|
|
160
158
|
await Promise.allSettled([rm(targetPath, { recursive: true, force: true }), rm(targetAgents, { recursive: true, force: true })]);
|
|
161
|
-
sendFailure(message.migrationId, "backup_failed", error);
|
|
159
|
+
sendFailure(message.migrationId, error instanceof CredentialMaterialError ? "credential_material" : "backup_failed", error);
|
|
162
160
|
return;
|
|
163
161
|
}
|
|
164
162
|
const install = input.install ?? installDaemonAutomatically;
|
|
@@ -197,7 +197,6 @@ export const ExecutionStartSchema = z.object({
|
|
|
197
197
|
language: z.enum(["zh", "en"]),
|
|
198
198
|
systemPrompt: z.string(),
|
|
199
199
|
wakePrompt: z.string(),
|
|
200
|
-
maintenancePurpose: z.literal("self_training").optional(),
|
|
201
200
|
}).strict(),
|
|
202
201
|
runtime: z.object({
|
|
203
202
|
name: RuntimeSchema,
|
package/dist/execution-runner.js
CHANGED
|
@@ -19,6 +19,7 @@ import { ProjectSkillRuntimeOwnershipUnverifiedError, } from "./project-skills/r
|
|
|
19
19
|
import { projectSkillExecutionProjection, projectSkillProjectionErrorCode } from "./project-skills/execution-adapter.js";
|
|
20
20
|
import { redactProjectSkillRuntimeRootError, } from "./project-skills/runtime-launch.js";
|
|
21
21
|
import { createProjectRegistry } from "./project-skills/registry.js";
|
|
22
|
+
import { ProjectDependencyError, } from "./project-dependencies.js";
|
|
22
23
|
import { ProjectContextUnavailableError, resolveProjectContext } from "./project-workspaces/resolver.js";
|
|
23
24
|
import { PROJECT_WORKSPACES_CAPABILITY } from "./machine-info.js";
|
|
24
25
|
import { PROJECT_SKILL_PROJECTION_V2_CAPABILITY } from "./project-skills/types.js";
|
|
@@ -315,7 +316,9 @@ function failedCompletion(spec, error, startedAt, finishedAt) {
|
|
|
315
316
|
? "queue_timeout"
|
|
316
317
|
: error instanceof ProjectContextUnavailableError
|
|
317
318
|
? error.code
|
|
318
|
-
:
|
|
319
|
+
: error instanceof ProjectDependencyError
|
|
320
|
+
? error.code
|
|
321
|
+
: projectSkillProjectionErrorCode(error) ?? "local_execution_failed";
|
|
319
322
|
return ExecutionCompletedSchema.parse({
|
|
320
323
|
type: "execution:completed",
|
|
321
324
|
protocolVersion: 1,
|
|
@@ -503,21 +506,68 @@ export async function runExecution(config, input, dependencies) {
|
|
|
503
506
|
await cancellable(dependencies.slot.ready, dependencies.cancellation);
|
|
504
507
|
}
|
|
505
508
|
let projectContext;
|
|
509
|
+
let trainingProjectContext;
|
|
506
510
|
let sessionContextFingerprint;
|
|
507
511
|
const logicalProjectContext = spec.workspace.projectContext;
|
|
508
|
-
|
|
512
|
+
dslog("project_dependencies.preflight", "项目依赖准备前置状态", {
|
|
513
|
+
execution_id: spec.executionId,
|
|
514
|
+
agent_handle: spec.agent.handle,
|
|
515
|
+
has_ability_release: spec.agent.abilityRelease !== undefined,
|
|
516
|
+
ability_release_id: spec.agent.abilityRelease?.releaseId,
|
|
517
|
+
ability_root_commit: spec.agent.abilityRelease?.rootCommit,
|
|
518
|
+
has_project_context: logicalProjectContext !== undefined,
|
|
519
|
+
project_ids: JSON.stringify(logicalProjectContext?.projectIds ?? []),
|
|
520
|
+
project_context_primary: logicalProjectContext?.primaryProjectId,
|
|
521
|
+
dependency_prepare_expected: spec.agent.abilityRelease !== undefined,
|
|
522
|
+
});
|
|
523
|
+
if (spec.agent.abilityRelease !== undefined && dependencies.projectDependencies !== undefined) {
|
|
524
|
+
if (dependencies.abilityRelease !== undefined) {
|
|
525
|
+
await cancellable(dependencies.abilityRelease.apply(config.agentsRoot, spec.agent.handle, spec.agent.abilityRelease), dependencies.cancellation);
|
|
526
|
+
}
|
|
527
|
+
const preparedProjectDependencies = await cancellable(dependencies.projectDependencies.prepare({
|
|
528
|
+
trainingRoot: join(config.agentsRoot, spec.agent.handle, "training"),
|
|
529
|
+
reposRoot: join(config.agentsRoot, "repos"),
|
|
530
|
+
lockRoot: join(config.agentsRoot, ".crew", "project-dependencies"),
|
|
531
|
+
}), dependencies.cancellation);
|
|
532
|
+
trainingProjectContext = Object.freeze({
|
|
533
|
+
projects: Object.freeze(preparedProjectDependencies.map((project) => Object.freeze({
|
|
534
|
+
repositoryKey: project.repositoryKey,
|
|
535
|
+
displayName: project.displayName,
|
|
536
|
+
repo: project.repo,
|
|
537
|
+
root: project.localRoot,
|
|
538
|
+
branch: project.branch,
|
|
539
|
+
resolvedCommit: project.resolvedCommit,
|
|
540
|
+
}))),
|
|
541
|
+
});
|
|
542
|
+
for (const project of preparedProjectDependencies) {
|
|
543
|
+
dslog("project_dependencies.prepared", "Training project dependency prepared", {
|
|
544
|
+
execution_id: spec.executionId,
|
|
545
|
+
agent_handle: spec.agent.handle,
|
|
546
|
+
repository_key: project.repositoryKey,
|
|
547
|
+
project_branch: project.branch,
|
|
548
|
+
project_branch_source: project.branchSource,
|
|
549
|
+
project_commit: project.resolvedCommit,
|
|
550
|
+
project_checkout_mode: project.checkoutMode,
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
else if (spec.agent.abilityRelease === undefined
|
|
555
|
+
&& logicalProjectContext !== undefined
|
|
556
|
+
&& logicalProjectContext.projectIds.length > 0) {
|
|
509
557
|
const projectSnapshot = {
|
|
510
558
|
projectIds: logicalProjectContext.projectIds,
|
|
511
559
|
...(logicalProjectContext.primaryProjectId === undefined
|
|
512
560
|
? {}
|
|
513
561
|
: { primaryProjectId: logicalProjectContext.primaryProjectId }),
|
|
514
562
|
};
|
|
515
|
-
|
|
563
|
+
const projectWorkspaceRegistry = dependencies.projectWorkspaceRegistry
|
|
564
|
+
?? dependencies.projectRegistry
|
|
565
|
+
?? createProjectRegistry(config.agentsRoot);
|
|
566
|
+
projectContext = await cancellable(resolveProjectContext(projectSnapshot, projectWorkspaceRegistry), dependencies.cancellation);
|
|
516
567
|
sessionContextFingerprint = projectSessionContextFingerprint(spec.runtime.name, projectSnapshot);
|
|
517
568
|
}
|
|
518
|
-
const selfTraining = spec.instructions.maintenancePurpose === "self_training";
|
|
519
569
|
let recalledMemory = "";
|
|
520
|
-
if (
|
|
570
|
+
if (spec.agent.memoryEnabled === true && dependencies.agentMemory !== undefined) {
|
|
521
571
|
try {
|
|
522
572
|
recalledMemory = await cancellable(dependencies.agentMemory.recall(spec.agent.handle, spec.instructions.wakePrompt, spec.executionId, spec.agent.memoryAgentId ?? null), dependencies.cancellation);
|
|
523
573
|
}
|
|
@@ -776,9 +826,7 @@ export async function runExecution(config, input, dependencies) {
|
|
|
776
826
|
const baseSystemPromptBudget = spec.agent.abilityRelease === undefined
|
|
777
827
|
? systemPromptBudget
|
|
778
828
|
: Math.max(0, Math.min(systemPromptBudget, Math.max(32 * 1024, systemPromptBudget - 168 * 1024)));
|
|
779
|
-
const systemPromptWithLocalFacts = withLocalExecutionFacts(spec.instructions.systemPrompt, baseSystemPromptBudget, {
|
|
780
|
-
...(selfTraining ? { isolateLocalMemory: true } : {}),
|
|
781
|
-
});
|
|
829
|
+
const systemPromptWithLocalFacts = withLocalExecutionFacts(spec.instructions.systemPrompt, baseSystemPromptBudget, { collaborationTools: config.codexCollaborationTools && spec.runtime.name === "codex" });
|
|
782
830
|
const boundedSystemPrompt = (context) => appendAgentMemoryContext(typeof systemPromptWithLocalFacts === "string"
|
|
783
831
|
? systemPromptWithLocalFacts
|
|
784
832
|
: systemPromptWithLocalFacts(context), recalledMemory, baseSystemPromptBudget);
|
|
@@ -791,6 +839,7 @@ export async function runExecution(config, input, dependencies) {
|
|
|
791
839
|
...(spec.workspace.resumeKey === undefined ? {} : { resumeKey: spec.workspace.resumeKey }),
|
|
792
840
|
...(sessionContextFingerprint === undefined ? {} : { sessionContextFingerprint }),
|
|
793
841
|
...(projectContext === undefined ? {} : { projectContext }),
|
|
842
|
+
...(trainingProjectContext === undefined ? {} : { trainingProjectContext }),
|
|
794
843
|
...(spec.context.wakeMessageId === undefined ? {} : { wakeMessageId: spec.context.wakeMessageId }),
|
|
795
844
|
...(spec.context.attachments === undefined ? {} : { attachments: spec.context.attachments }),
|
|
796
845
|
...(spec.agent.projectSkills === undefined
|
|
@@ -804,6 +853,7 @@ export async function runExecution(config, input, dependencies) {
|
|
|
804
853
|
name: spec.runtime.name,
|
|
805
854
|
...(spec.runtime.model === undefined ? {} : { model: spec.runtime.model }),
|
|
806
855
|
...(spec.runtime.reasoning === undefined ? {} : { reasoning: spec.runtime.reasoning }),
|
|
856
|
+
codexCollaborationTools: config.codexCollaborationTools,
|
|
807
857
|
},
|
|
808
858
|
effectivePermission: permission,
|
|
809
859
|
captureFinal: spec.reporting.captureFinal,
|
|
@@ -823,13 +873,13 @@ export async function runExecution(config, input, dependencies) {
|
|
|
823
873
|
} : {}),
|
|
824
874
|
},
|
|
825
875
|
session: {
|
|
826
|
-
enabled:
|
|
876
|
+
enabled: config.resume,
|
|
827
877
|
warmMs: config.resumeWarmMs,
|
|
828
878
|
budgetTokens: config.sessionBudgetTokens,
|
|
829
879
|
softTokens: config.sessionSoftTokens,
|
|
830
880
|
maxTurns: config.sessionMaxTurns,
|
|
831
881
|
},
|
|
832
|
-
|
|
882
|
+
localMemoryV2Enabled: config.localMemoryV2Handles?.has(spec.agent.handle) === true,
|
|
833
883
|
};
|
|
834
884
|
const result = await Promise.race([
|
|
835
885
|
execute(localInput, callbacks, localDependencies),
|
|
@@ -995,7 +1045,6 @@ export async function runExecution(config, input, dependencies) {
|
|
|
995
1045
|
}
|
|
996
1046
|
await dependencies.journal.complete(spec.executionId, completion);
|
|
997
1047
|
if (completion.outcome === "succeeded"
|
|
998
|
-
&& spec.instructions.maintenancePurpose !== "self_training"
|
|
999
1048
|
&& spec.agent.memoryEnabled === true
|
|
1000
1049
|
&& memoryCaptureFinalText !== null
|
|
1001
1050
|
&& dependencies.agentMemory !== undefined) {
|
package/dist/i18n.js
CHANGED
|
@@ -19,6 +19,8 @@ const zh = {
|
|
|
19
19
|
"Claude session started": "Claude 会话启动",
|
|
20
20
|
"Codex session started": "Codex 会话启动",
|
|
21
21
|
"Plan updated": "计划更新",
|
|
22
|
+
"Thinking (~{{tokens}} tokens, content not streamed by Claude Code)": "思考(约 {{tokens}} tokens,Claude Code 未输出思考正文)",
|
|
23
|
+
"Thinking (content not streamed by Claude Code)": "思考(Claude Code 未输出思考正文)",
|
|
22
24
|
"Files changed": "文件变更",
|
|
23
25
|
"Run failed": "运行出错",
|
|
24
26
|
"Run finished": "本轮结束",
|
|
@@ -4,7 +4,22 @@
|
|
|
4
4
|
* server 提示词是权威部分,绝不裁剪;项目工作区提示词是绑定执行的强制部分,放不下就直接失败;
|
|
5
5
|
* 只有本机事实(CREW_HOME / work-log / MEMORY 注入)是可选增强,按整段丢弃或按字节截断。
|
|
6
6
|
*/
|
|
7
|
-
import { buildRuntimeWorkspacePrompt, capMemoryForInject, capWorkLogForInject, } from "./prompt.js";
|
|
7
|
+
import { buildCollaborationToolsPrompt, buildRuntimeWorkspacePrompt, capMemoryForInject, capWorkLogForInject, } from "./prompt.js";
|
|
8
|
+
const trainingProjectJson = (project) => JSON.stringify({
|
|
9
|
+
repositoryKey: project.repositoryKey,
|
|
10
|
+
displayName: project.displayName,
|
|
11
|
+
repo: project.repo,
|
|
12
|
+
branch: project.branch,
|
|
13
|
+
resolvedCommit: project.resolvedCommit,
|
|
14
|
+
root: project.root,
|
|
15
|
+
});
|
|
16
|
+
export function buildTrainingGitProjectPrompt(context) {
|
|
17
|
+
if (context === undefined || context.projects.length === 0)
|
|
18
|
+
return "";
|
|
19
|
+
return "\n\n## Training Git projects\n" + context.projects
|
|
20
|
+
.map((project) => "- " + trainingProjectJson(project) + "\n Run project commands with: cd <root> && <command>")
|
|
21
|
+
.join("\n");
|
|
22
|
+
}
|
|
8
23
|
export function truncateUtf8(value, maxBytes) {
|
|
9
24
|
if (maxBytes <= 0)
|
|
10
25
|
return "";
|
|
@@ -31,28 +46,32 @@ function takeCompletePromptSections(sections, maxBytes) {
|
|
|
31
46
|
}
|
|
32
47
|
/** v1 server instructions opt in to daemon-owned paths and bounded local workspace context. */
|
|
33
48
|
export function withLocalExecutionFacts(serverPrompt, maxBytes, options = {}) {
|
|
34
|
-
return ({ workspace, resuming, projectContext }) => {
|
|
35
|
-
const memory =
|
|
49
|
+
return ({ workspace, resuming, projectContext, trainingProjectContext }) => {
|
|
50
|
+
const memory = capMemoryForInject(workspace.memory);
|
|
36
51
|
const workLog = resuming ? "" : capWorkLogForInject(workspace.workLog);
|
|
37
|
-
const
|
|
38
|
-
const
|
|
52
|
+
const collaborationPrompt = options.collaborationTools === true ? buildCollaborationToolsPrompt() : "";
|
|
53
|
+
const mandatoryWorkspacePrompt = `${buildRuntimeWorkspacePrompt(projectContext)}${buildTrainingGitProjectPrompt(trainingProjectContext)}`;
|
|
39
54
|
const localFactSections = [`\n\n## Local execution facts
|
|
40
|
-
- $CREW_HOME: ${
|
|
55
|
+
- $CREW_HOME: ${workspace.dir}
|
|
41
56
|
- $CREW_TASK_LOG: ${workspace.workLogPath}`,
|
|
42
57
|
...(memory ? [`\n\n## Injected MEMORY.md (bounded local context)\n${memory}`] : []),
|
|
43
58
|
...(workLog ? [`\n\n## Injected work-log (bounded local context)\n${workLog}`] : []),
|
|
44
59
|
];
|
|
45
|
-
const
|
|
60
|
+
const serverPromptBytes = Buffer.byteLength(serverPrompt, "utf8");
|
|
61
|
+
const collaborationBytes = Buffer.byteLength(collaborationPrompt, "utf8");
|
|
62
|
+
const mandatoryBytes = Buffer.byteLength(mandatoryWorkspacePrompt, "utf8");
|
|
63
|
+
const requiredBytes = serverPromptBytes + collaborationBytes + mandatoryBytes;
|
|
64
|
+
// 必需预算与 projectContext 无关:协作段落永远参与;无协作时与旧实现逐字节等价。
|
|
65
|
+
if (collaborationPrompt !== "" && requiredBytes > maxBytes) {
|
|
66
|
+
throw new Error("collaboration_tools_prompt_budget_exceeded");
|
|
67
|
+
}
|
|
46
68
|
if (mandatoryWorkspacePrompt !== "") {
|
|
47
|
-
const serverPromptBytes = Buffer.byteLength(serverPrompt, "utf8");
|
|
48
|
-
const mandatoryBytes = Buffer.byteLength(mandatoryWorkspacePrompt, "utf8");
|
|
49
|
-
const requiredBytes = serverPromptBytes + mandatoryBytes;
|
|
50
69
|
if (requiredBytes > maxBytes)
|
|
51
70
|
throw new Error("project_workspace_prompt_budget_exceeded");
|
|
52
71
|
const optionalFacts = takeCompletePromptSections(localFactSections, maxBytes - requiredBytes);
|
|
53
|
-
return `${serverPrompt}${optionalFacts}${mandatoryWorkspacePrompt}`;
|
|
72
|
+
return `${serverPrompt}${collaborationPrompt}${optionalFacts}${mandatoryWorkspacePrompt}`;
|
|
54
73
|
}
|
|
55
|
-
const remaining = maxBytes -
|
|
56
|
-
return `${serverPrompt}${truncateUtf8(
|
|
74
|
+
const remaining = maxBytes - requiredBytes;
|
|
75
|
+
return `${serverPrompt}${collaborationPrompt}${truncateUtf8(localFactSections.join(""), remaining)}`;
|
|
57
76
|
};
|
|
58
77
|
}
|