@bastani/atomic 0.9.11-alpha.6 → 0.9.11-alpha.7
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/CHANGELOG.md +14 -0
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/skills/impeccable/SKILL.md +33 -129
- package/dist/builtin/workflows/skills/impeccable/agents/impeccable_asset_producer.toml +11 -3
- package/dist/builtin/workflows/skills/impeccable/agents/impeccable_documenter.toml +26 -0
- package/dist/builtin/workflows/skills/impeccable/agents/impeccable_finish_reviewer.toml +35 -0
- package/dist/builtin/workflows/skills/impeccable/reference/android.md +1 -1
- package/dist/builtin/workflows/skills/impeccable/reference/animate.md +72 -189
- package/dist/builtin/workflows/skills/impeccable/reference/audit.md +10 -9
- package/dist/builtin/workflows/skills/impeccable/reference/audit.native.md +2 -2
- package/dist/builtin/workflows/skills/impeccable/reference/bolder.md +19 -108
- package/dist/builtin/workflows/skills/impeccable/reference/clarify.md +59 -253
- package/dist/builtin/workflows/skills/impeccable/reference/colorize.md +51 -222
- package/dist/builtin/workflows/skills/impeccable/reference/craft-floor.md +45 -0
- package/dist/builtin/workflows/skills/impeccable/reference/craft.md +3 -121
- package/dist/builtin/workflows/skills/impeccable/reference/critique.md +28 -20
- package/dist/builtin/workflows/skills/impeccable/reference/degraded/asset-producer.md +97 -0
- package/dist/builtin/workflows/skills/impeccable/reference/degraded/documenter.md +23 -0
- package/dist/builtin/workflows/skills/impeccable/reference/degraded/finish-reviewer.md +32 -0
- package/dist/builtin/workflows/skills/impeccable/reference/degraded/manual-edit-applier.md +92 -0
- package/dist/builtin/workflows/skills/impeccable/reference/delight.md +47 -279
- package/dist/builtin/workflows/skills/impeccable/reference/distill.md +2 -2
- package/dist/builtin/workflows/skills/impeccable/reference/doctor.md +53 -0
- package/dist/builtin/workflows/skills/impeccable/reference/document.md +60 -73
- package/dist/builtin/workflows/skills/impeccable/reference/harden.md +1 -12
- package/dist/builtin/workflows/skills/impeccable/reference/hooks.md +17 -4
- package/dist/builtin/workflows/skills/impeccable/reference/init.md +64 -163
- package/dist/builtin/workflows/skills/impeccable/reference/ios.md +1 -1
- package/dist/builtin/workflows/skills/impeccable/reference/layout.md +52 -153
- package/dist/builtin/workflows/skills/impeccable/reference/live.md +44 -32
- package/dist/builtin/workflows/skills/impeccable/reference/new-work.md +105 -0
- package/dist/builtin/workflows/skills/impeccable/reference/{product.md → operate.md} +6 -5
- package/dist/builtin/workflows/skills/impeccable/reference/optimize.md +4 -4
- package/dist/builtin/workflows/skills/impeccable/reference/overdrive.md +1 -4
- package/dist/builtin/workflows/skills/impeccable/reference/polish.md +68 -212
- package/dist/builtin/workflows/skills/impeccable/reference/quieter.md +3 -3
- package/dist/builtin/workflows/skills/impeccable/reference/routing.md +18 -0
- package/dist/builtin/workflows/skills/impeccable/reference/shape.md +38 -144
- package/dist/builtin/workflows/skills/impeccable/reference/typeset.md +48 -269
- package/dist/builtin/workflows/skills/impeccable/reference/visualize.md +38 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/command-metadata.json +1 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/concept-seed.mjs +584 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/context-signals.mjs +117 -9
- package/dist/builtin/workflows/skills/impeccable/scripts/context.mjs +486 -59
- package/dist/builtin/workflows/skills/impeccable/scripts/critique-storage.mjs +16 -45
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/browser/injected/index.mjs +96 -10
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/cli/main.mjs +143 -26
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/design-system.mjs +181 -12
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +3187 -182
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs +102 -7
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs +282 -70
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +183 -15
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs +22 -7
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/findings.mjs +7 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/node/file-system.mjs +16 -2
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/registry/antipatterns.mjs +155 -42
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/rules/checks.mjs +2988 -155
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/shared/constants.mjs +11 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/doctor.mjs +336 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/generate-image.mjs +232 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/hook-admin.mjs +90 -10
- package/dist/builtin/workflows/skills/impeccable/scripts/hook-lib.mjs +410 -78
- package/dist/builtin/workflows/skills/impeccable/scripts/hook.mjs +25 -8
- package/dist/builtin/workflows/skills/impeccable/scripts/lib/artifact-schema.mjs +93 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/lib/composition-catalog.mjs +165 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/lib/concept-catalog.mjs +329 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/lib/impeccable-config.mjs +20 -5
- package/dist/builtin/workflows/skills/impeccable/scripts/lib/impeccable-paths.mjs +16 -8
- package/dist/builtin/workflows/skills/impeccable/scripts/lib/provider.mjs +1 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/lib/staleness-deep.mjs +455 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/lib/staleness-notice.mjs +169 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/lib/staleness.mjs +457 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/lib/surface-briefs.mjs +151 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/lib/target-slug.mjs +33 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/lib/template-extensions.mjs +146 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live/completion.mjs +10 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/live/event-validation.mjs +15 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live/generation-preflight.mjs +149 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live/poll-lanes.mjs +14 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live/session-store.mjs +109 -32
- package/dist/builtin/workflows/skills/impeccable/scripts/live/source-lock.mjs +105 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live/source-search.mjs +105 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live/sveltekit-adapter.mjs +8 -6
- package/dist/builtin/workflows/skills/impeccable/scripts/live/tanstack-adapter.mjs +280 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-accept.mjs +208 -68
- package/dist/builtin/workflows/skills/impeccable/scripts/live-browser.js +563 -112
- package/dist/builtin/workflows/skills/impeccable/scripts/live-commit-manual-edits.mjs +3 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-inject.mjs +198 -13
- package/dist/builtin/workflows/skills/impeccable/scripts/live-insert.mjs +24 -6
- package/dist/builtin/workflows/skills/impeccable/scripts/live-manual-edit-evidence.mjs +6 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/live-poll.mjs +44 -14
- package/dist/builtin/workflows/skills/impeccable/scripts/live-server.mjs +398 -33
- package/dist/builtin/workflows/skills/impeccable/scripts/live-status.mjs +9 -5
- package/dist/builtin/workflows/skills/impeccable/scripts/live-wrap.mjs +81 -67
- package/dist/builtin/workflows/skills/impeccable/scripts/live.mjs +7 -2
- package/dist/builtin/workflows/skills/impeccable/scripts/palette.mjs +76 -81
- package/dist/builtin/workflows/skills/impeccable/scripts/pin.mjs +2 -2
- package/dist/builtin/workflows/skills/impeccable/scripts/serve-question.mjs +890 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/surface-brief.mjs +74 -0
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +201 -22
- package/dist/builtin/workflows/src/runs/foreground/executor-stage-control.ts +23 -9
- package/dist/builtin/workflows/src/runs/foreground/executor-stage-replay.ts +1 -0
- package/dist/builtin/workflows/src/runs/foreground/postmortem-stage-chat.ts +20 -5
- package/dist/builtin/workflows/src/runs/foreground/stage-control-registry.ts +10 -0
- package/dist/builtin/workflows/src/runs/foreground/stage-delivery-activity.ts +86 -0
- package/dist/builtin/workflows/src/runs/foreground/stage-runner-context.ts +6 -2
- package/dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts +19 -13
- package/dist/builtin/workflows/src/runs/foreground/stage-runner-send-user-message.ts +8 -0
- package/dist/builtin/workflows/src/runs/foreground/stage-runner-types.ts +16 -0
- package/dist/builtin/workflows/src/tui/stage-chat-view-delivery-activity.ts +121 -0
- package/dist/builtin/workflows/src/tui/stage-chat-view-live-events.ts +42 -0
- package/dist/builtin/workflows/src/tui/stage-chat-view-state.ts +16 -0
- package/dist/builtin/workflows/src/tui/stage-chat-view-types.ts +4 -0
- package/dist/modes/interactive/components/chat-session-host-actions.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-actions.js +2 -14
- package/dist/modes/interactive/components/chat-session-host-actions.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-events.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-events.js +9 -0
- package/dist/modes/interactive/components/chat-session-host-events.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-runtime.d.ts +25 -0
- package/dist/modes/interactive/components/chat-session-host-runtime.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host-runtime.js +53 -0
- package/dist/modes/interactive/components/chat-session-host-runtime.js.map +1 -1
- package/dist/modes/interactive/components/chat-session-host.d.ts +13 -0
- package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
- package/dist/modes/interactive/components/chat-session-host.js +22 -1
- package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
- package/dist/modes/interactive/interactive-agent-events.js +9 -3
- package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
- package/docs/tui.md +7 -2
- package/docs/workflows.md +1 -1
- package/npm-shrinkwrap.json +23 -23
- package/package.json +2 -2
- package/dist/builtin/workflows/skills/impeccable/reference/brand.md +0 -108
- package/dist/builtin/workflows/skills/impeccable/reference/codex.md +0 -105
- package/dist/builtin/workflows/skills/impeccable/reference/interaction-design.md +0 -189
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
5
|
+
import { resolveProjectRoot } from './context.mjs';
|
|
6
|
+
import {
|
|
7
|
+
listSurfaceBriefs,
|
|
8
|
+
resolveSurfaceBrief,
|
|
9
|
+
surfaceBriefPathForTarget,
|
|
10
|
+
writeSurfaceBrief,
|
|
11
|
+
} from './lib/surface-briefs.mjs';
|
|
12
|
+
|
|
13
|
+
function summary(brief, projectRoot) {
|
|
14
|
+
return {
|
|
15
|
+
slug: brief.slug,
|
|
16
|
+
path: path.relative(projectRoot, brief.path).split(path.sep).join('/'),
|
|
17
|
+
primaryTarget: brief.primaryTarget,
|
|
18
|
+
relatedTargets: brief.relatedTargets,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function main(argv) {
|
|
23
|
+
const [command, target, bodyFile, ...relatedTargets] = argv;
|
|
24
|
+
const projectRoot = resolveProjectRoot(process.cwd(), target ? { targetPath: target } : {});
|
|
25
|
+
if (command === 'path') {
|
|
26
|
+
const filePath = surfaceBriefPathForTarget(target, { projectRoot });
|
|
27
|
+
if (!filePath) throw new Error('surface brief path requires a concrete target');
|
|
28
|
+
process.stdout.write(`${path.relative(process.cwd(), filePath) || filePath}\n`);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (command === 'list') {
|
|
32
|
+
process.stdout.write(`${JSON.stringify(listSurfaceBriefs(projectRoot).map((brief) => summary(brief, projectRoot)), null, 2)}\n`);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (command === 'read') {
|
|
36
|
+
const result = resolveSurfaceBrief(projectRoot, target || null);
|
|
37
|
+
if (result.brief) {
|
|
38
|
+
process.stdout.write(result.brief.text);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (result.candidates.length) process.stderr.write(`${JSON.stringify(result.candidates.map((brief) => summary(brief, projectRoot)), null, 2)}\n`);
|
|
42
|
+
process.exit(2);
|
|
43
|
+
}
|
|
44
|
+
if (command === 'write') {
|
|
45
|
+
if (!target || !bodyFile) throw new Error('usage: surface-brief.mjs write <primary-target> <body-file>');
|
|
46
|
+
const filePath = writeSurfaceBrief({
|
|
47
|
+
projectRoot,
|
|
48
|
+
primaryTarget: target,
|
|
49
|
+
relatedTargets,
|
|
50
|
+
body: fs.readFileSync(bodyFile, 'utf-8'),
|
|
51
|
+
});
|
|
52
|
+
process.stdout.write(`${path.relative(process.cwd(), filePath) || filePath}\n`);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
throw new Error('usage: surface-brief.mjs <path|list|read|write> [target] [body-file] [related-target ...]');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function isMainModule() {
|
|
59
|
+
if (!process.argv[1]) return false;
|
|
60
|
+
try {
|
|
61
|
+
return fs.realpathSync(fileURLToPath(import.meta.url)) === fs.realpathSync(process.argv[1]);
|
|
62
|
+
} catch {
|
|
63
|
+
return import.meta.url === pathToFileURL(process.argv[1]).href;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (isMainModule()) {
|
|
68
|
+
try {
|
|
69
|
+
main(process.argv.slice(2));
|
|
70
|
+
} catch (error) {
|
|
71
|
+
process.stderr.write(`${error?.message || error}\n`);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -41452,16 +41452,95 @@ function isTerminalStageChatState(status) {
|
|
|
41452
41452
|
return isTerminalOrNonStreamingStageChatStatus(status);
|
|
41453
41453
|
}
|
|
41454
41454
|
|
|
41455
|
+
// dist/builtin/workflows/src/tui/stage-chat-view-delivery-activity.ts
|
|
41456
|
+
function subscribeStageChatDeliveryActivity(ctx) {
|
|
41457
|
+
const handle = ctx.handle;
|
|
41458
|
+
if (!handle?.subscribeDeliveryActivity)
|
|
41459
|
+
return null;
|
|
41460
|
+
return handle.subscribeDeliveryActivity((event) => {
|
|
41461
|
+
applyStageChatDeliveryActivityEvent(ctx, event);
|
|
41462
|
+
});
|
|
41463
|
+
}
|
|
41464
|
+
function applyStageChatDeliveryActivityEvent(ctx, event) {
|
|
41465
|
+
if (event.type === "delivery_start") {
|
|
41466
|
+
ctx.terminalLifecycleFenced = false;
|
|
41467
|
+
ctx.deliveryLifecycles.set(event.deliveryId, ctx.chatHost.beginExternalPromptLifecycle());
|
|
41468
|
+
return;
|
|
41469
|
+
}
|
|
41470
|
+
if (!ctx.deliveryLifecycles.has(event.deliveryId))
|
|
41471
|
+
return;
|
|
41472
|
+
const generation = ctx.deliveryLifecycles.get(event.deliveryId);
|
|
41473
|
+
ctx.deliveryLifecycles.delete(event.deliveryId);
|
|
41474
|
+
if (!ownsStageChatLifecycleGeneration(ctx, generation)) {
|
|
41475
|
+
ctx.chatHost.settleExternalPromptLifecycle(generation);
|
|
41476
|
+
}
|
|
41477
|
+
if (!hasActiveStageChatDelivery(ctx) && isStageChatContextTerminal(ctx)) {
|
|
41478
|
+
ctx.terminalLifecycleFenced = true;
|
|
41479
|
+
}
|
|
41480
|
+
}
|
|
41481
|
+
function ownsStageChatLifecycleGeneration(ctx, generation) {
|
|
41482
|
+
for (const active of ctx.deliveryLifecycles.values()) {
|
|
41483
|
+
if (active === generation)
|
|
41484
|
+
return true;
|
|
41485
|
+
}
|
|
41486
|
+
return false;
|
|
41487
|
+
}
|
|
41488
|
+
function hasActiveStageChatDelivery(ctx) {
|
|
41489
|
+
return ctx.deliveryLifecycles.size > 0;
|
|
41490
|
+
}
|
|
41491
|
+
function isStageChatContextTerminal(ctx) {
|
|
41492
|
+
return isTerminalStageChatState(ctx.lastObservedRunStatus) || isTerminalStageChatState(ctx.lastObservedStageStatus);
|
|
41493
|
+
}
|
|
41494
|
+
function reconcileStageChatDeliveryLifecycle(ctx) {
|
|
41495
|
+
if (!hasActiveStageChatDelivery(ctx))
|
|
41496
|
+
return;
|
|
41497
|
+
if (ctx.chatHost.isStreaming() && ctx.chatHost.hasAnimationTick())
|
|
41498
|
+
return;
|
|
41499
|
+
const generation = ctx.chatHost.reassertExternalPromptLifecycle();
|
|
41500
|
+
for (const deliveryId of [...ctx.deliveryLifecycles.keys()]) {
|
|
41501
|
+
ctx.deliveryLifecycles.set(deliveryId, generation);
|
|
41502
|
+
}
|
|
41503
|
+
}
|
|
41504
|
+
function invalidateStageChatDeliveryLifecycles(ctx) {
|
|
41505
|
+
ctx.deliveryLifecycles.clear();
|
|
41506
|
+
ctx.terminalLifecycleFenced = true;
|
|
41507
|
+
}
|
|
41508
|
+
|
|
41455
41509
|
// dist/builtin/workflows/src/tui/stage-chat-view-live-events.ts
|
|
41456
41510
|
function applyStageChatLiveHandleEvent(ctx, event) {
|
|
41511
|
+
const staleTerminalStart = isStaleTerminalLifecycleStart(ctx, event);
|
|
41457
41512
|
ctx.chatHost.applyAgentEvent(event);
|
|
41513
|
+
if (staleTerminalStart) {
|
|
41514
|
+
retainTerminalCleanup(ctx);
|
|
41515
|
+
return;
|
|
41516
|
+
}
|
|
41517
|
+
if (isCompactionEndEvent(event))
|
|
41518
|
+
reconcileStageChatDeliveryLifecycle(ctx);
|
|
41458
41519
|
if (!shouldCleanupAfterLiveEvent(ctx, event))
|
|
41459
41520
|
return;
|
|
41521
|
+
retainTerminalCleanup(ctx);
|
|
41522
|
+
}
|
|
41523
|
+
function retainTerminalCleanup(ctx) {
|
|
41460
41524
|
const hadAnimationTick = ctx.chatHost.hasAnimationTick();
|
|
41461
41525
|
ctx.chatHost.clearBusyForTerminalWorkflowStage();
|
|
41462
41526
|
if (hadAnimationTick !== ctx.chatHost.hasAnimationTick())
|
|
41463
41527
|
ctx.requestRender?.();
|
|
41464
41528
|
}
|
|
41529
|
+
function isStaleTerminalLifecycleStart(ctx, event) {
|
|
41530
|
+
if (!ctx.terminalLifecycleFenced)
|
|
41531
|
+
return false;
|
|
41532
|
+
const type = String(event.type ?? "");
|
|
41533
|
+
if (type !== "agent_start" && type !== "turn_start")
|
|
41534
|
+
return false;
|
|
41535
|
+
if (hasActiveStageChatDelivery(ctx))
|
|
41536
|
+
return false;
|
|
41537
|
+
if (ctx.chatHost.isStreaming())
|
|
41538
|
+
return false;
|
|
41539
|
+
return isCurrentRunOrStageTerminal(ctx);
|
|
41540
|
+
}
|
|
41541
|
+
function isCompactionEndEvent(event) {
|
|
41542
|
+
return String(event.type ?? "") === "compaction_end";
|
|
41543
|
+
}
|
|
41465
41544
|
function shouldCleanupAfterLiveEvent(ctx, event) {
|
|
41466
41545
|
if (!isToolExecutionLiveEvent(event))
|
|
41467
41546
|
return false;
|
|
@@ -41550,8 +41629,11 @@ function initializeStageChatView(ctx, opts) {
|
|
|
41550
41629
|
ctx.lastObservedStageStatus = undefined;
|
|
41551
41630
|
ctx.lastObservedRunStatus = undefined;
|
|
41552
41631
|
ctx.seenNoticeIds = new Set;
|
|
41632
|
+
ctx.deliveryLifecycles = new Map;
|
|
41633
|
+
ctx.terminalLifecycleFenced = false;
|
|
41553
41634
|
ctx._unsubscribeStore = null;
|
|
41554
41635
|
ctx._unsubscribeHandle = null;
|
|
41636
|
+
ctx._unsubscribeDeliveryActivity = null;
|
|
41555
41637
|
ctx._unsubscribeFooterData = null;
|
|
41556
41638
|
ctx._unregisterStageUiHost = null;
|
|
41557
41639
|
installFocusHold(ctx);
|
|
@@ -41581,6 +41663,7 @@ function initializeStageChatView(ctx, opts) {
|
|
|
41581
41663
|
ctx._unsubscribeStore = ctx.store.subscribe(() => handleStoreUpdate(ctx));
|
|
41582
41664
|
ctx._unsubscribeFooterData = ctx.footerData?.onBranchChange(() => ctx.requestRender?.()) ?? null;
|
|
41583
41665
|
if (ctx.handle) {
|
|
41666
|
+
ctx._unsubscribeDeliveryActivity = subscribeStageChatDeliveryActivity(ctx);
|
|
41584
41667
|
ctx._unsubscribeHandle = ctx.handle.subscribe((event) => applyStageChatLiveHandleEvent(ctx, event));
|
|
41585
41668
|
}
|
|
41586
41669
|
ctx.chatHost.syncAnimationTick();
|
|
@@ -41693,6 +41776,7 @@ function handleStoreUpdate(ctx) {
|
|
|
41693
41776
|
}
|
|
41694
41777
|
if (isTerminalStageChatTransition(ctx.lastObservedStageStatus, currentStageStatus) || isTerminalStageChatTransition(ctx.lastObservedRunStatus, currentRunStatus)) {
|
|
41695
41778
|
ctx.chatHost.clearBusyForTerminalWorkflowStage();
|
|
41779
|
+
invalidateStageChatDeliveryLifecycles(ctx);
|
|
41696
41780
|
changed = true;
|
|
41697
41781
|
}
|
|
41698
41782
|
ctx.lastObservedRunStatus = currentRunStatus;
|
|
@@ -41918,6 +42002,9 @@ function disposeStageChatView(ctx) {
|
|
|
41918
42002
|
ctx._unsubscribeStore = null;
|
|
41919
42003
|
ctx._unsubscribeHandle?.();
|
|
41920
42004
|
ctx._unsubscribeHandle = null;
|
|
42005
|
+
ctx._unsubscribeDeliveryActivity?.();
|
|
42006
|
+
ctx._unsubscribeDeliveryActivity = null;
|
|
42007
|
+
ctx.deliveryLifecycles.clear();
|
|
41921
42008
|
ctx._unsubscribeFooterData?.();
|
|
41922
42009
|
ctx._unsubscribeFooterData = null;
|
|
41923
42010
|
releaseMountedCustomUi(ctx);
|
|
@@ -48600,7 +48687,7 @@ function coordinatedPromptOwnershipObserver(turn) {
|
|
|
48600
48687
|
function unsupportedContentError() {
|
|
48601
48688
|
return new Error("atomic-workflows: this stage session adapter does not support non-string sendUserMessage content; provide a runtime sendUserMessage implementation for text/image blocks.");
|
|
48602
48689
|
}
|
|
48603
|
-
async function sendStageUserMessage(activeSession, content, options, beforeDelivery, promptStarted, admission) {
|
|
48690
|
+
async function sendStageUserMessage(activeSession, content, options, beforeDelivery, promptStarted, admission, activity) {
|
|
48604
48691
|
const streaming = activeSession.isStreaming || admission?.isOwned(activeSession) === true;
|
|
48605
48692
|
const deliverAs = streaming ? options?.deliverAs ?? "followUp" : options?.deliverAs;
|
|
48606
48693
|
if (activeSession.sendUserMessage !== undefined) {
|
|
@@ -48608,6 +48695,7 @@ async function sendStageUserMessage(activeSession, content, options, beforeDeliv
|
|
|
48608
48695
|
let reportedAction;
|
|
48609
48696
|
const ownership2 = streaming ? undefined : admission === undefined ? createLocalPromptOwnershipObserver(activeSession, promptStarted) : coordinatedPromptOwnershipObserver(admission.startTurn(activeSession, promptStarted ?? (() => {})));
|
|
48610
48697
|
ownership2?.arm();
|
|
48698
|
+
const deliveryId2 = streaming ? undefined : activity?.start();
|
|
48611
48699
|
try {
|
|
48612
48700
|
const delivery = activeSession.sendUserMessage(content, {
|
|
48613
48701
|
...deliverAs === undefined ? {} : { deliverAs },
|
|
@@ -48628,6 +48716,7 @@ async function sendStageUserMessage(activeSession, content, options, beforeDeliv
|
|
|
48628
48716
|
throw error;
|
|
48629
48717
|
} finally {
|
|
48630
48718
|
ownership2?.dispose();
|
|
48719
|
+
activity?.settle(deliveryId2);
|
|
48631
48720
|
}
|
|
48632
48721
|
}
|
|
48633
48722
|
if (typeof content !== "string")
|
|
@@ -48642,6 +48731,7 @@ async function sendStageUserMessage(activeSession, content, options, beforeDeliv
|
|
|
48642
48731
|
}
|
|
48643
48732
|
const ownership = admission === undefined ? createLocalPromptOwnershipObserver(activeSession, promptStarted) : coordinatedPromptOwnershipObserver(admission.startTurn(activeSession, promptStarted ?? (() => {})));
|
|
48644
48733
|
ownership.arm();
|
|
48734
|
+
const deliveryId = activity?.start();
|
|
48645
48735
|
try {
|
|
48646
48736
|
const turn = activeSession.prompt(content);
|
|
48647
48737
|
ownership.observeStreaming();
|
|
@@ -48653,6 +48743,7 @@ async function sendStageUserMessage(activeSession, content, options, beforeDeliv
|
|
|
48653
48743
|
throw error;
|
|
48654
48744
|
} finally {
|
|
48655
48745
|
ownership.dispose();
|
|
48746
|
+
activity?.settle(deliveryId);
|
|
48656
48747
|
}
|
|
48657
48748
|
}
|
|
48658
48749
|
|
|
@@ -48839,6 +48930,52 @@ class StageMessageAdmission {
|
|
|
48839
48930
|
}
|
|
48840
48931
|
}
|
|
48841
48932
|
|
|
48933
|
+
// dist/builtin/workflows/src/runs/foreground/stage-delivery-activity.ts
|
|
48934
|
+
class StageDeliveryActivity {
|
|
48935
|
+
listeners = new Set;
|
|
48936
|
+
active = new Set;
|
|
48937
|
+
nextDeliveryId = 0;
|
|
48938
|
+
subscribe(listener) {
|
|
48939
|
+
this.listeners.add(listener);
|
|
48940
|
+
for (const deliveryId of [...this.active]) {
|
|
48941
|
+
if (!this.listeners.has(listener))
|
|
48942
|
+
break;
|
|
48943
|
+
listener({ type: "delivery_start", deliveryId });
|
|
48944
|
+
}
|
|
48945
|
+
return () => {
|
|
48946
|
+
this.listeners.delete(listener);
|
|
48947
|
+
};
|
|
48948
|
+
}
|
|
48949
|
+
start() {
|
|
48950
|
+
const deliveryId = ++this.nextDeliveryId;
|
|
48951
|
+
this.active.add(deliveryId);
|
|
48952
|
+
this.emit({ type: "delivery_start", deliveryId });
|
|
48953
|
+
return deliveryId;
|
|
48954
|
+
}
|
|
48955
|
+
async runWithLease(operation) {
|
|
48956
|
+
const deliveryId = this.start();
|
|
48957
|
+
try {
|
|
48958
|
+
return await operation();
|
|
48959
|
+
} finally {
|
|
48960
|
+
this.settle(deliveryId);
|
|
48961
|
+
}
|
|
48962
|
+
}
|
|
48963
|
+
settle(deliveryId) {
|
|
48964
|
+
if (deliveryId === undefined || !this.active.delete(deliveryId))
|
|
48965
|
+
return;
|
|
48966
|
+
this.emit({ type: "delivery_settled", deliveryId });
|
|
48967
|
+
}
|
|
48968
|
+
dispose() {
|
|
48969
|
+
for (const deliveryId of [...this.active])
|
|
48970
|
+
this.settle(deliveryId);
|
|
48971
|
+
this.listeners.clear();
|
|
48972
|
+
}
|
|
48973
|
+
emit(event) {
|
|
48974
|
+
for (const listener of [...this.listeners])
|
|
48975
|
+
listener(event);
|
|
48976
|
+
}
|
|
48977
|
+
}
|
|
48978
|
+
|
|
48842
48979
|
// dist/builtin/workflows/src/runs/foreground/stage-runner-unresolved-overflow.ts
|
|
48843
48980
|
function unresolvedContextOverflowMessage(event) {
|
|
48844
48981
|
if (event === null || typeof event !== "object")
|
|
@@ -49105,6 +49242,7 @@ class StageSessionController {
|
|
|
49105
49242
|
sessionSettingsManager;
|
|
49106
49243
|
replacement = new StageSessionReplacement;
|
|
49107
49244
|
messageAdmission = new StageMessageAdmission;
|
|
49245
|
+
deliveryActivity = new StageDeliveryActivity;
|
|
49108
49246
|
constructor(opts, meta, effectiveStageOptions, structuredOutputCapture) {
|
|
49109
49247
|
this.opts = opts;
|
|
49110
49248
|
this.meta = meta;
|
|
@@ -49168,16 +49306,24 @@ class StageSessionController {
|
|
|
49168
49306
|
await session.closeWorkflowStageGeneration?.();
|
|
49169
49307
|
return session;
|
|
49170
49308
|
}
|
|
49171
|
-
async sendUserMessage(content, options, beforeDelivery) {
|
|
49309
|
+
async sendUserMessage(content, options, beforeDelivery, preparation) {
|
|
49172
49310
|
return this.messageAdmission.run(async (release) => {
|
|
49173
|
-
const pausedDelivery = this.pauseControl.deferRunnerOwnedDelivery(() => this.sendUserMessage(content, options, beforeDelivery));
|
|
49311
|
+
const pausedDelivery = this.pauseControl.deferRunnerOwnedDelivery(() => this.sendUserMessage(content, options, beforeDelivery, preparation));
|
|
49174
49312
|
if (pausedDelivery !== undefined) {
|
|
49175
49313
|
release();
|
|
49176
49314
|
return pausedDelivery;
|
|
49177
49315
|
}
|
|
49178
|
-
|
|
49316
|
+
preparation?.beforePreparation?.();
|
|
49317
|
+
const sessionFile = preparation?.sessionFile;
|
|
49318
|
+
const deliver = async (activity) => sendStageUserMessage(sessionFile === undefined ? await this.ensureSession("prompt") : await this.ensureSessionFromFile(sessionFile, "prompt"), content, options, beforeDelivery, release, this.messageAdmission, activity);
|
|
49319
|
+
if (this.session === undefined || sessionFile !== undefined)
|
|
49320
|
+
return this.deliveryActivity.runWithLease(() => deliver());
|
|
49321
|
+
return deliver(this.deliveryActivity);
|
|
49179
49322
|
});
|
|
49180
49323
|
}
|
|
49324
|
+
subscribeDeliveryActivity(listener) {
|
|
49325
|
+
return this.deliveryActivity.subscribe(listener);
|
|
49326
|
+
}
|
|
49181
49327
|
sealGeneration() {
|
|
49182
49328
|
this.generationSealed = true;
|
|
49183
49329
|
this.sharedOrchestrationContext?.messageAdmission?.boundary.seal();
|
|
@@ -49252,6 +49398,7 @@ class StageSessionController {
|
|
|
49252
49398
|
this.unsubscribeTerminateWatcher = undefined;
|
|
49253
49399
|
this.terminatingToolCallIds.clear();
|
|
49254
49400
|
this.messageAdmission.dispose();
|
|
49401
|
+
this.deliveryActivity.dispose();
|
|
49255
49402
|
await this.replacement.dispose();
|
|
49256
49403
|
await disposeStageSession(this.session);
|
|
49257
49404
|
}
|
|
@@ -49739,8 +49886,8 @@ function createStageContext(opts) {
|
|
|
49739
49886
|
async sendUserMessage(text, options) {
|
|
49740
49887
|
await controller.sendUserMessage(text, options);
|
|
49741
49888
|
},
|
|
49742
|
-
async __sendUserMessage(text, options, beforeDelivery) {
|
|
49743
|
-
return controller.sendUserMessage(text, options, beforeDelivery);
|
|
49889
|
+
async __sendUserMessage(text, options, beforeDelivery, preparation) {
|
|
49890
|
+
return controller.sendUserMessage(text, options, beforeDelivery, preparation);
|
|
49744
49891
|
},
|
|
49745
49892
|
async steer(text) {
|
|
49746
49893
|
await (await controller.ensureSession()).steer(text);
|
|
@@ -49751,6 +49898,9 @@ function createStageContext(opts) {
|
|
|
49751
49898
|
subscribe(listener) {
|
|
49752
49899
|
return controller.subscribe(listener);
|
|
49753
49900
|
},
|
|
49901
|
+
__subscribeDeliveryActivity(listener) {
|
|
49902
|
+
return controller.subscribeDeliveryActivity(listener);
|
|
49903
|
+
},
|
|
49754
49904
|
get sessionFile() {
|
|
49755
49905
|
return controller.currentSession?.sessionFile;
|
|
49756
49906
|
},
|
|
@@ -51274,6 +51424,7 @@ function createReplayStageContext(input) {
|
|
|
51274
51424
|
steer: async () => rejectReplayMutation("steer"),
|
|
51275
51425
|
followUp: async () => rejectReplayMutation("follow up"),
|
|
51276
51426
|
subscribe: () => () => {},
|
|
51427
|
+
__subscribeDeliveryActivity: () => () => {},
|
|
51277
51428
|
get sessionFile() {
|
|
51278
51429
|
return replaySource.sessionFile;
|
|
51279
51430
|
},
|
|
@@ -51371,18 +51522,28 @@ class StageToolExecutionBuffer {
|
|
|
51371
51522
|
|
|
51372
51523
|
// dist/builtin/workflows/src/runs/foreground/executor-stage-control.ts
|
|
51373
51524
|
function createStageControlHandle(runtime) {
|
|
51374
|
-
const
|
|
51525
|
+
const messagePreparation = () => {
|
|
51375
51526
|
const meta = runtime.innerCtx.__sessionMeta();
|
|
51376
|
-
if (meta.sessionId !== undefined || meta.sessionFile !== undefined)
|
|
51377
|
-
return;
|
|
51527
|
+
if (meta.sessionId !== undefined || meta.sessionFile !== undefined) {
|
|
51528
|
+
return { beforePreparation: runtime.throwIfStageMutationBlocked };
|
|
51529
|
+
}
|
|
51378
51530
|
if (runtime.stageSnapshot.sessionFile !== undefined) {
|
|
51379
|
-
|
|
51380
|
-
|
|
51381
|
-
|
|
51531
|
+
return {
|
|
51532
|
+
sessionFile: runtime.stageSnapshot.sessionFile,
|
|
51533
|
+
beforePreparation: runtime.throwIfStageMutationBlocked
|
|
51534
|
+
};
|
|
51382
51535
|
}
|
|
51383
51536
|
if (isTerminalStage(runtime.stageSnapshot)) {
|
|
51384
51537
|
throw new Error(`atomic-workflows: cannot message stage "${runtime.name}" because no retained session metadata is available.`);
|
|
51385
51538
|
}
|
|
51539
|
+
return { beforePreparation: runtime.throwIfStageMutationBlocked };
|
|
51540
|
+
};
|
|
51541
|
+
const ensureMessagingSession = async () => {
|
|
51542
|
+
const sessionFile = messagePreparation().sessionFile;
|
|
51543
|
+
if (sessionFile === undefined)
|
|
51544
|
+
return;
|
|
51545
|
+
await runtime.innerCtx.__ensureSessionFromFile(sessionFile);
|
|
51546
|
+
runtime.captureStageSessionMeta();
|
|
51386
51547
|
};
|
|
51387
51548
|
const toolExecutions = new StageToolExecutionBuffer;
|
|
51388
51549
|
const unsubscribeToolExecutions = runtime.innerCtx.subscribe((event) => toolExecutions.record(event));
|
|
@@ -51423,14 +51584,13 @@ function createStageControlHandle(runtime) {
|
|
|
51423
51584
|
},
|
|
51424
51585
|
async sendUserMessage(text, options, beforeDelivery) {
|
|
51425
51586
|
runtime.throwIfStageMutationBlocked();
|
|
51426
|
-
|
|
51427
|
-
runtime.throwIfStageMutationBlocked();
|
|
51587
|
+
const preparation = messagePreparation();
|
|
51428
51588
|
const admitDelivery = () => {
|
|
51429
51589
|
runtime.throwIfStageMutationBlocked();
|
|
51430
51590
|
beforeDelivery?.();
|
|
51431
51591
|
};
|
|
51432
51592
|
try {
|
|
51433
|
-
const action = await runtime.innerCtx.__sendUserMessage(text, options, admitDelivery);
|
|
51593
|
+
const action = await runtime.innerCtx.__sendUserMessage(text, options, admitDelivery, preparation);
|
|
51434
51594
|
if (action === "steer" || action === "followUp") {
|
|
51435
51595
|
runtime.state.resumeContinuationPending = "queued-user-message";
|
|
51436
51596
|
}
|
|
@@ -51441,10 +51601,10 @@ function createStageControlHandle(runtime) {
|
|
|
51441
51601
|
},
|
|
51442
51602
|
async prompt(text) {
|
|
51443
51603
|
runtime.throwIfStageMutationBlocked();
|
|
51444
|
-
|
|
51604
|
+
const preparation = messagePreparation();
|
|
51445
51605
|
let action;
|
|
51446
51606
|
try {
|
|
51447
|
-
action = await runtime.innerCtx.__sendUserMessage(text, undefined, runtime.throwIfStageMutationBlocked);
|
|
51607
|
+
action = await runtime.innerCtx.__sendUserMessage(text, undefined, runtime.throwIfStageMutationBlocked, preparation);
|
|
51448
51608
|
} finally {
|
|
51449
51609
|
runtime.captureStageSessionMeta();
|
|
51450
51610
|
}
|
|
@@ -51540,6 +51700,9 @@ function createStageControlHandle(runtime) {
|
|
|
51540
51700
|
subscribe(listener) {
|
|
51541
51701
|
return runtime.innerCtx.subscribe(listener);
|
|
51542
51702
|
},
|
|
51703
|
+
subscribeDeliveryActivity(listener) {
|
|
51704
|
+
return runtime.innerCtx.__subscribeDeliveryActivity(listener);
|
|
51705
|
+
},
|
|
51543
51706
|
async dispose() {
|
|
51544
51707
|
unsubscribeToolExecutions();
|
|
51545
51708
|
toolExecutions.clear();
|
|
@@ -61765,11 +61928,19 @@ function createPostMortemStageHandle(runId, stage, sessionFile, adapters, cwd, d
|
|
|
61765
61928
|
...defaultSessionDir !== undefined ? { defaultSessionDir } : {}
|
|
61766
61929
|
});
|
|
61767
61930
|
let disposed = false;
|
|
61768
|
-
const
|
|
61931
|
+
const throwIfClosed = () => {
|
|
61769
61932
|
if (disposed)
|
|
61770
61933
|
throw new Error(`Post-mortem stage chat "${stage.name}" is closed.`);
|
|
61771
|
-
|
|
61772
|
-
|
|
61934
|
+
};
|
|
61935
|
+
const messagePreparation = () => ({
|
|
61936
|
+
...context.__sessionMeta().sessionFile === undefined ? { sessionFile } : {},
|
|
61937
|
+
beforePreparation: throwIfClosed
|
|
61938
|
+
});
|
|
61939
|
+
const ensureAttached = async () => {
|
|
61940
|
+
throwIfClosed();
|
|
61941
|
+
const sessionFileToRestore = messagePreparation().sessionFile;
|
|
61942
|
+
if (sessionFileToRestore !== undefined) {
|
|
61943
|
+
await context.__ensureSessionFromFile(sessionFileToRestore);
|
|
61773
61944
|
}
|
|
61774
61945
|
};
|
|
61775
61946
|
return {
|
|
@@ -61799,8 +61970,13 @@ function createPostMortemStageHandle(runId, stage, sessionFile, adapters, cwd, d
|
|
|
61799
61970
|
await ensureAttached();
|
|
61800
61971
|
},
|
|
61801
61972
|
async sendUserMessage(text, options, beforeDelivery) {
|
|
61802
|
-
|
|
61803
|
-
|
|
61973
|
+
throwIfClosed();
|
|
61974
|
+
const preparation = messagePreparation();
|
|
61975
|
+
const admitDelivery = () => {
|
|
61976
|
+
throwIfClosed();
|
|
61977
|
+
beforeDelivery?.();
|
|
61978
|
+
};
|
|
61979
|
+
return context.__sendUserMessage(text, options, admitDelivery, preparation);
|
|
61804
61980
|
},
|
|
61805
61981
|
async prompt(text) {
|
|
61806
61982
|
await ensureAttached();
|
|
@@ -61823,6 +61999,9 @@ function createPostMortemStageHandle(runId, stage, sessionFile, adapters, cwd, d
|
|
|
61823
61999
|
subscribe(listener) {
|
|
61824
62000
|
return context.subscribe(listener);
|
|
61825
62001
|
},
|
|
62002
|
+
subscribeDeliveryActivity(listener) {
|
|
62003
|
+
return context.__subscribeDeliveryActivity(listener);
|
|
62004
|
+
},
|
|
61826
62005
|
async dispose() {
|
|
61827
62006
|
if (disposed)
|
|
61828
62007
|
return;
|
|
@@ -1,21 +1,31 @@
|
|
|
1
1
|
import type { StageControlHandle, AgentSessionEventListener } from "./stage-control-registry.js";
|
|
2
2
|
import type { LiveStageRuntime } from "./executor-stage-types.js";
|
|
3
|
-
import type { StageUserMessageDeliveryAction } from "./stage-runner-types.js";
|
|
3
|
+
import type { StageUserMessageDeliveryAction, StageUserMessagePreparation } from "./stage-runner-types.js";
|
|
4
4
|
import { isTerminalStage } from "./executor-scheduler.js";
|
|
5
5
|
import { StageToolExecutionBuffer } from "./stage-tool-execution-buffer.js";
|
|
6
6
|
|
|
7
7
|
export function createStageControlHandle(runtime: LiveStageRuntime): StageControlHandle {
|
|
8
|
-
const
|
|
8
|
+
const messagePreparation = (): StageUserMessagePreparation => {
|
|
9
9
|
const meta = runtime.innerCtx.__sessionMeta();
|
|
10
|
-
if (meta.sessionId !== undefined || meta.sessionFile !== undefined)
|
|
10
|
+
if (meta.sessionId !== undefined || meta.sessionFile !== undefined) {
|
|
11
|
+
return { beforePreparation: runtime.throwIfStageMutationBlocked };
|
|
12
|
+
}
|
|
11
13
|
if (runtime.stageSnapshot.sessionFile !== undefined) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
return {
|
|
15
|
+
sessionFile: runtime.stageSnapshot.sessionFile,
|
|
16
|
+
beforePreparation: runtime.throwIfStageMutationBlocked,
|
|
17
|
+
};
|
|
15
18
|
}
|
|
16
19
|
if (isTerminalStage(runtime.stageSnapshot)) {
|
|
17
20
|
throw new Error(`atomic-workflows: cannot message stage "${runtime.name}" because no retained session metadata is available.`);
|
|
18
21
|
}
|
|
22
|
+
return { beforePreparation: runtime.throwIfStageMutationBlocked };
|
|
23
|
+
};
|
|
24
|
+
const ensureMessagingSession = async (): Promise<void> => {
|
|
25
|
+
const sessionFile = messagePreparation().sessionFile;
|
|
26
|
+
if (sessionFile === undefined) return;
|
|
27
|
+
await runtime.innerCtx.__ensureSessionFromFile(sessionFile);
|
|
28
|
+
runtime.captureStageSessionMeta();
|
|
19
29
|
};
|
|
20
30
|
const toolExecutions = new StageToolExecutionBuffer();
|
|
21
31
|
const unsubscribeToolExecutions = runtime.innerCtx.subscribe((event) => toolExecutions.record(event));
|
|
@@ -57,8 +67,7 @@ export function createStageControlHandle(runtime: LiveStageRuntime): StageContro
|
|
|
57
67
|
},
|
|
58
68
|
async sendUserMessage(text, options, beforeDelivery) {
|
|
59
69
|
runtime.throwIfStageMutationBlocked();
|
|
60
|
-
|
|
61
|
-
runtime.throwIfStageMutationBlocked();
|
|
70
|
+
const preparation = messagePreparation();
|
|
62
71
|
const admitDelivery = (): void => {
|
|
63
72
|
runtime.throwIfStageMutationBlocked();
|
|
64
73
|
beforeDelivery?.();
|
|
@@ -68,6 +77,7 @@ export function createStageControlHandle(runtime: LiveStageRuntime): StageContro
|
|
|
68
77
|
text,
|
|
69
78
|
options,
|
|
70
79
|
admitDelivery,
|
|
80
|
+
preparation,
|
|
71
81
|
);
|
|
72
82
|
if (action === "steer" || action === "followUp") {
|
|
73
83
|
runtime.state.resumeContinuationPending = "queued-user-message";
|
|
@@ -79,13 +89,14 @@ export function createStageControlHandle(runtime: LiveStageRuntime): StageContro
|
|
|
79
89
|
},
|
|
80
90
|
async prompt(text: string) {
|
|
81
91
|
runtime.throwIfStageMutationBlocked();
|
|
82
|
-
|
|
92
|
+
const preparation = messagePreparation();
|
|
83
93
|
let action: StageUserMessageDeliveryAction | undefined;
|
|
84
94
|
try {
|
|
85
95
|
action = await runtime.innerCtx.__sendUserMessage(
|
|
86
96
|
text,
|
|
87
97
|
undefined,
|
|
88
98
|
runtime.throwIfStageMutationBlocked,
|
|
99
|
+
preparation,
|
|
89
100
|
);
|
|
90
101
|
} finally {
|
|
91
102
|
runtime.captureStageSessionMeta();
|
|
@@ -197,6 +208,9 @@ export function createStageControlHandle(runtime: LiveStageRuntime): StageContro
|
|
|
197
208
|
subscribe(listener: AgentSessionEventListener) {
|
|
198
209
|
return runtime.innerCtx.subscribe(listener);
|
|
199
210
|
},
|
|
211
|
+
subscribeDeliveryActivity(listener) {
|
|
212
|
+
return runtime.innerCtx.__subscribeDeliveryActivity(listener);
|
|
213
|
+
},
|
|
200
214
|
async dispose() {
|
|
201
215
|
unsubscribeToolExecutions();
|
|
202
216
|
toolExecutions.clear();
|
|
@@ -100,6 +100,7 @@ export function createReplayStageContext(input: {
|
|
|
100
100
|
steer: async () => rejectReplayMutation("steer"),
|
|
101
101
|
followUp: async () => rejectReplayMutation("follow up"),
|
|
102
102
|
subscribe: () => () => {},
|
|
103
|
+
__subscribeDeliveryActivity: () => () => {},
|
|
103
104
|
get sessionFile() { return replaySource.sessionFile; },
|
|
104
105
|
get sessionId() { return replaySource.sessionId ?? ""; },
|
|
105
106
|
setModel: async () => rejectReplayMutation("set model"),
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
type StageControlHandle,
|
|
35
35
|
type StageControlRegistry,
|
|
36
36
|
} from "./stage-control-registry.js";
|
|
37
|
+
import type { StageUserMessagePreparation } from "./stage-runner-types.js";
|
|
37
38
|
|
|
38
39
|
/** Why a terminal stage could not be revived as an interactive post-mortem chat. */
|
|
39
40
|
export type PostMortemUnavailableReason =
|
|
@@ -153,10 +154,18 @@ export function createPostMortemStageHandle(
|
|
|
153
154
|
...(defaultSessionDir !== undefined ? { defaultSessionDir } : {}),
|
|
154
155
|
});
|
|
155
156
|
let disposed = false;
|
|
156
|
-
const
|
|
157
|
+
const throwIfClosed = (): void => {
|
|
157
158
|
if (disposed) throw new Error(`Post-mortem stage chat "${stage.name}" is closed.`);
|
|
158
|
-
|
|
159
|
-
|
|
159
|
+
};
|
|
160
|
+
const messagePreparation = (): StageUserMessagePreparation => ({
|
|
161
|
+
...(context.__sessionMeta().sessionFile === undefined ? { sessionFile } : {}),
|
|
162
|
+
beforePreparation: throwIfClosed,
|
|
163
|
+
});
|
|
164
|
+
const ensureAttached = async (): Promise<void> => {
|
|
165
|
+
throwIfClosed();
|
|
166
|
+
const sessionFileToRestore = messagePreparation().sessionFile;
|
|
167
|
+
if (sessionFileToRestore !== undefined) {
|
|
168
|
+
await context.__ensureSessionFromFile(sessionFileToRestore);
|
|
160
169
|
}
|
|
161
170
|
};
|
|
162
171
|
return {
|
|
@@ -172,8 +181,13 @@ export function createPostMortemStageHandle(
|
|
|
172
181
|
get agentSession() { return context.__agentSession(); },
|
|
173
182
|
async ensureAttached() { await ensureAttached(); },
|
|
174
183
|
async sendUserMessage(text, options, beforeDelivery) {
|
|
175
|
-
|
|
176
|
-
|
|
184
|
+
throwIfClosed();
|
|
185
|
+
const preparation = messagePreparation();
|
|
186
|
+
const admitDelivery = (): void => {
|
|
187
|
+
throwIfClosed();
|
|
188
|
+
beforeDelivery?.();
|
|
189
|
+
};
|
|
190
|
+
return context.__sendUserMessage(text, options, admitDelivery, preparation);
|
|
177
191
|
},
|
|
178
192
|
async prompt(text: string) {
|
|
179
193
|
await ensureAttached();
|
|
@@ -194,6 +208,7 @@ export function createPostMortemStageHandle(
|
|
|
194
208
|
throw new Error("Post-mortem stage chat cannot pause or resume workflow execution.");
|
|
195
209
|
},
|
|
196
210
|
subscribe(listener: AgentSessionEventListener) { return context.subscribe(listener); },
|
|
211
|
+
subscribeDeliveryActivity(listener) { return context.__subscribeDeliveryActivity(listener); },
|
|
197
212
|
async dispose() {
|
|
198
213
|
if (disposed) return;
|
|
199
214
|
disposed = true;
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
28
|
import type { AgentSession, AgentSessionEvent } from "@bastani/atomic";
|
|
29
|
+
import type { StageDeliveryActivityEvent } from "./stage-delivery-activity.js";
|
|
29
30
|
import type { StageUserMessageDeliveryAction } from "./stage-runner-types.js";
|
|
30
31
|
|
|
31
32
|
export type StageControlStatus =
|
|
@@ -98,6 +99,15 @@ export interface StageControlHandle {
|
|
|
98
99
|
* before the session exists are buffered and bound on first attach.
|
|
99
100
|
*/
|
|
100
101
|
subscribe(listener: AgentSessionEventListener): () => void;
|
|
102
|
+
/**
|
|
103
|
+
* Subscribe to workflow-owned delivery lifecycle facts. Present only for
|
|
104
|
+
* handles backed by a live stage runner. An accepted idle delivery reports
|
|
105
|
+
* `delivery_start` before the public `agent_start` is published, letting an
|
|
106
|
+
* attached chat show Working for the whole turn.
|
|
107
|
+
*/
|
|
108
|
+
subscribeDeliveryActivity?(
|
|
109
|
+
listener: (event: StageDeliveryActivityEvent) => void,
|
|
110
|
+
): () => void;
|
|
101
111
|
/** Release the underlying SDK session and unregister this direct chat handle. */
|
|
102
112
|
dispose?(): void | Promise<void>;
|
|
103
113
|
}
|