@iowarp/clio-coder 0.4.5 → 0.4.6
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 +24 -0
- package/CONTRIBUTING.md +14 -9
- package/NOTICE +16 -0
- package/README.md +312 -685
- package/dist/{acp-H3CU2HBQ.js → acp-UVEVWSDL.js} +6 -6
- package/dist/{agents-IXQQZ7BD.js → agents-VWY37DTK.js} +31 -30
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-R7KYF7N3.js → auth-PCV2XQDV.js} +6 -6
- package/dist/{builtins-CRFDQUVP.js → builtins-PD652MTK.js} +3 -3
- package/dist/{chunk-SDWNDICN.js → chunk-24T2YZ7A.js} +58 -56
- package/dist/{chunk-FSTIBAGM.js → chunk-2AKYFREM.js} +7 -7
- package/dist/{chunk-SE4ZKILO.js → chunk-3BJGMT2D.js} +30 -9
- package/dist/{chunk-GVYWZNRK.js → chunk-3HQVBIKD.js} +2 -2
- package/dist/{chunk-EWD5P3GK.js → chunk-3JLFK5MW.js} +4 -4
- package/dist/{chunk-O2RQ7LCK.js → chunk-3O2ZAUGQ.js} +2 -2
- package/dist/{chunk-GXCCHKN6.js → chunk-3QKXHCGS.js} +4 -4
- package/dist/{chunk-YEJIG7LN.js → chunk-3WBALRQH.js} +7 -7
- package/dist/{chunk-I7VLWRK2.js → chunk-4DU2TVI4.js} +5 -5
- package/dist/{chunk-TEG3RYVZ.js → chunk-4U4TKZFR.js} +3 -3
- package/dist/{chunk-EHCPSZJF.js → chunk-4VMV6OS6.js} +2 -2
- package/dist/{chunk-T7FDXNRU.js → chunk-536HXRFE.js} +4 -4
- package/dist/{chunk-ZMZQEBKI.js → chunk-5QRX7SLS.js} +8 -8
- package/dist/{chunk-RXIOCVBZ.js → chunk-6HAO6X5B.js} +4 -4
- package/dist/{chunk-HGSLRG33.js → chunk-6OII3LOK.js} +2 -2
- package/dist/{chunk-U2JOLB7O.js → chunk-6RYDAVQT.js} +32 -32
- package/dist/{chunk-T53XI6I7.js → chunk-6VRRJT7L.js} +2 -2
- package/dist/{chunk-RLTT5GVY.js → chunk-7JSSKXG2.js} +4 -4
- package/dist/{chunk-633EXGZA.js → chunk-ACCKVSHU.js} +3 -3
- package/dist/{chunk-6SYEGZI3.js → chunk-B3MOMLJ4.js} +2 -2
- package/dist/{chunk-UXAC2FX4.js → chunk-BLTEAUCB.js} +3 -3
- package/dist/{chunk-DRD2A54W.js → chunk-BT7HGDOX.js} +15 -15
- package/dist/{chunk-F34AR6O3.js → chunk-DXLUVUD4.js} +5 -5
- package/dist/{chunk-HR3HPQ76.js → chunk-E7RF4KBO.js} +2 -2
- package/dist/chunk-EM2WNQS2.js +93 -0
- package/dist/{chunk-KYKNBD4Y.js → chunk-F5Z7EWMN.js} +953 -233
- package/dist/{chunk-VLPTKCKT.js → chunk-GLYBJ4RQ.js} +3 -3
- package/dist/{chunk-KDWLXVMN.js → chunk-HPTJF6DG.js} +16 -39
- package/dist/{chunk-6CDNRHWH.js → chunk-HZ2T2YED.js} +2 -2
- package/dist/{chunk-UTUNT5QL.js → chunk-HZFBVU5X.js} +7 -7
- package/dist/{chunk-KF6GFW6O.js → chunk-I2K2NCZQ.js} +7 -7
- package/dist/{chunk-5DDOTTG4.js → chunk-IGLVVNEG.js} +2 -2
- package/dist/{chunk-4SVIVOMC.js → chunk-IKRWLEDA.js} +5 -5
- package/dist/{chunk-R6MAYTMS.js → chunk-JMPL7NUB.js} +3 -3
- package/dist/{chunk-5ZMXGW7P.js → chunk-KAFMW7WM.js} +4 -85
- package/dist/{chunk-R6MICQYU.js → chunk-LIN2K3EL.js} +4 -4
- package/dist/{chunk-QEQISF75.js → chunk-LK2FN5JY.js} +1 -1
- package/dist/{chunk-YYB3MC65.js → chunk-N2OKBREN.js} +2 -2
- package/dist/{chunk-XXBQKW32.js → chunk-NNWJYUNO.js} +4 -4
- package/dist/{chunk-TZ7MFRG4.js → chunk-P5JMBPDJ.js} +22 -20
- package/dist/{chunk-WFKDPU7U.js → chunk-P6M7RKMI.js} +2 -2
- package/dist/{chunk-MDU3C27C.js → chunk-PZN2LQY6.js} +5 -5
- package/dist/{chunk-S32UQ5GL.js → chunk-Q7NNUHQV.js} +15 -15
- package/dist/{chunk-U7VQ4NI4.js → chunk-QCOV5DFY.js} +5 -5
- package/dist/{chunk-MC3JSVR6.js → chunk-QJMRYTCX.js} +7 -7
- package/dist/{chunk-DIMRLNIC.js → chunk-QNWRHOMF.js} +3 -3
- package/dist/{chunk-ILJ7DWGE.js → chunk-QXFBABFJ.js} +4 -4
- package/dist/chunk-R2CT5YDO.js +66 -0
- package/dist/{chunk-E3BQTQUP.js → chunk-RGZNQ5CT.js} +3 -3
- package/dist/{chunk-SBZX6ARC.js → chunk-SXQKNKRA.js} +7 -7
- package/dist/{chunk-WLMSOT73.js → chunk-TJFDL26W.js} +3 -3
- package/dist/{chunk-EQEJJ53P.js → chunk-VAHLPXPY.js} +2 -2
- package/dist/{chunk-7TKWWPD7.js → chunk-VANN3GDP.js} +3 -23
- package/dist/{chunk-GNQRWTMY.js → chunk-VHMX7SXF.js} +2 -2
- package/dist/{chunk-UL36QJX6.js → chunk-WKUYQBCG.js} +6 -6
- package/dist/{chunk-FKIOX6DS.js → chunk-WNGF5AJX.js} +9 -4
- package/dist/{chunk-ICO4TQ2F.js → chunk-WV6TDAPN.js} +36 -20
- package/dist/{chunk-K6RDB7IA.js → chunk-X3BI7HTV.js} +9 -9
- package/dist/{chunk-NY6IWDVU.js → chunk-XWMSPJYN.js} +2 -2
- package/dist/{chunk-7HBHHVCK.js → chunk-YPRSNUTC.js} +2 -2
- package/dist/{chunk-ONRTXOZY.js → chunk-ZS43Y2FT.js} +2 -2
- package/dist/cli/index.js +27 -27
- package/dist/{clio-5I2IBFYL.js → clio-QQCMTUZE.js} +6 -6
- package/dist/{code-nav-YXIAEZVS.js → code-nav-GUPM6766.js} +8 -8
- package/dist/{config-Y2JDJ3JJ.js → config-IIM7YOD3.js} +42 -41
- package/dist/{configure-SML6UBZ5.js → configure-4ZM5HWJX.js} +28 -10
- package/dist/{context-S2EEC3EJ.js → context-44BZLJ3J.js} +12 -12
- package/dist/{context-P5YSEO55.js → context-AIDVQKMW.js} +34 -33
- package/dist/{context-QQ53HSGJ.js → context-OL5P3HEP.js} +25 -24
- package/dist/{context-clear-TMEQCOTH.js → context-clear-OQV76MYP.js} +34 -33
- package/dist/{context-working-set-CNLSQN5K.js → context-working-set-ZUW3EGLS.js} +10 -9
- package/dist/{detail-5572VLBO.js → detail-UXPWRANG.js} +35 -34
- package/dist/{dispatch-runner-FRHD6P2O.js → dispatch-runner-P3ZW6G77.js} +38 -37
- package/dist/{doctor-N3LCM2LG.js → doctor-JJVGPZWT.js} +18 -17
- package/dist/{eval-BUU3ZOUZ.js → eval-V2RTN3UH.js} +26 -25
- package/dist/{evidence-DTGEN456.js → evidence-35PYWGSO.js} +34 -33
- package/dist/{evidence-SQ5DNFEN.js → evidence-CIGGKI6J.js} +36 -35
- package/dist/{evolve-IJNUFZDS.js → evolve-33SM3NJP.js} +34 -33
- package/dist/{fleet-ZNNVSYFO.js → fleet-LFO7SIPC.js} +62 -61
- package/dist/{fleet-commands-5YE7NPJL.js → fleet-commands-RLK72GU3.js} +9 -9
- package/dist/fleet-decisions-3SBSCTCW.js +1 -1
- package/dist/{fleet-graph-6HHPWF5T.js → fleet-graph-JZIBCGMW.js} +11 -11
- package/dist/{fleet-inspect-JEYMGCGC.js → fleet-inspect-2L5YGGZJ.js} +35 -34
- package/dist/{fleet-validate-4PM4GDDL.js → fleet-validate-LIAVKDUU.js} +12 -12
- package/dist/{fleet-verify-NJDTHTO3.js → fleet-verify-JIK3OQZR.js} +34 -33
- package/dist/{fleet-view-UP2BWQQY.js → fleet-view-IWHYGQKK.js} +35 -34
- package/dist/{init-S3GZQ5ZF.js → init-NJEDOTQW.js} +46 -45
- package/dist/{interop-YOTGXFJM.js → interop-RVCAYECG.js} +4 -4
- package/dist/{inventory-K2OZ36YJ.js → inventory-74UL7UHU.js} +35 -34
- package/dist/{library-GJI6W6OK.js → library-CTKZA7K3.js} +10 -10
- package/dist/{memory-OQOXQGYD.js → memory-I76I5VUH.js} +34 -33
- package/dist/{models-3IK2Y5WE.js → models-D4YDIQZQ.js} +19 -18
- package/dist/{monitor-FTJLTKCQ.js → monitor-NKVD55HX.js} +40 -39
- package/dist/{orchestrator-N47O7SFD.js → orchestrator-I6OATVPK.js} +658 -1092
- package/dist/{preload-65U34NG6.js → preload-EJAWJEIO.js} +34 -33
- package/dist/{reset-MUVQDLNL.js → reset-4XMQKDNZ.js} +5 -3
- package/dist/{resources-LM76COAO.js → resources-TVYVXK3Q.js} +10 -10
- package/dist/{run-3VFZQ33N.js → run-OWQNNSJU.js} +61 -60
- package/dist/{share-4JUB4BL7.js → share-NPZZMUXG.js} +11 -11
- package/dist/{skills-S36AAJHU.js → skills-OXFEAWMT.js} +12 -12
- package/dist/{skills-eval-G6T57L7M.js → skills-eval-J5TCKSJA.js} +38 -37
- package/dist/{skills-inventory-WLM46PJH.js → skills-inventory-7II4DM57.js} +10 -10
- package/dist/{slash-commands-GBARG3Y7.js → slash-commands-MDSDSWYF.js} +26 -25
- package/dist/{targets-N5REUETU.js → targets-KILZEOCE.js} +36 -20
- package/dist/{tasks-6BVY5YZF.js → tasks-R6P6OV22.js} +7 -7
- package/dist/{terminal-lease-57UEOJKS.js → terminal-lease-LZCG2KN3.js} +2 -2
- package/dist/{upgrade-4HD5HAIV.js → upgrade-D2OZH6IQ.js} +9 -9
- package/dist/{usage-4GWM2WWP.js → usage-PIASNUS4.js} +40 -39
- package/dist/{verifiers-GSKWKWVG.js → verifiers-LTHUY2PX.js} +9 -9
- package/dist/{verify-3AS3ULCY.js → verify-HYF7KBVE.js} +7 -7
- package/dist/{wiki-generate-7BV7XWIY.js → wiki-generate-RK7JQ5NP.js} +51 -50
- package/dist/worker/entry.js +41 -39
- package/docs/architecture/context-engine.md +1 -1
- package/docs/architecture/tui-design.md +45 -30
- package/docs/guide/commands-and-modes.md +26 -25
- package/docs/guide/configuration-and-targets.md +122 -27
- package/docs/guide/configuration-reference.md +9 -4
- package/docs/guide/fleet-dispatch.md +1 -6
- package/docs/guide/glossary.md +1 -1
- package/docs/guide/installation-and-lifecycle.md +44 -11
- package/docs/process/development-pipeline.md +1 -1
- package/docs/process/documentation-coverage.md +1 -1
- package/docs/process/release-cut-checklist.md +18 -6
- package/package.json +1 -1
- package/src/cli/ask.ts +10 -10
- package/src/cli/configure-editor.ts +51 -0
- package/src/cli/configure-interop.ts +1 -1
- package/src/cli/configure-oauth.ts +1 -1
- package/src/cli/configure-onboarding.ts +232 -96
- package/src/cli/configure-prompts.ts +76 -0
- package/src/cli/configure-quick.ts +274 -0
- package/src/cli/configure-target.ts +14 -2
- package/src/cli/configure.ts +413 -174
- package/src/cli/oauth-manual-input.ts +1 -1
- package/src/cli/reset.ts +2 -0
- package/src/cli/select.ts +35 -4
- package/src/cli/upgrade.ts +2 -2
- package/src/core/config.ts +6 -1
- package/src/core/defaults.ts +33 -11
- package/src/{interactive → core}/external-editor.ts +4 -4
- package/src/domains/config/classify.ts +1 -1
- package/src/domains/config/keybindings.ts +3 -31
- package/src/domains/providers/probe/fingerprint.ts +13 -6
- package/src/domains/providers/probe/reasoning.ts +2 -0
- package/src/domains/providers/runtimes/common/probe-helpers.ts +23 -7
- package/src/domains/providers/runtimes/protocol/anthropic-compat.ts +7 -2
- package/src/domains/providers/runtimes/protocol/openai-compat.ts +10 -4
- package/src/interactive/application-controller.ts +1 -31
- package/src/interactive/chat-panel.ts +163 -637
- package/src/interactive/chat-renderer.ts +13 -30
- package/src/interactive/dispatch-board.ts +1 -3
- package/src/interactive/editor-submit.ts +8 -31
- package/src/interactive/footer/dashboard.ts +8 -3
- package/src/interactive/footer/widgets.ts +50 -91
- package/src/interactive/interactive-application.ts +16 -42
- package/src/interactive/interactive-event-projection.ts +2 -44
- package/src/interactive/interactive-input-runtime.ts +3 -28
- package/src/interactive/interactive-presentation.ts +30 -9
- package/src/interactive/interactive-slash-runtime.ts +3 -40
- package/src/interactive/layout.ts +29 -4
- package/src/interactive/overlay-general-openers.ts +2 -0
- package/src/interactive/overlay-lifecycle.ts +1 -0
- package/src/interactive/overlay-session-lifecycle.ts +1 -1
- package/src/interactive/overlays/settings.ts +9 -8
- package/src/interactive/renderers/preview.ts +16 -0
- package/src/interactive/renderers/tool-execution.ts +67 -160
- package/src/interactive/renderers/worker-entry.ts +57 -41
- package/src/interactive/slash-autocomplete.ts +1 -6
- package/src/interactive/slash-commands.ts +7 -39
- package/src/interactive/status/controller.ts +0 -5
- package/src/interactive/status/state-machine.ts +44 -26
- package/src/interactive/status/types.ts +3 -0
- package/src/interactive/status/verbs.ts +13 -12
- package/src/interactive/transcript-detail.ts +50 -112
- package/src/interactive/view/artifacts.ts +4 -0
- package/src/interactive/view/view-overlay.ts +44 -34
- package/src/tools/presentation.ts +1 -1
- package/src/tools/registry.ts +1 -1
- package/src/tools/verify/numeric.ts +4 -4
|
@@ -19,6 +19,8 @@ export interface RetryOverlay {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export interface ToolOverlay {
|
|
22
|
+
toolCallId?: string;
|
|
23
|
+
startedAt?: number;
|
|
22
24
|
toolName: string;
|
|
23
25
|
toolPreview: string;
|
|
24
26
|
}
|
|
@@ -104,6 +106,7 @@ export interface AgentStatus {
|
|
|
104
106
|
* phase leaves `tool_running`.
|
|
105
107
|
*/
|
|
106
108
|
toolStartedAt?: number | undefined;
|
|
109
|
+
activeTools?: readonly ToolOverlay[];
|
|
107
110
|
retry?: RetryOverlay | undefined;
|
|
108
111
|
dispatch?: DispatchOverlay | undefined;
|
|
109
112
|
/**
|
|
@@ -44,30 +44,31 @@ function coreVerb(status: AgentStatus): { text: string; toneHint: VerbRender["to
|
|
|
44
44
|
case "idle":
|
|
45
45
|
return null;
|
|
46
46
|
case "preparing":
|
|
47
|
-
return { text:
|
|
47
|
+
return { text: "Preparing", toneHint: "normal" };
|
|
48
48
|
case "waiting_model":
|
|
49
49
|
return {
|
|
50
|
-
text: tier >= 2 ? "
|
|
50
|
+
text: tier >= 2 ? "Waiting for model" : status.localRuntime ? "Waiting for local model" : "Waiting for model",
|
|
51
51
|
toneHint: "normal",
|
|
52
52
|
};
|
|
53
53
|
case "thinking":
|
|
54
|
-
return { text:
|
|
54
|
+
return { text: "Thinking", toneHint: "normal" };
|
|
55
55
|
case "writing":
|
|
56
|
-
return { text: "
|
|
56
|
+
return { text: "Writing", toneHint: "normal" };
|
|
57
57
|
case "tool_running": {
|
|
58
58
|
const name = status.tool?.toolName ?? "tool";
|
|
59
|
-
if (name === ToolNames.
|
|
60
|
-
|
|
59
|
+
if (name === ToolNames.Dispatch) return { text: "Waiting for worker", toneHint: "normal" };
|
|
60
|
+
if (name === ToolNames.AskUser) return { text: "Needs input", toneHint: "normal" };
|
|
61
|
+
return { text: `Running ${name}`, toneHint: "normal" };
|
|
61
62
|
}
|
|
62
63
|
case "tool_blocked":
|
|
63
|
-
return { text: "
|
|
64
|
+
return { text: "Needs approval", toneHint: "warn" };
|
|
64
65
|
case "retrying": {
|
|
65
66
|
const retry = status.retry;
|
|
66
67
|
const wait = retry && retry.waitMs > 0 ? ` · ${formatStatusElapsed(retry.waitMs)}` : "";
|
|
67
68
|
return { text: `retrying ${retry?.attempt ?? 0}/${retry?.maxAttempts ?? 0}${wait}`, toneHint: "warn" };
|
|
68
69
|
}
|
|
69
70
|
case "compacting":
|
|
70
|
-
return { text: "
|
|
71
|
+
return { text: "Compacting context", toneHint: "normal" };
|
|
71
72
|
case "dispatching": {
|
|
72
73
|
const agent = status.dispatch?.agentName;
|
|
73
74
|
if (tier >= 2)
|
|
@@ -75,7 +76,7 @@ function coreVerb(status: AgentStatus): { text: string; toneHint: VerbRender["to
|
|
|
75
76
|
return { text: agent ? `dispatching agent: ${agent}` : "dispatching agent", toneHint: "normal" };
|
|
76
77
|
}
|
|
77
78
|
case "stuck":
|
|
78
|
-
return { text: "
|
|
79
|
+
return { text: "No output", toneHint: "error" };
|
|
79
80
|
case "ended": {
|
|
80
81
|
const stop = status.summary?.stopReason ?? "stop";
|
|
81
82
|
const elapsed = status.summary ? ` · ${formatStatusElapsed(status.summary.elapsedMs)}` : "";
|
|
@@ -97,7 +98,7 @@ export function resolveFooterVerb(status: AgentStatus, now: number, terminalCols
|
|
|
97
98
|
if (status.phase === "stuck") {
|
|
98
99
|
const elapsed = elapsedSince(status, now);
|
|
99
100
|
return {
|
|
100
|
-
text: terminalCols < 60 ? "
|
|
101
|
+
text: terminalCols < 60 ? "No output" : `No output · ${elapsed} · Esc to cancel`,
|
|
101
102
|
toneHint: "error",
|
|
102
103
|
};
|
|
103
104
|
}
|
|
@@ -117,12 +118,12 @@ function inlineParts(
|
|
|
117
118
|
terminalCols: number,
|
|
118
119
|
): { text: string; hint: string | null; toneHint: VerbRender["toneHint"] } | null {
|
|
119
120
|
if (status.phase === "stuck")
|
|
120
|
-
return { text: `
|
|
121
|
+
return { text: `No output for ${noProgressSince(status, now)}.`, hint: "Press Esc to cancel.", toneHint: "error" };
|
|
121
122
|
const core = coreVerb(status);
|
|
122
123
|
if (!core) return null;
|
|
123
124
|
const text = core.text.replace(/^[a-z]/, (c) => c.toUpperCase());
|
|
124
125
|
if (status.watchdogTier >= 3) {
|
|
125
|
-
const hint = terminalCols < 50 ? null : `(no
|
|
126
|
+
const hint = terminalCols < 50 ? null : `(no output for ${noProgressSince(status, now)}; press Esc to cancel)`;
|
|
126
127
|
return { text, hint, toneHint: core.toneHint };
|
|
127
128
|
}
|
|
128
129
|
if (terminalCols < 50 || status.phase === "tool_blocked") return { text, hint: null, toneHint: core.toneHint };
|
|
@@ -1,120 +1,58 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
* becomes a decision about how much of each foldable transcript block is open
|
|
4
|
-
* before the operator touches it.
|
|
5
|
-
*
|
|
6
|
-
* The chat panel used to consult the verbosity string in four places, each
|
|
7
|
-
* spelling the rule a little differently, and nothing else (running rows, live
|
|
8
|
-
* tool output, worker cards in replay) consulted it at all. The panel now reads
|
|
9
|
-
* this policy once per frame and threads it down; the verbosity string never
|
|
10
|
-
* reaches a renderer.
|
|
11
|
-
*
|
|
12
|
-
* Operator toggles (`Alt+O`, `Alt+R`, expand-all, collapse-all) are overrides
|
|
13
|
-
* layered on top of this policy, not fights with it: the effective state of a
|
|
14
|
-
* block is `override ?? policy`, and `resolveFold` is that one rule.
|
|
15
|
-
*
|
|
16
|
-
* Pure module: no I/O, no UI imports.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
import type { OutputVerbosity } from "../core/defaults.js";
|
|
20
|
-
import type { ToolFoldDefault, ToolPresentationPolicy } from "../tools/presentation.js";
|
|
21
|
-
|
|
22
|
-
/** A block's fold state. The same vocabulary serves tools, workers, thinking, and local bash. */
|
|
23
|
-
export type Fold = ToolFoldDefault;
|
|
24
|
-
|
|
25
|
-
/** An operator's explicit choice for one block, or none. */
|
|
26
|
-
export type FoldOverride = Fold | undefined;
|
|
1
|
+
/** Presentation budgets for the same captured session. Detailed is still bounded. */
|
|
2
|
+
import type { OutputStyle } from "../core/defaults.js";
|
|
27
3
|
|
|
28
4
|
export interface TranscriptDetailPolicy {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
5
|
+
style: OutputStyle;
|
|
6
|
+
reasoningRows: number;
|
|
7
|
+
resultRows: number;
|
|
8
|
+
bashRows: number;
|
|
9
|
+
operatorBashRows: number;
|
|
10
|
+
diffRows: number;
|
|
11
|
+
workerRows: number;
|
|
12
|
+
workerActivity: boolean;
|
|
13
|
+
errorRows: number;
|
|
38
14
|
receipt: "none" | "compact" | "full";
|
|
39
|
-
/** Failed tool under its folded row: the bounded excerpt, or the full body. */
|
|
40
|
-
errors: "excerpt" | "body";
|
|
41
15
|
}
|
|
42
16
|
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
17
|
+
const POLICIES: Record<OutputStyle, TranscriptDetailPolicy> = {
|
|
18
|
+
compact: {
|
|
19
|
+
style: "compact",
|
|
20
|
+
reasoningRows: 0,
|
|
21
|
+
resultRows: 0,
|
|
22
|
+
bashRows: 0,
|
|
23
|
+
operatorBashRows: 3,
|
|
24
|
+
diffRows: 0,
|
|
25
|
+
workerRows: 0,
|
|
26
|
+
workerActivity: false,
|
|
27
|
+
errorRows: 4,
|
|
28
|
+
receipt: "none",
|
|
29
|
+
},
|
|
30
|
+
standard: {
|
|
31
|
+
style: "standard",
|
|
32
|
+
reasoningRows: 3,
|
|
33
|
+
resultRows: 0,
|
|
34
|
+
bashRows: 0,
|
|
35
|
+
operatorBashRows: 6,
|
|
36
|
+
diffRows: 8,
|
|
37
|
+
workerRows: 3,
|
|
38
|
+
workerActivity: false,
|
|
39
|
+
errorRows: 4,
|
|
40
|
+
receipt: "compact",
|
|
41
|
+
},
|
|
42
|
+
detailed: {
|
|
43
|
+
style: "detailed",
|
|
44
|
+
reasoningRows: 12,
|
|
45
|
+
resultRows: 8,
|
|
46
|
+
bashRows: 12,
|
|
47
|
+
operatorBashRows: 12,
|
|
48
|
+
diffRows: 20,
|
|
49
|
+
workerRows: 8,
|
|
50
|
+
workerActivity: true,
|
|
51
|
+
errorRows: 12,
|
|
52
|
+
receipt: "full",
|
|
53
|
+
},
|
|
59
54
|
};
|
|
60
55
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
runningTool: "body",
|
|
64
|
-
thinking: "rail",
|
|
65
|
-
worker: "expanded",
|
|
66
|
-
receipt: "full",
|
|
67
|
-
errors: "body",
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Map a verbosity to the full policy table. An absent verbosity (a panel built
|
|
72
|
-
* without settings) is the balanced default, so the literal never has to be
|
|
73
|
-
* spelled by the caller.
|
|
74
|
-
*/
|
|
75
|
-
export function transcriptDetail(verbosity: OutputVerbosity | undefined): TranscriptDetailPolicy {
|
|
76
|
-
switch (verbosity) {
|
|
77
|
-
case "minimal":
|
|
78
|
-
return MINIMAL;
|
|
79
|
-
case "verbose":
|
|
80
|
-
return VERBOSE;
|
|
81
|
-
default:
|
|
82
|
-
return DEFAULT;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/** Effective state of one block: the operator's override when set, else the policy's answer. */
|
|
87
|
-
export function resolveFold(override: FoldOverride, policyFold: Fold): Fold {
|
|
88
|
-
return override ?? policyFold;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/** The fold the policy gives a finished tool call, through the tool's own presentation when asked to. */
|
|
92
|
-
export function policyToolFold(detail: TranscriptDetailPolicy, presentation: ToolPresentationPolicy): Fold {
|
|
93
|
-
if (detail.toolBody === "per-tool") return presentation.foldDefault;
|
|
94
|
-
return detail.toolBody;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/** The fold the policy gives an in-flight tool call. */
|
|
98
|
-
export function policyRunningToolFold(detail: TranscriptDetailPolicy): Fold {
|
|
99
|
-
return detail.runningTool === "body" ? "expanded" : "folded";
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/** The fold the policy gives a reasoning stretch. */
|
|
103
|
-
export function policyThinkingFold(detail: TranscriptDetailPolicy): Fold {
|
|
104
|
-
return detail.thinking === "rail" ? "expanded" : "folded";
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* The fold the policy gives a worker block. `askedByModel` is the origin rule
|
|
109
|
-
* the caller already knows: a run the model asked for folds, the operator's own
|
|
110
|
-
* run opens.
|
|
111
|
-
*/
|
|
112
|
-
export function policyWorkerFold(detail: TranscriptDetailPolicy, askedByModel: boolean): Fold {
|
|
113
|
-
if (detail.worker === "origin") return askedByModel ? "folded" : "expanded";
|
|
114
|
-
return detail.worker;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/** The override that flips a block away from its current effective state. */
|
|
118
|
-
export function toggledFold(effective: Fold): Fold {
|
|
119
|
-
return effective === "expanded" ? "folded" : "expanded";
|
|
56
|
+
export function transcriptDetail(style: OutputStyle = "standard"): TranscriptDetailPolicy {
|
|
57
|
+
return POLICIES[style];
|
|
120
58
|
}
|
|
@@ -44,6 +44,7 @@ import { clockLocal } from "../format-time.js";
|
|
|
44
44
|
import { abbreviateModelId } from "../theme/index.js";
|
|
45
45
|
|
|
46
46
|
export type ViewArtifactCategory =
|
|
47
|
+
| "transcript"
|
|
47
48
|
| "accountability"
|
|
48
49
|
| "evidence"
|
|
49
50
|
| "receipt"
|
|
@@ -86,6 +87,7 @@ export interface ArtifactProvider {
|
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
export interface ArtifactProviderDeps {
|
|
90
|
+
readTranscript?: (() => ViewArtifact[]) | undefined;
|
|
89
91
|
stateDir: string;
|
|
90
92
|
dataDir?: string | undefined;
|
|
91
93
|
dispatch?: Pick<DispatchContract, "listRuns" | "getRun"> | undefined;
|
|
@@ -94,6 +96,7 @@ export interface ArtifactProviderDeps {
|
|
|
94
96
|
}
|
|
95
97
|
|
|
96
98
|
export const VIEW_ARTIFACT_CATEGORIES: readonly ViewArtifactCategory[] = [
|
|
99
|
+
"transcript",
|
|
97
100
|
"accountability",
|
|
98
101
|
"evidence",
|
|
99
102
|
"receipt",
|
|
@@ -1560,6 +1563,7 @@ export class SafetyAuditArtifactProvider implements ArtifactProvider {
|
|
|
1560
1563
|
|
|
1561
1564
|
export function createDefaultArtifactProviders(deps: ArtifactProviderDeps): ArtifactProvider[] {
|
|
1562
1565
|
return [
|
|
1566
|
+
{ category: "transcript", list: async () => deps.readTranscript?.() ?? [] },
|
|
1563
1567
|
new AccountabilityArtifactProvider(deps),
|
|
1564
1568
|
new EvidenceArtifactProvider(deps),
|
|
1565
1569
|
new ReceiptArtifactProvider(deps),
|
|
@@ -102,6 +102,8 @@ function artifactKey(artifact: ViewArtifact): string {
|
|
|
102
102
|
|
|
103
103
|
function categoryLabel(category: ViewArtifactCategory): string {
|
|
104
104
|
switch (category) {
|
|
105
|
+
case "transcript":
|
|
106
|
+
return "Transcript details";
|
|
105
107
|
case "accountability":
|
|
106
108
|
return "Accountability";
|
|
107
109
|
case "evidence":
|
|
@@ -129,6 +131,7 @@ function categoryLabel(category: ViewArtifactCategory): string {
|
|
|
129
131
|
|
|
130
132
|
const VIEW_ARTIFACT_CATEGORY_SET = new Set<ViewArtifactCategory>(VIEW_ARTIFACT_CATEGORIES);
|
|
131
133
|
const BARE_CATEGORY_FILTERS = new Set<ViewArtifactCategory>([
|
|
134
|
+
"transcript",
|
|
132
135
|
"task-ledger",
|
|
133
136
|
"workspace",
|
|
134
137
|
"protected-artifact",
|
|
@@ -275,11 +278,8 @@ function groupedViewRows(artifacts: ReadonlyArray<ViewArtifact>): RenderedViewRo
|
|
|
275
278
|
const rows: RenderedViewRow[] = [];
|
|
276
279
|
for (const category of VIEW_ARTIFACT_CATEGORIES) {
|
|
277
280
|
const items = artifacts.filter((artifact) => artifact.category === category);
|
|
281
|
+
if (items.length === 0) continue;
|
|
278
282
|
rows.push({ type: "group", category });
|
|
279
|
-
if (items.length === 0) {
|
|
280
|
-
rows.push({ type: "empty", category });
|
|
281
|
-
continue;
|
|
282
|
-
}
|
|
283
283
|
for (const item of items) {
|
|
284
284
|
rows.push({ type: "item", category, item, itemIndex: artifacts.indexOf(item) });
|
|
285
285
|
}
|
|
@@ -393,11 +393,11 @@ function viewFooterHint(focus: ViewPaneFocus, canVerify: boolean, innerWidth?: n
|
|
|
393
393
|
const tiers =
|
|
394
394
|
focus === "list"
|
|
395
395
|
? [
|
|
396
|
-
"[↑↓] select · [type] filter · [
|
|
397
|
-
"[↑↓] select · [
|
|
398
|
-
"[↑↓] select · [
|
|
396
|
+
"[↑↓] select · [type] filter · [Enter] detail · [Esc] close",
|
|
397
|
+
"[↑↓] select · [Enter] detail · [Esc] close",
|
|
398
|
+
"[↑↓] select · [Enter] detail",
|
|
399
399
|
]
|
|
400
|
-
: ["[↑↓] scroll · [
|
|
400
|
+
: ["[↑↓] scroll · [Esc] back", "[↑↓] scroll · [Tab] list"];
|
|
401
401
|
return tiers.find((tier) => visibleWidth(tier) <= budget) ?? (tiers.at(-1) as string);
|
|
402
402
|
}
|
|
403
403
|
if (focus === "list") {
|
|
@@ -405,20 +405,21 @@ function viewFooterHint(focus: ViewPaneFocus, canVerify: boolean, innerWidth?: n
|
|
|
405
405
|
{ key: "↑↓", verb: "select" },
|
|
406
406
|
{ key: "←→", verb: "category" },
|
|
407
407
|
{ key: "type", verb: "filter" },
|
|
408
|
-
{ key: "
|
|
409
|
-
|
|
410
|
-
{ key: "o", verb: "path" },
|
|
408
|
+
{ key: "Enter", verb: "content" },
|
|
409
|
+
{ key: "Ctrl+U", verb: "clear filter" },
|
|
411
410
|
]);
|
|
412
411
|
}
|
|
413
|
-
return buildHint(
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
412
|
+
return buildHint(
|
|
413
|
+
[
|
|
414
|
+
{ key: "↑↓", verb: "scroll" },
|
|
415
|
+
{ key: "←→", verb: "category" },
|
|
416
|
+
{ key: "PgUp/PgDn", verb: "page" },
|
|
417
|
+
{ key: "g/G", verb: "top/bottom" },
|
|
418
|
+
...(canVerify ? [{ key: "v", verb: "verify" }] : []),
|
|
419
|
+
{ key: "o", verb: "path" },
|
|
420
|
+
],
|
|
421
|
+
"back",
|
|
422
|
+
);
|
|
422
423
|
}
|
|
423
424
|
|
|
424
425
|
export class ViewOverlayView implements Component {
|
|
@@ -528,10 +529,11 @@ export class ViewOverlayView implements Component {
|
|
|
528
529
|
const content = this.content;
|
|
529
530
|
if (!content) return [];
|
|
530
531
|
if (content.status === "error") return content.lines.flatMap((line) => wrapTextWithAnsi(line, Math.max(1, width)));
|
|
531
|
-
if (content.format !== "markdown") return content.lines;
|
|
532
532
|
if (content.renderedLines && content.renderWidth === width) return content.renderedLines;
|
|
533
|
-
const
|
|
534
|
-
|
|
533
|
+
const rendered =
|
|
534
|
+
content.format === "markdown"
|
|
535
|
+
? new Markdown(content.lines.join("\n"), 0, 0, markdownTheme(clioTheme())).render(width)
|
|
536
|
+
: content.lines.flatMap((line) => wrapTextWithAnsi(line, Math.max(1, width)));
|
|
535
537
|
content.renderWidth = width;
|
|
536
538
|
content.renderedLines = rendered;
|
|
537
539
|
return rendered;
|
|
@@ -556,6 +558,7 @@ export class ViewOverlayView implements Component {
|
|
|
556
558
|
}
|
|
557
559
|
|
|
558
560
|
const filtered = this.filteredArtifacts();
|
|
561
|
+
if (filtered.length === 0) return this.fixedLines([...lines, theme.fg("dim", "No matching details.")], width, height);
|
|
559
562
|
const rows = groupedViewRows(filtered);
|
|
560
563
|
const selectedRow = rows.findIndex((row) => row.type === "item" && row.itemIndex === this.selectedIndex);
|
|
561
564
|
const rowHeight = Math.max(1, height - 1);
|
|
@@ -634,7 +637,11 @@ export class ViewOverlayView implements Component {
|
|
|
634
637
|
}
|
|
635
638
|
|
|
636
639
|
handleInput(data: string): void {
|
|
637
|
-
if (
|
|
640
|
+
if (
|
|
641
|
+
matchesKey(data, "tab") ||
|
|
642
|
+
matchesKey(data, "shift+tab") ||
|
|
643
|
+
(this.focus === "list" && matchesKey(data, "enter"))
|
|
644
|
+
) {
|
|
638
645
|
this.focus = this.focus === "list" ? "content" : "list";
|
|
639
646
|
this.options.requestRender?.();
|
|
640
647
|
return;
|
|
@@ -647,21 +654,19 @@ export class ViewOverlayView implements Component {
|
|
|
647
654
|
this.selectCategory(1);
|
|
648
655
|
return;
|
|
649
656
|
}
|
|
650
|
-
if (data === "v") {
|
|
657
|
+
if (this.focus === "content" && data === "v") {
|
|
651
658
|
this.verifySelected();
|
|
652
659
|
return;
|
|
653
660
|
}
|
|
654
|
-
if (data === "o") {
|
|
661
|
+
if (this.focus === "content" && data === "o") {
|
|
655
662
|
this.openPathNotice();
|
|
656
663
|
return;
|
|
657
664
|
}
|
|
658
665
|
if (matchesKey(data, "esc")) {
|
|
659
|
-
if (this.focus === "
|
|
660
|
-
this.
|
|
661
|
-
this.
|
|
662
|
-
|
|
663
|
-
}
|
|
664
|
-
this.options.onClose();
|
|
666
|
+
if (this.focus === "content") {
|
|
667
|
+
this.focus = "list";
|
|
668
|
+
this.options.requestRender?.();
|
|
669
|
+
} else this.options.onClose();
|
|
665
670
|
return;
|
|
666
671
|
}
|
|
667
672
|
if (this.focus === "content") {
|
|
@@ -675,14 +680,19 @@ export class ViewOverlayView implements Component {
|
|
|
675
680
|
|
|
676
681
|
private handleListInput(data: string): boolean {
|
|
677
682
|
const filtered = this.filteredArtifacts();
|
|
678
|
-
if (matchesKey(data, "up")
|
|
683
|
+
if (matchesKey(data, "up")) {
|
|
679
684
|
if (filtered.length > 0) this.selectIndex(this.selectedIndex - 1);
|
|
680
685
|
return true;
|
|
681
686
|
}
|
|
682
|
-
if (matchesKey(data, "down")
|
|
687
|
+
if (matchesKey(data, "down")) {
|
|
683
688
|
if (filtered.length > 0) this.selectIndex(this.selectedIndex + 1);
|
|
684
689
|
return true;
|
|
685
690
|
}
|
|
691
|
+
if (matchesKey(data, "ctrl+u")) {
|
|
692
|
+
this.filterText = "";
|
|
693
|
+
this.selectInitialFilterMatch();
|
|
694
|
+
return true;
|
|
695
|
+
}
|
|
686
696
|
if (matchesKey(data, "backspace")) {
|
|
687
697
|
if (this.filterText.length > 0) {
|
|
688
698
|
this.filterText = this.filterText.slice(0, -1);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Typed tool presentation policy. Answers, per tool, what the transcript's
|
|
3
|
-
*
|
|
3
|
+
* Standard view needs to know: does the block open folded
|
|
4
4
|
* or expanded, does the folded row keep a mutation diff visible, and does a
|
|
5
5
|
* failed folded row carry an output excerpt.
|
|
6
6
|
*
|
package/src/tools/registry.ts
CHANGED
|
@@ -107,7 +107,7 @@ export interface ToolMetadata {
|
|
|
107
107
|
*/
|
|
108
108
|
promptHint?: ToolPromptHintMetadata;
|
|
109
109
|
/**
|
|
110
|
-
* How transcript surfaces present this tool's block under
|
|
110
|
+
* How transcript surfaces present this tool's block under Standard output style.
|
|
111
111
|
* Optional: tools that declare nothing fold like every other tool.
|
|
112
112
|
*/
|
|
113
113
|
presentation?: ToolPresentationPolicy;
|
|
@@ -133,15 +133,15 @@ export function parseNumericPayload(text: string, label: string): NumericPayload
|
|
|
133
133
|
const keys = Object.keys(record);
|
|
134
134
|
if (keys.length > NUMERIC_PAYLOAD_CAPS.keys)
|
|
135
135
|
return new Error(`${label} exceeds the ${NUMERIC_PAYLOAD_CAPS.keys}-key cap`);
|
|
136
|
-
const
|
|
136
|
+
const entries: Array<[string, number | number[]]> = [];
|
|
137
137
|
let elements = 0;
|
|
138
138
|
for (const key of keys) {
|
|
139
139
|
const value = record[key];
|
|
140
140
|
if (typeof value === "number") {
|
|
141
|
-
|
|
141
|
+
entries.push([key, value]);
|
|
142
142
|
elements += 1;
|
|
143
143
|
} else if (Array.isArray(value) && value.every((entry) => typeof entry === "number")) {
|
|
144
|
-
|
|
144
|
+
entries.push([key, [...(value as number[])]]);
|
|
145
145
|
elements += value.length;
|
|
146
146
|
} else {
|
|
147
147
|
return new Error(`${label}.${key} must be a number or an array of numbers`);
|
|
@@ -150,7 +150,7 @@ export function parseNumericPayload(text: string, label: string): NumericPayload
|
|
|
150
150
|
return new Error(`${label} exceeds the ${NUMERIC_PAYLOAD_CAPS.elements}-element cap`);
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
|
-
return
|
|
153
|
+
return Object.fromEntries(entries);
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
function deviation(actual: number, expected: number, index?: number): NumericDeviation {
|