@akagilnc/pi-workflow-roles 0.1.4243 → 0.1.4274
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 +27 -23
- package/README.zh-CN.md +24 -21
- package/dist/acp-host/production-host.js +4607 -3524
- package/dist/engine-detour-tool.js +64 -5
- package/dist/engine-detour-usage.js +285 -0
- package/dist/headless-host/production-host.js +6057 -4974
- package/dist/navigator-attendance.js +0 -2
- package/dist/navigator-public-session.js +2 -4
- package/dist/navigator-session-contracts.js +6 -13
- package/dist/pi/role-turn-host.js +10 -0
- package/dist/public-cli/config.js +16 -20
- package/dist/public-cli/main.js +935 -613
- package/dist/public-cli/post-admission.js +72 -43
- package/dist/public-cli/registry.js +0 -57
- package/dist/public-cli/settlement.js +80 -24
- package/dist/public-cli/turn-request.js +3 -0
- package/dist/public-role-summons.js +121 -96
- package/package.json +1 -1
- package/src/engine-detour-tool.ts +106 -8
- package/src/engine-detour-usage.ts +373 -0
- package/src/host-contracts.ts +12 -1
- package/src/navigator-attendance.ts +0 -2
- package/src/navigator-public-session.ts +3 -3
- package/src/navigator-session-contracts.ts +8 -14
- package/src/pi/adapter.ts +6 -0
- package/src/pi/role-turn-host.ts +6 -0
- package/src/public-cli/cli.ts +115 -307
- package/src/public-cli/config.ts +35 -23
- package/src/public-cli/post-admission.ts +91 -49
- package/src/public-cli/registry.ts +2 -66
- package/src/public-cli/settlement.ts +148 -23
- package/src/public-cli/turn-request.ts +5 -0
- package/src/public-role-summons.ts +197 -125
- package/src/role-envelope.ts +2 -0
|
@@ -189,27 +189,55 @@ function hostSelectionFailureFromUnknown(error: unknown): HostSelectionFailure |
|
|
|
189
189
|
return failure;
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
-
|
|
193
|
-
readonly role: PublicCallableRole;
|
|
192
|
+
type SummonEnvOk = {
|
|
194
193
|
readonly home: string;
|
|
194
|
+
readonly principalAuthority: import("./host-contracts.ts").DurablePrincipalAuthority;
|
|
195
195
|
readonly agentDir: string;
|
|
196
|
-
readonly
|
|
196
|
+
readonly sessionAppender: typeof import("./pi/role-turn-host.ts").appendPiSessionCustomEntry;
|
|
197
197
|
readonly packageRoot: string;
|
|
198
|
+
readonly roleTurnHost: RoleTurnHost;
|
|
199
|
+
readonly cwd: string;
|
|
198
200
|
readonly credentials: CredentialProviders;
|
|
199
|
-
readonly
|
|
200
|
-
readonly
|
|
201
|
-
readonly
|
|
202
|
-
readonly
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
201
|
+
readonly model?: import("./host-contracts.ts").HostInstitutionalModelSelection;
|
|
202
|
+
readonly engine?: string;
|
|
203
|
+
readonly engineModel?: string;
|
|
204
|
+
readonly host?: string;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
/** #178: missing model is ok:false (typed fact), not a thrown message. */
|
|
208
|
+
type SummonEnvBuild =
|
|
209
|
+
| { readonly ok: true; readonly env: SummonEnvOk }
|
|
210
|
+
| { readonly ok: false; readonly missingModelMessage: string };
|
|
211
|
+
|
|
212
|
+
async function createSummonEnv(
|
|
213
|
+
options: {
|
|
214
|
+
readonly role: PublicCallableRole;
|
|
215
|
+
readonly home: string;
|
|
216
|
+
readonly agentDir: string;
|
|
217
|
+
readonly cwd: string;
|
|
218
|
+
readonly packageRoot: string;
|
|
219
|
+
readonly credentials: CredentialProviders;
|
|
220
|
+
readonly seat: EffectiveSeat;
|
|
221
|
+
readonly extraPiArgs?: readonly string[];
|
|
222
|
+
readonly roleTurnHost?: RoleTurnHost;
|
|
223
|
+
readonly hostAdapters?: readonly NamedRoleTurnHostAdapter[];
|
|
224
|
+
},
|
|
225
|
+
/** #178: after host selection, before missing-model — structural argv parse once. */
|
|
226
|
+
afterHost?: () => void,
|
|
227
|
+
): Promise<SummonEnvBuild> {
|
|
228
|
+
const [
|
|
229
|
+
{ piDurablePrincipalAuthority },
|
|
230
|
+
{ appendPiSessionCustomEntry },
|
|
231
|
+
{ resolveRoleTurnHost },
|
|
232
|
+
{ missingResolvedSeatModelMessage, resolvedSeatWithModel },
|
|
233
|
+
] = await Promise.all([
|
|
234
|
+
import("./pi/durable-principal.ts"),
|
|
235
|
+
import("./pi/role-turn-host.ts"),
|
|
236
|
+
import("./public-cli/role-turn-host-resolution.ts"),
|
|
237
|
+
import("./public-cli/config.ts"),
|
|
238
|
+
]);
|
|
210
239
|
const principalAuthority = piDurablePrincipalAuthority;
|
|
211
|
-
//
|
|
212
|
-
// selects; injected roleTurnHost is the pi adapter only.
|
|
240
|
+
// Host first → argv (afterHost) → missing-model → provider projection (#617/#178/#840).
|
|
213
241
|
const roleTurnHost = resolveRoleTurnHost(
|
|
214
242
|
{
|
|
215
243
|
packageRoot: options.packageRoot,
|
|
@@ -221,32 +249,39 @@ async function createSummonEnv(options: {
|
|
|
221
249
|
},
|
|
222
250
|
{ role: options.role, seat: options.seat, principalAuthority },
|
|
223
251
|
);
|
|
224
|
-
|
|
225
|
-
|
|
252
|
+
afterHost?.();
|
|
253
|
+
const seatWithModel = resolvedSeatWithModel(options.seat);
|
|
254
|
+
if (seatWithModel === undefined) {
|
|
255
|
+
return {
|
|
256
|
+
ok: false,
|
|
257
|
+
missingModelMessage: missingResolvedSeatModelMessage(options.role),
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
const hostName = seatWithModel.host ?? "pi";
|
|
226
261
|
const { loadHostProvidersTable, projectHostFacingProvider } = await import(
|
|
227
262
|
"./public-cli/host-providers.ts"
|
|
228
263
|
);
|
|
229
|
-
const hostFacingSelection =
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
loadHostProvidersTable(options.home),
|
|
236
|
-
options.home,
|
|
237
|
-
);
|
|
264
|
+
const hostFacingSelection = projectHostFacingProvider(
|
|
265
|
+
seatWithModel.selection,
|
|
266
|
+
hostName,
|
|
267
|
+
loadHostProvidersTable(options.home),
|
|
268
|
+
options.home,
|
|
269
|
+
);
|
|
238
270
|
return {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
271
|
+
ok: true,
|
|
272
|
+
env: {
|
|
273
|
+
home: options.home,
|
|
274
|
+
principalAuthority,
|
|
275
|
+
agentDir: options.agentDir,
|
|
276
|
+
sessionAppender: appendPiSessionCustomEntry,
|
|
277
|
+
packageRoot: options.packageRoot,
|
|
278
|
+
roleTurnHost,
|
|
279
|
+
cwd: options.cwd,
|
|
280
|
+
credentials: options.credentials,
|
|
281
|
+
...(hostFacingSelection === undefined ? {} : { model: hostFacingSelection }),
|
|
282
|
+
...projectSeatEngine(seatWithModel),
|
|
283
|
+
...projectSeatHost(seatWithModel),
|
|
284
|
+
},
|
|
250
285
|
};
|
|
251
286
|
}
|
|
252
287
|
|
|
@@ -271,56 +306,100 @@ export async function summonPublicRole(
|
|
|
271
306
|
const credentials =
|
|
272
307
|
options.credentials ?? (await loadCredentialProviders(agentDir));
|
|
273
308
|
const config = await loadPublicCliConfig(home);
|
|
274
|
-
// Nested summons
|
|
275
|
-
// Parent run host is not an override channel (#821 / ADR 0082: --host 旗标>席位配置>缺省 pi).
|
|
309
|
+
// Nested summons: officer seat only (flag>seat>default pi). #178 order below.
|
|
276
310
|
const seat = resolveEffectiveSeat(config, options.role, credentials);
|
|
277
|
-
let summonEnv;
|
|
278
|
-
try {
|
|
279
|
-
summonEnv = await createSummonEnv({
|
|
280
|
-
role: options.role,
|
|
281
|
-
home,
|
|
282
|
-
agentDir,
|
|
283
|
-
cwd: options.cwd,
|
|
284
|
-
packageRoot,
|
|
285
|
-
credentials,
|
|
286
|
-
seat,
|
|
287
|
-
...(options.extraPiArgs === undefined ? {} : { extraPiArgs: options.extraPiArgs }),
|
|
288
|
-
...(options.roleTurnHost === undefined ? {} : { roleTurnHost: options.roleTurnHost }),
|
|
289
|
-
...(options.hostAdapters === undefined ? {} : { hostAdapters: options.hostAdapters }),
|
|
290
|
-
});
|
|
291
|
-
} catch (error) {
|
|
292
|
-
const failure = hostSelectionFailureFromUnknown(error);
|
|
293
|
-
if (failure !== undefined) {
|
|
294
|
-
const { formatHostSelectionFailure } = await import("./public-cli/role-turn-host-resolution.ts");
|
|
295
|
-
return { exitCode: 1, stderr: formatHostSelectionFailure(failure) };
|
|
296
|
-
}
|
|
297
|
-
throw error;
|
|
298
|
-
}
|
|
299
|
-
const env = {
|
|
300
|
-
...summonEnv,
|
|
301
|
-
// Station child role run (#840): omit automatic navigator attendance.
|
|
302
|
-
stationChild: true,
|
|
303
|
-
// Host config passthrough only — same face as public CLI (#422 / #675).
|
|
304
|
-
...(config.autoResumeLimit === undefined
|
|
305
|
-
? {}
|
|
306
|
-
: { autoResumeLimit: config.autoResumeLimit }),
|
|
307
|
-
// Parent cancellation reaches the nested activation's own turn dispatch.
|
|
308
|
-
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
309
|
-
// #753: reask rides the existing notary same-ticket resume summons.instruction.
|
|
310
|
-
...(options.reviewReask === undefined ? {} : { reviewReask: options.reviewReask }),
|
|
311
|
-
// #879: verbatim submission body on officer dialogue content channel.
|
|
312
|
-
...(options.gateReviewInstruction === undefined
|
|
313
|
-
? {}
|
|
314
|
-
: { gateReviewInstruction: options.gateReviewInstruction }),
|
|
315
|
-
...(options.boundTicketNumber === undefined
|
|
316
|
-
? {}
|
|
317
|
-
: { boundTicketNumber: options.boundTicketNumber }),
|
|
318
|
-
// createRunId is the only remaining env overlay — host is seat-selected above.
|
|
319
|
-
...(options.createRunId === undefined ? {} : { createRunId: options.createRunId }),
|
|
320
|
-
};
|
|
321
311
|
const captured = options.io === undefined ? createCapturingIo() : undefined;
|
|
322
312
|
const io = options.io ?? captured!.io;
|
|
323
313
|
|
|
314
|
+
const summonEnvInput = {
|
|
315
|
+
role: options.role,
|
|
316
|
+
home,
|
|
317
|
+
agentDir,
|
|
318
|
+
cwd: options.cwd,
|
|
319
|
+
packageRoot,
|
|
320
|
+
credentials,
|
|
321
|
+
seat,
|
|
322
|
+
...(options.extraPiArgs === undefined ? {} : { extraPiArgs: options.extraPiArgs }),
|
|
323
|
+
...(options.roleTurnHost === undefined ? {} : { roleTurnHost: options.roleTurnHost }),
|
|
324
|
+
...(options.hostAdapters === undefined ? {} : { hostAdapters: options.hostAdapters }),
|
|
325
|
+
} as const;
|
|
326
|
+
|
|
327
|
+
type Prepared =
|
|
328
|
+
| { readonly ok: true; readonly env: Record<string, unknown> }
|
|
329
|
+
| { readonly ok: false; readonly exitCode: number; readonly stderr?: string };
|
|
330
|
+
|
|
331
|
+
async function prepareSummonEnv(afterHost: () => void): Promise<Prepared> {
|
|
332
|
+
try {
|
|
333
|
+
const built = await createSummonEnv(summonEnvInput, afterHost);
|
|
334
|
+
if (!built.ok) {
|
|
335
|
+
return { ok: false, exitCode: 1, stderr: built.missingModelMessage };
|
|
336
|
+
}
|
|
337
|
+
return {
|
|
338
|
+
ok: true,
|
|
339
|
+
env: {
|
|
340
|
+
...built.env,
|
|
341
|
+
stationChild: true,
|
|
342
|
+
...(config.autoResumeLimit === undefined
|
|
343
|
+
? {}
|
|
344
|
+
: { autoResumeLimit: config.autoResumeLimit }),
|
|
345
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
346
|
+
...(options.reviewReask === undefined ? {} : { reviewReask: options.reviewReask }),
|
|
347
|
+
...(options.gateReviewInstruction === undefined
|
|
348
|
+
? {}
|
|
349
|
+
: { gateReviewInstruction: options.gateReviewInstruction }),
|
|
350
|
+
...(options.boundTicketNumber === undefined
|
|
351
|
+
? {}
|
|
352
|
+
: { boundTicketNumber: options.boundTicketNumber }),
|
|
353
|
+
...(options.createRunId === undefined ? {} : { createRunId: options.createRunId }),
|
|
354
|
+
},
|
|
355
|
+
};
|
|
356
|
+
} catch (error) {
|
|
357
|
+
const failure = hostSelectionFailureFromUnknown(error);
|
|
358
|
+
if (failure !== undefined) {
|
|
359
|
+
const { formatHostSelectionFailure } = await import("./public-cli/role-turn-host-resolution.ts");
|
|
360
|
+
return { ok: false, exitCode: 1, stderr: formatHostSelectionFailure(failure) };
|
|
361
|
+
}
|
|
362
|
+
const { CliUsageError } = await import("./public-cli/cli-errors.ts");
|
|
363
|
+
if (error instanceof CliUsageError) {
|
|
364
|
+
const { presentStructuralRejection } = await import("./public-cli/settlement.ts");
|
|
365
|
+
presentStructuralRejection(error, io);
|
|
366
|
+
return { ok: false, exitCode: 2 };
|
|
367
|
+
}
|
|
368
|
+
throw error;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function projectPrepareFailure(prepared: Extract<Prepared, { ok: false }>): PublicSummonResult {
|
|
373
|
+
const parts = [prepared.stderr, captured?.stderrText()].filter(
|
|
374
|
+
(s): s is string => typeof s === "string" && s !== "",
|
|
375
|
+
);
|
|
376
|
+
const stderr = parts.length === 0 ? undefined : parts.join("");
|
|
377
|
+
return {
|
|
378
|
+
exitCode: prepared.exitCode,
|
|
379
|
+
...(stderr === undefined ? {} : { stderr }),
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/** Host → argv once → missing-model → runner. */
|
|
384
|
+
async function runPrepared<TParsed>(
|
|
385
|
+
parse: (argv: readonly string[]) => TParsed,
|
|
386
|
+
run: (
|
|
387
|
+
env: Record<string, unknown>,
|
|
388
|
+
parseOnce: () => TParsed,
|
|
389
|
+
) => Promise<{
|
|
390
|
+
exitCode: number;
|
|
391
|
+
terminal?: TerminalResult;
|
|
392
|
+
admitted?: { readonly runDirectory?: string };
|
|
393
|
+
}>,
|
|
394
|
+
) {
|
|
395
|
+
let parsedArgv!: TParsed;
|
|
396
|
+
const prepared = await prepareSummonEnv(() => {
|
|
397
|
+
parsedArgv = parse(options.argv);
|
|
398
|
+
});
|
|
399
|
+
if (!prepared.ok) return { fail: projectPrepareFailure(prepared) as PublicSummonResult };
|
|
400
|
+
return { ok: await run(prepared.env, () => parsedArgv) };
|
|
401
|
+
}
|
|
402
|
+
|
|
324
403
|
let result: {
|
|
325
404
|
exitCode: number;
|
|
326
405
|
terminal?: TerminalResult;
|
|
@@ -332,7 +411,10 @@ export async function summonPublicRole(
|
|
|
332
411
|
import("./public-cli/notary-run.ts"),
|
|
333
412
|
import("./public-cli/invocation.ts"),
|
|
334
413
|
]);
|
|
335
|
-
|
|
414
|
+
const stepped = await runPrepared(parseNotaryArgv, (env, once) =>
|
|
415
|
+
runPublicNotary(options.argv, env as never, io, once));
|
|
416
|
+
if ("fail" in stepped) return stepped.fail;
|
|
417
|
+
result = stepped.ok;
|
|
336
418
|
break;
|
|
337
419
|
}
|
|
338
420
|
case "inspector": {
|
|
@@ -340,49 +422,30 @@ export async function summonPublicRole(
|
|
|
340
422
|
import("./public-cli/inspector-run.ts"),
|
|
341
423
|
import("./public-cli/invocation.ts"),
|
|
342
424
|
]);
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
const [{ runPublicInstructionSeat }, { parseAuditorArgv }] = await Promise.all([
|
|
348
|
-
import("./public-cli/instruction-seat-run.ts"),
|
|
349
|
-
import("./public-cli/invocation.ts"),
|
|
350
|
-
]);
|
|
351
|
-
result = await runPublicInstructionSeat(
|
|
352
|
-
options.argv,
|
|
353
|
-
env,
|
|
354
|
-
io,
|
|
355
|
-
"auditor",
|
|
356
|
-
parseAuditorArgv,
|
|
357
|
-
);
|
|
358
|
-
break;
|
|
359
|
-
}
|
|
360
|
-
case "navigator": {
|
|
361
|
-
const [{ runPublicInstructionSeat }, { parseNavigatorArgv }] = await Promise.all([
|
|
362
|
-
import("./public-cli/instruction-seat-run.ts"),
|
|
363
|
-
import("./public-cli/invocation.ts"),
|
|
364
|
-
]);
|
|
365
|
-
result = await runPublicInstructionSeat(
|
|
366
|
-
options.argv,
|
|
367
|
-
env,
|
|
368
|
-
io,
|
|
369
|
-
"navigator",
|
|
370
|
-
parseNavigatorArgv,
|
|
371
|
-
);
|
|
425
|
+
const stepped = await runPrepared(parseInspectorArgv, (env, once) =>
|
|
426
|
+
runPublicInspector(options.argv, env as never, io, once));
|
|
427
|
+
if ("fail" in stepped) return stepped.fail;
|
|
428
|
+
result = stepped.ok;
|
|
372
429
|
break;
|
|
373
430
|
}
|
|
431
|
+
case "auditor":
|
|
432
|
+
case "navigator":
|
|
374
433
|
case "gatekeeper": {
|
|
375
|
-
const
|
|
434
|
+
const seat = options.role;
|
|
435
|
+
const [{ runPublicInstructionSeat }, invocation] = await Promise.all([
|
|
376
436
|
import("./public-cli/instruction-seat-run.ts"),
|
|
377
437
|
import("./public-cli/invocation.ts"),
|
|
378
438
|
]);
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
)
|
|
439
|
+
const parse =
|
|
440
|
+
seat === "auditor"
|
|
441
|
+
? invocation.parseAuditorArgv
|
|
442
|
+
: seat === "navigator"
|
|
443
|
+
? invocation.parseNavigatorArgv
|
|
444
|
+
: invocation.parseGatekeeperArgv;
|
|
445
|
+
const stepped = await runPrepared(parse, (env, once) =>
|
|
446
|
+
runPublicInstructionSeat(options.argv, env as never, io, seat, once));
|
|
447
|
+
if ("fail" in stepped) return stepped.fail;
|
|
448
|
+
result = stepped.ok;
|
|
386
449
|
break;
|
|
387
450
|
}
|
|
388
451
|
case "judge": {
|
|
@@ -390,7 +453,10 @@ export async function summonPublicRole(
|
|
|
390
453
|
import("./public-cli/judge-run.ts"),
|
|
391
454
|
import("./public-cli/invocation.ts"),
|
|
392
455
|
]);
|
|
393
|
-
|
|
456
|
+
const stepped = await runPrepared(parseJudgeArgv, (env, once) =>
|
|
457
|
+
runPublicJudge(options.argv, env as never, io, once));
|
|
458
|
+
if ("fail" in stepped) return stepped.fail;
|
|
459
|
+
result = stepped.ok;
|
|
394
460
|
break;
|
|
395
461
|
}
|
|
396
462
|
case "doctor": {
|
|
@@ -398,7 +464,10 @@ export async function summonPublicRole(
|
|
|
398
464
|
import("./public-cli/doctor-run.ts"),
|
|
399
465
|
import("./public-cli/invocation.ts"),
|
|
400
466
|
]);
|
|
401
|
-
|
|
467
|
+
const stepped = await runPrepared(parseDoctorArgv, (env, once) =>
|
|
468
|
+
runPublicDoctor(options.argv, env as never, io, once));
|
|
469
|
+
if ("fail" in stepped) return stepped.fail;
|
|
470
|
+
result = stepped.ok;
|
|
402
471
|
break;
|
|
403
472
|
}
|
|
404
473
|
case "diarist": {
|
|
@@ -406,7 +475,10 @@ export async function summonPublicRole(
|
|
|
406
475
|
import("./public-cli/diarist-run.ts"),
|
|
407
476
|
import("./public-cli/invocation.ts"),
|
|
408
477
|
]);
|
|
409
|
-
|
|
478
|
+
const stepped = await runPrepared(parseDiaristArgv, (env, once) =>
|
|
479
|
+
runPublicDiarist(options.argv, env as never, io, once));
|
|
480
|
+
if ("fail" in stepped) return stepped.fail;
|
|
481
|
+
result = stepped.ok;
|
|
410
482
|
break;
|
|
411
483
|
}
|
|
412
484
|
}
|
package/src/role-envelope.ts
CHANGED
|
@@ -175,6 +175,8 @@ export async function prepareRoleEnvelope(options: {
|
|
|
175
175
|
model: request.model === undefined ? undefined : { provider: request.model.provider },
|
|
176
176
|
runDirectory: request.runDirectory,
|
|
177
177
|
...(request.courtAttemptId === undefined ? {} : { courtAttemptId: request.courtAttemptId }),
|
|
178
|
+
...(request.invocationScopeId === undefined ? {} : { invocationScopeId: request.invocationScopeId }),
|
|
179
|
+
...(request.host === undefined || request.host.trim() === "" ? {} : { host: request.host.trim() }),
|
|
178
180
|
sessionManager: {
|
|
179
181
|
getLeafEntry: () => sessionEntries.at(-1) as ReturnType<HostContext["sessionManager"]["getLeafEntry"]>,
|
|
180
182
|
getLeafId: () => runId,
|