@sortedyuan/maybecode 0.3.2 → 0.5.0
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/README.md +166 -55
- package/README.zh-CN.md +267 -0
- package/dist/application.d.ts +40 -34
- package/dist/application.d.ts.map +1 -1
- package/dist/application.js +290 -170
- package/dist/application.js.map +1 -1
- package/dist/args.d.ts +2 -2
- package/dist/args.d.ts.map +1 -1
- package/dist/args.js +50 -27
- package/dist/args.js.map +1 -1
- package/dist/bin.js +82 -71
- package/dist/bin.js.map +4 -4
- package/dist/cli/chunk-3IORPKBL.js +3572 -0
- package/dist/cli/chunk-3IORPKBL.js.map +7 -0
- package/dist/cli/{chunk-LVTRXPDS.js → chunk-4B2Z6KW7.js} +1547 -1536
- package/dist/cli/chunk-4B2Z6KW7.js.map +7 -0
- package/dist/cli/{chunk-JT6VBKOM.js → chunk-4WG6JIJJ.js} +127 -33
- package/dist/cli/{chunk-JT6VBKOM.js.map → chunk-4WG6JIJJ.js.map} +3 -3
- package/dist/cli/{chunk-K5JWPNSY.js → chunk-5SLWALZK.js} +3521 -16164
- package/dist/cli/chunk-5SLWALZK.js.map +7 -0
- package/dist/cli/chunk-MNBYXL5Y.js +132 -0
- package/dist/cli/chunk-MNBYXL5Y.js.map +7 -0
- package/dist/cli/{chunk-F4XRPLUM.js → chunk-SLWLUEHQ.js} +226 -86
- package/dist/cli/chunk-SLWLUEHQ.js.map +7 -0
- package/dist/cli/chunk-UQDZ55LQ.js +199 -0
- package/dist/cli/chunk-UQDZ55LQ.js.map +7 -0
- package/dist/cli/{chunk-7ISOHFS7.js → chunk-WMSG5ZTR.js} +717 -388
- package/dist/cli/chunk-WMSG5ZTR.js.map +7 -0
- package/dist/cli/chunk-WVIRS76R.js +4057 -0
- package/dist/cli/chunk-WVIRS76R.js.map +7 -0
- package/dist/cli/{chunk-HOU5ITUK.js → chunk-XTEMRAQW.js} +1 -1
- package/dist/cli/chunk-XTEMRAQW.js.map +7 -0
- package/dist/cli/chunk-Z3BOPBVU.js +91 -0
- package/dist/cli/chunk-Z3BOPBVU.js.map +7 -0
- package/dist/cli/{configured-WHY3GGAJ.js → configured-ACNM6TRQ.js} +10 -9
- package/dist/cli/{file-type-R2T7TBHI.js → file-type-HLHPV7WC.js} +817 -13
- package/dist/cli/file-type-HLHPV7WC.js.map +7 -0
- package/dist/cli/mcp-auth-XD5U7WCV.js +74 -0
- package/dist/cli/mcp-auth-XD5U7WCV.js.map +7 -0
- package/dist/cli/onboarding-WQWCPYEO.js +530 -0
- package/dist/cli/onboarding-WQWCPYEO.js.map +7 -0
- package/dist/cli/onboarding-check-HRRI5OJ7.js +32 -0
- package/dist/cli/onboarding-check-HRRI5OJ7.js.map +7 -0
- package/dist/cli/{retained-tui-VJ3VX4R3.js → retained-tui-QF5VMYLC.js} +788 -332
- package/dist/cli/retained-tui-QF5VMYLC.js.map +7 -0
- package/dist/cli/{sixel-LWTCM76G.js → sixel-ISZ4FZ3U.js} +37 -37
- package/dist/cli/{sixel-LWTCM76G.js.map → sixel-ISZ4FZ3U.js.map} +1 -1
- package/dist/cli/{team-T7G7PPNN.js → team-O2I5BXHM.js} +7 -6
- package/dist/cli/{team-v2-JGBBQ7FR.js → team-v2-YYO2G7DJ.js} +816 -390
- package/dist/cli/team-v2-YYO2G7DJ.js.map +7 -0
- package/dist/cli/{web-server-FOMNPY7Q.js → web-server-SXMH6FGA.js} +55 -19
- package/dist/cli/web-server-SXMH6FGA.js.map +7 -0
- package/dist/cli/{web-ui-COB6PKC5.js → web-ui-UWQUFE4W.js} +7 -6
- package/dist/config-schema.json +337 -0
- package/dist/configured.d.ts +18 -11
- package/dist/configured.d.ts.map +1 -1
- package/dist/configured.js +213 -390
- package/dist/configured.js.map +1 -1
- package/dist/controller.d.ts +19 -18
- package/dist/controller.d.ts.map +1 -1
- package/dist/delegation-commands.d.ts +1 -1
- package/dist/delegation-commands.d.ts.map +1 -1
- package/dist/delegation-commands.js +8 -8
- package/dist/delegation-commands.js.map +1 -1
- package/dist/errors.d.ts +2 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +2 -1
- package/dist/errors.js.map +1 -1
- package/dist/events.d.ts +8 -6
- package/dist/events.d.ts.map +1 -1
- package/dist/fork-picker.d.ts.map +1 -1
- package/dist/fork-picker.js +19 -5
- package/dist/fork-picker.js.map +1 -1
- package/dist/git-request.d.ts +6 -6
- package/dist/git-request.d.ts.map +1 -1
- package/dist/git-request.js +28 -15
- package/dist/git-request.js.map +1 -1
- package/dist/goal-commands.d.ts +1 -1
- package/dist/goal-commands.d.ts.map +1 -1
- package/dist/goal-commands.js +12 -5
- package/dist/goal-commands.js.map +1 -1
- package/dist/index.d.ts +5 -37
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -36
- package/dist/index.js.map +1 -1
- package/dist/instructions.d.ts +2 -7
- package/dist/instructions.d.ts.map +1 -1
- package/dist/instructions.js +7 -15
- package/dist/instructions.js.map +1 -1
- package/dist/keymap.d.ts +2 -2
- package/dist/keymap.d.ts.map +1 -1
- package/dist/keymap.js +2 -2
- package/dist/keymap.js.map +1 -1
- package/dist/maybecode-config.schema.json +1765 -0
- package/dist/mcp-auth.d.ts +1 -1
- package/dist/mcp-auth.d.ts.map +1 -1
- package/dist/mcp-auth.js +11 -8
- package/dist/mcp-auth.js.map +1 -1
- package/dist/mcp-commands.d.ts.map +1 -1
- package/dist/mcp-commands.js +18 -4
- package/dist/mcp-commands.js.map +1 -1
- package/dist/mcp-interaction-ui.d.ts.map +1 -1
- package/dist/mcp-interaction-ui.js +11 -4
- package/dist/mcp-interaction-ui.js.map +1 -1
- package/dist/media-history.d.ts +1 -1
- package/dist/media-history.d.ts.map +1 -1
- package/dist/media-history.js +8 -2
- package/dist/media-history.js.map +1 -1
- package/dist/model-picker.d.ts.map +1 -1
- package/dist/model-picker.js +10 -11
- package/dist/model-picker.js.map +1 -1
- package/dist/model-transition.d.ts +11 -0
- package/dist/model-transition.d.ts.map +1 -0
- package/dist/model-transition.js +48 -0
- package/dist/model-transition.js.map +1 -0
- package/dist/model.d.ts +2 -2
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +8 -4
- package/dist/model.js.map +1 -1
- package/dist/onboarding-check.d.ts +3 -0
- package/dist/onboarding-check.d.ts.map +1 -0
- package/dist/onboarding-check.js +22 -0
- package/dist/onboarding-check.js.map +1 -0
- package/dist/onboarding.d.ts +6 -0
- package/dist/onboarding.d.ts.map +1 -0
- package/dist/onboarding.js +463 -0
- package/dist/onboarding.js.map +1 -0
- package/dist/plugins/application.d.ts +6 -4
- package/dist/plugins/application.d.ts.map +1 -1
- package/dist/plugins/application.js +106 -52
- package/dist/plugins/application.js.map +1 -1
- package/dist/plugins/instructions.d.ts +1 -1
- package/dist/plugins/instructions.d.ts.map +1 -1
- package/dist/plugins/instructions.js +24 -11
- package/dist/plugins/instructions.js.map +1 -1
- package/dist/plugins/resources.d.ts +2 -2
- package/dist/plugins/resources.d.ts.map +1 -1
- package/dist/plugins/resources.js +22 -12
- package/dist/plugins/resources.js.map +1 -1
- package/dist/policy.d.ts +1 -1
- package/dist/policy.d.ts.map +1 -1
- package/dist/policy.js +59 -11
- package/dist/policy.js.map +1 -1
- package/dist/run.d.ts +2 -0
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +38 -33
- package/dist/run.js.map +1 -1
- package/dist/runtime-instructions.d.ts +1 -1
- package/dist/runtime-instructions.d.ts.map +1 -1
- package/dist/runtime-instructions.js +15 -7
- package/dist/runtime-instructions.js.map +1 -1
- package/dist/session-navigation.d.ts +6 -0
- package/dist/session-navigation.d.ts.map +1 -0
- package/dist/session-navigation.js +64 -0
- package/dist/session-navigation.js.map +1 -0
- package/dist/session-picker.d.ts +1 -1
- package/dist/session-picker.d.ts.map +1 -1
- package/dist/session-picker.js +23 -32
- package/dist/session-picker.js.map +1 -1
- package/dist/settings.d.ts +718 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +14 -0
- package/dist/settings.js.map +1 -0
- package/dist/skills.d.ts +1 -1
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +10 -12
- package/dist/skills.js.map +1 -1
- package/dist/slash-commands.d.ts +2 -2
- package/dist/slash-commands.d.ts.map +1 -1
- package/dist/slash-commands.js +149 -67
- package/dist/slash-commands.js.map +1 -1
- package/dist/team-execution.d.ts +10 -0
- package/dist/team-execution.d.ts.map +1 -0
- package/dist/team-execution.js +29 -0
- package/dist/team-execution.js.map +1 -0
- package/dist/team-patches.d.ts.map +1 -1
- package/dist/team-patches.js +149 -52
- package/dist/team-patches.js.map +1 -1
- package/dist/team-plan.d.ts +2 -2
- package/dist/team-plan.d.ts.map +1 -1
- package/dist/team-plan.js +115 -34
- package/dist/team-plan.js.map +1 -1
- package/dist/team-recovery.d.ts +1 -1
- package/dist/team-recovery.d.ts.map +1 -1
- package/dist/team-recovery.js +40 -10
- package/dist/team-recovery.js.map +1 -1
- package/dist/team-v2.d.ts.map +1 -1
- package/dist/team-v2.js +335 -104
- package/dist/team-v2.js.map +1 -1
- package/dist/team-verification.d.ts +4 -2
- package/dist/team-verification.d.ts.map +1 -1
- package/dist/team-verification.js +300 -97
- package/dist/team-verification.js.map +1 -1
- package/dist/team.d.ts +2 -2
- package/dist/team.d.ts.map +1 -1
- package/dist/team.js +172 -62
- package/dist/team.js.map +1 -1
- package/dist/terminal-web.d.ts +1 -0
- package/dist/terminal-web.d.ts.map +1 -1
- package/dist/terminal-web.js +28 -10
- package/dist/terminal-web.js.map +1 -1
- package/dist/ui/actions.d.ts.map +1 -1
- package/dist/ui/actions.js.map +1 -1
- package/dist/ui/retained-tui.d.ts.map +1 -1
- package/dist/ui/retained-tui.js +231 -173
- package/dist/ui/retained-tui.js.map +1 -1
- package/dist/ui/{prototype-view.d.ts → terminal-view.d.ts} +7 -7
- package/dist/ui/terminal-view.d.ts.map +1 -0
- package/dist/ui/{prototype-view.js → terminal-view.js} +185 -98
- package/dist/ui/terminal-view.js.map +1 -0
- package/dist/web-commands.d.ts.map +1 -1
- package/dist/web-commands.js +160 -57
- package/dist/web-commands.js.map +1 -1
- package/dist/web-extension.d.ts.map +1 -1
- package/dist/web-extension.js +14 -4
- package/dist/web-extension.js.map +1 -1
- package/dist/web-server.d.ts.map +1 -1
- package/dist/web-server.js +2 -1
- package/dist/web-server.js.map +1 -1
- package/dist/web-ui.d.ts.map +1 -1
- package/dist/web-ui.js +167 -40
- package/dist/web-ui.js.map +1 -1
- package/dist/workspace-configuration.d.ts +7 -0
- package/dist/workspace-configuration.d.ts.map +1 -0
- package/dist/workspace-configuration.js +134 -0
- package/dist/workspace-configuration.js.map +1 -0
- package/dist/workspace-state.d.ts +20 -0
- package/dist/workspace-state.d.ts.map +1 -0
- package/dist/workspace-state.js +2 -0
- package/dist/workspace-state.js.map +1 -0
- package/dist/workspace.d.ts +26 -43
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +261 -323
- package/dist/workspace.js.map +1 -1
- package/package.json +21 -31
- package/dist/cli/chunk-7ISOHFS7.js.map +0 -7
- package/dist/cli/chunk-F4XRPLUM.js.map +0 -7
- package/dist/cli/chunk-H7SNBFO4.js +0 -5522
- package/dist/cli/chunk-H7SNBFO4.js.map +0 -7
- package/dist/cli/chunk-HOU5ITUK.js.map +0 -7
- package/dist/cli/chunk-K5JWPNSY.js.map +0 -7
- package/dist/cli/chunk-LVTRXPDS.js.map +0 -7
- package/dist/cli/chunk-VAZMCNBB.js +0 -686
- package/dist/cli/chunk-VAZMCNBB.js.map +0 -7
- package/dist/cli/chunk-WOFEI42C.js +0 -7820
- package/dist/cli/chunk-WOFEI42C.js.map +0 -7
- package/dist/cli/file-type-R2T7TBHI.js.map +0 -7
- package/dist/cli/mcp-auth-UNRHSIKJ.js +0 -63
- package/dist/cli/mcp-auth-UNRHSIKJ.js.map +0 -7
- package/dist/cli/retained-tui-VJ3VX4R3.js.map +0 -7
- package/dist/cli/team-v2-JGBBQ7FR.js.map +0 -7
- package/dist/cli/tui-SA74DKMA.js +0 -1705
- package/dist/cli/tui-SA74DKMA.js.map +0 -7
- package/dist/cli/web-server-FOMNPY7Q.js.map +0 -7
- package/dist/delegation.d.ts +0 -2
- package/dist/delegation.d.ts.map +0 -1
- package/dist/delegation.js +0 -2
- package/dist/delegation.js.map +0 -1
- package/dist/history-memory.d.ts +0 -2
- package/dist/history-memory.d.ts.map +0 -1
- package/dist/history-memory.js +0 -2
- package/dist/history-memory.js.map +0 -1
- package/dist/subagent-budget.d.ts +0 -2
- package/dist/subagent-budget.d.ts.map +0 -1
- package/dist/subagent-budget.js +0 -2
- package/dist/subagent-budget.js.map +0 -1
- package/dist/subagent-files.d.ts +0 -2
- package/dist/subagent-files.d.ts.map +0 -1
- package/dist/subagent-files.js +0 -2
- package/dist/subagent-files.js.map +0 -1
- package/dist/subagent-host.d.ts +0 -2
- package/dist/subagent-host.d.ts.map +0 -1
- package/dist/subagent-host.js +0 -2
- package/dist/subagent-host.js.map +0 -1
- package/dist/subagent-instructions.d.ts +0 -2
- package/dist/subagent-instructions.d.ts.map +0 -1
- package/dist/subagent-instructions.js +0 -2
- package/dist/subagent-instructions.js.map +0 -1
- package/dist/subagents.d.ts +0 -2
- package/dist/subagents.d.ts.map +0 -1
- package/dist/subagents.js +0 -2
- package/dist/subagents.js.map +0 -1
- package/dist/summarizer.d.ts +0 -2
- package/dist/summarizer.d.ts.map +0 -1
- package/dist/summarizer.js +0 -2
- package/dist/summarizer.js.map +0 -1
- package/dist/tui.d.ts +0 -7
- package/dist/tui.d.ts.map +0 -1
- package/dist/tui.js +0 -1109
- package/dist/tui.js.map +0 -1
- package/dist/ui/prototype-view.d.ts.map +0 -1
- package/dist/ui/prototype-view.js.map +0 -1
- /package/dist/cli/{configured-WHY3GGAJ.js.map → configured-ACNM6TRQ.js.map} +0 -0
- /package/dist/cli/{team-T7G7PPNN.js.map → team-O2I5BXHM.js.map} +0 -0
- /package/dist/cli/{web-ui-COB6PKC5.js.map → web-ui-UWQUFE4W.js.map} +0 -0
package/dist/team-v2.js
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { mkdir, open, readFile, realpath,
|
|
2
|
+
import { mkdir, open, readFile, realpath, stat } from "node:fs/promises";
|
|
3
3
|
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
4
|
-
import { defineAgent } from "@sortedyuan/
|
|
5
|
-
import { createEditTool, createReadTool, createWriteTool } from "@sortedyuan/coding-tools";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
4
|
+
import { defineAgent } from "@sortedyuan/may";
|
|
5
|
+
import { createEditTool, createReadTool, createWriteTool, createGlobTool, createGrepTool, createFetchTool, } from "@sortedyuan/coding-tools";
|
|
6
|
+
import { TeamExecutionEnvironments } from "./team-execution.js";
|
|
7
|
+
import { loadMayConfig } from "@sortedyuan/may/config";
|
|
8
|
+
import { CoordinationRuntime, createApplicationAgent, FileArtifactStore, FileSharedBudget, TaskWorkspaceManager, } from "@sortedyuan/coordination";
|
|
8
9
|
import { FileCoordinationStore } from "@sortedyuan/coordination/file-store";
|
|
9
|
-
import { resolveRunBudget } from "@sortedyuan/core";
|
|
10
|
-
import { FileSessionStore } from "@sortedyuan/session/file-store";
|
|
11
|
-
import { withFileAccess } from "@sortedyuan/
|
|
12
|
-
import
|
|
10
|
+
import { resolveRunBudget } from "@sortedyuan/may/core";
|
|
11
|
+
import { FileSessionStore } from "@sortedyuan/may/session/file-store";
|
|
12
|
+
import { hasErrorCode, withFileAccess } from "@sortedyuan/may/storage";
|
|
13
|
+
import writeFileAtomic from "write-file-atomic";
|
|
14
|
+
import { getDefaultMaybeCodeDataDirectory, resolveMaybeCodeRecording } from "./configured.js";
|
|
15
|
+
import { readMaybeCodeSettings } from "./settings.js";
|
|
13
16
|
import { createMaybeCodeModel, selectMaybeCodeModel } from "./model.js";
|
|
14
17
|
import { createListTool } from "./team.js";
|
|
15
|
-
import { createTeamPreset, loadTeamPlan, parseTeamPlan } from "./team-plan.js";
|
|
18
|
+
import { createTeamPreset, loadTeamPlan, parseTeamPlan, } from "./team-plan.js";
|
|
16
19
|
import { TeamVerificationStore } from "./team-verification.js";
|
|
17
20
|
import { inspectTeam, readTeamResolution, retryImpact, teamReviewDigest } from "./team-recovery.js";
|
|
18
21
|
import { applyTeamPatch, createTeamPatch, readTeamPatch, renderTeamPatchDiff } from "./team-patches.js";
|
|
@@ -35,21 +38,43 @@ export async function runTeamV2Command(command, dependencies) {
|
|
|
35
38
|
if (!(await stat(workspace)).isDirectory() || inside(workspace, directory) || inside(directory, workspace))
|
|
36
39
|
throw new Error("Team data directory must be outside and not overlap the source workspace");
|
|
37
40
|
const mode = command.mode ?? "read-only";
|
|
38
|
-
const plan = command.planPath
|
|
39
|
-
|
|
41
|
+
const plan = command.planPath
|
|
42
|
+
? await loadTeamPlan(command.planPath, { mode })
|
|
43
|
+
: createTeamPreset(command.preset ?? "supervisor", command.value, {
|
|
44
|
+
mode,
|
|
45
|
+
...(command.model ? { model: command.model } : {}),
|
|
46
|
+
});
|
|
40
47
|
config = await (dependencies.loadConfig ?? loadMayConfig)(command.configPath ? { path: command.configPath } : {});
|
|
41
|
-
const fallback = command.model ??
|
|
48
|
+
const fallback = command.model ??
|
|
49
|
+
(Object.values(plan.roles).every((role) => role.model !== undefined)
|
|
50
|
+
? Object.values(plan.roles)[0].model
|
|
51
|
+
: undefined);
|
|
42
52
|
const defaultModel = selectMaybeCodeModel(config, fallback ? { model: fallback } : {});
|
|
43
53
|
const roleModels = {};
|
|
44
54
|
for (const [name, role] of Object.entries(plan.roles)) {
|
|
45
55
|
const selected = selectMaybeCodeModel(config, { model: role.model ?? defaultModel.profile });
|
|
46
|
-
const runBudget = resolveRunBudget(resolveRunBudget(config.
|
|
56
|
+
const runBudget = resolveRunBudget(resolveRunBudget(readMaybeCodeSettings(config).runBudget, DEFAULT_RUN_BUDGET), role.runBudget);
|
|
47
57
|
roleModels[name] = { profile: selected.profile, fingerprint: modelFingerprint(selected), runBudget };
|
|
48
58
|
}
|
|
49
|
-
manifest = {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
59
|
+
manifest = {
|
|
60
|
+
execution: readMaybeCodeSettings(config).execution ?? { mode: "host" },
|
|
61
|
+
fetch: readMaybeCodeSettings(config).fetch ?? {},
|
|
62
|
+
format: 1,
|
|
63
|
+
version: VERSION,
|
|
64
|
+
id,
|
|
65
|
+
createdAt: new Date().toISOString(),
|
|
66
|
+
workspace,
|
|
67
|
+
configPath: resolve(config.path),
|
|
68
|
+
model: defaultModel.profile,
|
|
69
|
+
prompt: command.value,
|
|
70
|
+
mode,
|
|
71
|
+
allowChecks: command.allowChecks === true,
|
|
72
|
+
plan,
|
|
73
|
+
roleModels,
|
|
74
|
+
maxModelCalls: command.maxModelCalls ?? 32,
|
|
75
|
+
maxTotalTokens: command.maxTotalTokens ?? 524_288,
|
|
76
|
+
maxConcurrent: command.maxConcurrent ?? plan.limits?.maxConcurrent ?? 2,
|
|
77
|
+
};
|
|
53
78
|
validateManifest(manifest, id);
|
|
54
79
|
await mkdir(directory, { recursive: true, mode: 0o700 });
|
|
55
80
|
await writeJson(join(directory, "manifest.json"), manifest, true);
|
|
@@ -69,7 +94,7 @@ export async function runTeamV2Command(command, dependencies) {
|
|
|
69
94
|
write(`Last acceptance projection (may be stale): ${await withFileAccess(path, "shared", () => readFile(path, "utf8"))}\n`);
|
|
70
95
|
}
|
|
71
96
|
catch (error) {
|
|
72
|
-
if (!
|
|
97
|
+
if (!hasErrorCode(error, "ENOENT"))
|
|
73
98
|
throw error;
|
|
74
99
|
}
|
|
75
100
|
return 0;
|
|
@@ -81,8 +106,10 @@ export async function runTeamV2Command(command, dependencies) {
|
|
|
81
106
|
}
|
|
82
107
|
const executes = command.action === "run" || command.action === "resume";
|
|
83
108
|
const selections = new Map();
|
|
109
|
+
let recording;
|
|
84
110
|
if (executes) {
|
|
85
111
|
config ??= await (dependencies.loadConfig ?? loadMayConfig)({ path: manifest.configPath });
|
|
112
|
+
recording = resolveMaybeCodeRecording(config);
|
|
86
113
|
for (const [name, binding] of Object.entries(manifest.roleModels)) {
|
|
87
114
|
const selected = selectMaybeCodeModel(config, { model: binding.profile });
|
|
88
115
|
if (modelFingerprint(selected) !== binding.fingerprint)
|
|
@@ -91,6 +118,13 @@ export async function runTeamV2Command(command, dependencies) {
|
|
|
91
118
|
}
|
|
92
119
|
}
|
|
93
120
|
const ledger = await FileSharedBudget.open(join(directory, "budget"), id, budgetLimits);
|
|
121
|
+
const settings = readMaybeCodeSettings({
|
|
122
|
+
providers: {},
|
|
123
|
+
models: {},
|
|
124
|
+
path: manifest.configPath,
|
|
125
|
+
apps: { maybecode: { execution: manifest.execution ?? { mode: "host" }, fetch: manifest.fetch ?? {} } },
|
|
126
|
+
});
|
|
127
|
+
const executionEnvironments = new TeamExecutionEnvironments(settings.execution);
|
|
94
128
|
let workspaces;
|
|
95
129
|
let artifacts;
|
|
96
130
|
let verification;
|
|
@@ -99,13 +133,46 @@ export async function runTeamV2Command(command, dependencies) {
|
|
|
99
133
|
let timer;
|
|
100
134
|
let cancelling;
|
|
101
135
|
let retryAuthorized = false;
|
|
102
|
-
const
|
|
103
|
-
|
|
136
|
+
const backgroundTasks = new Set();
|
|
137
|
+
const backgroundErrors = [];
|
|
138
|
+
let failBackground;
|
|
139
|
+
const backgroundFailed = new Promise((resolve) => {
|
|
140
|
+
failBackground = resolve;
|
|
141
|
+
});
|
|
142
|
+
const trackBackground = (operation) => {
|
|
143
|
+
const task = operation.then(() => {
|
|
144
|
+
backgroundTasks.delete(task);
|
|
145
|
+
}, (error) => {
|
|
146
|
+
backgroundTasks.delete(task);
|
|
147
|
+
backgroundErrors.push(error);
|
|
148
|
+
failBackground(error);
|
|
149
|
+
cancel();
|
|
150
|
+
});
|
|
151
|
+
backgroundTasks.add(task);
|
|
152
|
+
};
|
|
153
|
+
const cancel = () => {
|
|
154
|
+
if (runtime && !cancelling) {
|
|
155
|
+
cancelling = runtime.cancel(`cancel-${id}`);
|
|
156
|
+
trackBackground(cancelling);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
104
159
|
try {
|
|
105
|
-
artifacts = await FileArtifactStore.open(join(directory, "artifacts"), id, {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
160
|
+
artifacts = await FileArtifactStore.open(join(directory, "artifacts"), id, {
|
|
161
|
+
policyVersion: VERSION,
|
|
162
|
+
authorizeRead: () => true,
|
|
163
|
+
maxArtifacts: 256,
|
|
164
|
+
maxArtifactBytes: 262_144,
|
|
165
|
+
maxTotalBytes: 16_777_216,
|
|
166
|
+
});
|
|
167
|
+
workspaces = await TaskWorkspaceManager.open({
|
|
168
|
+
sourceDirectory: manifest.workspace,
|
|
169
|
+
directory: join(directory, "workspaces"),
|
|
170
|
+
});
|
|
171
|
+
verification = await TeamVerificationStore.open({
|
|
172
|
+
directory: join(directory, "verification"),
|
|
173
|
+
checks: manifest.plan.checks,
|
|
174
|
+
executionFor: (workspace) => executionEnvironments.get(workspace),
|
|
175
|
+
});
|
|
109
176
|
const sessionStore = new FileSessionStore(join(directory, "sessions"));
|
|
110
177
|
const models = new Map();
|
|
111
178
|
const modelFor = (name) => {
|
|
@@ -115,42 +182,86 @@ export async function runTeamV2Command(command, dependencies) {
|
|
|
115
182
|
if (!selected)
|
|
116
183
|
throw new Error("A host control command cannot start a model");
|
|
117
184
|
const maxOutputTokens = Math.min(4096, selected.limits?.maxOutputTokens ?? 4096, ...[selected.options.maxTokens, selected.options.maxOutputTokens].filter((n) => typeof n === "number" && n > 0 && Number.isSafeInteger(n)));
|
|
118
|
-
const selection = {
|
|
119
|
-
|
|
120
|
-
|
|
185
|
+
const selection = {
|
|
186
|
+
...selected,
|
|
187
|
+
options: { ...selected.options, maxTokens: maxOutputTokens, maxOutputTokens },
|
|
188
|
+
limits: { ...selected.limits, maxOutputTokens },
|
|
189
|
+
};
|
|
190
|
+
model = ledger.wrapModel((dependencies.createModel ?? createMaybeCodeModel)(selection), {
|
|
191
|
+
reservation: { totalTokens: RESERVATION },
|
|
192
|
+
});
|
|
121
193
|
models.set(name, model);
|
|
122
194
|
}
|
|
123
195
|
return model;
|
|
124
196
|
};
|
|
125
197
|
const agents = {};
|
|
126
198
|
for (const [name, role] of Object.entries(manifest.plan.roles)) {
|
|
127
|
-
const scoped = (execution, workspace) =>
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
199
|
+
const scoped = async (execution, workspace) => {
|
|
200
|
+
const environment = await executionEnvironments.get(workspace);
|
|
201
|
+
return createApplicationAgent({
|
|
202
|
+
version: authorityVersion,
|
|
203
|
+
store: sessionStore,
|
|
204
|
+
delegation: role.delegateTo.length > 0,
|
|
205
|
+
messaging: role.messaging,
|
|
206
|
+
definition: ({ tools }) => {
|
|
207
|
+
const available = [
|
|
208
|
+
createReadTool({ cwd: workspace, maxBytes: 262_144, maxLines: 160 }),
|
|
209
|
+
createGlobTool({ cwd: workspace, execution: environment }),
|
|
210
|
+
createGrepTool({ cwd: workspace, execution: environment }),
|
|
211
|
+
createFetchTool(settings?.fetch ?? {}),
|
|
212
|
+
createListTool(workspace),
|
|
213
|
+
...artifacts.forTask(execution.task.id).tools(),
|
|
214
|
+
...verification.forTask(execution, workspace, { allowCommands: manifest.allowChecks }).tools(),
|
|
215
|
+
...(manifest.mode === "coding"
|
|
216
|
+
? [
|
|
217
|
+
createWriteTool({ cwd: workspace, maxBytes: 262_144 }),
|
|
218
|
+
createEditTool({ cwd: workspace, maxBytes: 262_144 }),
|
|
219
|
+
]
|
|
220
|
+
: []),
|
|
221
|
+
];
|
|
222
|
+
const selectedTools = available
|
|
223
|
+
.filter((tool) => role.tools.includes(tool.name))
|
|
224
|
+
.map((tool) => {
|
|
225
|
+
if (!["write", "edit"].includes(tool.name))
|
|
226
|
+
return tool;
|
|
227
|
+
return {
|
|
228
|
+
...tool,
|
|
229
|
+
async execute(input, context) {
|
|
230
|
+
if ((await verification.snapshot()).checks.some((check) => check.status === "unknown" ||
|
|
231
|
+
(check.taskId === execution.task.id && check.status === "pending")))
|
|
232
|
+
throw new Error("Pending or unknown check effects block editing; stop and reconcile uncertain processes first");
|
|
233
|
+
return tool.execute(input, context);
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
});
|
|
237
|
+
const allowed = new Set([...selectedTools, ...tools].map((tool) => tool.name));
|
|
238
|
+
const roleBudget = manifest.roleModels[name].runBudget;
|
|
239
|
+
const budget = config ? resolveRunBudget(roleBudget, readMaybeCodeSettings(config).runBudget) : roleBudget;
|
|
240
|
+
if (!recording)
|
|
241
|
+
throw new Error("A host control command cannot start a model");
|
|
242
|
+
return defineAgent({
|
|
243
|
+
...recording,
|
|
244
|
+
model: modelFor(name),
|
|
245
|
+
tools: [...selectedTools, ...tools],
|
|
246
|
+
runBudget: budget,
|
|
247
|
+
instructions: instructions(manifest, name, role),
|
|
248
|
+
toolScope: { workspaceId: workspace },
|
|
249
|
+
permissionPolicy: (check) => (allowed.has(check.tool.name) ? "allow" : "deny"),
|
|
250
|
+
});
|
|
251
|
+
},
|
|
252
|
+
});
|
|
253
|
+
};
|
|
150
254
|
const publish = async (execution, output) => {
|
|
151
|
-
await artifacts
|
|
255
|
+
await artifacts
|
|
256
|
+
.forTask(execution.task.id)
|
|
257
|
+
.publish(`${execution.task.dispatchId}-${execution.task.turn ?? 0}-final`, {
|
|
258
|
+
name: `${execution.task.id.slice(0, 100)}-result.md`,
|
|
259
|
+
text: output.text,
|
|
260
|
+
mimeType: "text/markdown",
|
|
261
|
+
});
|
|
152
262
|
};
|
|
153
|
-
agents[name] = {
|
|
263
|
+
agents[name] = {
|
|
264
|
+
version: authorityVersion,
|
|
154
265
|
async execute(execution, context) {
|
|
155
266
|
if ((await verification.snapshot()).checks.some((check) => check.status === "unknown"))
|
|
156
267
|
throw new Error("Unknown check effects block a new Agent Run; reconcile before retrying");
|
|
@@ -159,15 +270,25 @@ export async function runTeamV2Command(command, dependencies) {
|
|
|
159
270
|
for (const dependency of execution.dependencies) {
|
|
160
271
|
const source = await workspaces.prepare(dependency.taskId);
|
|
161
272
|
const acceptance = await verification.acceptance(dependency.taskId, source.directory, executionOf(runtime.snapshot(), dependency.taskId));
|
|
162
|
-
const record = {
|
|
163
|
-
|
|
273
|
+
const record = {
|
|
274
|
+
taskId: dependency.taskId,
|
|
275
|
+
status: acceptance.status,
|
|
276
|
+
workspaceFingerprint: acceptance.workspaceFingerprint,
|
|
277
|
+
checks: acceptance.checks.slice(0, 16),
|
|
278
|
+
checksTruncated: acceptance.checks.length > 16,
|
|
164
279
|
evidenceValid: acceptance.report?.evidence.every((item) => item.valid) ?? false,
|
|
165
|
-
detail: acceptance.detail
|
|
166
|
-
|
|
167
|
-
|
|
280
|
+
detail: acceptance.detail,
|
|
281
|
+
};
|
|
282
|
+
dependencyResults.push({
|
|
283
|
+
...dependency,
|
|
284
|
+
output: {
|
|
285
|
+
...dependency.output,
|
|
286
|
+
text: `${dependency.output.text}\n\nHost verification record (scoped to that task's private workspace, not the source checkout or every claim):\n${JSON.stringify(record)}`,
|
|
287
|
+
},
|
|
288
|
+
});
|
|
168
289
|
}
|
|
169
290
|
const submitted = { ...execution, dependencies: dependencyResults };
|
|
170
|
-
const output = await scoped(submitted, isolated.directory).execute(submitted, context);
|
|
291
|
+
const output = await (await scoped(submitted, isolated.directory)).execute(submitted, context);
|
|
171
292
|
if (!("yielded" in output)) {
|
|
172
293
|
await publish(execution, output);
|
|
173
294
|
// Only deterministic file checks run automatically; command checks need explicit invocation.
|
|
@@ -178,24 +299,35 @@ export async function runTeamV2Command(command, dependencies) {
|
|
|
178
299
|
return output;
|
|
179
300
|
},
|
|
180
301
|
async recover(execution) {
|
|
181
|
-
const output = await scoped(execution, manifest.workspace).recover(execution);
|
|
302
|
+
const output = await (await scoped(execution, manifest.workspace)).recover(execution);
|
|
182
303
|
if (output.status === "completed")
|
|
183
304
|
await publish(execution, output.output);
|
|
184
305
|
return output;
|
|
185
|
-
},
|
|
306
|
+
},
|
|
307
|
+
};
|
|
186
308
|
}
|
|
187
|
-
const options = {
|
|
188
|
-
|
|
309
|
+
const options = {
|
|
310
|
+
id,
|
|
311
|
+
store: new FileCoordinationStore(join(directory, "coordination")),
|
|
312
|
+
agents,
|
|
313
|
+
policy: {
|
|
314
|
+
version: authorityVersion,
|
|
189
315
|
authorize: (task) => Object.hasOwn(manifest.plan.roles, task.agent),
|
|
190
316
|
authorizeDelegation: (parent, child) => manifest.plan.roles[parent.agent]?.delegateTo.includes(child.agent) === true,
|
|
191
|
-
authorizeMessage: (sender, recipient) => manifest.plan.roles[sender.agent]?.messaging === true &&
|
|
317
|
+
authorizeMessage: (sender, recipient) => manifest.plan.roles[sender.agent]?.messaging === true &&
|
|
318
|
+
manifest.plan.roles[recipient.agent]?.messaging === true,
|
|
192
319
|
authorizeRetry: (task, finding) => {
|
|
193
320
|
if (retryAuthorized)
|
|
194
321
|
return true;
|
|
195
322
|
// Dispatch rechecks the exact durable host approval, not an ephemeral CLI flag.
|
|
196
323
|
const state = runtime?.snapshot(), current = state?.tasks.find((entry) => entry.id === task.id);
|
|
197
324
|
const previous = current?.attempts?.at(-1);
|
|
198
|
-
if (current?.status !== "queued" ||
|
|
325
|
+
if (current?.status !== "queued" ||
|
|
326
|
+
!previous ||
|
|
327
|
+
previous.task.dispatchId !== task.dispatchId ||
|
|
328
|
+
previous.task.sessionId !== task.sessionId ||
|
|
329
|
+
previous.finding !== finding ||
|
|
330
|
+
!/^retry-[a-f0-9]{64}$/u.test(previous.commandId))
|
|
199
331
|
return false;
|
|
200
332
|
const receipt = state?.commands[previous.commandId];
|
|
201
333
|
if (!receipt)
|
|
@@ -203,10 +335,26 @@ export async function runTeamV2Command(command, dependencies) {
|
|
|
203
335
|
const value = JSON.parse(receipt);
|
|
204
336
|
return value.type === "retry" && value.taskId === task.id && value.finding === finding;
|
|
205
337
|
},
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
338
|
+
},
|
|
339
|
+
};
|
|
340
|
+
runtime =
|
|
341
|
+
command.action === "run"
|
|
342
|
+
? await CoordinationRuntime.create({
|
|
343
|
+
...options,
|
|
344
|
+
tasks: manifest.plan.tasks,
|
|
345
|
+
limits: {
|
|
346
|
+
maxTasks: 128,
|
|
347
|
+
maxDepth: 2,
|
|
348
|
+
maxTaskTurns: 4,
|
|
349
|
+
maxDurationMs: 600_000,
|
|
350
|
+
maxOutputBytes: 65_536,
|
|
351
|
+
maxMessages: 24,
|
|
352
|
+
maxMessageBytes: 8192,
|
|
353
|
+
...manifest.plan.limits,
|
|
354
|
+
maxConcurrent: manifest.maxConcurrent,
|
|
355
|
+
},
|
|
356
|
+
})
|
|
357
|
+
: await CoordinationRuntime.resume(options);
|
|
210
358
|
write(`Team ${id}\nMode: ${manifest.mode}; source application requires a separate reviewed patch confirmation.\nRecords: ${directory}\n`);
|
|
211
359
|
if (manifest.allowChecks)
|
|
212
360
|
write("Configured test processes explicitly authorized; no OS sandbox or automatic dependency installation.\n");
|
|
@@ -220,16 +368,20 @@ export async function runTeamV2Command(command, dependencies) {
|
|
|
220
368
|
write(`[${task.id}] ${task.status}${task.detail ? `: ${task.detail}` : ""}\n`);
|
|
221
369
|
}
|
|
222
370
|
}
|
|
223
|
-
else if (event.type === "agent.event" &&
|
|
371
|
+
else if (event.type === "agent.event" &&
|
|
372
|
+
event.event.type === "run.event" &&
|
|
373
|
+
event.event.event.type === "tool.started")
|
|
224
374
|
write(`[${event.taskId}] tool ${event.event.event.call.name}\n`);
|
|
225
375
|
else if (event.type === "runtime.failed")
|
|
226
376
|
write("Team runtime failed; inspect recovery records.\n");
|
|
227
377
|
}
|
|
228
378
|
})();
|
|
229
|
-
|
|
379
|
+
trackBackground(relay);
|
|
230
380
|
if (command.action === "retry" || command.action === "reconcile") {
|
|
231
381
|
const state = runtime.snapshot(), budget = await ledger.snapshot(), checks = await verification.snapshot();
|
|
232
|
-
const operation = command.action === "retry"
|
|
382
|
+
const operation = command.action === "retry"
|
|
383
|
+
? retryImpact(state, command.task, command.finding)
|
|
384
|
+
: await readTeamResolution(command.resolutionPath);
|
|
233
385
|
// Resume may repeat evidence inspection and increment revision without changing meaning.
|
|
234
386
|
const { revision: _revision, ...stableState } = state;
|
|
235
387
|
const digest = teamReviewDigest({ operation, state: stableState, budget, checks });
|
|
@@ -241,7 +393,8 @@ export async function runTeamV2Command(command, dependencies) {
|
|
|
241
393
|
if (command.confirm !== digest)
|
|
242
394
|
throw new Error("Review digest changed or mismatched; inspect a fresh preview");
|
|
243
395
|
if (command.action === "retry") {
|
|
244
|
-
if ((await ledger.totals()).blocked ||
|
|
396
|
+
if ((await ledger.totals()).blocked ||
|
|
397
|
+
checks.checks.some((check) => ["unknown", "pending"].includes(check.status)))
|
|
245
398
|
throw new Error("Reconcile unknown usage/check effects before retrying; no reset or replay is allowed");
|
|
246
399
|
retryAuthorized = true;
|
|
247
400
|
await runtime.retryTask(`retry-${digest}`, command.task, command.finding);
|
|
@@ -253,7 +406,10 @@ export async function runTeamV2Command(command, dependencies) {
|
|
|
253
406
|
else if (resolution.kind === "check")
|
|
254
407
|
await verification.reconcile(resolution.commandId, { status: resolution.outcome }, resolution.finding);
|
|
255
408
|
else
|
|
256
|
-
await runtime.resolveRecovery(`resolve-${digest}`, resolution.taskId, resolution.finding, {
|
|
409
|
+
await runtime.resolveRecovery(`resolve-${digest}`, resolution.taskId, resolution.finding, {
|
|
410
|
+
status: resolution.outcome,
|
|
411
|
+
detail: resolution.finding,
|
|
412
|
+
});
|
|
257
413
|
}
|
|
258
414
|
write("Recorded. No agents or checks executed. Use team resume explicitly when ready.\n");
|
|
259
415
|
return 0;
|
|
@@ -266,7 +422,9 @@ export async function runTeamV2Command(command, dependencies) {
|
|
|
266
422
|
throw new Error("Settle all active/unknown team work before reviewing or applying a patch");
|
|
267
423
|
if (command.action === "diff") {
|
|
268
424
|
const taskIds = command.tasks.split(",");
|
|
269
|
-
if (!taskIds.length ||
|
|
425
|
+
if (!taskIds.length ||
|
|
426
|
+
new Set(taskIds).size !== taskIds.length ||
|
|
427
|
+
taskIds.some((id) => state.tasks.find((task) => task.id === id)?.status !== "completed"))
|
|
270
428
|
throw new Error("Select distinct completed task ids for review");
|
|
271
429
|
const patch = await createTeamPatch({ directory, workspaces, taskIds });
|
|
272
430
|
write(renderTeamPatchDiff(patch));
|
|
@@ -274,22 +432,31 @@ export async function runTeamV2Command(command, dependencies) {
|
|
|
274
432
|
return 0;
|
|
275
433
|
}
|
|
276
434
|
const patch = await readTeamPatch(directory, command.patch);
|
|
277
|
-
const uncheckedTasks = patch.taskSnapshots
|
|
435
|
+
const uncheckedTasks = patch.taskSnapshots
|
|
436
|
+
.map((task) => task.taskId)
|
|
437
|
+
.filter((taskId) => !manifest.plan.checks.some((check) => check.taskId === taskId));
|
|
278
438
|
if (uncheckedTasks.length)
|
|
279
439
|
write(`Unverified patch tasks (human review only): ${uncheckedTasks.join(", ")}. Other tasks' passing checks do not verify these edits.\n`);
|
|
280
|
-
if ((await ledger.totals()).blocked ||
|
|
440
|
+
if ((await ledger.totals()).blocked ||
|
|
441
|
+
(await verification.snapshot()).checks.some((check) => ["pending", "unknown"].includes(check.status)))
|
|
281
442
|
throw new Error("Reconcile unknown team effects before applying source changes");
|
|
282
443
|
for (const checkTaskId of new Set(manifest.plan.checks.map((check) => check.taskId))) {
|
|
283
444
|
const task = state.tasks.find((task) => task.id === checkTaskId);
|
|
284
445
|
if (task?.status !== "completed")
|
|
285
446
|
throw new Error("All configured acceptance tasks must complete before source application");
|
|
286
447
|
const workspace = await workspaces.prepare(checkTaskId);
|
|
287
|
-
if ((await verification.acceptance(checkTaskId, workspace.directory, executionOf(state, checkTaskId))).status !==
|
|
448
|
+
if ((await verification.acceptance(checkTaskId, workspace.directory, executionOf(state, checkTaskId))).status !==
|
|
449
|
+
"passed")
|
|
288
450
|
throw new Error(`Acceptance is not passed/current for ${checkTaskId}; use team verify and inspect reports`);
|
|
289
451
|
}
|
|
290
452
|
if (!manifest.plan.checks.length)
|
|
291
453
|
write("No configured acceptance checks: this is an explicit human-reviewed, unverified source application.\n");
|
|
292
|
-
const result = await applyTeamPatch({
|
|
454
|
+
const result = await applyTeamPatch({
|
|
455
|
+
directory,
|
|
456
|
+
workspaces,
|
|
457
|
+
patchId: patch.id,
|
|
458
|
+
confirmDigest: command.confirm,
|
|
459
|
+
});
|
|
293
460
|
write(`${JSON.stringify(result, null, 2)}\n`);
|
|
294
461
|
return result.status === "applied" ? 0 : 1;
|
|
295
462
|
}
|
|
@@ -305,14 +472,16 @@ export async function runTeamV2Command(command, dependencies) {
|
|
|
305
472
|
controller.abort("Team verification cancelled");
|
|
306
473
|
}
|
|
307
474
|
catch (error) {
|
|
308
|
-
if (!
|
|
475
|
+
if (!hasErrorCode(error, "ENOENT")) {
|
|
309
476
|
controller.abort("Cannot establish cancellation state");
|
|
310
477
|
throw error;
|
|
311
478
|
}
|
|
312
479
|
}
|
|
313
480
|
};
|
|
314
481
|
await observeCancellation();
|
|
315
|
-
timer = setInterval(() => {
|
|
482
|
+
timer = setInterval(() => {
|
|
483
|
+
trackBackground(observeCancellation());
|
|
484
|
+
}, 300);
|
|
316
485
|
const state = runtime.snapshot();
|
|
317
486
|
for (const check of manifest.plan.checks) {
|
|
318
487
|
if (signal.aborted) {
|
|
@@ -324,7 +493,11 @@ export async function runTeamV2Command(command, dependencies) {
|
|
|
324
493
|
continue;
|
|
325
494
|
}
|
|
326
495
|
const workspace = await workspaces.prepare(check.taskId);
|
|
327
|
-
const result = await verification.runCheck(`host-${randomUUID()}`, check, workspace.directory, {
|
|
496
|
+
const result = await verification.runCheck(`host-${randomUUID()}`, check, workspace.directory, {
|
|
497
|
+
allowCommands: manifest.allowChecks,
|
|
498
|
+
signal,
|
|
499
|
+
execution: executionOf(state, check.taskId),
|
|
500
|
+
});
|
|
328
501
|
write(`Check ${check.id}: ${result.status}${result.detail ? ` (${result.detail})` : ""}\n`);
|
|
329
502
|
}
|
|
330
503
|
const acceptance = await summarizeAcceptance(directory, state, manifest, workspaces, verification);
|
|
@@ -338,7 +511,7 @@ export async function runTeamV2Command(command, dependencies) {
|
|
|
338
511
|
cancel();
|
|
339
512
|
}
|
|
340
513
|
catch (error) {
|
|
341
|
-
if (!
|
|
514
|
+
if (!hasErrorCode(error, "ENOENT")) {
|
|
342
515
|
cancel();
|
|
343
516
|
throw error;
|
|
344
517
|
}
|
|
@@ -348,13 +521,21 @@ export async function runTeamV2Command(command, dependencies) {
|
|
|
348
521
|
await checkCancellation();
|
|
349
522
|
if (dependencies.signal?.aborted)
|
|
350
523
|
cancel();
|
|
351
|
-
timer = setInterval(() => {
|
|
524
|
+
timer = setInterval(() => {
|
|
525
|
+
trackBackground(checkCancellation());
|
|
526
|
+
}, 300);
|
|
352
527
|
await cancelling;
|
|
353
|
-
if ((await ledger.totals()).blocked ||
|
|
528
|
+
if ((await ledger.totals()).blocked ||
|
|
529
|
+
(await verification.snapshot()).checks.some((check) => check.status === "unknown")) {
|
|
354
530
|
write("Unknown usage/check effects or exceeded budget block execution. No new Run started; inspect and reconcile explicitly.\n");
|
|
355
531
|
return 1;
|
|
356
532
|
}
|
|
357
|
-
const result = await
|
|
533
|
+
const result = await Promise.race([
|
|
534
|
+
runtime.wait(),
|
|
535
|
+
backgroundFailed.then((error) => {
|
|
536
|
+
throw error;
|
|
537
|
+
}),
|
|
538
|
+
]);
|
|
358
539
|
await cancelling;
|
|
359
540
|
const final = result.tasks.find((task) => task.id === manifest.plan.resultTaskId);
|
|
360
541
|
if (final?.output?.text)
|
|
@@ -376,11 +557,26 @@ export async function runTeamV2Command(command, dependencies) {
|
|
|
376
557
|
clearInterval(timer);
|
|
377
558
|
dependencies.signal?.removeEventListener("abort", cancel);
|
|
378
559
|
try {
|
|
379
|
-
await runtime
|
|
380
|
-
|
|
560
|
+
const results = await Promise.allSettled([...(runtime ? [runtime.close()] : []), ...(relay ? [relay] : [])]);
|
|
561
|
+
while (backgroundTasks.size)
|
|
562
|
+
await Promise.all(backgroundTasks);
|
|
563
|
+
const failures = [
|
|
564
|
+
...new Set([
|
|
565
|
+
...backgroundErrors,
|
|
566
|
+
...results.flatMap((result) => (result.status === "rejected" ? [result.reason] : [])),
|
|
567
|
+
]),
|
|
568
|
+
];
|
|
569
|
+
if (failures.length)
|
|
570
|
+
throw new AggregateError(failures, "Team background operations failed");
|
|
381
571
|
}
|
|
382
572
|
finally {
|
|
383
|
-
await Promise.all([
|
|
573
|
+
await Promise.all([
|
|
574
|
+
verification?.close(),
|
|
575
|
+
workspaces?.close(),
|
|
576
|
+
artifacts?.close(),
|
|
577
|
+
ledger.close(),
|
|
578
|
+
executionEnvironments.close(),
|
|
579
|
+
]);
|
|
384
580
|
}
|
|
385
581
|
}
|
|
386
582
|
}
|
|
@@ -403,14 +599,33 @@ async function summarizeAcceptance(directory, state, manifest, workspaces, verif
|
|
|
403
599
|
}
|
|
404
600
|
const required = [...new Set(manifest.plan.checks.map((check) => check.taskId))];
|
|
405
601
|
const failed = Object.values(tasks).some((task) => task.status === "failed");
|
|
406
|
-
const status = failed
|
|
407
|
-
|
|
602
|
+
const status = failed
|
|
603
|
+
? "failed"
|
|
604
|
+
: required.length &&
|
|
605
|
+
state.tasks.every((task) => task.status === "completed") &&
|
|
606
|
+
required.every((id) => tasks[id]?.status === "passed")
|
|
607
|
+
? "passed"
|
|
608
|
+
: "unverified";
|
|
609
|
+
const result = {
|
|
610
|
+
format: 1,
|
|
611
|
+
revision: state.revision,
|
|
612
|
+
status,
|
|
613
|
+
tasks,
|
|
614
|
+
note: "Scoped configured checks only, not proof of every natural-language claim. Verify rechecks exact workspace fingerprints.",
|
|
615
|
+
};
|
|
408
616
|
await writeJson(join(directory, "acceptance.json"), result);
|
|
409
617
|
return result;
|
|
410
618
|
}
|
|
411
619
|
function modelFingerprint(selection) {
|
|
412
|
-
return teamReviewDigest({
|
|
413
|
-
|
|
620
|
+
return teamReviewDigest({
|
|
621
|
+
profile: selection.profile,
|
|
622
|
+
provider: selection.provider,
|
|
623
|
+
adapter: selection.adapter,
|
|
624
|
+
model: selection.model,
|
|
625
|
+
options: selection.options,
|
|
626
|
+
baseURL: selection.providerConfig.baseURL,
|
|
627
|
+
limits: selection.limits,
|
|
628
|
+
});
|
|
414
629
|
}
|
|
415
630
|
async function readManifest(directory, id) {
|
|
416
631
|
const path = join(directory, "manifest.json");
|
|
@@ -423,10 +638,22 @@ async function readManifest(directory, id) {
|
|
|
423
638
|
});
|
|
424
639
|
}
|
|
425
640
|
function validateManifest(value, id) {
|
|
426
|
-
if (!value ||
|
|
641
|
+
if (!value ||
|
|
642
|
+
value.format !== 1 ||
|
|
643
|
+
value.version !== VERSION ||
|
|
644
|
+
value.id !== id ||
|
|
645
|
+
!isAbsolute(value.workspace) ||
|
|
646
|
+
!isAbsolute(value.configPath) ||
|
|
647
|
+
typeof value.prompt !== "string" ||
|
|
648
|
+
typeof value.model !== "string" ||
|
|
649
|
+
!["coding", "read-only"].includes(value.mode) ||
|
|
650
|
+
typeof value.allowChecks !== "boolean")
|
|
427
651
|
throw new Error("Invalid v2 team manifest");
|
|
428
652
|
parseTeamPlan(value.plan, { mode: value.mode });
|
|
429
|
-
if (![value.maxModelCalls, value.maxTotalTokens, value.maxConcurrent].every((n) => Number.isSafeInteger(n) && n > 0) ||
|
|
653
|
+
if (![value.maxModelCalls, value.maxTotalTokens, value.maxConcurrent].every((n) => Number.isSafeInteger(n) && n > 0) ||
|
|
654
|
+
value.maxModelCalls > 10_000 ||
|
|
655
|
+
value.maxConcurrent > 8 ||
|
|
656
|
+
value.maxTotalTokens < RESERVATION)
|
|
430
657
|
throw new Error("Invalid team limits; token budget must hold at least 32768 tokens");
|
|
431
658
|
if (!value.roleModels || Object.keys(value.roleModels).length !== Object.keys(value.plan.roles).length)
|
|
432
659
|
throw new Error("Invalid role model bindings");
|
|
@@ -438,27 +665,30 @@ function validateManifest(value, id) {
|
|
|
438
665
|
}
|
|
439
666
|
}
|
|
440
667
|
async function writeJson(path, value, exclusive = false) {
|
|
668
|
+
const contents = `${JSON.stringify(value, null, 2)}\n`;
|
|
441
669
|
await withFileAccess(path, "exclusive", async () => {
|
|
442
|
-
|
|
443
|
-
|
|
670
|
+
if (!exclusive)
|
|
671
|
+
return writeFileAtomic(path, contents, { mode: 0o600 });
|
|
672
|
+
const file = await open(path, "wx", 0o600);
|
|
444
673
|
try {
|
|
445
|
-
await file.writeFile(
|
|
674
|
+
await file.writeFile(contents);
|
|
446
675
|
await file.sync();
|
|
447
676
|
}
|
|
448
677
|
finally {
|
|
449
678
|
await file.close();
|
|
450
679
|
}
|
|
451
|
-
if (!exclusive)
|
|
452
|
-
await rename(target, path);
|
|
453
680
|
});
|
|
454
681
|
}
|
|
455
|
-
function inside(root, path) {
|
|
682
|
+
function inside(root, path) {
|
|
683
|
+
const child = relative(root, path);
|
|
684
|
+
return child === "" || (!isAbsolute(child) && child !== ".." && !child.startsWith(`..${sep}`));
|
|
685
|
+
}
|
|
456
686
|
async function canonicalPotentialPath(path) {
|
|
457
687
|
try {
|
|
458
688
|
return await realpath(path);
|
|
459
689
|
}
|
|
460
690
|
catch (error) {
|
|
461
|
-
if (!
|
|
691
|
+
if (!hasErrorCode(error, "ENOENT"))
|
|
462
692
|
throw error;
|
|
463
693
|
const parent = dirname(path);
|
|
464
694
|
if (parent === path)
|
|
@@ -466,6 +696,7 @@ async function canonicalPotentialPath(path) {
|
|
|
466
696
|
return join(await canonicalPotentialPath(parent), relative(parent, path));
|
|
467
697
|
}
|
|
468
698
|
}
|
|
469
|
-
function safeTerminal(text) {
|
|
470
|
-
|
|
699
|
+
function safeTerminal(text) {
|
|
700
|
+
return text.replace(/[\u0000-\u0008\u000b-\u001f\u007f-\u009f]/gu, "");
|
|
701
|
+
}
|
|
471
702
|
//# sourceMappingURL=team-v2.js.map
|