@north-light/crouter 0.3.169 → 0.3.171
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/build-root.d.ts +1 -16
- package/dist/build-root.js +1 -25
- package/dist/builtin-memory/insights/capture.md +66 -0
- package/dist/builtin-memory/insights/init.md +45 -0
- package/dist/builtin-memory/internal/plugins.md +12 -11
- package/dist/cli.js +2 -6
- package/dist/clients/attach/__tests__/attach-keybindings.test.js +7 -1
- package/dist/clients/attach/__tests__/context-message.test.js +50 -3
- package/dist/clients/attach/__tests__/diagram.test.js +1 -1
- package/dist/clients/attach/chrome/header.d.ts +10 -0
- package/dist/clients/attach/chrome/header.js +35 -0
- package/dist/clients/attach/chrome/status-line.d.ts +3 -0
- package/dist/clients/attach/chrome/status-line.js +5 -0
- package/dist/clients/attach/chrome/widgets.js +7 -18
- package/dist/clients/attach/input/controller.d.ts +10 -0
- package/dist/clients/attach/input/controller.js +3 -0
- package/dist/clients/attach/overlays/help.d.ts +33 -0
- package/dist/clients/attach/overlays/help.js +204 -0
- package/dist/clients/attach/render/chat-view.d.ts +81 -9
- package/dist/clients/attach/render/chat-view.js +434 -90
- package/dist/clients/attach/render/context-message.js +3 -3
- package/dist/clients/attach/render/diagram.js +2 -2
- package/dist/clients/attach/render/measured-container.d.ts +94 -0
- package/dist/clients/attach/render/measured-container.js +307 -0
- package/dist/clients/attach/render/transcript-copy.d.ts +9 -0
- package/dist/clients/attach/render/transcript-copy.js +81 -0
- package/dist/clients/attach/render/viewport.d.ts +29 -0
- package/dist/clients/attach/render/viewport.js +160 -0
- package/dist/clients/attach/session/bindings.d.ts +5 -1
- package/dist/clients/attach/session/bindings.js +16 -0
- package/dist/clients/attach/session/context.d.ts +5 -3
- package/dist/clients/attach/session/frame.d.ts +34 -0
- package/dist/clients/attach/session/frame.js +173 -0
- package/dist/clients/attach/session/frames.d.ts +2 -0
- package/dist/clients/attach/session/frames.js +3 -0
- package/dist/clients/attach/session/input-wiring.d.ts +10 -4
- package/dist/clients/attach/session/input-wiring.js +13 -13
- package/dist/clients/attach/session/keys.d.ts +4 -1
- package/dist/clients/attach/session/keys.js +9 -4
- package/dist/clients/attach/session/layout.d.ts +10 -8
- package/dist/clients/attach/session/layout.js +32 -31
- package/dist/clients/attach/session/mouse.d.ts +15 -0
- package/dist/clients/attach/session/mouse.js +61 -0
- package/dist/clients/attach/slash/dispatch.d.ts +10 -0
- package/dist/clients/attach/slash/dispatch.js +35 -2
- package/dist/clients/attach/viewer.js +605 -581
- package/dist/clients/web/dev-server.d.ts +4 -1
- package/dist/clients/web/dev-server.js +8 -19
- package/dist/clients/web/web-cmd.js +1 -1
- package/dist/commands/human/prompts.js +16 -6
- package/dist/commands/pkg/plugin-manage.js +143 -68
- package/dist/commands/sys/__tests__/setup-core.test.js +4 -2
- package/dist/commands/sys/setup-core.js +21 -16
- package/dist/core/__tests__/human-deliver.test.js +62 -2
- package/dist/core/clipboard-text.d.ts +8 -0
- package/dist/core/clipboard-text.js +18 -0
- package/dist/core/command-manifests/registry.d.ts +1 -3
- package/dist/core/command-plugins/bundle.d.ts +29 -0
- package/dist/core/command-plugins/bundle.js +198 -0
- package/dist/core/command-plugins/discovery.d.ts +0 -8
- package/dist/core/command-plugins/discovery.js +2 -39
- package/dist/core/command-plugins/transport/http-fetch.d.ts +4 -30
- package/dist/core/command-plugins/transport/http-fetch.js +17 -95
- package/dist/core/command.d.ts +9 -13
- package/dist/core/command.js +12 -17
- package/dist/core/config.js +2 -1
- package/dist/core/keybindings/__tests__/resolve.test.js +4 -0
- package/dist/core/keybindings/attach-control.d.ts +3 -0
- package/dist/core/keybindings/attach-control.js +1 -0
- package/dist/core/keybindings/catalog.d.ts +2 -2
- package/dist/core/keybindings/catalog.js +8 -0
- package/dist/core/runtime/broker-protocol.d.ts +13 -1
- package/dist/core/runtime/broker.js +213 -5
- package/dist/core/runtime/canvas-extensions.d.ts +3 -0
- package/dist/core/runtime/canvas-extensions.js +3 -0
- package/dist/core/runtime/front-door.js +4 -4
- package/dist/core/runtime/kickoff.d.ts +1 -5
- package/dist/core/runtime/kickoff.js +1 -5
- package/dist/core/runtime/naming.d.ts +7 -0
- package/dist/core/runtime/naming.js +5 -2
- package/dist/core/runtime/node-read.js +15 -0
- package/dist/core/runtime/package-health.d.ts +6 -21
- package/dist/core/runtime/package-health.js +12 -123
- package/dist/core/runtime/stop-guard.d.ts +1 -1
- package/dist/core/runtime/stop-guard.js +3 -3
- package/dist/core/runtime/tool-group-summary.d.ts +19 -0
- package/dist/core/runtime/tool-group-summary.js +117 -0
- package/dist/core/termrender/code-doc.d.ts +12 -0
- package/dist/core/termrender/code-doc.js +91 -0
- package/dist/core/termrender/display.d.ts +12 -0
- package/dist/core/termrender/display.js +19 -0
- package/dist/core/termrender/termrender.d.ts +73 -0
- package/dist/core/termrender/termrender.js +795 -0
- package/dist/core/termrender/version.d.ts +1 -0
- package/dist/core/termrender/version.js +1 -0
- package/dist/core/user-settings.d.ts +14 -0
- package/dist/core/user-settings.js +20 -0
- package/dist/daemon/crtrd.js +5 -6
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/pi-extensions/__tests__/canvas-structured-output.test.d.ts +1 -0
- package/dist/pi-extensions/__tests__/canvas-structured-output.test.js +63 -0
- package/dist/pi-extensions/canvas-stophook.js +2 -2
- package/dist/pi-extensions/canvas-structured-output.js +52 -8
- package/dist/pi-extensions/summary-tool.d.ts +33 -0
- package/dist/pi-extensions/summary-tool.js +62 -0
- package/dist/shared/generated-context.d.ts +19 -4
- package/dist/shared/generated-context.js +98 -7
- package/dist/shared/tool-groups.d.ts +23 -0
- package/dist/shared/tool-groups.js +60 -0
- package/dist/types.d.ts +11 -0
- package/dist/types.js +1 -0
- package/dist/web-client/assets/{index-U_NZ66VE.js → index-D7I3gHCL.js} +26 -19
- package/dist/web-client/index.html +1 -1
- package/dist/web-client/sw.js +1 -1
- package/package.json +3 -1
- package/runtime.lock.json +62 -3
- package/scripts/postinstall.mjs +14 -1
- package/dist/core/command-plugins/store.d.ts +0 -16
- package/dist/core/command-plugins/store.js +0 -64
- package/dist/core/runtime/fault-recovery-nudge.d.ts +0 -3
- package/dist/core/runtime/fault-recovery-nudge.js +0 -3
package/dist/core/command.js
CHANGED
|
@@ -14,6 +14,7 @@ import { readFileSync } from 'node:fs';
|
|
|
14
14
|
import { spawnSync } from 'node:child_process';
|
|
15
15
|
import { constants as osConstants } from 'node:os';
|
|
16
16
|
import { isatty } from 'node:tty';
|
|
17
|
+
import { resolve } from 'node:path';
|
|
17
18
|
// ---------------------------------------------------------------------------
|
|
18
19
|
// Factory functions
|
|
19
20
|
// ---------------------------------------------------------------------------
|
|
@@ -268,6 +269,7 @@ function flagNameToKey(name) {
|
|
|
268
269
|
export async function parseArgv(params, tokens, options) {
|
|
269
270
|
const result = {};
|
|
270
271
|
const provided = new Set(); // Track explicitly-provided parameter names
|
|
272
|
+
const contextFilePaths = new Map();
|
|
271
273
|
// Index params by kind for quick lookup
|
|
272
274
|
const positionalParam = params.find((p) => p.kind === 'positional');
|
|
273
275
|
const stdinParam = params.find((p) => p.kind === 'stdin');
|
|
@@ -332,6 +334,7 @@ export async function parseArgv(params, tokens, options) {
|
|
|
332
334
|
}
|
|
333
335
|
const contextFileKey = flagNameToKey(contextFileParam.name);
|
|
334
336
|
result[contextFileKey] = parsed;
|
|
337
|
+
contextFilePaths.set(contextFileKey, resolve(pathVal));
|
|
335
338
|
provided.add(contextFileKey);
|
|
336
339
|
i++;
|
|
337
340
|
continue;
|
|
@@ -539,9 +542,12 @@ export async function parseArgv(params, tokens, options) {
|
|
|
539
542
|
if (options?.onProvidedParams !== undefined) {
|
|
540
543
|
options.onProvidedParams(provided);
|
|
541
544
|
}
|
|
545
|
+
if (options?.onContextFilePaths !== undefined) {
|
|
546
|
+
options.onContextFilePaths(contextFilePaths);
|
|
547
|
+
}
|
|
542
548
|
return result;
|
|
543
549
|
}
|
|
544
|
-
export async function runCli(root, argv
|
|
550
|
+
export async function runCli(root, argv) {
|
|
545
551
|
// argv is process.argv — strip node binary + script path. `--json` is a
|
|
546
552
|
// global: pull it out anywhere it appears so the rest of argv parses against
|
|
547
553
|
// the leaf schema unchanged, and switch stdout from rendered prose to raw
|
|
@@ -564,21 +570,6 @@ export async function runCli(root, argv, options) {
|
|
|
564
570
|
}
|
|
565
571
|
let { node, path, remaining } = walk(root, tokens);
|
|
566
572
|
try {
|
|
567
|
-
// An unknown first token that misses at root is the only site absent
|
|
568
|
-
// HTTP-plugin stores may hydrate. A deeper unknown token under a known
|
|
569
|
-
// command never triggers it. Invoke the seam once; if it hydrated commands,
|
|
570
|
-
// re-walk the original argv against the rebuilt root. Keeping it inside the
|
|
571
|
-
// try sends any seam failure through the ordinary error handler.
|
|
572
|
-
if (options?.onUnknownFirstTokenMiss !== undefined &&
|
|
573
|
-
node.kind === 'root' &&
|
|
574
|
-
path.length === 0 &&
|
|
575
|
-
remaining.length > 0 &&
|
|
576
|
-
remaining[0] !== '-h' &&
|
|
577
|
-
remaining[0] !== '--help') {
|
|
578
|
-
const rebuilt = await options.onUnknownFirstTokenMiss();
|
|
579
|
-
if (rebuilt !== undefined)
|
|
580
|
-
({ node, path, remaining } = walk(rebuilt, tokens));
|
|
581
|
-
}
|
|
582
573
|
// Passthrough branches (e.g. `crtr capture`) opt out of the tree model
|
|
583
574
|
// entirely: forward every token after the branch verbatim to an external
|
|
584
575
|
// binary before any of the normal unknown-path / help / dispatch logic
|
|
@@ -618,13 +609,17 @@ export async function runCli(root, argv, options) {
|
|
|
618
609
|
const leaf = node;
|
|
619
610
|
const params = leaf.help.params !== undefined ? leaf.help.params : [];
|
|
620
611
|
let providedParams = new Set();
|
|
612
|
+
let contextFilePaths = new Map();
|
|
621
613
|
const input = await parseArgv(params, remaining, {
|
|
622
614
|
leafPath: path,
|
|
623
615
|
onProvidedParams: (provided) => {
|
|
624
616
|
providedParams = provided;
|
|
625
617
|
},
|
|
618
|
+
onContextFilePaths: (paths) => {
|
|
619
|
+
contextFilePaths = paths;
|
|
620
|
+
},
|
|
626
621
|
});
|
|
627
|
-
const context = { providedParams };
|
|
622
|
+
const context = { providedParams, contextFilePaths };
|
|
628
623
|
const result = await operationIdContext.fresh(() => leaf.run(input, context));
|
|
629
624
|
if (result !== undefined && result !== null) {
|
|
630
625
|
if (isJsonOutput()) {
|
package/dist/core/config.js
CHANGED
|
@@ -441,6 +441,7 @@ function mergeConfig(partial) {
|
|
|
441
441
|
? partial.condensed_history
|
|
442
442
|
: defaults.condensed_history;
|
|
443
443
|
const fold_finished_tools = typeof partial.fold_finished_tools === 'boolean' ? partial.fold_finished_tools : defaults.fold_finished_tools;
|
|
444
|
+
const summarize_tool_calls = typeof partial.summarize_tool_calls === 'boolean' ? partial.summarize_tool_calls : defaults.summarize_tool_calls;
|
|
444
445
|
const keybindings = normalizeKeybindings(partial.keybindings);
|
|
445
446
|
const modelLadders = mergeModelLadders(partial.modelLadders);
|
|
446
447
|
const modelRoutes = mergeModelRoutes(partial.modelRoutes);
|
|
@@ -448,7 +449,7 @@ function mergeConfig(partial) {
|
|
|
448
449
|
const kinds = mergeKinds(partial.kinds);
|
|
449
450
|
const remoteCanvas = mergeRemoteCanvas(partial.remoteCanvas);
|
|
450
451
|
const spawnEnv = mergeSpawnEnv(partial.spawnEnv, defaults.spawnEnv?.allow);
|
|
451
|
-
return { schema_version, marketplaces, plugins, auto_update, max_panes_per_window, auto_open_child_viewers, brokerThresholds, completion_bell, live_cycles, condensed_history, fold_finished_tools, keybindings, modelLadders, ...(Object.keys(modelRoutes).length > 0 ? { modelRoutes } : {}), ...(modelRouting !== undefined ? { modelRouting } : {}), kinds, remoteCanvas, spawnEnv };
|
|
452
|
+
return { schema_version, marketplaces, plugins, auto_update, max_panes_per_window, auto_open_child_viewers, brokerThresholds, completion_bell, live_cycles, condensed_history, fold_finished_tools, summarize_tool_calls, keybindings, modelLadders, ...(Object.keys(modelRoutes).length > 0 ? { modelRoutes } : {}), ...(modelRouting !== undefined ? { modelRouting } : {}), kinds, remoteCanvas, spawnEnv };
|
|
452
453
|
}
|
|
453
454
|
/** Raw (un-defaulted) partial config for one scope, or null if the scope has
|
|
454
455
|
* no root or no config.json. Used by `readMergedLaunchConfig` to layer
|
|
@@ -34,12 +34,16 @@ const REQUIRED_IDS = [
|
|
|
34
34
|
['clear-or-detach', 'crtr.attach.clear-or-detach'],
|
|
35
35
|
['mode-cycle', 'crtr.mode.cycle'],
|
|
36
36
|
['graph.toggle', 'crtr.attach.graph.toggle'],
|
|
37
|
+
['help.toggle', 'crtr.attach.help.toggle'],
|
|
37
38
|
['model-ladder.next', 'crtr.attach.model-ladder.next'],
|
|
38
39
|
['model-ladder.previous', 'crtr.attach.model-ladder.previous'],
|
|
39
40
|
['command.inspect', 'crtr.attach.command.inspect'],
|
|
40
41
|
['file-review', 'crtr.attach.file-review'],
|
|
41
42
|
['profile-files', 'crtr.attach.profile-files'],
|
|
42
43
|
]),
|
|
44
|
+
...ids('crtr.attach.scroll', ['up', 'down', 'page-up', 'page-down', 'live']),
|
|
45
|
+
'crtr.attach.mouse.toggle',
|
|
46
|
+
'crtr.attach.copy.message',
|
|
43
47
|
...ids('crtr.graph', ['down', 'up', 'first', 'last', 'collapse-or-manager', 'expand-or-child', 'focus', 'revive', 'focus-manager', 'close-subtree', 'dismiss']),
|
|
44
48
|
...ids('crtr.graph.confirm', ['accept', 'cancel']),
|
|
45
49
|
...ids('crtr.view.host', ['force-quit', 'editor.backspace']),
|
|
@@ -10,6 +10,9 @@ export declare const ATTACH_CONTROL_BINDINGS: readonly [{
|
|
|
10
10
|
}, {
|
|
11
11
|
readonly menuId: "crtr.tmux.menu.attach.graph.toggle";
|
|
12
12
|
readonly actionId: "crtr.attach.graph.toggle";
|
|
13
|
+
}, {
|
|
14
|
+
readonly menuId: "crtr.tmux.menu.attach.help.toggle";
|
|
15
|
+
readonly actionId: "crtr.attach.help.toggle";
|
|
13
16
|
}, {
|
|
14
17
|
readonly menuId: "crtr.tmux.menu.attach.model-ladder.next";
|
|
15
18
|
readonly actionId: "crtr.attach.model-ladder.next";
|
|
@@ -3,6 +3,7 @@ export const ATTACH_CONTROL_BINDINGS = [
|
|
|
3
3
|
{ menuId: 'crtr.tmux.menu.attach.clear-or-detach', actionId: 'crtr.attach.clear-or-detach' },
|
|
4
4
|
{ menuId: 'crtr.tmux.menu.attach.mode-cycle', actionId: 'crtr.mode.cycle' },
|
|
5
5
|
{ menuId: 'crtr.tmux.menu.attach.graph.toggle', actionId: 'crtr.attach.graph.toggle' },
|
|
6
|
+
{ menuId: 'crtr.tmux.menu.attach.help.toggle', actionId: 'crtr.attach.help.toggle' },
|
|
6
7
|
{ menuId: 'crtr.tmux.menu.attach.model-ladder.next', actionId: 'crtr.attach.model-ladder.next' },
|
|
7
8
|
{ menuId: 'crtr.tmux.menu.attach.model-ladder.previous', actionId: 'crtr.attach.model-ladder.previous' },
|
|
8
9
|
{ menuId: 'crtr.tmux.menu.attach.command.inspect', actionId: 'crtr.attach.command.inspect' },
|
|
@@ -10,8 +10,8 @@ type ProfileMenuAction = 'up' | 'down' | 'select' | 'accept-default' | 'abort' |
|
|
|
10
10
|
type SetupAction = 'cancel' | 'tab-next' | 'tab-previous' | 'open' | 'list-down' | 'list-up' | 'toggle' | 'details' | 'advance' | 'cell-previous' | 'cell-next';
|
|
11
11
|
type SetupKeybindingAction = 'edit' | 'commit-edit' | 'cancel-edit' | 'unbind' | 'reset-row' | 'reset-all' | 'save' | 'discard' | 'page-up' | 'page-down' | 'filter' | 'filter-delete' | 'filter-clear';
|
|
12
12
|
type SetupModelsAction = 'open' | 'commit' | 'cancel' | 'scope-next';
|
|
13
|
-
export type BindingId = `crtr.tmux.menu.${TmuxMenuAction}` | `crtr.tmux.menu.issue.${'idea' | 'bug'}` | AttachMenuBindingId | `crtr.tmux.menu-global.${TmuxMenuEntryAction}` | `crtr.tmux.node.${'next' | 'previous'}` | `crtr.tmux.view.${'next' | 'previous'}` | 'crtr.tmux.inbox.toggle' | AttachBindingId | `crtr.graph.${GraphAction}` | `crtr.graph.confirm.${'accept' | 'cancel'}` | `crtr.view.host.${'force-quit' | 'editor.backspace'}` | `crtr.view.canvas.${'down' | 'up' | 'refresh' | 'quit'}` | `crtr.view.chat.${'submit' | 'contextual-cancel' | 'reconnect' | 'quit'}` | `crtr.view.git-pr.${'down' | 'up' | 'refresh' | 'quit'}` | `crtr.view.inbox.${InboxAction}` | `crtr.view.linkedin.${LinkedinAction}` | `crtr.view.prompt-review.${'down' | 'up' | 'compare-previous' | 'compare-next' | 'toggle-mode' | 'expand' | 'export' | 'refresh' | 'quit'}` | `crtr.view.workspace-sidebar.${'down' | 'up' | 'open' | 'refresh' | 'quit'}` | `crtr.view.inspector.${'down' | 'up' | 'section-next' | 'section-prev' | 'page-down' | 'page-up' | 'toggle-detail' | 'cancel-item' | 'open-log' | 'confirm' | 'dismiss' | 'retarget' | 'refresh' | 'quit'}` | `crtr.view-picker.${'down' | 'up' | 'run' | 'quit'}` | `crtr.browse.${BrowseAction}` | `crtr.browse.search.${'cancel' | 'commit' | 'delete' | 'quit'}` | `crtr.profile.menu.${ProfileMenuAction}` | `crtr.profile.search.${'up' | 'down' | 'pick' | 'back' | 'delete' | 'abort'}` | `crtr.setup.${SetupAction}` | `crtr.setup.confirm.${'accept' | 'back'}` | `crtr.setup.keybindings.${SetupKeybindingAction}` | `crtr.setup.models.${SetupModelsAction}`;
|
|
14
|
-
export declare const BINDING_CATALOG: readonly [BindingDefinition<"crtr.tmux.menu.open">, BindingDefinition<"crtr.tmux.menu.attach">, ...(BindingDefinition<BindingId> | BindingDefinition<"crtr.tmux.node.next"> | BindingDefinition<"crtr.tmux.node.previous"> | BindingDefinition<"crtr.tmux.inbox.toggle"> | BindingDefinition<"crtr.tmux.view.next"> | BindingDefinition<"crtr.tmux.view.previous"> | BindingDefinition<"crtr.graph.down"> | BindingDefinition<"crtr.graph.up"> | BindingDefinition<"crtr.graph.first"> | BindingDefinition<"crtr.graph.last"> | BindingDefinition<"crtr.graph.collapse-or-manager"> | BindingDefinition<"crtr.graph.expand-or-child"> | BindingDefinition<"crtr.graph.focus"> | BindingDefinition<"crtr.graph.revive"> | BindingDefinition<"crtr.graph.focus-manager"> | BindingDefinition<"crtr.graph.close-subtree"> | BindingDefinition<"crtr.graph.dismiss"> | BindingDefinition<"crtr.graph.confirm.accept"> | BindingDefinition<"crtr.graph.confirm.cancel"> | BindingDefinition<"crtr.view.host.force-quit"> | BindingDefinition<"crtr.view.host.editor.backspace"> | BindingDefinition<"crtr.view.chat.submit"> | BindingDefinition<"crtr.view.chat.contextual-cancel"> | BindingDefinition<"crtr.view.chat.reconnect"> | BindingDefinition<"crtr.view.chat.quit"> | BindingDefinition<"crtr.view.prompt-review.down"> | BindingDefinition<"crtr.view.prompt-review.up"> | BindingDefinition<"crtr.view.prompt-review.compare-previous"> | BindingDefinition<"crtr.view.prompt-review.compare-next"> | BindingDefinition<"crtr.view.prompt-review.toggle-mode"> | BindingDefinition<"crtr.view.prompt-review.expand"> | BindingDefinition<"crtr.view.prompt-review.export"> | BindingDefinition<"crtr.view.prompt-review.refresh"> | BindingDefinition<"crtr.view.prompt-review.quit"> | BindingDefinition<"crtr.view.workspace-sidebar.down"> | BindingDefinition<"crtr.view.workspace-sidebar.up"> | BindingDefinition<"crtr.view.workspace-sidebar.open"> | BindingDefinition<"crtr.view.workspace-sidebar.refresh"> | BindingDefinition<"crtr.view.workspace-sidebar.quit"> | BindingDefinition<"crtr.view.inspector.down"> | BindingDefinition<"crtr.view.inspector.up"> | BindingDefinition<"crtr.view.inspector.section-next"> | BindingDefinition<"crtr.view.inspector.section-prev"> | BindingDefinition<"crtr.view.inspector.page-down"> | BindingDefinition<"crtr.view.inspector.page-up"> | BindingDefinition<"crtr.view.inspector.toggle-detail"> | BindingDefinition<"crtr.view.inspector.cancel-item"> | BindingDefinition<"crtr.view.inspector.open-log"> | BindingDefinition<"crtr.view.inspector.confirm"> | BindingDefinition<"crtr.view.inspector.dismiss"> | BindingDefinition<"crtr.view.inspector.retarget"> | BindingDefinition<"crtr.view.inspector.refresh"> | BindingDefinition<"crtr.view.inspector.quit"> | BindingDefinition<"crtr.view-picker.down"> | BindingDefinition<"crtr.view-picker.up"> | BindingDefinition<"crtr.view-picker.run"> | BindingDefinition<"crtr.view-picker.quit"> | BindingDefinition<"crtr.browse.quit"> | BindingDefinition<"crtr.browse.down"> | BindingDefinition<"crtr.browse.up"> | BindingDefinition<"crtr.browse.first"> | BindingDefinition<"crtr.browse.last"> | BindingDefinition<"crtr.browse.expand-or-child"> | BindingDefinition<"crtr.browse.collapse-or-parent"> | BindingDefinition<"crtr.browse.toggle-fold"> | BindingDefinition<"crtr.browse.tab-next"> | BindingDefinition<"crtr.browse.tab-previous"> | BindingDefinition<"crtr.browse.tab.2" | "crtr.browse.tab.1" | "crtr.browse.tab.3" | "crtr.browse.tab.4" | "crtr.browse.tab.5"> | BindingDefinition<"crtr.browse.close-subtree"> | BindingDefinition<"crtr.browse.confirm-close"> | BindingDefinition<"crtr.browse.sort"> | BindingDefinition<"crtr.browse.scope"> | BindingDefinition<"crtr.browse.profile"> | BindingDefinition<"crtr.browse.residents"> | BindingDefinition<"crtr.browse.preview"> | BindingDefinition<"crtr.browse.search"> | BindingDefinition<"crtr.browse.revive-now"> | BindingDefinition<"crtr.browse.focus"> | BindingDefinition<"crtr.browse.focus-background"> | BindingDefinition<"crtr.browse.search.cancel"> | BindingDefinition<"crtr.browse.search.commit"> | BindingDefinition<"crtr.browse.search.delete"> | BindingDefinition<"crtr.browse.search.quit"> | BindingDefinition<"crtr.profile.menu.up"> | BindingDefinition<"crtr.profile.menu.down"> | BindingDefinition<"crtr.profile.menu.select"> | BindingDefinition<"crtr.profile.menu.accept-default"> | BindingDefinition<"crtr.profile.menu.abort"> | BindingDefinition<"crtr.profile.menu.slot.2" | "crtr.profile.menu.slot.1" | "crtr.profile.menu.slot.3" | "crtr.profile.menu.slot.4" | "crtr.profile.menu.slot.5" | "crtr.profile.menu.slot.9" | "crtr.profile.menu.slot.8" | "crtr.profile.menu.slot.6" | "crtr.profile.menu.slot.7">)[], BindingDefinition<"crtr.profile.menu.create">, BindingDefinition<"crtr.profile.menu.search-existing">, BindingDefinition<"crtr.profile.menu.use-root">, BindingDefinition<"crtr.profile.menu.set-default">, BindingDefinition<"crtr.profile.menu.add-directory">, BindingDefinition<"crtr.profile.menu.unpin">, BindingDefinition<"crtr.profile.search.up">, BindingDefinition<"crtr.profile.search.down">, BindingDefinition<"crtr.profile.search.pick">, BindingDefinition<"crtr.profile.search.back">, BindingDefinition<"crtr.profile.search.delete">, BindingDefinition<"crtr.profile.search.abort">, BindingDefinition<"crtr.setup.cancel">, BindingDefinition<"crtr.setup.tab-next">, BindingDefinition<"crtr.setup.tab-previous">, BindingDefinition<"crtr.setup.open">, BindingDefinition<"crtr.setup.list-down">, BindingDefinition<"crtr.setup.list-up">, BindingDefinition<"crtr.setup.toggle">, BindingDefinition<"crtr.setup.details">, BindingDefinition<"crtr.setup.advance">, BindingDefinition<"crtr.setup.confirm.accept">, BindingDefinition<"crtr.setup.confirm.back">, BindingDefinition<"crtr.setup.keybindings.edit">, BindingDefinition<"crtr.setup.keybindings.commit-edit">, BindingDefinition<"crtr.setup.keybindings.cancel-edit">, BindingDefinition<"crtr.setup.keybindings.unbind">, BindingDefinition<"crtr.setup.keybindings.reset-row">, BindingDefinition<"crtr.setup.keybindings.reset-all">, BindingDefinition<"crtr.setup.keybindings.save">, BindingDefinition<"crtr.setup.keybindings.discard">, BindingDefinition<"crtr.setup.keybindings.page-up">, BindingDefinition<"crtr.setup.keybindings.page-down">, BindingDefinition<"crtr.setup.keybindings.filter">, BindingDefinition<"crtr.setup.keybindings.filter-delete">, BindingDefinition<"crtr.setup.keybindings.filter-clear">, BindingDefinition<"crtr.setup.cell-previous">, BindingDefinition<"crtr.setup.cell-next">, BindingDefinition<"crtr.setup.models.open">, BindingDefinition<"crtr.setup.models.scope-next">, BindingDefinition<"crtr.setup.models.commit">, BindingDefinition<"crtr.setup.models.cancel">];
|
|
13
|
+
export type BindingId = `crtr.tmux.menu.${TmuxMenuAction}` | `crtr.tmux.menu.issue.${'idea' | 'bug'}` | AttachMenuBindingId | `crtr.tmux.menu-global.${TmuxMenuEntryAction}` | `crtr.tmux.node.${'next' | 'previous'}` | `crtr.tmux.view.${'next' | 'previous'}` | 'crtr.tmux.inbox.toggle' | `crtr.attach.scroll.${'up' | 'down' | 'page-up' | 'page-down' | 'live'}` | 'crtr.attach.mouse.toggle' | 'crtr.attach.copy.message' | 'crtr.attach.help.toggle' | AttachBindingId | `crtr.graph.${GraphAction}` | `crtr.graph.confirm.${'accept' | 'cancel'}` | `crtr.view.host.${'force-quit' | 'editor.backspace'}` | `crtr.view.canvas.${'down' | 'up' | 'refresh' | 'quit'}` | `crtr.view.chat.${'submit' | 'contextual-cancel' | 'reconnect' | 'quit'}` | `crtr.view.git-pr.${'down' | 'up' | 'refresh' | 'quit'}` | `crtr.view.inbox.${InboxAction}` | `crtr.view.linkedin.${LinkedinAction}` | `crtr.view.prompt-review.${'down' | 'up' | 'compare-previous' | 'compare-next' | 'toggle-mode' | 'expand' | 'export' | 'refresh' | 'quit'}` | `crtr.view.workspace-sidebar.${'down' | 'up' | 'open' | 'refresh' | 'quit'}` | `crtr.view.inspector.${'down' | 'up' | 'section-next' | 'section-prev' | 'page-down' | 'page-up' | 'toggle-detail' | 'cancel-item' | 'open-log' | 'confirm' | 'dismiss' | 'retarget' | 'refresh' | 'quit'}` | `crtr.view-picker.${'down' | 'up' | 'run' | 'quit'}` | `crtr.browse.${BrowseAction}` | `crtr.browse.search.${'cancel' | 'commit' | 'delete' | 'quit'}` | `crtr.profile.menu.${ProfileMenuAction}` | `crtr.profile.search.${'up' | 'down' | 'pick' | 'back' | 'delete' | 'abort'}` | `crtr.setup.${SetupAction}` | `crtr.setup.confirm.${'accept' | 'back'}` | `crtr.setup.keybindings.${SetupKeybindingAction}` | `crtr.setup.models.${SetupModelsAction}`;
|
|
14
|
+
export declare const BINDING_CATALOG: readonly [BindingDefinition<"crtr.tmux.menu.open">, BindingDefinition<"crtr.tmux.menu.attach">, ...(BindingDefinition<BindingId> | BindingDefinition<"crtr.tmux.node.next"> | BindingDefinition<"crtr.tmux.node.previous"> | BindingDefinition<"crtr.tmux.inbox.toggle"> | BindingDefinition<"crtr.tmux.view.next"> | BindingDefinition<"crtr.tmux.view.previous"> | BindingDefinition<"crtr.attach.scroll.up"> | BindingDefinition<"crtr.attach.scroll.down"> | BindingDefinition<"crtr.attach.scroll.page-up"> | BindingDefinition<"crtr.attach.scroll.page-down"> | BindingDefinition<"crtr.attach.scroll.live"> | BindingDefinition<"crtr.attach.mouse.toggle"> | BindingDefinition<"crtr.attach.copy.message"> | BindingDefinition<"crtr.graph.down"> | BindingDefinition<"crtr.graph.up"> | BindingDefinition<"crtr.graph.first"> | BindingDefinition<"crtr.graph.last"> | BindingDefinition<"crtr.graph.collapse-or-manager"> | BindingDefinition<"crtr.graph.expand-or-child"> | BindingDefinition<"crtr.graph.focus"> | BindingDefinition<"crtr.graph.revive"> | BindingDefinition<"crtr.graph.focus-manager"> | BindingDefinition<"crtr.graph.close-subtree"> | BindingDefinition<"crtr.graph.dismiss"> | BindingDefinition<"crtr.graph.confirm.accept"> | BindingDefinition<"crtr.graph.confirm.cancel"> | BindingDefinition<"crtr.view.host.force-quit"> | BindingDefinition<"crtr.view.host.editor.backspace"> | BindingDefinition<"crtr.view.chat.submit"> | BindingDefinition<"crtr.view.chat.contextual-cancel"> | BindingDefinition<"crtr.view.chat.reconnect"> | BindingDefinition<"crtr.view.chat.quit"> | BindingDefinition<"crtr.view.prompt-review.down"> | BindingDefinition<"crtr.view.prompt-review.up"> | BindingDefinition<"crtr.view.prompt-review.compare-previous"> | BindingDefinition<"crtr.view.prompt-review.compare-next"> | BindingDefinition<"crtr.view.prompt-review.toggle-mode"> | BindingDefinition<"crtr.view.prompt-review.expand"> | BindingDefinition<"crtr.view.prompt-review.export"> | BindingDefinition<"crtr.view.prompt-review.refresh"> | BindingDefinition<"crtr.view.prompt-review.quit"> | BindingDefinition<"crtr.view.workspace-sidebar.down"> | BindingDefinition<"crtr.view.workspace-sidebar.up"> | BindingDefinition<"crtr.view.workspace-sidebar.open"> | BindingDefinition<"crtr.view.workspace-sidebar.refresh"> | BindingDefinition<"crtr.view.workspace-sidebar.quit"> | BindingDefinition<"crtr.view.inspector.down"> | BindingDefinition<"crtr.view.inspector.up"> | BindingDefinition<"crtr.view.inspector.section-next"> | BindingDefinition<"crtr.view.inspector.section-prev"> | BindingDefinition<"crtr.view.inspector.page-down"> | BindingDefinition<"crtr.view.inspector.page-up"> | BindingDefinition<"crtr.view.inspector.toggle-detail"> | BindingDefinition<"crtr.view.inspector.cancel-item"> | BindingDefinition<"crtr.view.inspector.open-log"> | BindingDefinition<"crtr.view.inspector.confirm"> | BindingDefinition<"crtr.view.inspector.dismiss"> | BindingDefinition<"crtr.view.inspector.retarget"> | BindingDefinition<"crtr.view.inspector.refresh"> | BindingDefinition<"crtr.view.inspector.quit"> | BindingDefinition<"crtr.view-picker.down"> | BindingDefinition<"crtr.view-picker.up"> | BindingDefinition<"crtr.view-picker.run"> | BindingDefinition<"crtr.view-picker.quit"> | BindingDefinition<"crtr.browse.quit"> | BindingDefinition<"crtr.browse.down"> | BindingDefinition<"crtr.browse.up"> | BindingDefinition<"crtr.browse.first"> | BindingDefinition<"crtr.browse.last"> | BindingDefinition<"crtr.browse.expand-or-child"> | BindingDefinition<"crtr.browse.collapse-or-parent"> | BindingDefinition<"crtr.browse.toggle-fold"> | BindingDefinition<"crtr.browse.tab-next"> | BindingDefinition<"crtr.browse.tab-previous"> | BindingDefinition<"crtr.browse.tab.2" | "crtr.browse.tab.1" | "crtr.browse.tab.3" | "crtr.browse.tab.4" | "crtr.browse.tab.5"> | BindingDefinition<"crtr.browse.close-subtree"> | BindingDefinition<"crtr.browse.confirm-close"> | BindingDefinition<"crtr.browse.sort"> | BindingDefinition<"crtr.browse.scope"> | BindingDefinition<"crtr.browse.profile"> | BindingDefinition<"crtr.browse.residents"> | BindingDefinition<"crtr.browse.preview"> | BindingDefinition<"crtr.browse.search"> | BindingDefinition<"crtr.browse.revive-now"> | BindingDefinition<"crtr.browse.focus"> | BindingDefinition<"crtr.browse.focus-background"> | BindingDefinition<"crtr.browse.search.cancel"> | BindingDefinition<"crtr.browse.search.commit"> | BindingDefinition<"crtr.browse.search.delete"> | BindingDefinition<"crtr.browse.search.quit"> | BindingDefinition<"crtr.profile.menu.up"> | BindingDefinition<"crtr.profile.menu.down"> | BindingDefinition<"crtr.profile.menu.select"> | BindingDefinition<"crtr.profile.menu.accept-default"> | BindingDefinition<"crtr.profile.menu.abort"> | BindingDefinition<"crtr.profile.menu.slot.2" | "crtr.profile.menu.slot.1" | "crtr.profile.menu.slot.3" | "crtr.profile.menu.slot.4" | "crtr.profile.menu.slot.5" | "crtr.profile.menu.slot.9" | "crtr.profile.menu.slot.8" | "crtr.profile.menu.slot.6" | "crtr.profile.menu.slot.7">)[], BindingDefinition<"crtr.profile.menu.create">, BindingDefinition<"crtr.profile.menu.search-existing">, BindingDefinition<"crtr.profile.menu.use-root">, BindingDefinition<"crtr.profile.menu.set-default">, BindingDefinition<"crtr.profile.menu.add-directory">, BindingDefinition<"crtr.profile.menu.unpin">, BindingDefinition<"crtr.profile.search.up">, BindingDefinition<"crtr.profile.search.down">, BindingDefinition<"crtr.profile.search.pick">, BindingDefinition<"crtr.profile.search.back">, BindingDefinition<"crtr.profile.search.delete">, BindingDefinition<"crtr.profile.search.abort">, BindingDefinition<"crtr.setup.cancel">, BindingDefinition<"crtr.setup.tab-next">, BindingDefinition<"crtr.setup.tab-previous">, BindingDefinition<"crtr.setup.open">, BindingDefinition<"crtr.setup.list-down">, BindingDefinition<"crtr.setup.list-up">, BindingDefinition<"crtr.setup.toggle">, BindingDefinition<"crtr.setup.details">, BindingDefinition<"crtr.setup.advance">, BindingDefinition<"crtr.setup.confirm.accept">, BindingDefinition<"crtr.setup.confirm.back">, BindingDefinition<"crtr.setup.keybindings.edit">, BindingDefinition<"crtr.setup.keybindings.commit-edit">, BindingDefinition<"crtr.setup.keybindings.cancel-edit">, BindingDefinition<"crtr.setup.keybindings.unbind">, BindingDefinition<"crtr.setup.keybindings.reset-row">, BindingDefinition<"crtr.setup.keybindings.reset-all">, BindingDefinition<"crtr.setup.keybindings.save">, BindingDefinition<"crtr.setup.keybindings.discard">, BindingDefinition<"crtr.setup.keybindings.page-up">, BindingDefinition<"crtr.setup.keybindings.page-down">, BindingDefinition<"crtr.setup.keybindings.filter">, BindingDefinition<"crtr.setup.keybindings.filter-delete">, BindingDefinition<"crtr.setup.keybindings.filter-clear">, BindingDefinition<"crtr.setup.cell-previous">, BindingDefinition<"crtr.setup.cell-next">, BindingDefinition<"crtr.setup.models.open">, BindingDefinition<"crtr.setup.models.scope-next">, BindingDefinition<"crtr.setup.models.commit">, BindingDefinition<"crtr.setup.models.cancel">];
|
|
15
15
|
export declare const BINDING_IDS: ReadonlySet<string>;
|
|
16
16
|
export declare const SAFETY_REQUIREMENTS: readonly SafetyRequirement[];
|
|
17
17
|
export {};
|
|
@@ -74,11 +74,19 @@ export const BINDING_CATALOG = Object.freeze([
|
|
|
74
74
|
...attachEntry('crtr.tmux.menu.attach.clear-or-detach', 'crtr.attach.clear-or-detach', 'Clear or detach', 'Clear input or detach when input is empty.', 'c', ['ctrl+c']),
|
|
75
75
|
...attachEntry('crtr.tmux.menu.attach.mode-cycle', 'crtr.mode.cycle', 'Cycle mode', 'Cycle the active agent mode.', 'p', ['alt+shift+p']),
|
|
76
76
|
...attachEntry('crtr.tmux.menu.attach.graph.toggle', 'crtr.attach.graph.toggle', 'Toggle graph', 'Open or close the graph overlay.', 'g', ['alt+g']),
|
|
77
|
+
...attachEntry('crtr.tmux.menu.attach.help.toggle', 'crtr.attach.help.toggle', 'Help', 'Open the attach help overlay.', 'k', ['alt+shift+k']),
|
|
77
78
|
...attachEntry('crtr.tmux.menu.attach.model-ladder.next', 'crtr.attach.model-ladder.next', 'Next model ladder', 'Move to the next model ladder rung.', ']', ['alt+m']),
|
|
78
79
|
...attachEntry('crtr.tmux.menu.attach.model-ladder.previous', 'crtr.attach.model-ladder.previous', 'Previous model ladder', 'Move to the previous model ladder rung.', '[', ['alt+shift+m']),
|
|
79
80
|
...attachEntry('crtr.tmux.menu.attach.command.inspect', 'crtr.attach.command.inspect', 'Inspect loaded command', 'Open the loaded slash command’s expanded prompt.', 'h', ['alt+shift+h']),
|
|
80
81
|
...attachEntry('crtr.tmux.menu.attach.file-review', 'crtr.attach.file-review', 'Review a file', 'Open a line-anchored review of a file named in the transcript.', 'r', ['alt+shift+r']),
|
|
81
82
|
...attachEntry('crtr.tmux.menu.attach.profile-files', 'crtr.attach.profile-files', 'Search profile files', 'Search files across the node’s profile projects, cwd, and ancestor crouter memory stores.', 'f', []),
|
|
83
|
+
b('crtr.attach.scroll.up', 'Attach', 'Scroll up', 'Scroll the transcript one line up.', ['shift+up'], 'terminal', ATTACH_CONTEXTS),
|
|
84
|
+
b('crtr.attach.scroll.down', 'Attach', 'Scroll down', 'Scroll the transcript one line down.', ['shift+down'], 'terminal', ATTACH_CONTEXTS),
|
|
85
|
+
b('crtr.attach.scroll.page-up', 'Attach', 'Scroll page up', 'Scroll the transcript one page up.', ['pageup'], 'terminal', ATTACH_CONTEXTS),
|
|
86
|
+
b('crtr.attach.scroll.page-down', 'Attach', 'Scroll page down', 'Scroll the transcript one page down.', ['pagedown'], 'terminal', ATTACH_CONTEXTS),
|
|
87
|
+
b('crtr.attach.scroll.live', 'Attach', 'Return to live', 'Return the transcript to the live bottom.', ['shift+end'], 'terminal', ATTACH_CONTEXTS),
|
|
88
|
+
b('crtr.attach.mouse.toggle', 'Attach', 'Toggle mouse wheel scrolling', 'Toggle mouse wheel scrolling on or off.', ['alt+shift+o'], 'terminal', ATTACH_CONTEXTS),
|
|
89
|
+
b('crtr.attach.copy.message', 'Attach', 'Copy visible message', 'Copy the newest message visible in the transcript viewport.', ['alt+shift+y'], 'terminal', ATTACH_CONTEXTS),
|
|
82
90
|
b('crtr.graph.down', 'GRAPH', 'Move down', 'Move to the next graph row.', ['j'], 'terminal', ['graph']),
|
|
83
91
|
b('crtr.graph.up', 'GRAPH', 'Move up', 'Move to the previous graph row.', ['k'], 'terminal', ['graph']),
|
|
84
92
|
b('crtr.graph.first', 'GRAPH', 'First row', 'Move to the first graph row.', ['g'], 'terminal', ['graph']),
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AgentSession, AgentSessionEvent, RpcExtensionUIRequest, RpcExtensionUIResponse, RpcSessionState, SessionEntry, SessionInfo, SettingsConfig, SessionStats } from '@earendil-works/pi-coding-agent';
|
|
2
2
|
import type { Api, ImageContent, Model } from '@earendil-works/pi-ai';
|
|
3
3
|
import type { BrokerErrorFrame } from '../../api/dto/broker.js';
|
|
4
|
+
import type { ToolGroupSummary } from '../../shared/tool-groups.js';
|
|
4
5
|
/** pi's own RPC types, re-exported unchanged. `broker-protocol` stays the one
|
|
5
6
|
* import site for the wire union; the shapes themselves are pi's, versioned by
|
|
6
7
|
* pi, so a pi change is a compile error here instead of silent drift. */
|
|
@@ -45,6 +46,10 @@ export interface BrokerSnapshot {
|
|
|
45
46
|
}>;
|
|
46
47
|
title: string | undefined;
|
|
47
48
|
};
|
|
49
|
+
/** Broker-owned summaries keyed by the first tool-call id in each group.
|
|
50
|
+
* Structured objects with bullets, nodesSpawned, and filesEdited.
|
|
51
|
+
* Optional so snapshots from an older live runtime remain readable. */
|
|
52
|
+
toolGroupSummaries?: Record<string, ToolGroupSummary>;
|
|
48
53
|
}
|
|
49
54
|
/** Opens the connection and FIXES this client's role for its lifetime. A repeated
|
|
50
55
|
* `hello` on an already-helloed socket never changes the established role. */
|
|
@@ -563,10 +568,17 @@ export interface ExtensionUIDismissFrame {
|
|
|
563
568
|
type: 'extension_ui_dismiss';
|
|
564
569
|
id: string;
|
|
565
570
|
}
|
|
571
|
+
/** A completed broker-side tool-group summary. The viewer owns presentation;
|
|
572
|
+
* this frame carries the durable group key and structured summary object. */
|
|
573
|
+
export interface ToolGroupSummaryFrame {
|
|
574
|
+
type: 'tool_group_summary';
|
|
575
|
+
key: string;
|
|
576
|
+
summary: ToolGroupSummary;
|
|
577
|
+
}
|
|
566
578
|
/** Everything the broker can send. Live `AgentSessionEvent`s are relayed
|
|
567
579
|
* verbatim (the broker adds nothing); the broker's own control frames carry
|
|
568
580
|
* non-colliding `type` discriminants. */
|
|
569
|
-
export type BrokerToClient = WelcomeFrame | ModelChangedFrame | ErrorFrame | AckFrame | BrokerDataFrame | BashStartFrame | BashOutputFrame | BashEndFrame | ExtensionUIRequestFrame | ExtensionUIDismissFrame | AgentSessionEvent;
|
|
581
|
+
export type BrokerToClient = WelcomeFrame | ModelChangedFrame | ErrorFrame | AckFrame | BrokerDataFrame | BashStartFrame | BashOutputFrame | BashEndFrame | ExtensionUIRequestFrame | ExtensionUIDismissFrame | ToolGroupSummaryFrame | AgentSessionEvent;
|
|
570
582
|
/** Encode one frame as a single newline-terminated JSON line. */
|
|
571
583
|
export declare function encodeFrame(frame: ClientToBroker | BrokerToClient): string;
|
|
572
584
|
/** Byte bounds for a {@link FrameDecoder} (C5). */
|
|
@@ -32,6 +32,8 @@ import { operationIdContext } from '../events/operation-id.js';
|
|
|
32
32
|
import { findMissingPackagePaths } from './package-health.js';
|
|
33
33
|
import { SessionListCache } from './session-list-cache.js';
|
|
34
34
|
import { getNode, updateNode } from '../canvas/index.js';
|
|
35
|
+
import { readConfig } from '../config.js';
|
|
36
|
+
import { atomicWriteJson, readJsonIfExists } from '../fs-utils.js';
|
|
35
37
|
import { buildRefInventory } from '../memory/inline-ref-inventory.js';
|
|
36
38
|
import { buildGuidance } from '../memory/inline-ref-guidance.js';
|
|
37
39
|
import { clearSessionCache } from '../substrate/session-cache.js';
|
|
@@ -44,7 +46,9 @@ import { PoolCredentialStore } from '../pool-credential-store.js';
|
|
|
44
46
|
import { clearFault, isModelNotFoundError, isProviderUnconfiguredError, readFault, recordFault, recordFaultForCurrentNode } from './fault.js';
|
|
45
47
|
import { clearCleanAbort, markBusy, markCleanAbort } from './busy.js';
|
|
46
48
|
import { extractCoolingDeadline } from './managed-provider-cooling.js';
|
|
47
|
-
import { AUTH_FAULT_RECOVERY_BODY, CONNECTION_FAULT_RECOVERY_BODY, PROVIDER_FAULT_RECOVERY_BODY } from '
|
|
49
|
+
import { AUTH_FAULT_RECOVERY_BODY, CONNECTION_FAULT_RECOVERY_BODY, PROVIDER_FAULT_RECOVERY_BODY, formatModelFallbackRecovery, generatedContextText, } from '../../shared/generated-context.js';
|
|
50
|
+
import { assistantVisibleText, isTrueUserMessage, normalizeToolGroupSummaryRecord, } from '../../shared/tool-groups.js';
|
|
51
|
+
import { headlessToolGroupSummary, serializeToolGroup } from './tool-group-summary.js';
|
|
48
52
|
import { markFatalOnExhaust, nextFaultRetry, policyFor } from './fault-recovery.js';
|
|
49
53
|
import { probeOnline as probeOnlineReal } from './connectivity.js';
|
|
50
54
|
import { CRTR_CYCLE_CUSTOM_TYPE, cycleAwareMessages } from './session-cycles.js';
|
|
@@ -588,7 +592,26 @@ export async function runBroker(nodeId, startupAt = process.hrtime.bigint(), sta
|
|
|
588
592
|
const displayStatuses = new Map();
|
|
589
593
|
const displayWidgets = new Map();
|
|
590
594
|
let displayTitle;
|
|
595
|
+
const toolSummariesPath = join(jobDir(nodeId), 'tool-summaries.json');
|
|
596
|
+
const toolGroupSummaries = new Map();
|
|
597
|
+
try {
|
|
598
|
+
const persisted = readJsonIfExists(toolSummariesPath);
|
|
599
|
+
for (const [key, summary] of Object.entries(normalizeToolGroupSummaryRecord(persisted))) {
|
|
600
|
+
toolGroupSummaries.set(key, summary);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
catch {
|
|
604
|
+
// A malformed sidecar merely withholds summaries; transcript tools remain visible.
|
|
605
|
+
}
|
|
606
|
+
const summaryAttempted = new Set(toolGroupSummaries.keys());
|
|
607
|
+
const generatingToolGroups = new Set();
|
|
608
|
+
const toolGroupsByCallId = new Map();
|
|
609
|
+
const summaryTasks = new Set();
|
|
610
|
+
let openToolGroup;
|
|
611
|
+
let lastToolGroupBoundaryProse = '';
|
|
612
|
+
let sawAssistantProse = false;
|
|
591
613
|
let disposed = false;
|
|
614
|
+
let disposePending = false;
|
|
592
615
|
let agentRunActive = false;
|
|
593
616
|
let shutdownRequested = false;
|
|
594
617
|
let server;
|
|
@@ -729,6 +752,168 @@ export async function runBroker(nodeId, startupAt = process.hrtime.bigint(), sta
|
|
|
729
752
|
}
|
|
730
753
|
broadcast(frame);
|
|
731
754
|
};
|
|
755
|
+
/** Record and asynchronously summarize the maximal non-boundary region between
|
|
756
|
+
* visible prose messages. A boundary can land while a tool is still running,
|
|
757
|
+
* so closed groups retain their call ids until every result has joined the
|
|
758
|
+
* same serialized segment; only then may they become collapsible. */
|
|
759
|
+
const ensureOpenToolGroup = () => {
|
|
760
|
+
if (openToolGroup === undefined) {
|
|
761
|
+
openToolGroup = {
|
|
762
|
+
toolCount: 0,
|
|
763
|
+
pieces: [],
|
|
764
|
+
boundaryProse: lastToolGroupBoundaryProse,
|
|
765
|
+
pendingToolIds: new Set(),
|
|
766
|
+
closed: false,
|
|
767
|
+
summarizeWhenSettled: false,
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
return openToolGroup;
|
|
771
|
+
};
|
|
772
|
+
const generateSettledToolGroup = (group) => {
|
|
773
|
+
if (!group.closed || group.pendingToolIds.size > 0 || group.key === undefined || !group.summarizeWhenSettled)
|
|
774
|
+
return;
|
|
775
|
+
const key = group.key;
|
|
776
|
+
if (summaryAttempted.has(key) || generatingToolGroups.has(key))
|
|
777
|
+
return;
|
|
778
|
+
summaryAttempted.add(key);
|
|
779
|
+
generatingToolGroups.add(key);
|
|
780
|
+
let task;
|
|
781
|
+
task = headlessToolGroupSummary(serializeToolGroup(group.boundaryProse, group.pieces))
|
|
782
|
+
.then((summary) => {
|
|
783
|
+
if (summary === null)
|
|
784
|
+
return;
|
|
785
|
+
toolGroupSummaries.set(key, summary);
|
|
786
|
+
try {
|
|
787
|
+
atomicWriteJson(toolSummariesPath, Object.fromEntries(toolGroupSummaries));
|
|
788
|
+
}
|
|
789
|
+
catch {
|
|
790
|
+
// A delivery without durable state would disappear on reattach, so do
|
|
791
|
+
// not advertise it. The calls remain folded normally instead.
|
|
792
|
+
toolGroupSummaries.delete(key);
|
|
793
|
+
return;
|
|
794
|
+
}
|
|
795
|
+
broadcast({ type: 'tool_group_summary', key, summary });
|
|
796
|
+
})
|
|
797
|
+
.catch(() => undefined)
|
|
798
|
+
.finally(() => {
|
|
799
|
+
generatingToolGroups.delete(key);
|
|
800
|
+
summaryTasks.delete(task);
|
|
801
|
+
});
|
|
802
|
+
summaryTasks.add(task);
|
|
803
|
+
};
|
|
804
|
+
const finishOpenToolGroup = () => {
|
|
805
|
+
const group = openToolGroup;
|
|
806
|
+
openToolGroup = undefined;
|
|
807
|
+
if (group === undefined)
|
|
808
|
+
return;
|
|
809
|
+
group.closed = true;
|
|
810
|
+
// Configuration is read at the boundary, not when a slow tool later settles.
|
|
811
|
+
group.summarizeWhenSettled = readConfig('user').summarize_tool_calls;
|
|
812
|
+
generateSettledToolGroup(group);
|
|
813
|
+
};
|
|
814
|
+
const visibleBoundary = (prose) => {
|
|
815
|
+
finishOpenToolGroup();
|
|
816
|
+
lastToolGroupBoundaryProse = prose;
|
|
817
|
+
};
|
|
818
|
+
const observeToolGroupEvent = (event) => {
|
|
819
|
+
// The viewer turns every compaction_end into a summary, cancellation, or
|
|
820
|
+
// error line, each of which is a hard transcript seam.
|
|
821
|
+
if (event.type === 'compaction_end') {
|
|
822
|
+
finishOpenToolGroup();
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
// A failed automatic retry is rendered as ChatView's visible error line.
|
|
826
|
+
// Successful retries only clear activity and remain within the same group.
|
|
827
|
+
if (event.type === 'auto_retry_end' && event.success !== true) {
|
|
828
|
+
finishOpenToolGroup();
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
// The attach viewer renders aborted and errored assistant endings as visible
|
|
832
|
+
// transcript seams. Close their completed tool run here too; any tool that
|
|
833
|
+
// never emitted its execution_end keeps the group unsettled and visible.
|
|
834
|
+
if (event.type === 'message_end') {
|
|
835
|
+
const message = event.message;
|
|
836
|
+
if (message !== null && typeof message === 'object') {
|
|
837
|
+
const item = message;
|
|
838
|
+
if (item.role === 'assistant' && (item.stopReason === 'aborted' || item.stopReason === 'error')) {
|
|
839
|
+
finishOpenToolGroup();
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
844
|
+
if (event.type === 'tool_execution_start') {
|
|
845
|
+
const group = ensureOpenToolGroup();
|
|
846
|
+
const id = typeof event.toolCallId === 'string' ? event.toolCallId : '';
|
|
847
|
+
if (group.key === undefined && id !== '')
|
|
848
|
+
group.key = id;
|
|
849
|
+
if (id !== '') {
|
|
850
|
+
group.pendingToolIds.add(id);
|
|
851
|
+
toolGroupsByCallId.set(id, group);
|
|
852
|
+
}
|
|
853
|
+
group.toolCount += 1;
|
|
854
|
+
group.pieces.push({ type: 'tool', name: typeof event.toolName === 'string' ? event.toolName : 'tool', args: event.args });
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
857
|
+
if (event.type === 'tool_execution_end') {
|
|
858
|
+
const id = typeof event.toolCallId === 'string' ? event.toolCallId : '';
|
|
859
|
+
const group = id === '' ? openToolGroup : toolGroupsByCallId.get(id);
|
|
860
|
+
if (group !== undefined) {
|
|
861
|
+
group.pieces.push({
|
|
862
|
+
type: 'result',
|
|
863
|
+
name: typeof event.toolName === 'string' ? event.toolName : 'tool',
|
|
864
|
+
result: event.result,
|
|
865
|
+
isError: event.isError === true,
|
|
866
|
+
});
|
|
867
|
+
if (id !== '') {
|
|
868
|
+
group.pendingToolIds.delete(id);
|
|
869
|
+
toolGroupsByCallId.delete(id);
|
|
870
|
+
}
|
|
871
|
+
generateSettledToolGroup(group);
|
|
872
|
+
}
|
|
873
|
+
return;
|
|
874
|
+
}
|
|
875
|
+
if (event.type !== 'message_start' && event.type !== 'message_update')
|
|
876
|
+
return;
|
|
877
|
+
const message = event.message;
|
|
878
|
+
if (message === null || typeof message !== 'object')
|
|
879
|
+
return;
|
|
880
|
+
const item = message;
|
|
881
|
+
const role = item.role;
|
|
882
|
+
if (role === 'assistant') {
|
|
883
|
+
if (event.type === 'message_start')
|
|
884
|
+
sawAssistantProse = false;
|
|
885
|
+
const prose = assistantVisibleText(item);
|
|
886
|
+
if (!sawAssistantProse && prose.trim() !== '') {
|
|
887
|
+
sawAssistantProse = true;
|
|
888
|
+
visibleBoundary(prose);
|
|
889
|
+
}
|
|
890
|
+
return;
|
|
891
|
+
}
|
|
892
|
+
if (event.type !== 'message_start')
|
|
893
|
+
return;
|
|
894
|
+
if (role === 'compactionSummary' || role === 'branchSummary' || role === 'bashExecution' || role === 'status' || role === 'error' || item.customType === 'crtr-cycle-divider') {
|
|
895
|
+
finishOpenToolGroup();
|
|
896
|
+
return;
|
|
897
|
+
}
|
|
898
|
+
if (isTrueUserMessage(item)) {
|
|
899
|
+
visibleBoundary(generatedContextText(item));
|
|
900
|
+
return;
|
|
901
|
+
}
|
|
902
|
+
if (item.display === false)
|
|
903
|
+
return;
|
|
904
|
+
const text = generatedContextText(item);
|
|
905
|
+
const isBearingsOrRevive = item.customType === 'crtr-context' || (role === 'user' && text.startsWith('You have been revived fresh after a context refresh'));
|
|
906
|
+
if (isBearingsOrRevive) {
|
|
907
|
+
if (openToolGroup !== undefined && text !== '')
|
|
908
|
+
openToolGroup.pieces.push({ type: 'text', text });
|
|
909
|
+
return;
|
|
910
|
+
}
|
|
911
|
+
// Generated inbox/situational/nudge and visible custom output are part of
|
|
912
|
+
// the between-message activity and may begin a group before its first tool.
|
|
913
|
+
const group = ensureOpenToolGroup();
|
|
914
|
+
if (text !== '')
|
|
915
|
+
group.pieces.push({ type: 'text', text });
|
|
916
|
+
};
|
|
732
917
|
// ---------------------------------------------------------------------------
|
|
733
918
|
// F2: message_update coalescing. `relayEvent` is the single entry point for
|
|
734
919
|
// engine events headed to viewers: a message_update is held (latest wins) and
|
|
@@ -951,9 +1136,7 @@ export async function runBroker(nodeId, startupAt = process.hrtime.bigint(), sta
|
|
|
951
1136
|
// node from reviving straight back into fault-recovery chrome.
|
|
952
1137
|
if (unconfigured)
|
|
953
1138
|
clearFault(nodeId, { link: 'pi→provider' });
|
|
954
|
-
await operationIdContext.fresh(() => session.prompt(unconfigured
|
|
955
|
-
? `The previous model (${currentSpec}) had no usable provider credential, so you were automatically switched to ${resolved}. Continue the task from where the failed turn left off.`
|
|
956
|
-
: `The previous model (${currentSpec}) was unavailable (provider 404 not_found), so you were automatically switched to ${resolved}. Continue the task from where the failed turn left off.`));
|
|
1139
|
+
await operationIdContext.fresh(() => session.prompt(formatModelFallbackRecovery(currentSpec, resolved, unconfigured ? 'credential' : 'not-found')));
|
|
957
1140
|
})()
|
|
958
1141
|
.catch((err) => {
|
|
959
1142
|
emitEvent({
|
|
@@ -1295,6 +1478,7 @@ export async function runBroker(nodeId, startupAt = process.hrtime.bigint(), sta
|
|
|
1295
1478
|
widgets: Object.fromEntries([...displayWidgets].map(([k, w]) => [k, { lines: [...w.lines], placement: w.placement }])),
|
|
1296
1479
|
title: displayTitle,
|
|
1297
1480
|
},
|
|
1481
|
+
toolGroupSummaries: Object.fromEntries(toolGroupSummaries),
|
|
1298
1482
|
});
|
|
1299
1483
|
// Send a client its catch-up snapshot. welcome.pending_dialog carries a single
|
|
1300
1484
|
// still-in-flight dialog to a WRITABLE client attaching mid-dialog; an observer
|
|
@@ -1337,7 +1521,7 @@ export async function runBroker(nodeId, startupAt = process.hrtime.bigint(), sta
|
|
|
1337
1521
|
// The single exit helper (plan §0): dispose the engine, close + unlink the
|
|
1338
1522
|
// socket, exit 0. Idempotent — every trigger converges here.
|
|
1339
1523
|
// -------------------------------------------------------------------------
|
|
1340
|
-
const
|
|
1524
|
+
const completeExit = (status) => {
|
|
1341
1525
|
if (disposed)
|
|
1342
1526
|
return;
|
|
1343
1527
|
disposed = true;
|
|
@@ -1381,6 +1565,23 @@ export async function runBroker(nodeId, startupAt = process.hrtime.bigint(), sta
|
|
|
1381
1565
|
}
|
|
1382
1566
|
process.exit(status);
|
|
1383
1567
|
};
|
|
1568
|
+
const disposeAndExit = (reason, status = 0) => {
|
|
1569
|
+
if (disposed)
|
|
1570
|
+
return;
|
|
1571
|
+
// A normal terminal shutdown follows a visible boundary that may have just
|
|
1572
|
+
// launched a capped (45s) headless summary. Keep the broker and its child
|
|
1573
|
+
// alive until those already-started tasks persist/broadcast, rather than
|
|
1574
|
+
// process.exit() orphaning pi and losing the sidecar. Abrupt failures and
|
|
1575
|
+
// signals retain their existing immediate teardown behavior.
|
|
1576
|
+
if ((reason === 'shutdown-hook' || reason === 'shutdown-after-settle') && summaryTasks.size > 0) {
|
|
1577
|
+
if (disposePending)
|
|
1578
|
+
return;
|
|
1579
|
+
disposePending = true;
|
|
1580
|
+
void Promise.allSettled([...summaryTasks]).finally(() => completeExit(status));
|
|
1581
|
+
return;
|
|
1582
|
+
}
|
|
1583
|
+
completeExit(status);
|
|
1584
|
+
};
|
|
1384
1585
|
// A stophook can request shutdown while pi is still unwinding a completed
|
|
1385
1586
|
// turn. Let that turn reach agent_settled first: inbox delivery commits its
|
|
1386
1587
|
// durable cursor there, and only there. Explicit operator shutdown and OS
|
|
@@ -1491,6 +1692,7 @@ export async function runBroker(nodeId, startupAt = process.hrtime.bigint(), sta
|
|
|
1491
1692
|
return;
|
|
1492
1693
|
}
|
|
1493
1694
|
}
|
|
1695
|
+
observeToolGroupEvent(event);
|
|
1494
1696
|
relayEvent(event, generation);
|
|
1495
1697
|
if (event.type === 'agent_settled')
|
|
1496
1698
|
scheduleFaultRetry();
|
|
@@ -1526,6 +1728,9 @@ export async function runBroker(nodeId, startupAt = process.hrtime.bigint(), sta
|
|
|
1526
1728
|
providerFallbackInFlight = null;
|
|
1527
1729
|
notFoundFallbackInFlight = null;
|
|
1528
1730
|
reloadAuthInFlight = null;
|
|
1731
|
+
openToolGroup = undefined;
|
|
1732
|
+
toolGroupsByCallId.clear();
|
|
1733
|
+
sawAssistantProse = false;
|
|
1529
1734
|
await candidateSession.bindExtensions({
|
|
1530
1735
|
uiContext,
|
|
1531
1736
|
// 'rpc' — NOT 'print'. Per pi docs/rpc.md:1078 this is exactly our shape:
|
|
@@ -1810,6 +2015,9 @@ export async function runBroker(nodeId, startupAt = process.hrtime.bigint(), sta
|
|
|
1810
2015
|
// Order before any held assistant message_update, so a `!` run mid-stream
|
|
1811
2016
|
// never renders ahead of the update it follows.
|
|
1812
2017
|
flushPendingUpdate();
|
|
2018
|
+
// The live bash component is a visible transcript boundary, even though
|
|
2019
|
+
// its persisted bashExecution message arrives later via the session.
|
|
2020
|
+
finishOpenToolGroup();
|
|
1813
2021
|
broadcast({ type: 'bash_start', command, excludeFromContext: exclude });
|
|
1814
2022
|
void session
|
|
1815
2023
|
.executeBash(command, (chunk) => broadcast({ type: 'bash_output', chunk }), {
|
|
@@ -12,6 +12,9 @@ export declare const CANVAS_BASH_VALVE_PATH: string;
|
|
|
12
12
|
* (`runtime/naming.ts`) to give it a constrained-schema `name_session` tool.
|
|
13
13
|
* Deliberately absent from CANVAS_EXTENSIONS: a node must never carry it. */
|
|
14
14
|
export declare const NAMING_TOOL_PATH: string;
|
|
15
|
+
/** NOT a canvas extension — loaded only by the broker's headless tool-group
|
|
16
|
+
* summarizer, which is the sole owner of summary generation and persistence. */
|
|
17
|
+
export declare const SUMMARY_TOOL_PATH: string;
|
|
15
18
|
/** The canvas extensions every node loads, in order. The inbox watcher commits
|
|
16
19
|
* its cursor at agent_settled before the stophook checks it for idle release. */
|
|
17
20
|
export declare const CANVAS_EXTENSIONS: string[];
|
|
@@ -24,6 +24,9 @@ export const CANVAS_BASH_VALVE_PATH = resolveExtension('canvas-bash-valve');
|
|
|
24
24
|
* (`runtime/naming.ts`) to give it a constrained-schema `name_session` tool.
|
|
25
25
|
* Deliberately absent from CANVAS_EXTENSIONS: a node must never carry it. */
|
|
26
26
|
export const NAMING_TOOL_PATH = resolveExtension('naming-tool');
|
|
27
|
+
/** NOT a canvas extension — loaded only by the broker's headless tool-group
|
|
28
|
+
* summarizer, which is the sole owner of summary generation and persistence. */
|
|
29
|
+
export const SUMMARY_TOOL_PATH = resolveExtension('summary-tool');
|
|
27
30
|
/** The canvas extensions every node loads, in order. The inbox watcher commits
|
|
28
31
|
* its cursor at agent_settled before the stophook checks it for idle release. */
|
|
29
32
|
export const CANVAS_EXTENSIONS = [
|
|
@@ -151,7 +151,7 @@ export async function maybeBootRoot(argv) {
|
|
|
151
151
|
// Unambiguous front-door launch → boot a resident root inline (exec pi in
|
|
152
152
|
// this terminal). Does not return. Load the heavy boot-path deps lazily now
|
|
153
153
|
// that we've committed to booting (see the import note at the top of file).
|
|
154
|
-
const [{ bootRoot }, { resumeRoot }, {
|
|
154
|
+
const [{ bootRoot }, { resumeRoot }, { rendererWarning, missingPackageWarning, piAgentDir }] = await Promise.all([
|
|
155
155
|
import('./boot-root.js'),
|
|
156
156
|
import('./resume-root.js'),
|
|
157
157
|
import('./package-health.js'),
|
|
@@ -164,9 +164,9 @@ export async function maybeBootRoot(argv) {
|
|
|
164
164
|
const warn = missingPackageWarning(piAgentDir());
|
|
165
165
|
if (warn !== null)
|
|
166
166
|
process.stderr.write(`\n${warn}\n\n`);
|
|
167
|
-
const
|
|
168
|
-
if (
|
|
169
|
-
process.stderr.write(`\n${
|
|
167
|
+
const rendererWarn = rendererWarning();
|
|
168
|
+
if (rendererWarn !== null)
|
|
169
|
+
process.stderr.write(`\n${rendererWarn}\n\n`);
|
|
170
170
|
}
|
|
171
171
|
catch {
|
|
172
172
|
/* best-effort diagnostic — never block a boot */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type NodeMeta } from '../canvas/index.js';
|
|
2
2
|
import { type WakeOrigin } from './bearings.js';
|
|
3
|
-
export { REVIVE_KICKOFF_SENTINEL } from '../../shared/generated-context.js';
|
|
3
|
+
export { REVIVE_KICKOFF_SENTINEL, RUNTIME_RESTART_CONTINUATION, } from '../../shared/generated-context.js';
|
|
4
4
|
/** The goal file — the prompt/task a node was spawned with, persisted at birth
|
|
5
5
|
* so a fresh revive can re-read its mandate. */
|
|
6
6
|
export declare function goalPath(nodeId: string): string;
|
|
@@ -16,10 +16,6 @@ export declare function captureGoalIfAbsent(nodeId: string, text: string): boole
|
|
|
16
16
|
/** Sentinel opening the fresh-revive kickoff message (see buildReviveKickoff).
|
|
17
17
|
* The goal-capture extension and attached renderers share its pure definition,
|
|
18
18
|
* so the same exact contract controls both prompt exclusion and display. */
|
|
19
|
-
/** Injected only when a broker cleanly persisted an aborted in-flight turn
|
|
20
|
-
* before a daemon restart. The transcript already carries the full picture, so
|
|
21
|
-
* this is a bare nudge — a longer explanation only destabilizes the resume. */
|
|
22
|
-
export declare const RUNTIME_RESTART_CONTINUATION = "continue";
|
|
23
19
|
/** The yield-message file — a short note `crtr node yield` records for the next
|
|
24
20
|
* fresh/cycling revive ("on wake, do X"). It remains durable through failed
|
|
25
21
|
* launch attempts and is cleared only when session_start confirms a boot. */
|
|
@@ -25,7 +25,7 @@ import { buildWakeBearings } from './bearings.js';
|
|
|
25
25
|
import { personaDrift, commitPersonaAck } from './persona.js';
|
|
26
26
|
import { readInboxSince, readCursor, writeCursor, coalesce, } from '../feed/inbox.js';
|
|
27
27
|
import { REVIVE_KICKOFF_SENTINEL } from '../../shared/generated-context.js';
|
|
28
|
-
export { REVIVE_KICKOFF_SENTINEL } from '../../shared/generated-context.js';
|
|
28
|
+
export { REVIVE_KICKOFF_SENTINEL, RUNTIME_RESTART_CONTINUATION, } from '../../shared/generated-context.js';
|
|
29
29
|
// ---------------------------------------------------------------------------
|
|
30
30
|
// Companion context files: the goal (the spawning mandate) and the one-shot
|
|
31
31
|
// yield message (a note from the prior self to the revived self).
|
|
@@ -65,10 +65,6 @@ export function captureGoalIfAbsent(nodeId, text) {
|
|
|
65
65
|
/** Sentinel opening the fresh-revive kickoff message (see buildReviveKickoff).
|
|
66
66
|
* The goal-capture extension and attached renderers share its pure definition,
|
|
67
67
|
* so the same exact contract controls both prompt exclusion and display. */
|
|
68
|
-
/** Injected only when a broker cleanly persisted an aborted in-flight turn
|
|
69
|
-
* before a daemon restart. The transcript already carries the full picture, so
|
|
70
|
-
* this is a bare nudge — a longer explanation only destabilizes the resume. */
|
|
71
|
-
export const RUNTIME_RESTART_CONTINUATION = 'continue';
|
|
72
68
|
/** The yield-message file — a short note `crtr node yield` records for the next
|
|
73
69
|
* fresh/cycling revive ("on wake, do X"). It remains durable through failed
|
|
74
70
|
* launch attempts and is cleared only when session_start confirms a boot. */
|