@fitlab-ai/agent-infra 0.11.10 → 0.11.12
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/bin/internal-cli.js +2 -2
- package/dist/lib/agent-clients/adapter.js +27 -1
- package/dist/lib/agent-clients/adapters/claude-code.js +5 -1
- package/dist/lib/agent-clients/adapters/codex-lifecycle/app-server.js +78 -63
- package/dist/lib/agent-clients/adapters/codex-lifecycle/binding.js +114 -0
- package/dist/lib/agent-clients/adapters/codex-lifecycle/cli.js +447 -0
- package/dist/lib/agent-clients/adapters/codex-lifecycle/controller-client.js +130 -0
- package/dist/lib/agent-clients/adapters/codex-lifecycle/controller-operation.js +131 -0
- package/dist/lib/{sandbox/control → agent-clients/adapters/codex-lifecycle}/controller-registration.js +2 -2
- package/dist/lib/agent-clients/adapters/codex-lifecycle/evidence.js +48 -1
- package/dist/lib/agent-clients/adapters/codex-lifecycle/recovery.js +124 -62
- package/dist/lib/{internal/codex-sandbox-controller.js → agent-clients/adapters/codex-lifecycle/sandbox-controller-cli.js} +3 -3
- package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +3 -5
- package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +222 -210
- package/dist/lib/agent-clients/adapters/codex-orchestration.js +468 -0
- package/dist/lib/agent-clients/adapters/codex-sandbox.js +13 -0
- package/dist/lib/agent-clients/adapters/codex.js +44 -1
- package/dist/lib/agent-clients/adapters/index.js +2 -10
- package/dist/lib/agent-clients/tokens.js +3 -2
- package/dist/lib/internal/agent-client.js +132 -72
- package/dist/lib/internal/cli-route-inventory.js +2 -2
- package/dist/lib/internal/manual-validation.js +2 -2
- package/dist/lib/internal/platform-pr.js +4 -5
- package/dist/lib/internal/task-artifact.js +1 -1
- package/dist/lib/internal/task-create.js +15 -1
- package/dist/lib/internal/task-finalization.js +1 -3
- package/dist/lib/internal/task-operation-registry.js +5 -139
- package/dist/lib/internal/task-validate.js +1 -1
- package/dist/lib/platform/issues.js +18 -6
- package/dist/lib/platform/pr-summary.js +45 -8
- package/dist/lib/platform/pull-requests.js +79 -14
- package/dist/lib/platform/verification-sync.js +17 -14
- package/dist/lib/runtime/agent-runtime.js +6 -29
- package/dist/lib/sandbox/commands/control-status.js +1 -0
- package/dist/lib/sandbox/commands/create.js +19 -2
- package/dist/lib/sandbox/commands/enter.js +47 -33
- package/dist/lib/sandbox/control/agent-operation.js +34 -0
- package/dist/lib/sandbox/control/client.js +68 -161
- package/dist/lib/sandbox/control/executor.js +13 -87
- package/dist/lib/sandbox/control/host-recovery.js +218 -0
- package/dist/lib/sandbox/control/protocol.js +15 -44
- package/dist/lib/sandbox/control/server.js +57 -51
- package/dist/lib/sandbox/environment.js +150 -0
- package/dist/lib/sandbox/mounts.js +2 -1
- package/dist/lib/sandbox/recovery.js +11 -1
- package/dist/lib/sandbox/removal.js +9 -5
- package/dist/lib/sandbox/workspace-identity.js +0 -14
- package/dist/lib/sandbox/workspace-view.js +41 -23
- package/dist/lib/task/artifact-command.js +7 -2
- package/dist/lib/task/artifact-lifecycle.js +2 -1
- package/dist/lib/task/capabilities.js +4 -1
- package/dist/lib/task/control-authority.js +54 -266
- package/dist/lib/task/control-recovery.js +1 -1
- package/dist/lib/task/create.js +2 -2
- package/dist/lib/task/delegation-receipts.js +74 -161
- package/dist/lib/task/events.js +89 -45
- package/dist/lib/task/finalization.js +58 -60
- package/dist/lib/task/frontmatter.js +24 -1
- package/dist/lib/task/ledger-intents.js +2 -1
- package/dist/lib/task/lifecycle.js +84 -97
- package/dist/lib/task/orchestration.js +182 -129
- package/dist/lib/task/platform-operation-journal.js +12 -0
- package/dist/lib/task/platform-operation-recovery.js +14 -7
- package/dist/lib/task/resolve-ref.js +8 -3
- package/dist/lib/task/runtime-paths.js +10 -0
- package/dist/lib/task/verification-engine.js +28 -15
- package/dist/lib/task/workspace-snapshot.js +1 -1
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-clients/adapter.ts +61 -0
- package/lib/agent-clients/adapters/claude-code.ts +5 -1
- package/lib/agent-clients/adapters/codex-lifecycle/app-server.ts +105 -80
- package/lib/agent-clients/adapters/codex-lifecycle/binding.ts +147 -0
- package/lib/agent-clients/adapters/codex-lifecycle/cli.ts +510 -0
- package/lib/agent-clients/adapters/codex-lifecycle/controller-client.ts +158 -0
- package/lib/agent-clients/adapters/codex-lifecycle/controller-context.ts +1 -1
- package/lib/agent-clients/adapters/codex-lifecycle/controller-operation.ts +151 -0
- package/lib/{sandbox/control → agent-clients/adapters/codex-lifecycle}/controller-registration.ts +4 -4
- package/lib/agent-clients/adapters/codex-lifecycle/evidence.ts +43 -0
- package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +8 -5
- package/lib/agent-clients/adapters/codex-lifecycle/recovery.ts +190 -65
- package/lib/{internal/codex-sandbox-controller.ts → agent-clients/adapters/codex-lifecycle/sandbox-controller-cli.ts} +2 -2
- package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +3 -5
- package/lib/agent-clients/adapters/codex-lifecycle/store.ts +272 -223
- package/lib/agent-clients/adapters/codex-orchestration.ts +632 -0
- package/lib/agent-clients/adapters/codex-sandbox.ts +13 -0
- package/lib/agent-clients/adapters/codex.ts +48 -1
- package/lib/agent-clients/adapters/index.ts +7 -20
- package/lib/agent-clients/tokens.ts +4 -3
- package/lib/internal/agent-client.ts +142 -73
- package/lib/internal/cli-route-inventory.ts +2 -2
- package/lib/internal/manual-validation.ts +2 -2
- package/lib/internal/platform-pr.ts +3 -4
- package/lib/internal/task-artifact.ts +1 -1
- package/lib/internal/task-create.ts +15 -2
- package/lib/internal/task-finalization.ts +1 -3
- package/lib/internal/task-operation-registry.ts +5 -151
- package/lib/internal/task-validate.ts +1 -1
- package/lib/platform/issues.ts +18 -6
- package/lib/platform/pr-summary.ts +43 -7
- package/lib/platform/pull-requests.ts +74 -13
- package/lib/platform/verification-sync.ts +18 -14
- package/lib/runtime/agent-runtime.ts +6 -41
- package/lib/sandbox/commands/control-status.ts +1 -0
- package/lib/sandbox/commands/create.ts +25 -2
- package/lib/sandbox/commands/enter.ts +42 -39
- package/lib/sandbox/control/agent-operation.ts +49 -0
- package/lib/sandbox/control/client.ts +86 -210
- package/lib/sandbox/control/executor.ts +17 -96
- package/lib/sandbox/control/host-recovery.ts +195 -0
- package/lib/sandbox/control/protocol.ts +24 -55
- package/lib/sandbox/control/server.ts +54 -52
- package/lib/sandbox/environment.ts +162 -0
- package/lib/sandbox/mounts.ts +2 -1
- package/lib/sandbox/recovery.ts +13 -1
- package/lib/sandbox/removal.ts +12 -5
- package/lib/sandbox/tool-types.ts +1 -0
- package/lib/sandbox/workspace-identity.ts +0 -26
- package/lib/sandbox/workspace-view.ts +42 -24
- package/lib/task/artifact-command.ts +9 -2
- package/lib/task/artifact-lifecycle.ts +2 -1
- package/lib/task/capabilities.ts +5 -2
- package/lib/task/control-authority.ts +65 -382
- package/lib/task/control-recovery.ts +2 -2
- package/lib/task/create.ts +3 -3
- package/lib/task/delegation-receipts.ts +87 -231
- package/lib/task/events.ts +101 -43
- package/lib/task/finalization.ts +57 -58
- package/lib/task/frontmatter.ts +25 -1
- package/lib/task/ledger-intents.ts +2 -1
- package/lib/task/lifecycle.ts +82 -87
- package/lib/task/orchestration.ts +237 -176
- package/lib/task/platform-operation-journal.ts +29 -2
- package/lib/task/platform-operation-recovery.ts +12 -6
- package/lib/task/resolve-ref.ts +8 -3
- package/lib/task/runtime-paths.ts +12 -0
- package/lib/task/verification-engine.ts +27 -16
- package/lib/task/workspace-snapshot.ts +1 -1
- package/package.json +1 -1
- package/templates/.agents/hooks/lifecycle-delegation.js +1 -25
- package/templates/.agents/rules/README.en.md +2 -2
- package/templates/.agents/rules/README.zh-CN.md +2 -2
- package/templates/.agents/rules/issue-sync.en.md +1 -1
- package/templates/.agents/rules/issue-sync.zh-CN.md +1 -1
- package/templates/.agents/rules/next-step-output.en.md +6 -19
- package/templates/.agents/rules/next-step-output.zh-CN.md +6 -19
- package/templates/.agents/rules/no-mid-flow-questions.en.md +19 -0
- package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +19 -0
- package/templates/.agents/rules/review-handshake.en.md +3 -0
- package/templates/.agents/rules/review-handshake.zh-CN.md +3 -0
- package/templates/.agents/rules/task-management.en.md +1 -1
- package/templates/.agents/rules/task-management.zh-CN.md +1 -1
- package/templates/.agents/skills/analyze-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/block-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/block-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/cancel-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/check-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/check-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/close-codescan/SKILL.en.md +3 -0
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +3 -0
- package/templates/.agents/skills/close-dependabot/SKILL.en.md +3 -0
- package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +3 -0
- package/templates/.agents/skills/code-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/code-task/reference/branch-management.en.md +1 -1
- package/templates/.agents/skills/code-task/reference/branch-management.zh-CN.md +1 -1
- package/templates/.agents/skills/code-task/reference/dual-mode.en.md +2 -0
- package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +2 -0
- package/templates/.agents/skills/code-task/reference/fix-mode.en.md +1 -1
- package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +1 -1
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +1 -2
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +1 -2
- package/templates/.agents/skills/complete-task/SKILL.en.md +0 -3
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +0 -3
- package/templates/.agents/skills/create-pr/SKILL.en.md +1 -1
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/create-pr/reference/branch-strategy.en.md +2 -2
- package/templates/.agents/skills/create-pr/reference/branch-strategy.zh-CN.md +2 -2
- package/templates/.agents/skills/create-task/SKILL.en.md +3 -5
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +3 -4
- package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
- package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/import-dependabot/SKILL.en.md +1 -1
- package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/import-issue/SKILL.en.md +1 -1
- package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/plan-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/review-analysis/SKILL.en.md +1 -1
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/review-code/SKILL.en.md +5 -5
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/review-plan/SKILL.en.md +1 -1
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/review-pr/SKILL.en.md +1 -1
- package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/run-manual-validation/SKILL.en.md +1 -1
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/test/SKILL.en.md +4 -1
- package/templates/.agents/skills/test/SKILL.zh-CN.md +4 -1
- package/templates/.agents/skills/test-integration/SKILL.en.md +5 -2
- package/templates/.agents/skills/test-integration/SKILL.zh-CN.md +5 -2
- package/templates/.agents/skills/update-agent-infra/SKILL.en.md +4 -1
- package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +4 -1
- package/templates/.agents/skills/upgrade-dependency/SKILL.en.md +5 -2
- package/templates/.agents/skills/upgrade-dependency/SKILL.zh-CN.md +5 -2
- package/templates/.agents/skills/watch-pr/SKILL.en.md +2 -2
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +1 -1
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +1 -1
- package/dist/lib/agent-clients/adapters/codex-lifecycle/capability-store.js +0 -546
- package/dist/lib/internal/codex-lifecycle.js +0 -385
- package/dist/lib/task/codex-orchestration.js +0 -206
- package/dist/lib/task/finalization-handoff.js +0 -93
- package/lib/agent-clients/adapters/codex-lifecycle/capability-store.ts +0 -776
- package/lib/internal/codex-lifecycle.ts +0 -390
- package/lib/task/codex-orchestration.ts +0 -276
- package/lib/task/finalization-handoff.ts +0 -105
|
@@ -3,10 +3,10 @@ import path from 'node:path';
|
|
|
3
3
|
import { AgentClientConfigError, normalizeAgentClients } from '../agent-clients/config.js';
|
|
4
4
|
import { normalizeCustomToolInvocations } from '../agent-clients/custom-tool-invocations.js';
|
|
5
5
|
import { renderNextStepCommands } from '../agent-clients/next-steps.js';
|
|
6
|
-
import { getAgentClientModelSelection } from '../agent-clients/registry.js';
|
|
6
|
+
import { getAgentClientAdapter, getAgentClientModelSelection } from '../agent-clients/registry.js';
|
|
7
7
|
import { isAgentClientId } from '../agent-clients/types.js';
|
|
8
8
|
import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.js';
|
|
9
|
-
const USAGE = 'Usage: agent-infra-internal agent-client <next-steps|model-selection> [options]\n';
|
|
9
|
+
const USAGE = 'Usage: agent-infra-internal agent-client <next-steps|model-selection|launch-carrier> [options]\n';
|
|
10
10
|
function failure(code, message) {
|
|
11
11
|
process.stdout.write(`${JSON.stringify({
|
|
12
12
|
status: 'failed',
|
|
@@ -72,71 +72,113 @@ function parseArgs(args) {
|
|
|
72
72
|
format
|
|
73
73
|
};
|
|
74
74
|
}
|
|
75
|
-
function
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
failure('AGENT_CLIENT_PAYLOAD_INVALID', `invalid or duplicate option '${flag}'`);
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
const value = args[++index];
|
|
88
|
-
if (!value || value.startsWith('--')) {
|
|
89
|
-
failure('AGENT_CLIENT_PAYLOAD_INVALID', `option '${flag}' requires a value`);
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
seen.add(flag);
|
|
93
|
-
values[flag] = value;
|
|
75
|
+
function parseLaunchCarrierArgs(args) {
|
|
76
|
+
const allowed = new Set(['--client', '--adapter-context', '--stage', '--round', '--role', '--format']);
|
|
77
|
+
const values = {};
|
|
78
|
+
const seen = new Set();
|
|
79
|
+
for (let index = 1; index < args.length; index += 1) {
|
|
80
|
+
const flag = args[index];
|
|
81
|
+
if (!allowed.has(flag) || seen.has(flag)) {
|
|
82
|
+
failure('AGENT_CLIENT_PAYLOAD_INVALID', `invalid or duplicate option '${flag}'`);
|
|
83
|
+
return null;
|
|
94
84
|
}
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
return;
|
|
85
|
+
const value = args[++index];
|
|
86
|
+
if (!value || value.startsWith('--')) {
|
|
87
|
+
failure('AGENT_CLIENT_PAYLOAD_INVALID', `option '${flag}' requires a value`);
|
|
88
|
+
return null;
|
|
100
89
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
90
|
+
seen.add(flag);
|
|
91
|
+
values[flag] = value;
|
|
92
|
+
}
|
|
93
|
+
const round = Number(values['--round']);
|
|
94
|
+
if (!isAgentClientId(values['--client']) || !values['--adapter-context'] || !values['--stage'] || !values['--role']
|
|
95
|
+
|| !Number.isSafeInteger(round) || round < 1 || (values['--format'] ?? 'json') !== 'json') {
|
|
96
|
+
failure('AGENT_CLIENT_PAYLOAD_INVALID', 'launch-carrier requires client, adapter context, stage, positive round, role, and json format');
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
client: values['--client'],
|
|
101
|
+
adapterContext: values['--adapter-context'],
|
|
102
|
+
stage: values['--stage'],
|
|
103
|
+
round,
|
|
104
|
+
role: values['--role']
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function launchCarrier(args) {
|
|
108
|
+
const parsed = parseLaunchCarrierArgs(args);
|
|
109
|
+
if (!parsed)
|
|
110
|
+
return;
|
|
111
|
+
const createCarrier = getAgentClientAdapter(parsed.client).orchestrationAdapter?.createLaunchCarrier;
|
|
112
|
+
if (!createCarrier) {
|
|
113
|
+
process.stdout.write(`${JSON.stringify({
|
|
114
|
+
status: 'failed', changed: false, client: parsed.client, carrier: null,
|
|
115
|
+
error: { code: 'AGENT_CLIENT_LAUNCH_CARRIER_UNSUPPORTED', message: `Agent Client '${parsed.client}' does not support lifecycle launch carriers` }
|
|
116
|
+
})}\n`);
|
|
117
|
+
process.exitCode = 1;
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
try {
|
|
121
|
+
const carrier = createCarrier(parsed.adapterContext, { stage: parsed.stage, round: parsed.round, role: parsed.role });
|
|
122
|
+
process.stdout.write(`${JSON.stringify({ status: 'ready', changed: false, client: parsed.client, carrier, error: null })}\n`);
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
process.stdout.write(`${JSON.stringify({
|
|
126
|
+
status: 'failed', changed: false, client: parsed.client, carrier: null,
|
|
127
|
+
error: { code: error instanceof Error && error.name ? error.name : 'AGENT_CLIENT_LAUNCH_CARRIER_INVALID', message: error instanceof Error ? error.message : String(error) }
|
|
128
|
+
})}\n`);
|
|
129
|
+
process.exitCode = 1;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function modelSelection(args) {
|
|
133
|
+
const values = {};
|
|
134
|
+
const seen = new Set();
|
|
135
|
+
for (let index = 1; index < args.length; index += 1) {
|
|
136
|
+
const flag = args[index];
|
|
137
|
+
if (!['--client', '--format'].includes(flag) || seen.has(flag)) {
|
|
138
|
+
failure('AGENT_CLIENT_PAYLOAD_INVALID', `invalid or duplicate option '${flag}'`);
|
|
106
139
|
return;
|
|
107
140
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
process.stdout.write(`Model selection: ${context.completeness} catalog\nSource: ${context.source}\n`);
|
|
113
|
-
for (const model of context.models) {
|
|
114
|
-
const efforts = model.reasoningEfforts?.length
|
|
115
|
-
? ` (${model.reasoningEfforts.join(', ')})`
|
|
116
|
-
: '';
|
|
117
|
-
process.stdout.write(`- ${model.id}${efforts}\n`);
|
|
118
|
-
}
|
|
119
|
-
if (context.guidance)
|
|
120
|
-
process.stdout.write(`${context.guidance}\n`);
|
|
141
|
+
const value = args[++index];
|
|
142
|
+
if (!value || value.startsWith('--')) {
|
|
143
|
+
failure('AGENT_CLIENT_PAYLOAD_INVALID', `option '${flag}' requires a value`);
|
|
144
|
+
return;
|
|
121
145
|
}
|
|
146
|
+
seen.add(flag);
|
|
147
|
+
values[flag] = value;
|
|
148
|
+
}
|
|
149
|
+
const client = values['--client'];
|
|
150
|
+
const format = values['--format'] ?? 'text';
|
|
151
|
+
if (!isAgentClientId(client) || !['text', 'json'].includes(format)) {
|
|
152
|
+
failure('AGENT_CLIENT_PAYLOAD_INVALID', 'model-selection requires a known --client and text|json format');
|
|
122
153
|
return;
|
|
123
154
|
}
|
|
124
|
-
const
|
|
125
|
-
if (
|
|
155
|
+
const context = getAgentClientModelSelection(client);
|
|
156
|
+
if (format === 'json') {
|
|
157
|
+
process.stdout.write(`${JSON.stringify({ status: 'resolved', changed: false, client, context, error: null })}\n`);
|
|
126
158
|
return;
|
|
127
|
-
let config;
|
|
128
|
-
try {
|
|
129
|
-
const configPath = path.join(process.cwd(), '.agents', '.airc.json');
|
|
130
|
-
const raw = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
131
|
-
if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {
|
|
132
|
-
throw new Error('configuration root must be an object');
|
|
133
|
-
}
|
|
134
|
-
config = raw;
|
|
135
159
|
}
|
|
136
|
-
|
|
137
|
-
|
|
160
|
+
renderModelSelection(context);
|
|
161
|
+
}
|
|
162
|
+
function renderModelSelection(context) {
|
|
163
|
+
if (context.kind === 'interactive-only') {
|
|
164
|
+
process.stdout.write(`Model selection: interactive-only\nCommand: ${context.command}\n${context.guidance}\n`);
|
|
138
165
|
return;
|
|
139
166
|
}
|
|
167
|
+
process.stdout.write(`Model selection: ${context.completeness} catalog\nSource: ${context.source}\n`);
|
|
168
|
+
for (const model of context.models) {
|
|
169
|
+
const efforts = model.reasoningEfforts?.length ? ` (${model.reasoningEfforts.join(', ')})` : '';
|
|
170
|
+
process.stdout.write(`- ${model.id}${efforts}\n`);
|
|
171
|
+
}
|
|
172
|
+
if (context.guidance)
|
|
173
|
+
process.stdout.write(`${context.guidance}\n`);
|
|
174
|
+
}
|
|
175
|
+
function renderNextSteps(args) {
|
|
176
|
+
const parsed = parseArgs(args);
|
|
177
|
+
if (!parsed || process.exitCode)
|
|
178
|
+
return;
|
|
179
|
+
const config = readAgentClientConfig();
|
|
180
|
+
if (!config)
|
|
181
|
+
return;
|
|
140
182
|
try {
|
|
141
183
|
const clients = normalizeAgentClients(config);
|
|
142
184
|
const custom = normalizeCustomToolInvocations(config);
|
|
@@ -148,22 +190,7 @@ function agentClient(args = []) {
|
|
|
148
190
|
...(parsed.taskRef ? { taskRef: parsed.taskRef } : {}),
|
|
149
191
|
...(parsed.version ? { version: parsed.version } : {})
|
|
150
192
|
});
|
|
151
|
-
|
|
152
|
-
process.stdout.write(`${JSON.stringify({
|
|
153
|
-
status: 'rendered',
|
|
154
|
-
changed: false,
|
|
155
|
-
commands,
|
|
156
|
-
diagnostics: custom.diagnostics,
|
|
157
|
-
error: null
|
|
158
|
-
})}\n`);
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
for (const command of commands) {
|
|
162
|
-
process.stdout.write(` - ${command.displayName}: ${command.command}\n`);
|
|
163
|
-
}
|
|
164
|
-
for (const diagnostic of custom.diagnostics) {
|
|
165
|
-
process.stderr.write(`${diagnostic.code} at ${diagnostic.path}\n`);
|
|
166
|
-
}
|
|
193
|
+
writeNextStepOutput(parsed.format, commands, custom.diagnostics);
|
|
167
194
|
}
|
|
168
195
|
catch (error) {
|
|
169
196
|
if (error instanceof AgentClientConfigError) {
|
|
@@ -173,5 +200,38 @@ function agentClient(args = []) {
|
|
|
173
200
|
failure('AGENT_CLIENT_RENDER_INVALID', error instanceof Error ? error.message : String(error));
|
|
174
201
|
}
|
|
175
202
|
}
|
|
203
|
+
function readAgentClientConfig() {
|
|
204
|
+
try {
|
|
205
|
+
const raw = JSON.parse(fs.readFileSync(path.join(process.cwd(), '.agents', '.airc.json'), 'utf8'));
|
|
206
|
+
if (typeof raw !== 'object' || raw === null || Array.isArray(raw))
|
|
207
|
+
throw new Error('configuration root must be an object');
|
|
208
|
+
return raw;
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
failure('AGENT_CLIENT_CONFIG_INVALID', String(error));
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
function writeNextStepOutput(format, commands, diagnostics) {
|
|
216
|
+
if (format === 'json') {
|
|
217
|
+
process.stdout.write(`${JSON.stringify({ status: 'rendered', changed: false, commands, diagnostics, error: null })}\n`);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
for (const command of commands)
|
|
221
|
+
process.stdout.write(` - ${command.displayName}: ${command.command}\n`);
|
|
222
|
+
for (const diagnostic of diagnostics)
|
|
223
|
+
process.stderr.write(`${diagnostic.code} at ${diagnostic.path}\n`);
|
|
224
|
+
}
|
|
225
|
+
function agentClient(args = []) {
|
|
226
|
+
if (!ensureInternalHandlerRoute('agent-client', args))
|
|
227
|
+
return;
|
|
228
|
+
if (internalHandlerRoute('agent-client', 'launch-carrier', args[0] ?? '')) {
|
|
229
|
+
return launchCarrier(args);
|
|
230
|
+
}
|
|
231
|
+
if (internalHandlerRoute('agent-client', 'model-selection', args[0] ?? '')) {
|
|
232
|
+
return modelSelection(args);
|
|
233
|
+
}
|
|
234
|
+
renderNextSteps(args);
|
|
235
|
+
}
|
|
176
236
|
export { agentClient };
|
|
177
237
|
//# sourceMappingURL=agent-client.js.map
|
|
@@ -33,8 +33,8 @@ export const INTERNAL_HANDLER_ROUTE_SELECTORS = Object.freeze({
|
|
|
33
33
|
'task-create': ['input'],
|
|
34
34
|
'task-qualification': ['proposal', 'confirm', 'supersede', 'revoke'],
|
|
35
35
|
'sandbox-control': ['serve', 'execute', 'recover', 'client'],
|
|
36
|
-
'agent-client': ['next-steps', 'model-selection'],
|
|
37
|
-
'codex-lifecycle': ['preflight', '
|
|
36
|
+
'agent-client': ['next-steps', 'model-selection', 'launch-carrier'],
|
|
37
|
+
'codex-lifecycle': ['preflight', 'hook-event', 'resolve-start', 'resolve-stop', 'consume'],
|
|
38
38
|
'codex-sandbox-controller': ['verify-context', 'run'],
|
|
39
39
|
'git-workflow': ['inspect', 'preview-tree', 'snapshot', 'compare-trees', 'commit', 'push-rebased'],
|
|
40
40
|
'task-delivery': ['deliver'],
|
|
@@ -196,7 +196,7 @@ async function executeManualValidationTransactionLocked(taskRef, values, cwd, re
|
|
|
196
196
|
if (transaction.phase === 'prepared') {
|
|
197
197
|
const staged = await syncPullRequestSummary(taskRef, {
|
|
198
198
|
cwd, client: options.client, agent, body: pendingBody, changeReportFile: path.resolve(cwd, values.changeReportFile), primaryResult: primaryResult, strict: true,
|
|
199
|
-
manualValidation: { phase: 'pending' }, lockAlreadyHeld: true
|
|
199
|
+
manualValidation: { phase: 'pending', transactionId: transaction.transactionId }, lockAlreadyHeld: true
|
|
200
200
|
});
|
|
201
201
|
if (!['applied', 'no-op'].includes(staged.status))
|
|
202
202
|
transactionFailure(staged.error ?? { code: 'MANUAL_VALIDATION_TRANSACTION_FAILED', message: 'pending summary staging failed' });
|
|
@@ -261,7 +261,7 @@ async function executeManualValidationTransactionLocked(taskRef, values, cwd, re
|
|
|
261
261
|
try {
|
|
262
262
|
await syncPullRequestSummary(taskRef, {
|
|
263
263
|
cwd, client: options.client, agent, body: pendingBody, changeReportFile: path.resolve(cwd, values.changeReportFile), primaryResult: primaryResult, strict: true,
|
|
264
|
-
manualValidation: { phase: 'pending' }, lockAlreadyHeld: true
|
|
264
|
+
manualValidation: { phase: 'pending', transactionId: transaction.transactionId }, lockAlreadyHeld: true
|
|
265
265
|
});
|
|
266
266
|
}
|
|
267
267
|
catch {
|
|
@@ -10,7 +10,7 @@ const USAGE = `Usage: agent-infra-internal platform-pr inspect <task-ref> [--cwd
|
|
|
10
10
|
agent-infra-internal platform-pr bind <task-ref> --pr <token> --agent <agent> [--dry-run] [--cwd <path>]
|
|
11
11
|
agent-infra-internal platform-pr skip <task-ref> --agent <agent> [--dry-run] [--cwd <path>]
|
|
12
12
|
agent-infra-internal platform-pr sync <task-ref> --agent <agent> [--metadata] [--closing-issue] --result <pr_created|pr_reused|no_op> [--dry-run] [--cwd <path>]
|
|
13
|
-
agent-infra-internal platform-pr sync-in-labels --pr <
|
|
13
|
+
agent-infra-internal platform-pr sync-in-labels --pr <token> [--dry-run] [--cwd <path>]
|
|
14
14
|
agent-infra-internal platform-pr summary-context <task-ref> [--cwd <path>]
|
|
15
15
|
agent-infra-internal platform-pr change-report <task-ref> --agent <agent> --mechanical-file <path> --precheck-file <path> [--dry-run] [--cwd <path>]
|
|
16
16
|
agent-infra-internal platform-pr summary-sync <task-ref> --agent <agent> --body-file <path|-> --change-report-file <path> --result <pr_created|pr_reused|no_op> [--manual-phase pending|final ...] [--strict] [--dry-run] [--cwd <path>]
|
|
@@ -91,13 +91,12 @@ async function platformPr(args = []) {
|
|
|
91
91
|
fail(`sync-in-labels does not accept --${unexpected}`);
|
|
92
92
|
return;
|
|
93
93
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
fail('sync-in-labels requires a positive --pr');
|
|
94
|
+
if (typeof values.pr !== 'string' || !values.pr || values.pr.trim() !== values.pr) {
|
|
95
|
+
fail('sync-in-labels requires a non-empty --pr token');
|
|
97
96
|
return;
|
|
98
97
|
}
|
|
99
98
|
const cwd = path.resolve(typeof values.cwd === 'string' ? values.cwd : process.cwd());
|
|
100
|
-
finish(await syncPlatformPullRequestInLabels(pr, { cwd, dryRun: values.dryRun === true }));
|
|
99
|
+
finish(await syncPlatformPullRequestInLabels(values.pr, { cwd, dryRun: values.dryRun === true }));
|
|
101
100
|
return;
|
|
102
101
|
}
|
|
103
102
|
const taskRef = args[1];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { parseArtifactCommand, executeArtifactCommand } from '../task/artifact-command.js';
|
|
2
2
|
import { ensureInternalHandlerRoute } from './cli-route-inventory.js';
|
|
3
|
-
const USAGE = `Usage: agent-infra-internal task-artifact <N | TASK-id> inspect --family <family> [--source-finding <id> --source-artifact <name> --source-sha256 <digest>]\n agent-infra-internal task-artifact <N | TASK-id> init --family <family> --artifact <artifact> [--locale <zh-CN|en>]\n agent-infra-internal task-artifact <N | TASK-id> preflight|finalize-local --family <analysis|plan|code> --artifact <artifact>\n\nInspect, initialize, preflight, or finalize workflow artifact facts.\n`;
|
|
3
|
+
const USAGE = `Usage: agent-infra-internal task-artifact <N | TASK-id> inspect --family <family> [--reason-code <reason>] [--source-finding <id> --source-artifact <name> --source-sha256 <digest>]\n agent-infra-internal task-artifact <N | TASK-id> init --family <family> --artifact <artifact> [--locale <zh-CN|en>]\n agent-infra-internal task-artifact <N | TASK-id> preflight|finalize-local --family <analysis|plan|code> --artifact <artifact>\n\nInspect, initialize, preflight, or finalize workflow artifact facts.\n`;
|
|
4
4
|
function taskArtifact(args = []) {
|
|
5
5
|
if (!ensureInternalHandlerRoute('task-artifact', args))
|
|
6
6
|
return;
|
|
@@ -54,7 +54,21 @@ async function taskCreate(args) {
|
|
|
54
54
|
throw new Error('TASK_CREATE_INPUT_INVALID: input must be a regular file');
|
|
55
55
|
if (stat.size > SANDBOX_CONTROL_MAX_BYTES)
|
|
56
56
|
throw new Error('TASK_CREATE_INPUT_TOO_LARGE: input exceeds the control limit');
|
|
57
|
-
const
|
|
57
|
+
const inputContent = fs.readFileSync(inputPath, 'utf8');
|
|
58
|
+
let candidate;
|
|
59
|
+
try {
|
|
60
|
+
candidate = validateTaskCreateCandidate(JSON.parse(inputContent));
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
64
|
+
const code = /^([A-Z][A-Z0-9_]+)/.exec(message)?.[1] ?? 'TASK_CREATE_INPUT_INVALID';
|
|
65
|
+
output(failed(code, message, false, {
|
|
66
|
+
requestId: null,
|
|
67
|
+
accepted: false,
|
|
68
|
+
recovery: 'new-request-id'
|
|
69
|
+
}));
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
58
72
|
const environment = resolveSandboxControlTransport();
|
|
59
73
|
if (environment.kind === 'fail-closed') {
|
|
60
74
|
output(failed(environment.reasonCode ?? 'TASK_CONTROL_TRANSPORT_INVALID', 'sandbox client control configuration is invalid'));
|
|
@@ -65,9 +65,7 @@ async function taskFinalization(args = []) {
|
|
|
65
65
|
const transport = resolveSandboxControlTransport(process.env, { localWorkflow: true });
|
|
66
66
|
if (transport.kind === 'sandbox-local') {
|
|
67
67
|
try {
|
|
68
|
-
const response = requestSandboxTaskFinalization({
|
|
69
|
-
agent: boundOperation.request.agent
|
|
70
|
-
});
|
|
68
|
+
const response = requestSandboxTaskFinalization({ agent: boundOperation.request.agent });
|
|
71
69
|
process.stdout.write(response.stdout);
|
|
72
70
|
process.stderr.write(response.stderr);
|
|
73
71
|
process.exitCode = response.exitCode ?? 1;
|
|
@@ -3,7 +3,8 @@ import path from 'node:path';
|
|
|
3
3
|
import { accessSandboxTaskView, parseSandboxTaskView, taskViewFromStatus } from '../sandbox/control/task-view.js';
|
|
4
4
|
import { resolveTaskRef } from '../task/resolve-ref.js';
|
|
5
5
|
import { PUBLIC_CLI_COMMAND_ALIASES, PUBLIC_CLI_SELECTOR_ALIASES, internalRouteSelector } from './cli-route-inventory.js';
|
|
6
|
-
import {
|
|
6
|
+
import { hasSandboxControlMarker, resolveSandboxControlTransport, sandboxTaskMarkerState } from '../sandbox/environment.js';
|
|
7
|
+
export { resolveSandboxControlTransport } from '../sandbox/environment.js';
|
|
7
8
|
const descriptor = (dispatcher, command, selector, scope, effect, taskRefSource = scope === 'non-task' ? 'none' : 'argv') => ({ dispatcher, command, selector, scope, effect, taskRefSource, guardBeforeImport: true });
|
|
8
9
|
function internalTaskRoutes() {
|
|
9
10
|
return [
|
|
@@ -18,8 +19,8 @@ function internalTaskRoutes() {
|
|
|
18
19
|
descriptor('internal', 'sandbox-control', 'client', 'conditional', 'progress', 'delegated'),
|
|
19
20
|
descriptor('internal', 'agent-client', 'next-steps', 'non-task', 'diagnostic', 'none'),
|
|
20
21
|
descriptor('internal', 'agent-client', 'model-selection', 'non-task', 'diagnostic', 'none'),
|
|
22
|
+
descriptor('internal', 'agent-client', 'launch-carrier', 'non-task', 'diagnostic', 'none'),
|
|
21
23
|
descriptor('internal', 'codex-lifecycle', 'preflight', 'non-task', 'diagnostic', 'none'),
|
|
22
|
-
descriptor('internal', 'codex-lifecycle', 'capability-arm', 'conditional', 'progress'),
|
|
23
24
|
descriptor('internal', 'codex-lifecycle', 'hook-event', 'conditional', 'progress'),
|
|
24
25
|
descriptor('internal', 'codex-lifecycle', 'resolve-start', 'conditional', 'progress'),
|
|
25
26
|
descriptor('internal', 'codex-lifecycle', 'resolve-stop', 'conditional', 'progress'),
|
|
@@ -232,141 +233,6 @@ export function resolveDelegatedTaskOperation(args) {
|
|
|
232
233
|
return null;
|
|
233
234
|
return resolveTaskOperation('internal', rest[0], rest.slice(1));
|
|
234
235
|
}
|
|
235
|
-
const TASK_MARKER_KEYS = [
|
|
236
|
-
'AGENT_INFRA_TASK_ID',
|
|
237
|
-
'AGENT_INFRA_CONTROL_TOKEN',
|
|
238
|
-
'AGENT_INFRA_CONTROL_GENERATION',
|
|
239
|
-
'AGENT_INFRA_CONTROL_DIR',
|
|
240
|
-
'AGENT_INFRA_CONTROL_STATUS_DIR',
|
|
241
|
-
'AGENT_INFRA_RUNTIME_DIR'
|
|
242
|
-
];
|
|
243
|
-
const TASK_CONTROL_MARKER_KEYS = [
|
|
244
|
-
'AGENT_INFRA_CONTROL_TOKEN',
|
|
245
|
-
'AGENT_INFRA_CONTROL_GENERATION',
|
|
246
|
-
'AGENT_INFRA_CONTROL_DIR',
|
|
247
|
-
'AGENT_INFRA_CONTROL_STATUS_DIR'
|
|
248
|
-
];
|
|
249
|
-
const TASK_CONTROL_CONFIG_KEYS = [
|
|
250
|
-
'AGENT_INFRA_CONTROL_TOKEN',
|
|
251
|
-
'AGENT_INFRA_CONTROL_GENERATION',
|
|
252
|
-
'AGENT_INFRA_CONTROL_ROOT_ID',
|
|
253
|
-
'AGENT_INFRA_CONTROL_DIR',
|
|
254
|
-
'AGENT_INFRA_CONTROL_STATUS_DIR'
|
|
255
|
-
];
|
|
256
|
-
export const SANDBOX_CONTROL_STATUS_MOUNT = '/run/agent-infra/control-status';
|
|
257
|
-
function nativeDirectoryProbe(candidate) {
|
|
258
|
-
try {
|
|
259
|
-
// The fixed mount is a trust anchor. Do not use a mutable node:fs export:
|
|
260
|
-
// a preload must not turn a mounted sandbox into the direct-host path by
|
|
261
|
-
// replacing the ordinary filesystem probe.
|
|
262
|
-
const binding = process.binding('fs');
|
|
263
|
-
if (!Function.prototype.toString.call(binding.internalModuleStat).includes('[native code]'))
|
|
264
|
-
return 'unknown';
|
|
265
|
-
const result = binding.internalModuleStat(candidate);
|
|
266
|
-
if (result === 1)
|
|
267
|
-
return 'present';
|
|
268
|
-
if (result === -2)
|
|
269
|
-
return 'absent';
|
|
270
|
-
return 'unknown';
|
|
271
|
-
}
|
|
272
|
-
catch {
|
|
273
|
-
return 'unknown';
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
function taskMarkerState(env) {
|
|
277
|
-
const present = (key) => Boolean(env[key]);
|
|
278
|
-
const taskId = present('AGENT_INFRA_TASK_ID');
|
|
279
|
-
const controls = TASK_CONTROL_MARKER_KEYS.every(present);
|
|
280
|
-
const runtime = present('AGENT_INFRA_RUNTIME_DIR');
|
|
281
|
-
const any = TASK_MARKER_KEYS.some(present);
|
|
282
|
-
if (!any)
|
|
283
|
-
return 'none';
|
|
284
|
-
if (taskId && controls && runtime)
|
|
285
|
-
return 'task-bound';
|
|
286
|
-
if (!taskId && controls && !runtime)
|
|
287
|
-
return 'branch-only';
|
|
288
|
-
return 'incomplete';
|
|
289
|
-
}
|
|
290
|
-
export function resolveSandboxControlTransport(env = process.env, options = {}) {
|
|
291
|
-
const hasAnyMarker = TASK_MARKER_KEYS.some((key) => Boolean(env[key]))
|
|
292
|
-
|| Boolean(env.AGENT_INFRA_CONTROL_CONTROLLER_BINDING)
|
|
293
|
-
|| Boolean(env.AGENT_INFRA_EXECUTOR_MANIFEST);
|
|
294
|
-
const fixedStatusDir = options.statusMountPath
|
|
295
|
-
?? SANDBOX_CONTROL_STATUS_MOUNT;
|
|
296
|
-
const fixedStatusProbe = path.isAbsolute(fixedStatusDir)
|
|
297
|
-
? nativeDirectoryProbe(fixedStatusDir) : 'absent';
|
|
298
|
-
if (fixedStatusProbe === 'unknown') {
|
|
299
|
-
return { kind: 'fail-closed', reasonCode: 'SANDBOX_CONTROL_IDENTITY_UNAVAILABLE' };
|
|
300
|
-
}
|
|
301
|
-
const fixedStatusMounted = fixedStatusProbe === 'present';
|
|
302
|
-
// A fixed status mount is installed only in a task-bound sandbox. Its
|
|
303
|
-
// presence is not mutable by the sandbox process, so marker removal must
|
|
304
|
-
// never make that process look like a direct host invocation.
|
|
305
|
-
if (!hasAnyMarker) {
|
|
306
|
-
return fixedStatusMounted
|
|
307
|
-
? { kind: 'fail-closed', reasonCode: 'SANDBOX_CONTROL_CONFIGURATION_INCOMPLETE' }
|
|
308
|
-
: { kind: 'direct-host', reasonCode: null };
|
|
309
|
-
}
|
|
310
|
-
const hasCompleteConfig = TASK_CONTROL_CONFIG_KEYS.every((key) => Boolean(env[key]));
|
|
311
|
-
if (!hasCompleteConfig) {
|
|
312
|
-
return { kind: 'fail-closed', reasonCode: 'SANDBOX_CONTROL_CONFIGURATION_INCOMPLETE' };
|
|
313
|
-
}
|
|
314
|
-
const configuredStatusDir = env.AGENT_INFRA_CONTROL_STATUS_DIR;
|
|
315
|
-
const configuredStatusProbe = configuredStatusDir && path.isAbsolute(configuredStatusDir)
|
|
316
|
-
? nativeDirectoryProbe(configuredStatusDir) : 'absent';
|
|
317
|
-
if (configuredStatusProbe === 'unknown') {
|
|
318
|
-
return { kind: 'fail-closed', reasonCode: 'SANDBOX_CONTROL_IDENTITY_UNAVAILABLE' };
|
|
319
|
-
}
|
|
320
|
-
const statusDir = configuredStatusDir && path.isAbsolute(configuredStatusDir)
|
|
321
|
-
? configuredStatusProbe === 'present' ? configuredStatusDir : null
|
|
322
|
-
: fixedStatusMounted ? fixedStatusDir : null;
|
|
323
|
-
const statusMounted = statusDir !== null;
|
|
324
|
-
if (env.AGENT_INFRA_EXECUTOR_MANIFEST || env.AGENT_INFRA_CONTROL_CONTROLLER_BINDING) {
|
|
325
|
-
return { kind: 'fail-closed', reasonCode: 'TASK_CONTROL_TRANSPORT_INVALID' };
|
|
326
|
-
}
|
|
327
|
-
const taskBound = Boolean(env.AGENT_INFRA_TASK_ID);
|
|
328
|
-
const runtime = Boolean(env.AGENT_INFRA_RUNTIME_DIR);
|
|
329
|
-
if (statusMounted) {
|
|
330
|
-
let sentinel;
|
|
331
|
-
try {
|
|
332
|
-
sentinel = readSandboxControlIdentitySentinel(statusDir);
|
|
333
|
-
}
|
|
334
|
-
catch (error) {
|
|
335
|
-
const message = error instanceof Error ? error.message : '';
|
|
336
|
-
return { kind: 'fail-closed', reasonCode: message.endsWith('MISSING')
|
|
337
|
-
? 'SANDBOX_CONTROL_IDENTITY_MISSING'
|
|
338
|
-
: 'SANDBOX_CONTROL_IDENTITY_MALFORMED' };
|
|
339
|
-
}
|
|
340
|
-
if (sentinel.generation !== env.AGENT_INFRA_CONTROL_GENERATION) {
|
|
341
|
-
return { kind: 'fail-closed', reasonCode: 'SANDBOX_CONTROL_IDENTITY_GENERATION_MISMATCH' };
|
|
342
|
-
}
|
|
343
|
-
if (env.AGENT_INFRA_CONTROL_ROOT_ID && sentinel.controlRootId !== env.AGENT_INFRA_CONTROL_ROOT_ID) {
|
|
344
|
-
return { kind: 'fail-closed', reasonCode: 'SANDBOX_CONTROL_IDENTITY_ROOT_ID_MISMATCH' };
|
|
345
|
-
}
|
|
346
|
-
if (sentinel.mode === 'task-bound'
|
|
347
|
-
&& (sentinel.taskId !== env.AGENT_INFRA_TASK_ID || !runtime)) {
|
|
348
|
-
return { kind: 'fail-closed', reasonCode: 'SANDBOX_CONTROL_IDENTITY_TOPOLOGY_MISMATCH' };
|
|
349
|
-
}
|
|
350
|
-
if (sentinel.mode === 'branch-only' && (taskBound || runtime)) {
|
|
351
|
-
return { kind: 'fail-closed', reasonCode: 'SANDBOX_CONTROL_IDENTITY_TOPOLOGY_MISMATCH' };
|
|
352
|
-
}
|
|
353
|
-
if (!hasCompleteConfig) {
|
|
354
|
-
return { kind: 'fail-closed', reasonCode: 'SANDBOX_CONTROL_CONFIGURATION_INCOMPLETE' };
|
|
355
|
-
}
|
|
356
|
-
return { kind: options.localWorkflow ? 'sandbox-local' : 'broker-client', reasonCode: null };
|
|
357
|
-
}
|
|
358
|
-
if (!hasAnyMarker)
|
|
359
|
-
return { kind: 'direct-host', reasonCode: null };
|
|
360
|
-
if (!hasCompleteConfig || (taskBound && !runtime) || (!taskBound && runtime)) {
|
|
361
|
-
return { kind: 'fail-closed', reasonCode: 'SANDBOX_CONTROL_CONFIGURATION_INCOMPLETE' };
|
|
362
|
-
}
|
|
363
|
-
return options.localWorkflow
|
|
364
|
-
? { kind: 'fail-closed', reasonCode: 'SANDBOX_CONTROL_IDENTITY_MISSING' }
|
|
365
|
-
: { kind: 'broker-client', reasonCode: null };
|
|
366
|
-
}
|
|
367
|
-
export function hasTaskBoundMarker(env = process.env) {
|
|
368
|
-
return taskMarkerState(env) === 'task-bound';
|
|
369
|
-
}
|
|
370
236
|
function explicitTaskRefForOperation(dispatcher, command, args, selected) {
|
|
371
237
|
if (selected.taskRefSource === 'none' || selected.taskRefSource === 'environment')
|
|
372
238
|
return null;
|
|
@@ -446,7 +312,7 @@ function isSandboxExecutorRoute(dispatcher, command, args, env) {
|
|
|
446
312
|
&& first(args) === 'execute'
|
|
447
313
|
&& Boolean(env.AGENT_INFRA_EXECUTOR_MANIFEST)
|
|
448
314
|
&& Boolean(env.AGENT_INFRA_RUNTIME_DIR)
|
|
449
|
-
&& !
|
|
315
|
+
&& !hasSandboxControlMarker(env);
|
|
450
316
|
}
|
|
451
317
|
function viewFromEnvironment(env) {
|
|
452
318
|
const statusDir = env.AGENT_INFRA_CONTROL_STATUS_DIR;
|
|
@@ -492,7 +358,7 @@ export function guardTaskOperation(dispatcher, command, args = [], options = {})
|
|
|
492
358
|
taskView: null
|
|
493
359
|
};
|
|
494
360
|
}
|
|
495
|
-
const markerState =
|
|
361
|
+
const markerState = sandboxTaskMarkerState(env);
|
|
496
362
|
if (markerState === 'incomplete' && !isSandboxExecutorRoute(dispatcher, command, args, env)) {
|
|
497
363
|
throw new TaskViewOperationError('SANDBOX_TASK_VIEW_MARKER_INVALID', 'sandbox task markers are incomplete; refusing to infer host-direct authority');
|
|
498
364
|
}
|
|
@@ -152,7 +152,7 @@ function inplaceValidation(config, target, options) {
|
|
|
152
152
|
if (!row)
|
|
153
153
|
throw new Error('SANDBOX_VALIDATION_CONTAINER_NOT_FOUND');
|
|
154
154
|
const control = sandboxControlPaths({
|
|
155
|
-
base: config.controlBase, project: config.project,
|
|
155
|
+
base: config.controlBase, repoRoot: config.repoRoot, project: config.project,
|
|
156
156
|
container: row.name, identity: target.workspace
|
|
157
157
|
});
|
|
158
158
|
const manifest = readSandboxControlManifest(control.manifestPath);
|
|
@@ -472,7 +472,8 @@ async function syncPlatformIssueImpl(taskRef, options) {
|
|
|
472
472
|
let providerMetadata = null;
|
|
473
473
|
let repositoryLabels = [];
|
|
474
474
|
let milestones = [];
|
|
475
|
-
if (base.context.capabilities.triage && (options.status !== undefined || options.inLabels !== undefined || options.milestone !== undefined
|
|
475
|
+
if (base.context.capabilities.triage && (options.status !== undefined || options.inLabels !== undefined || options.milestone !== undefined
|
|
476
|
+
|| (base.context.capabilities.push && (options.issueType || options.fields)))) {
|
|
476
477
|
const metadata = base.provider.issues?.describeRepository
|
|
477
478
|
? await base.provider.issues.describeRepository({ context: providerOperationContext(base.loadedContext) })
|
|
478
479
|
: unsupportedProviderOperation(base.provider, 'issues.describeRepository');
|
|
@@ -551,18 +552,29 @@ async function syncPlatformIssueImpl(taskRef, options) {
|
|
|
551
552
|
}
|
|
552
553
|
}
|
|
553
554
|
if (options.issueType || options.fields) {
|
|
554
|
-
plan.operations.push(...(
|
|
555
|
-
?
|
|
556
|
-
|
|
555
|
+
plan.operations.push(...(!base.context.capabilities.push
|
|
556
|
+
? [
|
|
557
|
+
...(options.issueType ? [{ name: 'issue-type', status: 'skipped', reasonCode: 'PUSH_REQUIRED' }] : []),
|
|
558
|
+
...(options.fields ? [{ name: 'fields', status: 'skipped', reasonCode: 'PUSH_REQUIRED' }] : [])
|
|
559
|
+
]
|
|
560
|
+
: providerMetadata
|
|
561
|
+
? planProviderMetadata(inspected.value, providerMetadata, base.frontmatter, options, base.context.capabilities)
|
|
562
|
+
: [{ name: 'issue-type', status: 'skipped', reasonCode: 'ISSUE_TYPES_UNSUPPORTED' }]));
|
|
557
563
|
}
|
|
558
564
|
const failure = plan.operations.find((operation) => operation.status === 'failed');
|
|
559
565
|
if (failure)
|
|
560
566
|
return result('failed', base.resolved.taskId, base.issueNumber, { issue: snapshot, operations: plan.operations, error: { code: failure.reasonCode || 'ISSUE_SYNC_FAILED', message: `Operation ${failure.name} failed`, retryable: false } });
|
|
561
567
|
const planned = plan.operations.filter((operation) => operation.status === 'planned');
|
|
562
568
|
if (options.dryRun)
|
|
563
|
-
return result(planned.length ? 'planned' : 'no-op', base.resolved.taskId, base.issueNumber, {
|
|
569
|
+
return result(planned.length ? 'planned' : 'no-op', base.resolved.taskId, base.issueNumber, {
|
|
570
|
+
platform: base.context.platform, capabilities: base.context.capabilities,
|
|
571
|
+
issue: snapshot, operations: plan.operations, error: null
|
|
572
|
+
});
|
|
564
573
|
if (planned.length === 0)
|
|
565
|
-
return result('no-op', base.resolved.taskId, base.issueNumber, {
|
|
574
|
+
return result('no-op', base.resolved.taskId, base.issueNumber, {
|
|
575
|
+
platform: base.context.platform, capabilities: base.context.capabilities,
|
|
576
|
+
issue: snapshot, operations: plan.operations, error: null
|
|
577
|
+
});
|
|
566
578
|
const payload = applyRestOperations(snapshot, planned);
|
|
567
579
|
const updated = base.provider.issues?.update
|
|
568
580
|
? await base.provider.issues.update({ context: providerOperationContext(base.loadedContext), target: base.issueIdentity, currentLabels: snapshot.labels, patch: payload, mutation: { idempotencyKey: `issue:update:${base.resolved.taskId}` } })
|