@gaunt-sloth/core 2.0.0-alpha.4 → 2.0.0-alpha.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -20
- package/dist/config/colour.d.ts +38 -0
- package/dist/config/colour.js +36 -0
- package/dist/config/colour.js.map +1 -0
- package/dist/config/configDiscovery.d.ts +79 -0
- package/dist/config/configDiscovery.js +80 -0
- package/dist/config/configDiscovery.js.map +1 -0
- package/dist/config/defaults.d.ts +21 -21
- package/dist/config/defaults.js +11 -9
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/filesystem-tools.d.ts +41 -0
- package/dist/config/filesystem-tools.js +56 -0
- package/dist/config/filesystem-tools.js.map +1 -0
- package/dist/config/jsonc.d.ts +12 -0
- package/dist/config/jsonc.js +41 -0
- package/dist/config/jsonc.js.map +1 -0
- package/dist/config/loader.d.ts +165 -6
- package/dist/config/loader.js +963 -109
- package/dist/config/loader.js.map +1 -1
- package/dist/config/mouse.d.ts +50 -0
- package/dist/config/mouse.js +44 -0
- package/dist/config/mouse.js.map +1 -0
- package/dist/config/profiles.d.ts +68 -0
- package/dist/config/profiles.js +93 -0
- package/dist/config/profiles.js.map +1 -0
- package/dist/config/providerKeys.d.ts +69 -0
- package/dist/config/providerKeys.js +69 -0
- package/dist/config/providerKeys.js.map +1 -0
- package/dist/config/schema.d.ts +2695 -130
- package/dist/config/schema.js +1385 -68
- package/dist/config/schema.js.map +1 -1
- package/dist/config/shell-policy.d.ts +899 -111
- package/dist/config/shell-policy.js +800 -70
- package/dist/config/shell-policy.js.map +1 -1
- package/dist/config/tool-descriptions.d.ts +211 -0
- package/dist/config/tool-descriptions.js +272 -0
- package/dist/config/tool-descriptions.js.map +1 -0
- package/dist/config/types.d.ts +372 -34
- package/dist/config/types.js +1 -0
- package/dist/config/types.js.map +1 -1
- package/dist/config.d.ts +35 -1
- package/dist/config.js +16 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.d.ts +45 -0
- package/dist/constants.js +45 -0
- package/dist/constants.js.map +1 -1
- package/dist/core/GthAbstractAgent.d.ts +190 -11
- package/dist/core/GthAbstractAgent.js +551 -35
- package/dist/core/GthAbstractAgent.js.map +1 -1
- package/dist/core/GthAgentRunner.d.ts +565 -57
- package/dist/core/GthAgentRunner.js +1546 -140
- package/dist/core/GthAgentRunner.js.map +1 -1
- package/dist/core/GthLangChainAgent.d.ts +117 -2
- package/dist/core/GthLangChainAgent.js +644 -18
- package/dist/core/GthLangChainAgent.js.map +1 -1
- package/dist/core/approvals/annotations.d.ts +122 -0
- package/dist/core/approvals/annotations.js +137 -0
- package/dist/core/approvals/annotations.js.map +1 -0
- package/dist/core/approvals/grants.d.ts +216 -0
- package/dist/core/approvals/grants.js +469 -0
- package/dist/core/approvals/grants.js.map +1 -0
- package/dist/core/approvals/matcher.d.ts +202 -0
- package/dist/core/approvals/matcher.js +267 -0
- package/dist/core/approvals/matcher.js.map +1 -0
- package/dist/core/approvals/mcpSubjects.d.ts +40 -0
- package/dist/core/approvals/mcpSubjects.js +99 -0
- package/dist/core/approvals/mcpSubjects.js.map +1 -0
- package/dist/core/approvals/promptHeader.d.ts +28 -0
- package/dist/core/approvals/promptHeader.js +62 -0
- package/dist/core/approvals/promptHeader.js.map +1 -0
- package/dist/core/approvals/toolAnnotationSources.d.ts +105 -0
- package/dist/core/approvals/toolAnnotationSources.js +277 -0
- package/dist/core/approvals/toolAnnotationSources.js.map +1 -0
- package/dist/core/approvals/toolHost.d.ts +46 -0
- package/dist/core/approvals/toolHost.js +108 -0
- package/dist/core/approvals/toolHost.js.map +1 -0
- package/dist/core/debugCapture.d.ts +74 -0
- package/dist/core/debugCapture.js +100 -0
- package/dist/core/debugCapture.js.map +1 -0
- package/dist/core/gthLeanAgentFactory.d.ts +9 -0
- package/dist/core/gthLeanAgentFactory.js +10 -0
- package/dist/core/gthLeanAgentFactory.js.map +1 -0
- package/dist/core/launchBanner.d.ts +127 -0
- package/dist/core/launchBanner.js +414 -0
- package/dist/core/launchBanner.js.map +1 -0
- package/dist/core/modelLabel.d.ts +19 -0
- package/dist/core/modelLabel.js +26 -0
- package/dist/core/modelLabel.js.map +1 -0
- package/dist/core/plainToolIndication.d.ts +15 -0
- package/dist/core/plainToolIndication.js +174 -0
- package/dist/core/plainToolIndication.js.map +1 -0
- package/dist/core/reasoningBlocks.d.ts +65 -0
- package/dist/core/reasoningBlocks.js +103 -0
- package/dist/core/reasoningBlocks.js.map +1 -0
- package/dist/core/refusal.d.ts +53 -0
- package/dist/core/refusal.js +133 -0
- package/dist/core/refusal.js.map +1 -0
- package/dist/core/runHeader.d.ts +38 -0
- package/dist/core/runHeader.js +42 -0
- package/dist/core/runHeader.js.map +1 -0
- package/dist/core/runStats.d.ts +52 -0
- package/dist/core/runStats.js +118 -0
- package/dist/core/runStats.js.map +1 -0
- package/dist/core/shell/ShellCommandFailedError.d.ts +53 -0
- package/dist/core/shell/ShellCommandFailedError.js +67 -0
- package/dist/core/shell/ShellCommandFailedError.js.map +1 -0
- package/dist/core/shell/abstention.d.ts +88 -0
- package/dist/core/shell/abstention.js +184 -0
- package/dist/core/shell/abstention.js.map +1 -0
- package/dist/core/shell/approvalCapture.d.ts +271 -0
- package/dist/core/shell/approvalCapture.js +108 -0
- package/dist/core/shell/approvalCapture.js.map +1 -0
- package/dist/core/shell/approvalStop.d.ts +123 -0
- package/dist/core/shell/approvalStop.js +269 -0
- package/dist/core/shell/approvalStop.js.map +1 -0
- package/dist/core/shell/arity.d.ts +6 -0
- package/dist/core/shell/arity.js +20 -6
- package/dist/core/shell/arity.js.map +1 -1
- package/dist/core/shell/denylist.d.ts +11 -0
- package/dist/core/shell/denylist.js +37 -0
- package/dist/core/shell/denylist.js.map +1 -0
- package/dist/core/shell/escalationSeverity.d.ts +141 -0
- package/dist/core/shell/escalationSeverity.js +89 -0
- package/dist/core/shell/escalationSeverity.js.map +1 -0
- package/dist/core/shell/framing.d.ts +190 -0
- package/dist/core/shell/framing.js +633 -0
- package/dist/core/shell/framing.js.map +1 -0
- package/dist/core/shell/hardline.d.ts +103 -0
- package/dist/core/shell/hardline.js +780 -0
- package/dist/core/shell/hardline.js.map +1 -0
- package/dist/core/shell/negotiation.d.ts +328 -0
- package/dist/core/shell/negotiation.js +488 -0
- package/dist/core/shell/negotiation.js.map +1 -0
- package/dist/core/shell/normalize.d.ts +44 -4
- package/dist/core/shell/normalize.js +61 -7
- package/dist/core/shell/normalize.js.map +1 -1
- package/dist/core/shell/openWorld.d.ts +263 -0
- package/dist/core/shell/openWorld.js +1188 -0
- package/dist/core/shell/openWorld.js.map +1 -0
- package/dist/core/shell/rater.d.ts +873 -0
- package/dist/core/shell/rater.js +1454 -0
- package/dist/core/shell/rater.js.map +1 -0
- package/dist/core/shell/raterModel.d.ts +41 -0
- package/dist/core/shell/raterModel.js +51 -0
- package/dist/core/shell/raterModel.js.map +1 -0
- package/dist/core/shell/raterVocabulary.d.ts +121 -0
- package/dist/core/shell/raterVocabulary.js +116 -0
- package/dist/core/shell/raterVocabulary.js.map +1 -0
- package/dist/core/shell/rejection.d.ts +69 -0
- package/dist/core/shell/rejection.js +38 -0
- package/dist/core/shell/rejection.js.map +1 -0
- package/dist/core/toolCallRepair/grammar.d.ts +41 -0
- package/dist/core/toolCallRepair/grammar.js +116 -0
- package/dist/core/toolCallRepair/grammar.js.map +1 -0
- package/dist/core/toolCallRepair/index.d.ts +2 -0
- package/dist/core/toolCallRepair/index.js +7 -0
- package/dist/core/toolCallRepair/index.js.map +1 -0
- package/dist/core/toolCallRepair/payload.d.ts +36 -0
- package/dist/core/toolCallRepair/payload.js +341 -0
- package/dist/core/toolCallRepair/payload.js.map +1 -0
- package/dist/core/toolCallRepair/promote.d.ts +45 -0
- package/dist/core/toolCallRepair/promote.js +90 -0
- package/dist/core/toolCallRepair/promote.js.map +1 -0
- package/dist/core/toolDisplay.d.ts +123 -0
- package/dist/core/toolDisplay.js +451 -0
- package/dist/core/toolDisplay.js.map +1 -0
- package/dist/core/toolOutputChannel.d.ts +95 -0
- package/dist/core/toolOutputChannel.js +165 -0
- package/dist/core/toolOutputChannel.js.map +1 -0
- package/dist/core/types.d.ts +378 -16
- package/dist/core/types.js.map +1 -1
- package/dist/history/historyFormat.d.ts +28 -0
- package/dist/history/historyFormat.js +127 -0
- package/dist/history/historyFormat.js.map +1 -0
- package/dist/history/historyStore.d.ts +198 -0
- package/dist/history/historyStore.js +482 -0
- package/dist/history/historyStore.js.map +1 -0
- package/dist/history/recordSession.d.ts +37 -0
- package/dist/history/recordSession.js +56 -0
- package/dist/history/recordSession.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/providers/anthropic.d.ts +1 -1
- package/dist/providers/anthropic.js +17 -10
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/configurationPassthrough.d.ts +107 -0
- package/dist/providers/configurationPassthrough.js +148 -0
- package/dist/providers/configurationPassthrough.js.map +1 -0
- package/dist/providers/deepseek.d.ts +1 -1
- package/dist/providers/deepseek.js +5 -10
- package/dist/providers/deepseek.js.map +1 -1
- package/dist/providers/geminiSchemaSanitizer.d.ts +55 -0
- package/dist/providers/geminiSchemaSanitizer.js +347 -0
- package/dist/providers/geminiSchemaSanitizer.js.map +1 -0
- package/dist/providers/geminiThinking.d.ts +60 -0
- package/dist/providers/geminiThinking.js +92 -0
- package/dist/providers/geminiThinking.js.map +1 -0
- package/dist/providers/google-genai.d.ts +1 -1
- package/dist/providers/google-genai.js +23 -11
- package/dist/providers/google-genai.js.map +1 -1
- package/dist/providers/groq.d.ts +1 -1
- package/dist/providers/groq.js +17 -10
- package/dist/providers/groq.js.map +1 -1
- package/dist/providers/huggingface.d.ts +25 -0
- package/dist/providers/huggingface.js +69 -0
- package/dist/providers/huggingface.js.map +1 -0
- package/dist/providers/modelCatalog.d.ts +109 -0
- package/dist/providers/modelCatalog.js +245 -0
- package/dist/providers/modelCatalog.js.map +1 -0
- package/dist/providers/modelDiscovery.d.ts +153 -6
- package/dist/providers/modelDiscovery.js +295 -41
- package/dist/providers/modelDiscovery.js.map +1 -1
- package/dist/providers/ollama.d.ts +19 -5
- package/dist/providers/ollama.js +72 -52
- package/dist/providers/ollama.js.map +1 -1
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openai.js +39 -10
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/openrouter.d.ts +27 -5
- package/dist/providers/openrouter.js +88 -36
- package/dist/providers/openrouter.js.map +1 -1
- package/dist/providers/vertexai.d.ts +1 -1
- package/dist/providers/vertexai.js +24 -11
- package/dist/providers/vertexai.js.map +1 -1
- package/dist/providers/xai.d.ts +1 -1
- package/dist/providers/xai.js +25 -10
- package/dist/providers/xai.js.map +1 -1
- package/dist/runtime/askStructured.d.ts +105 -0
- package/dist/runtime/askStructured.js +120 -0
- package/dist/runtime/askStructured.js.map +1 -0
- package/dist/runtime/conversation.d.ts +64 -0
- package/dist/runtime/conversation.js +171 -0
- package/dist/runtime/conversation.js.map +1 -0
- package/dist/runtime/singleShot.d.ts +39 -5
- package/dist/runtime/singleShot.js +115 -36
- package/dist/runtime/singleShot.js.map +1 -1
- package/dist/runtime/structuredOutput.d.ts +104 -0
- package/dist/runtime/structuredOutput.js +393 -0
- package/dist/runtime/structuredOutput.js.map +1 -0
- package/dist/utils/ProgressIndicator.d.ts +21 -0
- package/dist/utils/ProgressIndicator.js +30 -3
- package/dist/utils/ProgressIndicator.js.map +1 -1
- package/dist/utils/aiignoreUtils.js.map +1 -1
- package/dist/utils/binaryOutputUtils.js.map +1 -1
- package/dist/utils/consoleUtils.d.ts +95 -0
- package/dist/utils/consoleUtils.js +112 -2
- package/dist/utils/consoleUtils.js.map +1 -1
- package/dist/utils/crashHandler.d.ts +87 -0
- package/dist/utils/crashHandler.js +128 -0
- package/dist/utils/crashHandler.js.map +1 -0
- package/dist/utils/debugDump.d.ts +134 -0
- package/dist/utils/debugDump.js +381 -0
- package/dist/utils/debugDump.js.map +1 -0
- package/dist/utils/debugUtils.d.ts +13 -4
- package/dist/utils/debugUtils.js +36 -13
- package/dist/utils/debugUtils.js.map +1 -1
- package/dist/utils/displayWidth.d.ts +53 -0
- package/dist/utils/displayWidth.js +195 -0
- package/dist/utils/displayWidth.js.map +1 -0
- package/dist/utils/fileUtils.d.ts +20 -1
- package/dist/utils/fileUtils.js +35 -2
- package/dist/utils/fileUtils.js.map +1 -1
- package/dist/utils/llmUtils.d.ts +39 -8
- package/dist/utils/llmUtils.js +76 -8
- package/dist/utils/llmUtils.js.map +1 -1
- package/dist/utils/redactSecrets.d.ts +63 -0
- package/dist/utils/redactSecrets.js +286 -0
- package/dist/utils/redactSecrets.js.map +1 -0
- package/dist/utils/systemPromptNotes.d.ts +222 -0
- package/dist/utils/systemPromptNotes.js +338 -0
- package/dist/utils/systemPromptNotes.js.map +1 -0
- package/dist/utils/systemUtils.d.ts +18 -1
- package/dist/utils/systemUtils.js +38 -3
- package/dist/utils/systemUtils.js.map +1 -1
- package/dist/utils/toolMatching.d.ts +30 -0
- package/dist/utils/toolMatching.js +44 -0
- package/dist/utils/toolMatching.js.map +1 -0
- package/dist/utils/untrustedText.d.ts +86 -0
- package/dist/utils/untrustedText.js +101 -0
- package/dist/utils/untrustedText.js.map +1 -0
- package/package.json +21 -6
- package/schema/gsloth-config.schema.json +1979 -353
- package/dist/core/shell/allowlist.d.ts +0 -75
- package/dist/core/shell/allowlist.js +0 -187
- package/dist/core/shell/allowlist.js.map +0 -1
- package/dist/core/shell/judge.d.ts +0 -161
- package/dist/core/shell/judge.js +0 -261
- package/dist/core/shell/judge.js.map +0 -1
package/dist/core/types.d.ts
CHANGED
|
@@ -1,10 +1,39 @@
|
|
|
1
1
|
import type { GthConfig } from '#src/config.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { DeclaredToolAnnotations } from '#src/core/approvals/annotations.js';
|
|
3
|
+
import type { ApprovalSubject } from '#src/core/approvals/matcher.js';
|
|
4
|
+
import type { RaterNegotiationRound, ShellSafetyVerdict } from '#src/core/shell/rater.js';
|
|
3
5
|
import type { BaseMessage } from '@langchain/core/messages';
|
|
4
6
|
import type { RunnableConfig } from '@langchain/core/runnables';
|
|
5
7
|
import type { StructuredToolInterface } from '@langchain/core/tools';
|
|
6
8
|
import type { IterableReadableStream } from '@langchain/core/utils/stream';
|
|
7
9
|
import type { BaseCheckpointSaver } from '@langchain/langgraph';
|
|
10
|
+
/**
|
|
11
|
+
* The approval and shell types this module's own surface is written in, re-exported so a consumer
|
|
12
|
+
* of the root barrel can NAME each of them. Every one is the declared type of something already
|
|
13
|
+
* reachable here — {@link PendingToolInterrupt}'s `subject`, `safetyVerdict` and
|
|
14
|
+
* `negotiationRounds`, and {@link GthAgentInterface#getDeclaredMcpToolAnnotations} — so without
|
|
15
|
+
* them an embedder receives values it cannot type, which is precisely what writing a typed
|
|
16
|
+
* {@link ToolApprovalCallback} asks of it.
|
|
17
|
+
*
|
|
18
|
+
* They stay declared where they are: the matcher owns the subject it matches on and the rater owns
|
|
19
|
+
* the verdict it returns, so a type moved here to become exportable would sit apart from the code
|
|
20
|
+
* that decides it. The re-export is type-only and erases at emit, so the barrel gains no runtime
|
|
21
|
+
* edge.
|
|
22
|
+
*
|
|
23
|
+
* The two modules' **runtime** surface is deliberately not re-exported, including the closed
|
|
24
|
+
* vocabularies `RATER_OUTCOMES` and `ShellSafetyVerdictSchema` that {@link RaterOutcome} and
|
|
25
|
+
* {@link ShellSafetyVerdict} are derived from: a type alias resolves its referent inside the
|
|
26
|
+
* declaration file it is emitted into, so naming either type needs neither value in scope. Values
|
|
27
|
+
* stay reachable at their own deep paths (`@gaunt-sloth/core/core/shell/rater.js`,
|
|
28
|
+
* `@gaunt-sloth/core/core/approvals/matcher.js`) at the usual deep-path risk.
|
|
29
|
+
*
|
|
30
|
+
* `packages/core/spec/coreBarrelTypeSurface.spec.ts` pins this: it type-checks a probe against the
|
|
31
|
+
* built `dist/` declarations, so dropping a name here fails as a named missing export rather than
|
|
32
|
+
* as a later consumer's problem.
|
|
33
|
+
*/
|
|
34
|
+
export type { DeclaredToolAnnotations } from '#src/core/approvals/annotations.js';
|
|
35
|
+
export type { ApprovalSubject, McpToolApprovalSubject, ShellApprovalSubject, ToolApprovalSubject, } from '#src/core/approvals/matcher.js';
|
|
36
|
+
export type { RaterNegotiationRound, RaterOutcome, ShellSafetyVerdict, } from '#src/core/shell/rater.js';
|
|
8
37
|
export type Message = BaseMessage;
|
|
9
38
|
export type StatusUpdateCallback = (level: StatusLevel, message: string) => void;
|
|
10
39
|
/**
|
|
@@ -22,6 +51,45 @@ export declare enum StatusLevel {
|
|
|
22
51
|
STREAM = 6
|
|
23
52
|
}
|
|
24
53
|
export type GthCommand = 'ask' | 'pr' | 'review' | 'chat' | 'code' | 'api' | 'exec';
|
|
54
|
+
/**
|
|
55
|
+
* GS2-16 — per-run analytics harvested from a finished agent turn, threaded into the opt-in
|
|
56
|
+
* history recorder ({@link recordSessionSafe}) so `gth insights` reports real numbers instead of
|
|
57
|
+
* zeros. All fields are best-effort: token counts are only present when the provider actually
|
|
58
|
+
* reported `usage_metadata` (otherwise omitted so the recorder stores NULL and the insights
|
|
59
|
+
* formatter suppresses the misleading `0`), and `tools` lists the names of tools invoked during
|
|
60
|
+
* the run (deduplicated, order-insensitive). There is no `costUsd` — cost requires a reliable
|
|
61
|
+
* price table this project does not carry, so it is deliberately never invented here.
|
|
62
|
+
*/
|
|
63
|
+
export interface GthRunStats {
|
|
64
|
+
/** Total prompt/input tokens across the run's LLM calls, when the provider reported usage. */
|
|
65
|
+
tokensInput?: number;
|
|
66
|
+
/** Total completion/output tokens across the run's LLM calls, when the provider reported usage. */
|
|
67
|
+
tokensOutput?: number;
|
|
68
|
+
/** Names of tools invoked during the run (deduplicated); empty when no tools were used. */
|
|
69
|
+
tools: string[];
|
|
70
|
+
/**
|
|
71
|
+
* BATCH-21 — one record per executed tool result (`ToolMessage`) observed during the run, in
|
|
72
|
+
* arrival order and NOT deduplicated (a tool called twice yields two records), so `gth eval`'s
|
|
73
|
+
* tool-RESULT assertions (`must_error` / `tool_result_json_path`) can grade what a tool
|
|
74
|
+
* *returned*, not just that it was called. Optional (additive): producers that predate the field
|
|
75
|
+
* simply omit it; {@link runStats.js finalizeRunStats} always sets it.
|
|
76
|
+
*/
|
|
77
|
+
toolResults?: GthToolResult[];
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* BATCH-21 — one executed tool call's result, harvested from its `ToolMessage` by the GS2-16
|
|
81
|
+
* run-stats accumulator (`core/runStats.ts`). Fail-soft like everything else there: `content` is
|
|
82
|
+
* omitted when no text payload could be derived, and is size-capped
|
|
83
|
+
* ({@link runStats.js TOOL_RESULT_CONTENT_CAP}) so a giant payload can't bloat run stats.
|
|
84
|
+
*/
|
|
85
|
+
export interface GthToolResult {
|
|
86
|
+
/** The tool that produced the result (`ToolMessage.name`). */
|
|
87
|
+
name: string;
|
|
88
|
+
/** `true` iff the result carried LangChain's real error signal (`ToolMessage.status === 'error'`). */
|
|
89
|
+
isError: boolean;
|
|
90
|
+
/** The result payload as text (a non-string payload is JSON-stringified), capped in length. */
|
|
91
|
+
content?: string;
|
|
92
|
+
}
|
|
25
93
|
/**
|
|
26
94
|
* Typed events emitted by the agent's {@link GthAgentInterface#streamWithEvents} path.
|
|
27
95
|
* This is the renderer contract shared by every consumer of an agent run — the AG-UI
|
|
@@ -49,6 +117,34 @@ export type AgentStreamEvent = {
|
|
|
49
117
|
} | {
|
|
50
118
|
type: 'tool_end';
|
|
51
119
|
id: string;
|
|
120
|
+
} | {
|
|
121
|
+
/**
|
|
122
|
+
* TUI-C17 — one live output chunk from an EXECUTING tool (a custom/dev toolkit child
|
|
123
|
+
* process's stdout/stderr, or its "Executing …" announcement), surfaced through the managed
|
|
124
|
+
* event stream instead of raw `process.stdout` so a renderer (the Ink TUI) can fold it into
|
|
125
|
+
* its view-model. Emitted by the tool-output channel merge
|
|
126
|
+
* (see `core/toolOutputChannel.js#mergeToolOutputIntoEvents`), NOT by `processEventStream`
|
|
127
|
+
* itself — consumers that don't opt into the merge (e.g. the AG-UI SSE encoder) never see it
|
|
128
|
+
* and the toolkits keep writing to stdout for them (today's headless behaviour).
|
|
129
|
+
*/
|
|
130
|
+
type: 'tool_output';
|
|
131
|
+
/**
|
|
132
|
+
* The tool call this chunk belongs to (LangChain's `ToolRunnableConfig.toolCall.id`,
|
|
133
|
+
* threaded through the toolkits), so a renderer can nest output under the exact call —
|
|
134
|
+
* TUI-C30 consumes this for per-call output previews. Optional only defensively: absent
|
|
135
|
+
* when the executing framework did not supply a tool call, in which case consumers should
|
|
136
|
+
* fall back to `name` attribution.
|
|
137
|
+
*/
|
|
138
|
+
id?: string;
|
|
139
|
+
/** The gth tool name (e.g. `run_shell_command`, a custom tool's name). Always known. */
|
|
140
|
+
name: string;
|
|
141
|
+
/** One verbatim streamed chunk of the child's stdout/stderr (or the notice text). */
|
|
142
|
+
chunk: string;
|
|
143
|
+
/**
|
|
144
|
+
* True when this chunk is the "🔧 Executing …" announcement rather than child output, so
|
|
145
|
+
* a richer renderer (TUI-C30) can style or strip it when previewing raw output lines.
|
|
146
|
+
*/
|
|
147
|
+
isNotice?: boolean;
|
|
52
148
|
} | {
|
|
53
149
|
type: 'tool_result';
|
|
54
150
|
id: string;
|
|
@@ -91,29 +187,168 @@ export interface PendingToolInterrupt {
|
|
|
91
187
|
name: string;
|
|
92
188
|
args: Record<string, unknown>;
|
|
93
189
|
/**
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
190
|
+
* [[TUI-C67]] — **what kind of call this is, as the gate itself decided it** (§3.1/§4.7.5): a
|
|
191
|
+
* `shell` subject carrying the command, a `tool` subject, or an `mcpTool` subject carrying the
|
|
192
|
+
* user's own `mcpServers` key. It is the discriminator `decideToolApprovalInner` matched rules
|
|
193
|
+
* on, travelling to the surface so the prompt can branch on the same one.
|
|
194
|
+
*
|
|
195
|
+
* Both terminal approval surfaces used to open with *the agent wants to run a shell command*,
|
|
196
|
+
* which EXT-80 made false for the most common prompt in `manual` and `write` — a file write, an
|
|
197
|
+
* MCP call or a custom tool, each announced as a shell command.
|
|
198
|
+
* `core/approvals/promptHeader.ts` renders the sentence from this field for both of them;
|
|
199
|
+
* re-deriving the kind from {@link name} on each surface would be a second classifier, free to
|
|
200
|
+
* disagree with the one that gated the call.
|
|
201
|
+
*
|
|
202
|
+
* **The ACP server is currently that second classifier, and the rule above still stands.**
|
|
203
|
+
* `acpPermissions.ts` titles its permission request from its own `shellCommandOf`, keyed on
|
|
204
|
+
* {@link name} rather than on this field, which it never reads — a divergence pinned by an
|
|
205
|
+
* assertion in `packages/agent/spec/acpServer.spec.ts`. Closing it means reading this field there
|
|
206
|
+
* rather than the tool name, and that is [[TUI-C89]]'s work; do not read the divergence's
|
|
207
|
+
* existence as licence to re-derive the kind anywhere else.
|
|
208
|
+
*
|
|
209
|
+
* **The runner attaches it to every interrupt it hands the approval callback**, including the
|
|
210
|
+
* plainest case where nothing else on this interface is set. Optional only because an interrupt
|
|
211
|
+
* read back out of graph state (`getPendingToolInterrupts`) is assembled before any subject
|
|
212
|
+
* exists; a surface that renders through `promptHeader` and is handed one of those renders the
|
|
213
|
+
* generic tool sentence, never a wrong one.
|
|
214
|
+
*/
|
|
215
|
+
subject?: ApprovalSubject;
|
|
216
|
+
/**
|
|
217
|
+
* CFG-26 — when the AI rater escalated this `run_shell_command` to the human (rather than
|
|
218
|
+
* approving it or bouncing it back to the model), the rater's verdict is attached here so the
|
|
219
|
+
* approval surface can show an "AI rater (<tier>): <reason>" notice. Absent when the rater is
|
|
220
|
+
* off, or when the command reached the human without being rated.
|
|
98
221
|
*/
|
|
99
222
|
safetyVerdict?: ShellSafetyVerdict;
|
|
223
|
+
/**
|
|
224
|
+
* EXT-71 §3.2 — when this call reached the human because a declared `approvals.escalate` entry
|
|
225
|
+
* matched it, the entry that fired, rendered for display. It is the provenance the prompt shows:
|
|
226
|
+
* an escalation the user cannot trace to the line they wrote reads as the gate malfunctioning.
|
|
227
|
+
* Absent whenever the escalation came from the rung or the rater instead.
|
|
228
|
+
*/
|
|
229
|
+
escalatedBy?: string;
|
|
230
|
+
/**
|
|
231
|
+
* EXT-71 §6 — **what a sticky choice will store**, rendered in the object form the user would
|
|
232
|
+
* write in a config file, e.g. `{ "type": "shell", "matcher": "exact", "pattern": "npm test" }`.
|
|
233
|
+
* The menu MUST show this at the moment of the choice, on every surface: the user is shown the
|
|
234
|
+
* thing they are agreeing to rather than a generalization of it, which is what makes the display
|
|
235
|
+
* honest and cheap at once.
|
|
236
|
+
*
|
|
237
|
+
* **For a tool call the stored thing is the tool, not the arguments** (§4.7.4), so this reads
|
|
238
|
+
* e.g. `{ "type": "mcpTool", "server": "fetcher", "matcher": "exact", "pattern": "fetch_url",
|
|
239
|
+
* "host": "docs.internal.example" }`. That is the one place a grant is deliberately broader than
|
|
240
|
+
* what the human was shown, which is why the display carries the most weight there.
|
|
241
|
+
*
|
|
242
|
+
* Absent exactly where no sticky grant is on offer — a `catastrophic` outcome (§4.2 withdraws
|
|
243
|
+
* the persistent grants), a rung that remembers nothing, a command that does not statically
|
|
244
|
+
* resolve, or a tool call naming more than one host (which has no honest single-host entry) — so
|
|
245
|
+
* a prompt never advertises a control that has already been withdrawn.
|
|
246
|
+
*/
|
|
247
|
+
grantPreview?: string;
|
|
248
|
+
/**
|
|
249
|
+
* §6 — **the same grant in the words a menu control is written in**: `npm test` for a shell
|
|
250
|
+
* command, `tool gth_web_fetch (host docs.internal.example)` or `mcpTool jira/create_issue` for a
|
|
251
|
+
* tool call. It is what the *always approve* control names, so the control reads as
|
|
252
|
+
* *always approve this tool for this host* rather than as a bare key.
|
|
253
|
+
*
|
|
254
|
+
* It is rendered by `describeApprovalEntry` — the one-liner every other provenance message uses,
|
|
255
|
+
* including the §4.7.4 notice that later withdraws the grant. Sharing the renderer is the point:
|
|
256
|
+
* a menu that describes a grant differently from the notice that withdraws it is how a user stops
|
|
257
|
+
* trusting either.
|
|
258
|
+
*
|
|
259
|
+
* Present exactly when {@link grantPreview} is, since both are rendered from the one entry
|
|
260
|
+
* `recordApproval` would write.
|
|
261
|
+
*/
|
|
262
|
+
grantSummary?: string;
|
|
263
|
+
/**
|
|
264
|
+
* [[TUI-C26]] §6 — **what the menu's *always reject* choice will record**, in the object form the
|
|
265
|
+
* user would write in a config file. The deny mirror of {@link grantPreview}, shown at the moment
|
|
266
|
+
* of the choice for the same reason: a control that does not say what it stores is one the user
|
|
267
|
+
* has to guess at.
|
|
268
|
+
*
|
|
269
|
+
* **Its availability is NOT the grant's**, and reading one off the other is the mistake this
|
|
270
|
+
* field exists to prevent. The matcher's own rule is *undecidable → no match on the allow side, a
|
|
271
|
+
* match on the deny side*, so a command the gate cannot statically resolve **can** be refused
|
|
272
|
+
* permanently even though it can never be allowed permanently. `always reject` also stays offered
|
|
273
|
+
* on a `catastrophic` verdict, where §4.2 withdraws every sticky grant: sticky refusal is safe in
|
|
274
|
+
* every direction, and it is only the grant that is ever made harder.
|
|
275
|
+
*
|
|
276
|
+
* Absent only where the entry grammar cannot hold one at all — today, an MCP call whose server
|
|
277
|
+
* could not be attributed (the grammar's `server` cannot be empty). Absent means the control is
|
|
278
|
+
* **not offered**, never offered-and-disabled.
|
|
279
|
+
*/
|
|
280
|
+
denyPreview?: string;
|
|
281
|
+
/**
|
|
282
|
+
* §6 — the same deny entry in the words the control is written in, through the one-liner every
|
|
283
|
+
* other provenance message uses. Present exactly when {@link denyPreview} is, since both are
|
|
284
|
+
* rendered from the one entry the runner would record.
|
|
285
|
+
*/
|
|
286
|
+
denySummary?: string;
|
|
287
|
+
/**
|
|
288
|
+
* [[EXT-29]] §6 — **every round of the §5 negotiation that preceded this escalation**, oldest
|
|
289
|
+
* first, when one did.
|
|
290
|
+
*
|
|
291
|
+
* The user is not asked to rule on the final command in isolation: *that the agent proposed
|
|
292
|
+
* `git reset --hard origin/main` three times unchanged, against two rejections that each told it
|
|
293
|
+
* what to fix, is itself the most important thing on the screen, and it is invisible if only the
|
|
294
|
+
* last attempt is shown.* `core/shell/negotiation.ts`'s `renderNegotiationTranscript` is the
|
|
295
|
+
* shared renderer, so two surfaces cannot describe one exchange two ways.
|
|
296
|
+
*
|
|
297
|
+
* Absent for every escalation that had no negotiation — `catastrophic` (§4.2 gives it no rounds
|
|
298
|
+
* at all), a declared `approvals.escalate` entry, an unrated rung, a tool subject.
|
|
299
|
+
*/
|
|
300
|
+
negotiationRounds?: readonly RaterNegotiationRound[];
|
|
301
|
+
/**
|
|
302
|
+
* [[EXT-29]] §5.3 — **how many attempts the agent actually made**, counted since a human was last
|
|
303
|
+
* involved rather than since the last approved call.
|
|
304
|
+
*
|
|
305
|
+
* It is a separate number from `negotiationRounds.length` because an approved call clears the
|
|
306
|
+
* transcript, and a surface reading the array's length reports only the attempts that happened
|
|
307
|
+
* after the last one. On the escalation this was measured from, the agent proposed the same
|
|
308
|
+
* command five times, was refused every time, and the human was shown three — the two calls it
|
|
309
|
+
* made in between were `git stash` and `git status`, both approved, both erasing the rounds
|
|
310
|
+
* before them. Persistence is the single most decision-relevant fact this block carries, so
|
|
311
|
+
* under-reporting it by nearly half is not a cosmetic count.
|
|
312
|
+
*
|
|
313
|
+
* Present exactly when {@link negotiationRounds} is, and never smaller than its length.
|
|
314
|
+
*/
|
|
315
|
+
negotiationAttempts?: number;
|
|
100
316
|
}
|
|
101
317
|
/**
|
|
102
|
-
* Persistence scope for an `approve` decision (
|
|
318
|
+
* Persistence scope for an `approve` decision (spec §6):
|
|
103
319
|
* - `once` — run this single invocation only; remember nothing (the default).
|
|
104
|
-
* - `session` — remember
|
|
105
|
-
* instance, so
|
|
106
|
-
*
|
|
320
|
+
* - `session` — remember **this command**, as an `exact` entry (§3.1), for the life of this runner
|
|
321
|
+
* instance, so the same command stops re-prompting. A longer variant of it still asks: the menu
|
|
322
|
+
* never widens, and breadth is something a human writes in a config file.
|
|
323
|
+
* - `always` — additionally persist that entry to the project store
|
|
107
324
|
* (`.gsloth/.gsloth-settings/shell-allowlist.json`) so it survives across runs.
|
|
108
325
|
*/
|
|
109
326
|
export type ToolApprovalScope = 'once' | 'session' | 'always';
|
|
327
|
+
/**
|
|
328
|
+
* §6 — persistence scope for a `reject` decision, the *always reject* half of the escalation menu:
|
|
329
|
+
* - `once` — refuse this single invocation; remember nothing (the default).
|
|
330
|
+
* - `session` — additionally record a **deny** entry for this call, in the one entry grammar, for
|
|
331
|
+
* the life of this runner instance. The matcher consults it before anything else, so the next
|
|
332
|
+
* identical call is refused without reaching a person at all.
|
|
333
|
+
*
|
|
334
|
+
* **There is deliberately no `always`.** An `approve` can persist because there is a project store
|
|
335
|
+
* to persist it to; there is no persisted deny store, and inventing one is a decision about a file
|
|
336
|
+
* users will have to live with rather than a rendering choice. So the scopes here are the ones the
|
|
337
|
+
* gate can actually honour, and a control that promised more would be §6's own failure mode — an
|
|
338
|
+
* affordance offered and then quietly refused.
|
|
339
|
+
*/
|
|
340
|
+
export type ToolRejectScope = 'once' | 'session';
|
|
110
341
|
/**
|
|
111
342
|
* A consumer-supplied decision on a {@link PendingToolInterrupt}: approve runs the tool,
|
|
112
343
|
* reject feeds the model a tool-rejected message (with the optional reason).
|
|
113
344
|
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
345
|
+
* Each arm carries an optional scope; when absent it means `once` (backward compatible — a bare
|
|
346
|
+
* `{ type: 'approve' }` or `{ type: 'reject' }` still type-checks and behaves as the single-shot
|
|
347
|
+
* decision that persists nothing).
|
|
348
|
+
*
|
|
349
|
+
* The two scopes are **different types on purpose**. Sharing {@link ToolApprovalScope} would let a
|
|
350
|
+
* surface send `{ type: 'reject', scope: 'always' }`, which type-checks, promises a persistence
|
|
351
|
+
* nothing implements, and degrades to a session refusal with no diagnostic.
|
|
117
352
|
*/
|
|
118
353
|
export type ToolApprovalDecision = {
|
|
119
354
|
type: 'approve';
|
|
@@ -121,6 +356,7 @@ export type ToolApprovalDecision = {
|
|
|
121
356
|
} | {
|
|
122
357
|
type: 'reject';
|
|
123
358
|
message?: string;
|
|
359
|
+
scope?: ToolRejectScope;
|
|
124
360
|
};
|
|
125
361
|
/**
|
|
126
362
|
* Callback the {@link GthAgentRunner} invokes when a run suspends on a tool-approval
|
|
@@ -129,8 +365,62 @@ export type ToolApprovalDecision = {
|
|
|
129
365
|
* silently hang or auto-approve.
|
|
130
366
|
*/
|
|
131
367
|
export type ToolApprovalCallback = (pending: PendingToolInterrupt) => Promise<ToolApprovalDecision> | ToolApprovalDecision;
|
|
368
|
+
/**
|
|
369
|
+
* [[TUI-C68]] §6.1 — what the **attack banner** is about: the command whose own structure the
|
|
370
|
+
* rater called hostile, and the rater's explanation of what it saw. Both are untrusted text and a
|
|
371
|
+
* surface must paint them through `core/shell/framing`.
|
|
372
|
+
*
|
|
373
|
+
* A separate shape from {@link PendingToolInterrupt} because it is a separate question. An approval
|
|
374
|
+
* prompt asks *may this run*, and every control on its menu is a legitimate answer carrying a
|
|
375
|
+
* scope; this asks *do you believe the rating is wrong*, has exactly one way through, and offers no
|
|
376
|
+
* scope at all — so a surface cannot reach for a menu control that does not exist here.
|
|
377
|
+
*/
|
|
378
|
+
export interface PendingAttackHalt {
|
|
379
|
+
/** The command the rater rated an attack, as the model wrote it. Untrusted text. */
|
|
380
|
+
command: string;
|
|
381
|
+
/** The rater's own explanation of what the command's structure showed. Untrusted text. */
|
|
382
|
+
reason: string;
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* §6.1 — the human's answer at the attack banner.
|
|
386
|
+
*
|
|
387
|
+
* **A string union rather than a boolean, and the polarity is deliberate.** `run-anyway` is the
|
|
388
|
+
* only value that runs anything; every other value — one a future surface invents, or `undefined`
|
|
389
|
+
* from a surface that forgot to return — stops the run. A boolean would put the irreversible answer
|
|
390
|
+
* one inverted comparison away, and there is nothing here worth being one typo from.
|
|
391
|
+
*/
|
|
392
|
+
export type AttackHaltAnswer = 'run-anyway' | 'stop';
|
|
393
|
+
/**
|
|
394
|
+
* §6.1 — callback the {@link GthAgentRunner} invokes when the rater rates a command an `attack`, so
|
|
395
|
+
* an interactive surface can show the red banner and let a human type their way past it.
|
|
396
|
+
*
|
|
397
|
+
* **Absent means halt**, exactly as an absent {@link ToolApprovalCallback} means the §6.2
|
|
398
|
+
* non-interactive exit. A surface that never wires this — a CI run, an AG-UI server, a surface
|
|
399
|
+
* nobody has written yet — keeps the halt, so forgetting fails safe. It may never block a
|
|
400
|
+
* non-interactive run, and no timeout turns waiting into a grant: waiting is something only a wired
|
|
401
|
+
* surface can cause.
|
|
402
|
+
*/
|
|
403
|
+
export type AttackHaltCallback = (halt: PendingAttackHalt) => Promise<AttackHaltAnswer> | AttackHaltAnswer;
|
|
404
|
+
/**
|
|
405
|
+
* GS2-95 — options for {@link GthAgentInterface#init} that name the run without changing how it
|
|
406
|
+
* behaves.
|
|
407
|
+
*/
|
|
408
|
+
export interface GthAgentInitOptions {
|
|
409
|
+
/**
|
|
410
|
+
* The name of the command the USER typed, for the run header only (`eval`, `batch`, `workflow`,
|
|
411
|
+
* `gth-batch`). Supplied by the command; the agent never invents it.
|
|
412
|
+
*
|
|
413
|
+
* It is a SEPARATE input from `command` because `command` is not a label: it selects the mode
|
|
414
|
+
* prompt (`readModePrompt`), the per-command approvals posture and the command-specific
|
|
415
|
+
* filesystem config. A command that runs its work through another verb's prompt — `gth eval`
|
|
416
|
+
* through `ask`, `gth batch` through `exec` — must be able to say its own name without moving the
|
|
417
|
+
* prompt it runs under. Omitted, the header falls back to the init verb, which is the right
|
|
418
|
+
* answer for every command whose verb IS its name.
|
|
419
|
+
*/
|
|
420
|
+
displayCommand?: string;
|
|
421
|
+
}
|
|
132
422
|
export interface GthAgentInterface {
|
|
133
|
-
init(command: GthCommand | undefined, configIn: GthConfig, checkpointSaver?: BaseCheckpointSaver | undefined): Promise<void>;
|
|
423
|
+
init(command: GthCommand | undefined, configIn: GthConfig, checkpointSaver?: BaseCheckpointSaver | undefined, options?: GthAgentInitOptions): Promise<void>;
|
|
134
424
|
invoke(messages: Message[], runConfig: RunnableConfig): Promise<string>;
|
|
135
425
|
stream(messages: Message[], runConfig: RunnableConfig): Promise<IterableReadableStream<string>>;
|
|
136
426
|
/**
|
|
@@ -155,22 +445,94 @@ export interface GthAgentInterface {
|
|
|
155
445
|
* approve/reject confirmation loop.
|
|
156
446
|
*/
|
|
157
447
|
getPendingToolInterrupts?(runConfig: RunnableConfig): Promise<PendingToolInterrupt[]>;
|
|
448
|
+
/**
|
|
449
|
+
* EXT-58 (spec §4.4) — the names of the tools registered with the graph at `init`. The runner
|
|
450
|
+
* intersects them with the built-in summaries table to tell the rater which already-granted
|
|
451
|
+
* built-ins it may offer as an alternative, so a suggestion can never name a tool the model does
|
|
452
|
+
* not have. Optional: an agent that does not track its tools simply omits it, and the rater then
|
|
453
|
+
* receives no granted list (and so suggests nothing).
|
|
454
|
+
*/
|
|
455
|
+
getRegisteredToolNames?(): string[];
|
|
456
|
+
/**
|
|
457
|
+
* EXT-70 (spec §4.7.1) — what the connected MCP servers declared about their own tools in their
|
|
458
|
+
* `tools/list` responses, keyed by the REGISTERED tool name (`mcp__<server>__<tool>`). The runner
|
|
459
|
+
* reads it as the `mcp` half of a declared-annotation lookup when it computes a call's effective
|
|
460
|
+
* annotation set.
|
|
461
|
+
*
|
|
462
|
+
* These are **claims, not credentials**: nothing here has been trusted, and an entry only becomes
|
|
463
|
+
* load-bearing where the user's `approvals.mcp` block believes that hint from that server.
|
|
464
|
+
* Optional — an agent that tracks no tools omits it, and every tool is then fail-closed, which is
|
|
465
|
+
* exactly what a fully distrustful configuration computes anyway.
|
|
466
|
+
*/
|
|
467
|
+
getDeclaredMcpToolAnnotations?(): ReadonlyMap<string, DeclaredToolAnnotations>;
|
|
468
|
+
/**
|
|
469
|
+
* GS2-16 — reset the per-run analytics accumulator so the NEXT turn's token/tool totals start
|
|
470
|
+
* from zero. Called by {@link GthAgentRunner} at each turn boundary (the runner is reused across
|
|
471
|
+
* turns in interactive sessions). Optional: agents that don't collect stats simply omit it.
|
|
472
|
+
*/
|
|
473
|
+
resetRunStats?(): void;
|
|
474
|
+
/**
|
|
475
|
+
* GS2-16 — the analytics harvested from the run(s) since the last {@link resetRunStats}. Used by
|
|
476
|
+
* the runner to thread token/tool data into the opt-in history recorder. Optional; when absent
|
|
477
|
+
* the runner records no analytics for that turn. Reading must never throw.
|
|
478
|
+
*/
|
|
479
|
+
getRunStats?(): GthRunStats;
|
|
158
480
|
cleanup?(): Promise<void>;
|
|
159
481
|
}
|
|
160
482
|
/**
|
|
161
483
|
* Factory that produces a {@link GthAgentInterface} implementation. Injected into
|
|
162
|
-
* {@link GthAgentRunner} so embedders can swap the lean `GthLangChainAgent` (default,
|
|
163
|
-
*
|
|
164
|
-
* importing deepagents.
|
|
484
|
+
* {@link GthAgentRunner} so embedders can swap the lean `GthLangChainAgent` (the default, in
|
|
485
|
+
* core) for another graph builder without core ever importing it.
|
|
165
486
|
*/
|
|
166
487
|
export type GthAgentFactory = (statusUpdate: StatusUpdateCallback, resolvers?: AgentResolvers) => GthAgentInterface;
|
|
167
488
|
export type ToolsResolver = (config: GthConfig, command?: GthCommand) => Promise<StructuredToolInterface[]>;
|
|
168
489
|
export type ToolsCleanup = () => Promise<void>;
|
|
169
490
|
export type MiddlewareResolver = (middleware: any[] | undefined, config: GthConfig) => Promise<any[]>;
|
|
170
491
|
export type MiddlewareCleanup = () => Promise<void>;
|
|
492
|
+
/**
|
|
493
|
+
* EXT-32 — one connected MCP server's discovery `instructions` string (from its MCP `initialize`
|
|
494
|
+
* handshake), paired with the server name it came from. Captured once during tool resolution and
|
|
495
|
+
* reused: injected (fenced + per-server-labelled) into the composed system prompt, and available
|
|
496
|
+
* for [[TUI-C20]]'s MCP debug tab to render the same captured text. Only servers that actually
|
|
497
|
+
* supplied non-empty instructions appear here.
|
|
498
|
+
*/
|
|
499
|
+
export interface McpServerInstruction {
|
|
500
|
+
/** The configured MCP server name (the key under `config.mcpServers`). */
|
|
501
|
+
server: string;
|
|
502
|
+
/** The server-provided instructions text (trimmed, non-empty). */
|
|
503
|
+
instructions: string;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* A per-server MCP connection failure captured during the most recent {@link ToolsResolver} call.
|
|
507
|
+
* Recorded when a configured MCP server can't be reached (connection/handshake/auth error), so the
|
|
508
|
+
* failure — otherwise a transient `displayWarning` that scrolls away the moment the Ink TUI takes
|
|
509
|
+
* over the screen — can be re-surfaced persistently in the chrome AND named in the /debug MCP tab
|
|
510
|
+
* (which renders per configured server and would otherwise show only a bare "no tools" line, with
|
|
511
|
+
* no hint that the server never connected). Mirrors {@link McpServerInstruction}.
|
|
512
|
+
*/
|
|
513
|
+
export interface McpConnectionFailure {
|
|
514
|
+
/** The configured MCP server name (the key under `config.mcpServers`). */
|
|
515
|
+
server: string;
|
|
516
|
+
/** A concise, human-readable reason (the underlying connection error's message). */
|
|
517
|
+
reason: string;
|
|
518
|
+
}
|
|
171
519
|
export interface AgentResolvers {
|
|
172
520
|
resolveTools?: ToolsResolver;
|
|
173
521
|
cleanupTools?: ToolsCleanup;
|
|
174
522
|
resolveMiddleware?: MiddlewareResolver;
|
|
175
523
|
cleanupMiddleware?: MiddlewareCleanup;
|
|
524
|
+
/**
|
|
525
|
+
* EXT-32 — the per-server MCP discovery instructions captured during the most recent
|
|
526
|
+
* {@link ToolsResolver} call (empty when no MCP servers are configured or none supplied
|
|
527
|
+
* instructions). Optional: resolvers without MCP support simply omit it, and the prompt
|
|
528
|
+
* composition treats an absent accessor as "no instructions" (no MCP section is emitted).
|
|
529
|
+
*/
|
|
530
|
+
getMcpServerInstructions?(): McpServerInstruction[];
|
|
531
|
+
/**
|
|
532
|
+
* The per-server MCP connection failures captured during the most recent {@link ToolsResolver}
|
|
533
|
+
* call (empty when every configured server connected, or none is configured). Optional: resolvers
|
|
534
|
+
* without MCP support omit it, and callers treat an absent accessor as "no failures". Read by the
|
|
535
|
+
* TUI to surface a persistent notice and to annotate the /debug MCP tab.
|
|
536
|
+
*/
|
|
537
|
+
getMcpConnectionFailures?(): McpConnectionFailure[];
|
|
176
538
|
}
|
package/dist/core/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAmDA;;;;GAIG;AACH,MAAM,CAAN,IAAY,WAQX;AARD,WAAY,WAAW;IACrB,+CAAS,CAAA;IACT,6CAAQ,CAAA;IACR,mDAAW,CAAA;IACX,mDAAW,CAAA;IACX,mDAAW,CAAA;IACX,+CAAS,CAAA;IACT,iDAAU,CAAA;AACZ,CAAC,EARW,WAAW,KAAX,WAAW,QAQtB"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
* GS2-7 (B20) — pure, presentation-only formatters for the history surfaces.
|
|
4
|
+
*
|
|
5
|
+
* Shared by the `gth history` / `gth insights` CLI commands AND the `/history` `/search`
|
|
6
|
+
* `/insights` TUI slash commands so both render identically and both are unit-testable without a
|
|
7
|
+
* DB or a terminal. Every function is a pure `data -> string[]` transform (one display line per
|
|
8
|
+
* element); no I/O, no colour codes.
|
|
9
|
+
*/
|
|
10
|
+
import type { ConversationSummary, HistoryInsights, SessionRecord, SessionSearchResult } from '#src/history/historyStore.js';
|
|
11
|
+
/**
|
|
12
|
+
* Render FTS search hits: a header line per hit plus its snippet (or a prompt preview when the
|
|
13
|
+
* snippet is empty). Returns a friendly single line when there are none.
|
|
14
|
+
*/
|
|
15
|
+
export declare function formatSearchResults(results: SessionSearchResult[]): string[];
|
|
16
|
+
/**
|
|
17
|
+
* GS2-19 — render a conversation-grained listing: one header + last-turn preview per conversation.
|
|
18
|
+
* The header carries the count / timespan / last message that make the conversation the top-level
|
|
19
|
+
* unit (`gth history list`), replacing the old flat per-turn list.
|
|
20
|
+
*/
|
|
21
|
+
export declare function formatConversationList(conversations: ConversationSummary[]): string[];
|
|
22
|
+
/**
|
|
23
|
+
* GS2-19 — render one conversation's full thread (all turns in order) for `gth history show <id>`.
|
|
24
|
+
* Each turn shows its prompt and response preview so a search hit can be expanded into context.
|
|
25
|
+
*/
|
|
26
|
+
export declare function formatConversationThread(turns: SessionRecord[]): string[];
|
|
27
|
+
/** Render the analytics summary: totals, top tools, per-command breakdown. */
|
|
28
|
+
export declare function formatInsightsSummary(insights: HistoryInsights): string[];
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/** Collapse whitespace and clip to `max` chars with an ellipsis, for one-line previews. */
|
|
2
|
+
function oneLine(text, max = 80) {
|
|
3
|
+
const s = (text ?? '').replace(/\s+/g, ' ').trim();
|
|
4
|
+
return s.length > max ? s.slice(0, max - 1) + '…' : s;
|
|
5
|
+
}
|
|
6
|
+
/** A compact `#id <ts> [command] model (conversation #cid)` header line for one turn. */
|
|
7
|
+
function headerLine(r) {
|
|
8
|
+
const parts = [`#${r.id}`, r.ts];
|
|
9
|
+
if (r.command)
|
|
10
|
+
parts.push(`[${r.command}]`);
|
|
11
|
+
if (r.model)
|
|
12
|
+
parts.push(r.model);
|
|
13
|
+
// GS2-19: a search hit resolves to the conversation it belongs to, so the reader can pull up the
|
|
14
|
+
// whole thread (`gth history show <cid>`). Older rows migrated from GS2-7 always have one now.
|
|
15
|
+
if (r.conversationId != null)
|
|
16
|
+
parts.push(`(conversation #${r.conversationId})`);
|
|
17
|
+
return parts.join(' ');
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Render FTS search hits: a header line per hit plus its snippet (or a prompt preview when the
|
|
21
|
+
* snippet is empty). Returns a friendly single line when there are none.
|
|
22
|
+
*/
|
|
23
|
+
export function formatSearchResults(results) {
|
|
24
|
+
if (results.length === 0)
|
|
25
|
+
return ['No matching sessions found.'];
|
|
26
|
+
const lines = [];
|
|
27
|
+
for (const r of results) {
|
|
28
|
+
lines.push(headerLine(r));
|
|
29
|
+
const detail = r.snippet && r.snippet.trim().length > 0 ? r.snippet : r.prompt;
|
|
30
|
+
const preview = oneLine(detail, 100);
|
|
31
|
+
if (preview)
|
|
32
|
+
lines.push(` ${preview}`);
|
|
33
|
+
}
|
|
34
|
+
return lines;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* GS2-19 — render a conversation-grained listing: one header + last-turn preview per conversation.
|
|
38
|
+
* The header carries the count / timespan / last message that make the conversation the top-level
|
|
39
|
+
* unit (`gth history list`), replacing the old flat per-turn list.
|
|
40
|
+
*/
|
|
41
|
+
export function formatConversationList(conversations) {
|
|
42
|
+
if (conversations.length === 0) {
|
|
43
|
+
return [
|
|
44
|
+
'No conversations recorded yet. Enable history with `history.enabled: true` in your config.',
|
|
45
|
+
];
|
|
46
|
+
}
|
|
47
|
+
const lines = [];
|
|
48
|
+
for (const c of conversations) {
|
|
49
|
+
const parts = [`#${c.id}`];
|
|
50
|
+
// Timespan across the conversation's turns; a 1-turn (or not-yet-started) conversation collapses
|
|
51
|
+
// to a single instant, so show one timestamp rather than an `a → a` range.
|
|
52
|
+
if (c.firstTs && c.lastTs && c.firstTs !== c.lastTs) {
|
|
53
|
+
parts.push(`${c.firstTs} → ${c.lastTs}`);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
parts.push(c.lastTs ?? c.firstTs ?? c.startedTs);
|
|
57
|
+
}
|
|
58
|
+
if (c.command)
|
|
59
|
+
parts.push(`[${c.command}]`);
|
|
60
|
+
if (c.model)
|
|
61
|
+
parts.push(c.model);
|
|
62
|
+
parts.push(`(${c.turnCount} ${c.turnCount === 1 ? 'turn' : 'turns'})`);
|
|
63
|
+
lines.push(parts.join(' '));
|
|
64
|
+
const preview = oneLine(c.lastPrompt, 100);
|
|
65
|
+
if (preview)
|
|
66
|
+
lines.push(` ${preview}`);
|
|
67
|
+
}
|
|
68
|
+
return lines;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* GS2-19 — render one conversation's full thread (all turns in order) for `gth history show <id>`.
|
|
72
|
+
* Each turn shows its prompt and response preview so a search hit can be expanded into context.
|
|
73
|
+
*/
|
|
74
|
+
export function formatConversationThread(turns) {
|
|
75
|
+
if (turns.length === 0)
|
|
76
|
+
return ['No turns found for that conversation.'];
|
|
77
|
+
const lines = [];
|
|
78
|
+
turns.forEach((t, i) => {
|
|
79
|
+
const header = t.ts ? `Turn ${i + 1} ${t.ts}` : `Turn ${i + 1}`;
|
|
80
|
+
lines.push(header);
|
|
81
|
+
const prompt = oneLine(t.prompt, 200);
|
|
82
|
+
if (prompt)
|
|
83
|
+
lines.push(` > ${prompt}`);
|
|
84
|
+
const response = oneLine(t.response, 200);
|
|
85
|
+
if (response)
|
|
86
|
+
lines.push(` ${response}`);
|
|
87
|
+
});
|
|
88
|
+
return lines;
|
|
89
|
+
}
|
|
90
|
+
/** Render the analytics summary: totals, top tools, per-command breakdown. */
|
|
91
|
+
export function formatInsightsSummary(insights) {
|
|
92
|
+
if (insights.sessionCount === 0) {
|
|
93
|
+
return [
|
|
94
|
+
'No sessions recorded yet. Enable history with `history.enabled: true` in your config.',
|
|
95
|
+
];
|
|
96
|
+
}
|
|
97
|
+
const lines = [];
|
|
98
|
+
lines.push(`Sessions: ${insights.sessionCount}`);
|
|
99
|
+
if (insights.firstTs && insights.lastTs) {
|
|
100
|
+
lines.push(`Span: ${insights.firstTs} → ${insights.lastTs}`);
|
|
101
|
+
}
|
|
102
|
+
// GS2-16: only surface the token/cost/top-tool lines when there is real data behind them.
|
|
103
|
+
// Older records (and providers that report no usage) leave these zero/empty; printing
|
|
104
|
+
// `Tokens: 0` / `$0.0000` / `(none recorded)` reads as "the run used nothing", which is
|
|
105
|
+
// misleading, so omit the line entirely instead. Sessions / Span / By-command always show.
|
|
106
|
+
if (insights.totalTokens > 0) {
|
|
107
|
+
lines.push(`Tokens: ${insights.totalTokens} total ` +
|
|
108
|
+
`(${insights.totalTokensInput} in / ${insights.totalTokensOutput} out)`);
|
|
109
|
+
}
|
|
110
|
+
// Cost is only ever recorded when a reliable price was available (the recorder never invents
|
|
111
|
+
// one), so a positive total is the signal that a cost line is meaningful.
|
|
112
|
+
if (insights.totalCostUsd > 0) {
|
|
113
|
+
lines.push(`Estimated cost: $${insights.totalCostUsd.toFixed(4)}`);
|
|
114
|
+
}
|
|
115
|
+
if (insights.perCommand.length > 0) {
|
|
116
|
+
lines.push('By command:');
|
|
117
|
+
for (const c of insights.perCommand)
|
|
118
|
+
lines.push(` ${c.command}: ${c.count}`);
|
|
119
|
+
}
|
|
120
|
+
if (insights.topTools.length > 0) {
|
|
121
|
+
lines.push('Top tools:');
|
|
122
|
+
for (const t of insights.topTools)
|
|
123
|
+
lines.push(` ${t.tool}: ${t.count}`);
|
|
124
|
+
}
|
|
125
|
+
return lines;
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=historyFormat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"historyFormat.js","sourceRoot":"","sources":["../../src/history/historyFormat.ts"],"names":[],"mappings":"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"}
|