@fitlab-ai/agent-infra 0.11.11 → 0.11.13
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 +7 -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 +211 -213
- package/dist/lib/agent-clients/adapters/codex-orchestration.js +468 -0
- package/dist/lib/agent-clients/adapters/codex.js +40 -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/sandbox-control.js +1 -81
- package/dist/lib/internal/task-finalization.js +26 -19
- package/dist/lib/internal/task-lifecycle.js +1 -1
- package/dist/lib/internal/task-operation-registry.js +1 -1
- package/dist/lib/internal/task-validate.js +1 -1
- package/dist/lib/platform/github-client.js +33 -3
- package/dist/lib/platform/issues.js +18 -6
- 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 +7 -2
- package/dist/lib/sandbox/commands/ls.js +4 -5
- package/dist/lib/sandbox/commands/rm.js +1 -1
- package/dist/lib/sandbox/control/agent-operation.js +34 -0
- package/dist/lib/sandbox/control/client.js +14 -201
- package/dist/lib/sandbox/control/executor.js +12 -125
- package/dist/lib/sandbox/control/lifecycle.js +66 -4
- package/dist/lib/sandbox/control/protocol.js +15 -54
- package/dist/lib/sandbox/control/server.js +216 -281
- package/dist/lib/sandbox/control/task-view.js +0 -13
- package/dist/lib/sandbox/mounts.js +9 -1
- package/dist/lib/sandbox/recovery.js +31 -10
- package/dist/lib/sandbox/removal.js +28 -5
- package/dist/lib/sandbox/workspace-identity.js +18 -6
- package/dist/lib/sandbox/workspace-view.js +56 -19
- package/dist/lib/task/commands/ls.js +3 -3
- package/dist/lib/task/control-authority.js +56 -264
- package/dist/lib/task/control-recovery.js +2 -3
- package/dist/lib/task/create.js +2 -2
- package/dist/lib/task/delegation-receipts.js +74 -161
- package/dist/lib/task/events.js +88 -44
- package/dist/lib/task/finalization.js +35 -6
- package/dist/lib/task/lifecycle.js +274 -115
- package/dist/lib/task/orchestration.js +201 -194
- package/dist/lib/task/runtime-paths.js +10 -0
- package/dist/lib/task/short-id.js +37 -27
- package/dist/lib/task/verification-engine.js +32 -26
- package/dist/lib/task/workspace-snapshot.js +1 -1
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-clients/adapter.ts +39 -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 +270 -224
- package/lib/agent-clients/adapters/codex-orchestration.ts +632 -0
- package/lib/agent-clients/adapters/codex.ts +44 -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/sandbox-control.ts +0 -97
- package/lib/internal/task-finalization.ts +30 -18
- package/lib/internal/task-lifecycle.ts +1 -1
- package/lib/internal/task-operation-registry.ts +1 -1
- package/lib/internal/task-validate.ts +1 -1
- package/lib/platform/github-client.ts +34 -3
- package/lib/platform/issues.ts +18 -6
- package/lib/runtime/agent-runtime.ts +6 -41
- package/lib/sandbox/commands/control-status.ts +1 -0
- package/lib/sandbox/commands/create.ts +7 -1
- package/lib/sandbox/commands/ls.ts +4 -5
- package/lib/sandbox/commands/rm.ts +1 -1
- package/lib/sandbox/control/agent-operation.ts +49 -0
- package/lib/sandbox/control/client.ts +20 -254
- package/lib/sandbox/control/executor.ts +13 -136
- package/lib/sandbox/control/lifecycle.ts +67 -4
- package/lib/sandbox/control/protocol.ts +22 -66
- package/lib/sandbox/control/server.ts +21 -95
- package/lib/sandbox/control/task-view.ts +0 -19
- package/lib/sandbox/mounts.ts +10 -1
- package/lib/sandbox/recovery.ts +38 -17
- package/lib/sandbox/removal.ts +33 -7
- package/lib/sandbox/workspace-identity.ts +16 -6
- package/lib/sandbox/workspace-view.ts +50 -18
- package/lib/task/commands/ls.ts +3 -3
- package/lib/task/control-authority.ts +66 -378
- package/lib/task/control-recovery.ts +3 -4
- package/lib/task/create.ts +3 -3
- package/lib/task/delegation-receipts.ts +87 -231
- package/lib/task/events.ts +100 -42
- package/lib/task/finalization.ts +37 -7
- package/lib/task/lifecycle.ts +257 -109
- package/lib/task/orchestration.ts +260 -237
- package/lib/task/runtime-paths.ts +12 -0
- package/lib/task/short-id.ts +33 -40
- package/lib/task/verification-engine.ts +30 -25
- 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 -1
- package/templates/.agents/rules/README.zh-CN.md +2 -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/strategy-pattern.en.md +25 -0
- package/templates/.agents/rules/strategy-pattern.zh-CN.md +25 -0
- package/templates/.agents/skills/analyze-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/analyze-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/code-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/code-task/reference/code-rules.en.md +4 -0
- package/templates/.agents/skills/code-task/reference/code-rules.zh-CN.md +4 -0
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +0 -1
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +0 -1
- package/templates/.agents/skills/complete-task/SKILL.en.md +5 -29
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +5 -26
- package/templates/.agents/skills/plan-task/SKILL.en.md +7 -4
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +7 -4
- 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 +1 -1
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +1 -1
- 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/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/run-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/run-task/SKILL.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/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
|
@@ -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'],
|
|
@@ -1,18 +1,8 @@
|
|
|
1
|
-
import { recoverSandboxControl, requestSandboxControl,
|
|
2
|
-
import { normalizeAgentToken, AGENT_USAGE_HINT } from '../agent-clients/tokens.js';
|
|
1
|
+
import { recoverSandboxControl, requestSandboxControl, SandboxControlClientError } from '../sandbox/control/client.js';
|
|
3
2
|
import { serveSandboxControl } from '../sandbox/control/server.js';
|
|
4
3
|
import { runSandboxControlExecutor } from '../sandbox/control/executor.js';
|
|
5
4
|
import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.js';
|
|
6
5
|
import { parseTaskCreateResult, taskCreateExitCode } from '../task/create-service.js';
|
|
7
|
-
import { serializeTaskFinalizationEnvelope } from '../task/finalization-envelope.js';
|
|
8
|
-
function writeFinalizationEnvelope(status, accepted, error, changed = false, result = null, requestId = null) {
|
|
9
|
-
process.stdout.write(serializeTaskFinalizationEnvelope({ status, changed, accepted, requestId, result, error }));
|
|
10
|
-
}
|
|
11
|
-
function finalizationErrorStatus(error) {
|
|
12
|
-
if (error.code === 'SANDBOX_CONTROL_RESULT_UNKNOWN')
|
|
13
|
-
return 'unknown';
|
|
14
|
-
return error.retryable ? 'blocked' : 'failed';
|
|
15
|
-
}
|
|
16
6
|
function writeClientError(error) {
|
|
17
7
|
process.stderr.write(`${error.detail.message}\n`);
|
|
18
8
|
if (error.requestId)
|
|
@@ -31,72 +21,6 @@ function recoveredExitCode(response) {
|
|
|
31
21
|
}
|
|
32
22
|
return response.exitCode ?? 1;
|
|
33
23
|
}
|
|
34
|
-
function finalizationResponseOutput(response) {
|
|
35
|
-
try {
|
|
36
|
-
const value = JSON.parse(response.stdout);
|
|
37
|
-
if (value.version === 2
|
|
38
|
-
&& value.status
|
|
39
|
-
&& ['completed', 'failed', 'blocked', 'unknown'].includes(value.status)
|
|
40
|
-
&& (typeof value.changed === 'boolean' || value.changed === null)) {
|
|
41
|
-
return serializeTaskFinalizationEnvelope({
|
|
42
|
-
status: value.status,
|
|
43
|
-
changed: value.changed,
|
|
44
|
-
accepted: true,
|
|
45
|
-
requestId: response.id,
|
|
46
|
-
result: value.result ?? null,
|
|
47
|
-
error: value.error ?? null
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
catch {
|
|
52
|
-
// Preserve non-envelope output for diagnostics from the executor.
|
|
53
|
-
}
|
|
54
|
-
return response.stdout;
|
|
55
|
-
}
|
|
56
|
-
function sandboxFinalizationClient(args) {
|
|
57
|
-
if (args.length !== 4 || !args[0] || args[1] !== 'complete' || args[2] !== '--agent' || !args[3]) {
|
|
58
|
-
const error = { code: 'TASK_FINALIZATION_PAYLOAD_INVALID', message: 'task ref, complete intent, and --agent are required', retryable: false };
|
|
59
|
-
writeFinalizationEnvelope('failed', false, error);
|
|
60
|
-
process.stderr.write('Usage: agent-infra-internal task-finalization <N | TASK-id> complete --agent <agent>\n');
|
|
61
|
-
process.exitCode = 1;
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
const agent = normalizeAgentToken(args[3]);
|
|
65
|
-
if (!agent) {
|
|
66
|
-
const error = { code: 'TASK_FINALIZATION_PAYLOAD_INVALID', message: `invalid --agent: ${AGENT_USAGE_HINT}`, retryable: false };
|
|
67
|
-
writeFinalizationEnvelope('failed', false, error);
|
|
68
|
-
process.exitCode = 1;
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
let response;
|
|
72
|
-
try {
|
|
73
|
-
response = requestSandboxTaskFinalization({ agent });
|
|
74
|
-
}
|
|
75
|
-
catch (error) {
|
|
76
|
-
if (!(error instanceof SandboxControlClientError))
|
|
77
|
-
throw error;
|
|
78
|
-
const status = finalizationErrorStatus(error.detail);
|
|
79
|
-
writeFinalizationEnvelope(status, error.accepted, error.detail, status === 'unknown' ? null : false, null, error.requestId);
|
|
80
|
-
writeClientError(error);
|
|
81
|
-
process.exitCode = error.detail.code === 'SANDBOX_CONTROL_RESULT_UNKNOWN' ? 1 : error.detail.retryable ? 2 : 1;
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
if (response.phase === 'rejected') {
|
|
85
|
-
const error = response.error ?? {
|
|
86
|
-
code: 'SANDBOX_CONTROL_REJECTED',
|
|
87
|
-
message: 'sandbox control rejected the finalization request',
|
|
88
|
-
retryable: false
|
|
89
|
-
};
|
|
90
|
-
const status = finalizationErrorStatus(error);
|
|
91
|
-
writeFinalizationEnvelope(status, error.code === 'SANDBOX_CONTROL_RESULT_UNKNOWN', error, status === 'unknown' ? null : false, null, response.id);
|
|
92
|
-
process.stderr.write(`${error.message}\n`);
|
|
93
|
-
process.exitCode = error.code === 'SANDBOX_CONTROL_RESULT_UNKNOWN' ? 1 : error.retryable ? 2 : 1;
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
process.stdout.write(finalizationResponseOutput(response));
|
|
97
|
-
process.stderr.write(response.stderr);
|
|
98
|
-
process.exitCode = response.exitCode ?? 1;
|
|
99
|
-
}
|
|
100
24
|
async function sandboxControl(args) {
|
|
101
25
|
if (!ensureInternalHandlerRoute('sandbox-control', args))
|
|
102
26
|
return;
|
|
@@ -152,10 +76,6 @@ async function sandboxControl(args) {
|
|
|
152
76
|
}
|
|
153
77
|
if (internalHandlerRoute('sandbox-control', 'client', operation ?? '')) {
|
|
154
78
|
const [family = '', ...commandArgs] = rest;
|
|
155
|
-
if (family === 'task-finalization') {
|
|
156
|
-
sandboxFinalizationClient(commandArgs);
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
79
|
let response;
|
|
160
80
|
try {
|
|
161
81
|
response = requestSandboxControl({ family, args: commandArgs });
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
1
2
|
import { createDirectHostExecutionContext, dispatchTaskControlOperation, parseTaskControlOperation } from '../task/control-authority.js';
|
|
2
3
|
import { applyTaskFinalization } from '../task/finalization.js';
|
|
3
4
|
import { detectRepoRoot, resolveTaskRef } from '../task/resolve-ref.js';
|
|
4
5
|
import { resolveSandboxControlTransport } from './task-operation-registry.js';
|
|
5
|
-
import {
|
|
6
|
+
import { quiesceSandboxControlForTaskCompletion } from '../sandbox/control/lifecycle.js';
|
|
7
|
+
import { resolveTaskRuntimeRoot } from '../task/runtime-paths.js';
|
|
6
8
|
import { serializeTaskFinalizationEnvelope } from '../task/finalization-envelope.js';
|
|
9
|
+
import { verifyTaskEvent } from '../task/verification.js';
|
|
7
10
|
import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.js';
|
|
8
11
|
const USAGE = 'Usage: agent-infra-internal task-finalization <N | TASK-id> complete --agent <agent>\n';
|
|
9
12
|
function envelope(status, changed, accepted, result, error, requestId = null) {
|
|
@@ -64,26 +67,30 @@ async function taskFinalization(args = []) {
|
|
|
64
67
|
};
|
|
65
68
|
const transport = resolveSandboxControlTransport(process.env, { localWorkflow: true });
|
|
66
69
|
if (transport.kind === 'sandbox-local') {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const clientError = error instanceof SandboxControlClientError ? error : null;
|
|
76
|
-
const detail = clientError
|
|
77
|
-
? clientError.detail
|
|
78
|
-
: { code: 'SANDBOX_CONTROL_CLIENT_FAILED', message: error instanceof Error ? error.message : String(error), retryable: false };
|
|
79
|
-
const status = detail.code === 'SANDBOX_CONTROL_RESULT_UNKNOWN'
|
|
80
|
-
? 'unknown'
|
|
81
|
-
: detail.retryable ? 'blocked' : 'failed';
|
|
82
|
-
const changed = status === 'unknown' ? null : false;
|
|
83
|
-
process.stdout.write(envelope(status, changed, clientError?.accepted ?? false, null, detail, clientError?.requestId ?? null));
|
|
84
|
-
process.exitCode = exitCode(status);
|
|
70
|
+
const statusDir = process.env.AGENT_INFRA_CONTROL_STATUS_DIR;
|
|
71
|
+
const taskId = process.env.AGENT_INFRA_TASK_ID;
|
|
72
|
+
const generation = process.env.AGENT_INFRA_CONTROL_GENERATION;
|
|
73
|
+
const controlRootId = process.env.AGENT_INFRA_CONTROL_ROOT_ID;
|
|
74
|
+
if (!statusDir || !taskId || !generation || !controlRootId || taskId !== resolved.taskId) {
|
|
75
|
+
const detail = { code: 'TASK_CONTROL_TRANSPORT_INVALID', message: 'sandbox task control identity is incomplete', retryable: false };
|
|
76
|
+
process.stdout.write(envelope('failed', false, true, null, detail));
|
|
77
|
+
process.exitCode = 1;
|
|
85
78
|
return;
|
|
86
79
|
}
|
|
80
|
+
const result = await applyTaskFinalization(boundOperation.request, {
|
|
81
|
+
repoRoot,
|
|
82
|
+
beforeLifecycle: async (currentTaskId) => {
|
|
83
|
+
if (currentTaskId !== taskId)
|
|
84
|
+
throw new Error('SANDBOX_CONTROL_IDENTITY_MISMATCH');
|
|
85
|
+
await quiesceSandboxControlForTaskCompletion(path.join(resolveTaskRuntimeRoot(taskId, { repoRoot }), 'sandbox-control'), { taskId, generation, controlRootId, statusDir });
|
|
86
|
+
},
|
|
87
|
+
preflight: (request, options) => verifyTaskEvent({ ...request, event: 'complete-task.hard-preflight' }, options)
|
|
88
|
+
});
|
|
89
|
+
const status = result.status === 'prepared' ? 'failed' : result.status;
|
|
90
|
+
process.stdout.write(envelope(status, result.changed, true, result, result.error
|
|
91
|
+
?? (result.status === 'prepared' ? { code: 'TASK_FINALIZATION_PREPARATION_INCOMPLETE', message: 'finalization did not commit', retryable: true } : null)));
|
|
92
|
+
process.exitCode = exitCode(status);
|
|
93
|
+
return;
|
|
87
94
|
}
|
|
88
95
|
const result = await dispatchTaskControlOperation(createDirectHostExecutionContext({ repoRoot }), boundOperation);
|
|
89
96
|
if (result.status === 'prepared') {
|
|
@@ -2,7 +2,7 @@ import { createDirectHostExecutionContext, dispatchTaskControlOperation, parseTa
|
|
|
2
2
|
import { lifecycleIntentCatalog } from '../task/lifecycle.js';
|
|
3
3
|
import { detectRepoRoot, resolveTaskRef } from '../task/resolve-ref.js';
|
|
4
4
|
import { ensureInternalHandlerRoute, internalHandlerRoute } from './cli-route-inventory.js';
|
|
5
|
-
const USAGE = `Usage: agent-infra-internal task-lifecycle <N | TASK-id> <intent> --agent <agent> [intent flags] [--dry-run]\n\nIntents: ${lifecycleIntentCatalog.join(', ')}\nrecover-started: --auto\n`;
|
|
5
|
+
const USAGE = `Usage: agent-infra-internal task-lifecycle <N | TASK-id> <intent> --agent <agent> [intent flags] [--dry-run]\n\nIntents: ${lifecycleIntentCatalog.filter((intent) => intent !== 'complete').join(', ')}\nrecover-started: --auto\n`;
|
|
6
6
|
function usageFailure(message) {
|
|
7
7
|
process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'LIFECYCLE_PAYLOAD_INVALID', message } })}\n`);
|
|
8
8
|
process.stderr.write(USAGE);
|
|
@@ -19,8 +19,8 @@ function internalTaskRoutes() {
|
|
|
19
19
|
descriptor('internal', 'sandbox-control', 'client', 'conditional', 'progress', 'delegated'),
|
|
20
20
|
descriptor('internal', 'agent-client', 'next-steps', 'non-task', 'diagnostic', 'none'),
|
|
21
21
|
descriptor('internal', 'agent-client', 'model-selection', 'non-task', 'diagnostic', 'none'),
|
|
22
|
+
descriptor('internal', 'agent-client', 'launch-carrier', 'non-task', 'diagnostic', 'none'),
|
|
22
23
|
descriptor('internal', 'codex-lifecycle', 'preflight', 'non-task', 'diagnostic', 'none'),
|
|
23
|
-
descriptor('internal', 'codex-lifecycle', 'capability-arm', 'conditional', 'progress'),
|
|
24
24
|
descriptor('internal', 'codex-lifecycle', 'hook-event', 'conditional', 'progress'),
|
|
25
25
|
descriptor('internal', 'codex-lifecycle', 'resolve-start', 'conditional', 'progress'),
|
|
26
26
|
descriptor('internal', 'codex-lifecycle', 'resolve-stop', 'conditional', 'progress'),
|
|
@@ -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);
|
|
@@ -18,6 +18,32 @@ function boundedFailureDetail(result) {
|
|
|
18
18
|
? diagnostic
|
|
19
19
|
: `${diagnostic.slice(0, ERROR_DETAIL_LIMIT)}… [truncated]`;
|
|
20
20
|
}
|
|
21
|
+
function requestDiagnostics(args, request, attempt, errorMessage) {
|
|
22
|
+
if (process.env.AGENT_INFRA_GH_DIAGNOSTICS !== '1' && !/rate.?limit/iu.test(errorMessage))
|
|
23
|
+
return '';
|
|
24
|
+
const apiIndex = args.indexOf('api');
|
|
25
|
+
const endpoint = apiIndex < 0
|
|
26
|
+
? args.slice(0, 2).filter((arg) => !arg.startsWith('-')).join(' ')
|
|
27
|
+
: args.slice(apiIndex + 1).find((arg) => !arg.startsWith('-') && !arg.includes('=')) || 'unknown';
|
|
28
|
+
const safeEndpoint = endpoint.startsWith('http')
|
|
29
|
+
? (() => {
|
|
30
|
+
try {
|
|
31
|
+
const url = new URL(endpoint);
|
|
32
|
+
return `${url.host}${url.pathname}`;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return 'unknown';
|
|
36
|
+
}
|
|
37
|
+
})()
|
|
38
|
+
: endpoint.split('?')[0] || 'unknown';
|
|
39
|
+
const methodIndex = args.findIndex((arg) => arg === '-X' || arg === '--method');
|
|
40
|
+
const methodFromArgs = methodIndex >= 0 ? args[methodIndex + 1] : undefined;
|
|
41
|
+
const method = methodFromArgs || request.method || (safeEndpoint === 'graphql' ? 'POST' : 'GET');
|
|
42
|
+
const tokenEnvironment = ['GH_TOKEN', 'GITHUB_TOKEN', 'GH_ENTERPRISE_TOKEN', 'GITHUB_ENTERPRISE_TOKEN']
|
|
43
|
+
.filter((name) => Boolean(process.env[name]));
|
|
44
|
+
const configDirOverride = Boolean(process.env.GH_CONFIG_DIR);
|
|
45
|
+
return ` [gh-diagnostic endpoint=${safeEndpoint} method=${method} attempt=${attempt} tokenEnv=${tokenEnvironment.join(',') || 'none'} ghConfigDirOverride=${configDirOverride}]`;
|
|
46
|
+
}
|
|
21
47
|
function defaultRunner(args, options) {
|
|
22
48
|
const command = process.env.AGENT_INFRA_GH_BIN || 'gh';
|
|
23
49
|
let prefix = [];
|
|
@@ -135,14 +161,18 @@ function createGitHubClient(options = {}) {
|
|
|
135
161
|
if (result.status === 0)
|
|
136
162
|
return { ok: true, value: result.stdout };
|
|
137
163
|
const error = classifyGitHubFailure(result);
|
|
164
|
+
const requestDetail = requestDiagnostics(args, request, attempt + 1, error.message);
|
|
165
|
+
const contextualError = requestDetail
|
|
166
|
+
? { ...error, message: `${error.message}${requestDetail}` }
|
|
167
|
+
: error;
|
|
138
168
|
if (!retryableMethod || !error.requestRetryable)
|
|
139
|
-
return { ok: false, error: clientError(
|
|
169
|
+
return { ok: false, error: clientError(contextualError) };
|
|
140
170
|
if (attempt >= delays.length) {
|
|
141
171
|
return {
|
|
142
172
|
ok: false,
|
|
143
173
|
error: error.code === 'NETWORK_TRANSIENT'
|
|
144
|
-
? { ...clientError(
|
|
145
|
-
: clientError(
|
|
174
|
+
? { ...clientError(contextualError), code: 'NETWORK_RETRY_EXHAUSTED', message: `${contextualError.message} (retry exhausted)` }
|
|
175
|
+
: clientError(contextualError)
|
|
146
176
|
};
|
|
147
177
|
}
|
|
148
178
|
sleep(delays[attempt]);
|
|
@@ -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}` } })
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
|
|
2
|
+
import { resolveTaskRuntimeRoot } from '../task/runtime-paths.js';
|
|
3
3
|
function runtimeError(code, message) {
|
|
4
4
|
const error = new Error(`${code}: ${message}`);
|
|
5
5
|
error.name = code;
|
|
@@ -9,16 +9,9 @@ function boundControlContext(env) {
|
|
|
9
9
|
return [
|
|
10
10
|
'AGENT_INFRA_CONTROL_TOKEN',
|
|
11
11
|
'AGENT_INFRA_CONTROL_GENERATION',
|
|
12
|
-
'AGENT_INFRA_EXECUTOR_MANIFEST'
|
|
13
|
-
'AGENT_INFRA_CODEX_CONTROLLER_CONTEXT'
|
|
12
|
+
'AGENT_INFRA_EXECUTOR_MANIFEST'
|
|
14
13
|
].some((key) => typeof env[key] === 'string' && env[key].length > 0);
|
|
15
14
|
}
|
|
16
|
-
function clientNamespace(client) {
|
|
17
|
-
if (!CLIENT_NAMESPACE.test(client)) {
|
|
18
|
-
throw runtimeError('AGENT_INFRA_RUNTIME_CLIENT_INVALID', `invalid runtime client namespace '${client}'`);
|
|
19
|
-
}
|
|
20
|
-
return client;
|
|
21
|
-
}
|
|
22
15
|
export function resolveAgentRuntimeRoot(options = {}) {
|
|
23
16
|
const env = options.env ?? process.env;
|
|
24
17
|
const configured = env.AGENT_INFRA_RUNTIME_DIR;
|
|
@@ -28,29 +21,13 @@ export function resolveAgentRuntimeRoot(options = {}) {
|
|
|
28
21
|
}
|
|
29
22
|
return path.resolve(configured);
|
|
30
23
|
}
|
|
24
|
+
const taskId = env.AGENT_INFRA_TASK_ID;
|
|
25
|
+
if (taskId) {
|
|
26
|
+
return resolveTaskRuntimeRoot(taskId, { repoRoot: options.repoRoot });
|
|
27
|
+
}
|
|
31
28
|
if (boundControlContext(env)) {
|
|
32
29
|
throw runtimeError('AGENT_INFRA_RUNTIME_DIR_REQUIRED', 'task-bound control context requires AGENT_INFRA_RUNTIME_DIR');
|
|
33
30
|
}
|
|
34
31
|
return path.join(path.resolve(options.repoRoot ?? process.cwd()), '.agents', 'workspace', '.runtime');
|
|
35
32
|
}
|
|
36
|
-
export function resolveAgentRuntimeStoreRoot(options = {}) {
|
|
37
|
-
const client = clientNamespace(options.client ?? 'codex');
|
|
38
|
-
if (options.explicitRoot)
|
|
39
|
-
return path.resolve(options.explicitRoot);
|
|
40
|
-
const env = options.env ?? process.env;
|
|
41
|
-
const runtimeRoot = resolveAgentRuntimeRoot({ repoRoot: options.repoRoot, env });
|
|
42
|
-
if (env.AGENT_INFRA_RUNTIME_DIR) {
|
|
43
|
-
if (!options.store) {
|
|
44
|
-
throw runtimeError('AGENT_INFRA_RUNTIME_STORE_INVALID', 'store kind is required for task-bound runtime');
|
|
45
|
-
}
|
|
46
|
-
return path.join(runtimeRoot, 'clients', client, options.store);
|
|
47
|
-
}
|
|
48
|
-
if (client === 'codex' && options.store) {
|
|
49
|
-
return path.join(runtimeRoot, `codex-${options.store}`);
|
|
50
|
-
}
|
|
51
|
-
if (!options.store) {
|
|
52
|
-
throw runtimeError('AGENT_INFRA_RUNTIME_STORE_INVALID', 'store kind is required');
|
|
53
|
-
}
|
|
54
|
-
return path.join(runtimeRoot, 'clients', client, options.store);
|
|
55
|
-
}
|
|
56
33
|
//# sourceMappingURL=agent-runtime.js.map
|