@oh-my-pi/pi-coding-agent 17.0.6 → 17.0.8
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 +65 -0
- package/dist/cli.js +4967 -4948
- package/dist/types/config/model-registry.d.ts +1 -1
- package/dist/types/config/model-resolver.d.ts +5 -1
- package/dist/types/config/settings-schema.d.ts +16 -0
- package/dist/types/dap/client.d.ts +19 -0
- package/dist/types/extensibility/extensions/runner.d.ts +4 -2
- package/dist/types/extensibility/extensions/types.d.ts +3 -0
- package/dist/types/extensibility/typebox.d.ts +4 -0
- package/dist/types/hindsight/client.d.ts +10 -0
- package/dist/types/hindsight/config.d.ts +8 -0
- package/dist/types/mcp/tool-bridge.d.ts +9 -0
- package/dist/types/mnemopi/state.d.ts +2 -0
- package/dist/types/modes/components/user-message.d.ts +25 -1
- package/dist/types/modes/controllers/extension-ui-controller.d.ts +8 -0
- package/dist/types/modes/interactive-mode.d.ts +7 -1
- package/dist/types/modes/types.d.ts +14 -1
- package/dist/types/modes/utils/ui-helpers.d.ts +12 -8
- package/dist/types/sdk.d.ts +1 -0
- package/dist/types/session/agent-session-error-log.test.d.ts +1 -0
- package/dist/types/session/agent-session.d.ts +78 -2
- package/dist/types/task/executor.d.ts +10 -0
- package/dist/types/task/index.d.ts +1 -0
- package/dist/types/task/prewalk.d.ts +3 -0
- package/dist/types/tools/ask.d.ts +10 -0
- package/dist/types/tools/tool-timeouts.d.ts +8 -2
- package/dist/types/utils/changelog.d.ts +4 -6
- package/package.json +12 -13
- package/src/cli/models-cli.ts +37 -17
- package/src/cli/update-cli.ts +14 -1
- package/src/config/model-discovery.ts +3 -2
- package/src/config/model-registry.ts +53 -26
- package/src/config/model-resolver.ts +56 -31
- package/src/config/settings-schema.ts +5 -0
- package/src/config/settings.ts +68 -5
- package/src/dap/client.ts +86 -7
- package/src/edit/diff.ts +4 -4
- package/src/eval/py/prelude.py +5 -5
- package/src/export/html/template.js +23 -9
- package/src/extensibility/extensions/runner.ts +9 -4
- package/src/extensibility/extensions/types.ts +3 -0
- package/src/extensibility/typebox.ts +22 -9
- package/src/hindsight/client.test.ts +42 -0
- package/src/hindsight/client.ts +40 -3
- package/src/hindsight/config.ts +18 -0
- package/src/launch/broker.ts +31 -5
- package/src/lsp/index.ts +1 -1
- package/src/main.ts +15 -5
- package/src/mcp/tool-bridge.ts +9 -0
- package/src/mnemopi/state.ts +70 -3
- package/src/modes/components/agent-dashboard.ts +6 -2
- package/src/modes/components/chat-transcript-builder.ts +13 -2
- package/src/modes/components/diff.ts +2 -2
- package/src/modes/components/plan-review-overlay.ts +20 -4
- package/src/modes/components/user-message.ts +100 -1
- package/src/modes/controllers/command-controller.ts +22 -5
- package/src/modes/controllers/event-controller.ts +4 -1
- package/src/modes/controllers/extension-ui-controller.ts +18 -0
- package/src/modes/controllers/input-controller.ts +47 -12
- package/src/modes/controllers/selector-controller.ts +82 -6
- package/src/modes/interactive-mode.ts +36 -4
- package/src/modes/types.ts +16 -3
- package/src/modes/utils/ui-helpers.ts +40 -20
- package/src/prompts/system/workflow-notice.md +1 -1
- package/src/sdk.ts +134 -48
- package/src/session/agent-session-error-log.test.ts +59 -0
- package/src/session/agent-session.ts +300 -26
- package/src/system-prompt.ts +1 -2
- package/src/task/executor.ts +41 -27
- package/src/task/index.ts +11 -0
- package/src/task/prewalk.ts +6 -0
- package/src/task/worktree.ts +25 -11
- package/src/tools/ask.ts +15 -0
- package/src/tools/bash.ts +14 -6
- package/src/tools/browser.ts +1 -1
- package/src/tools/debug.ts +1 -1
- package/src/tools/eval.ts +4 -5
- package/src/tools/fetch.ts +1 -1
- package/src/tools/hub/launch.ts +7 -0
- package/src/tools/tool-timeouts.ts +10 -3
- package/src/tools/write.ts +31 -0
- package/src/utils/changelog.ts +54 -58
- package/src/utils/git.ts +57 -49
|
@@ -44,7 +44,7 @@ interface ProviderOverride {
|
|
|
44
44
|
* See `xiaomi-tp-discovery-merge.test.ts` and the `refresh()` baseUrl-override
|
|
45
45
|
* regression in `model-registry.test.ts`.
|
|
46
46
|
*/
|
|
47
|
-
export declare function mergeDiscoveredModel<TApi extends Api>(model: Model<TApi>, existing: Model<Api> | undefined, providerOverride?: Pick<ProviderOverride, "baseUrl" | "headers" | "remoteCompaction" | "transport">): Model<TApi>;
|
|
47
|
+
export declare function mergeDiscoveredModel<TApi extends Api>(model: Model<TApi>, existing: Model<Api> | undefined, providerOverride?: Pick<ProviderOverride, "baseUrl" | "compat" | "headers" | "remoteCompaction" | "transport">): Model<TApi>;
|
|
48
48
|
export type ProviderDiscoveryStatus = "idle" | "ok" | "empty" | "cached" | "unavailable" | "unauthenticated";
|
|
49
49
|
export interface ProviderDiscoveryState {
|
|
50
50
|
provider: string;
|
|
@@ -265,8 +265,10 @@ export declare function resolveAllowedModels(modelRegistry: Pick<ModelRegistry,
|
|
|
265
265
|
export declare function filterAvailableModelsByEnabledPatterns(available: Model<Api>[], patterns: readonly string[], settings?: Settings): Model<Api>[];
|
|
266
266
|
export interface ResolveCliModelResult {
|
|
267
267
|
model: Model<Api> | undefined;
|
|
268
|
-
/** configuredPatterns
|
|
268
|
+
/** configuredPatterns contains the role's ordered primary candidates. */
|
|
269
269
|
configuredPatterns?: string[];
|
|
270
|
+
/** configuredRole identifies the role expanded into configuredPatterns. */
|
|
271
|
+
configuredRole?: string;
|
|
270
272
|
/** configuredPatternIndex identifies the configured role pattern that matched an available model. */
|
|
271
273
|
configuredPatternIndex?: number;
|
|
272
274
|
selector?: string;
|
|
@@ -283,6 +285,8 @@ export declare function resolveCliModel(options: {
|
|
|
283
285
|
cliProvider?: string;
|
|
284
286
|
cliModel?: string;
|
|
285
287
|
modelRegistry: CliModelRegistry;
|
|
288
|
+
/** Authenticated models to prefer for unqualified selectors; omit to preserve catalog-order behavior. */
|
|
289
|
+
availableModels?: Model<Api>[];
|
|
286
290
|
settings?: Settings;
|
|
287
291
|
preferences?: ModelMatchPreferences;
|
|
288
292
|
}): ResolveCliModelResult;
|
|
@@ -2968,6 +2968,22 @@ export declare const SETTINGS_SCHEMA: {
|
|
|
2968
2968
|
readonly type: "boolean";
|
|
2969
2969
|
readonly default: false;
|
|
2970
2970
|
};
|
|
2971
|
+
readonly "hindsight.requestTimeoutMs": {
|
|
2972
|
+
readonly type: "number";
|
|
2973
|
+
readonly default: 30000;
|
|
2974
|
+
};
|
|
2975
|
+
readonly "hindsight.reflectTimeoutMs": {
|
|
2976
|
+
readonly type: "number";
|
|
2977
|
+
readonly default: 120000;
|
|
2978
|
+
};
|
|
2979
|
+
readonly "hindsight.recallTimeoutMs": {
|
|
2980
|
+
readonly type: "number";
|
|
2981
|
+
readonly default: 30000;
|
|
2982
|
+
};
|
|
2983
|
+
readonly "hindsight.retainTimeoutMs": {
|
|
2984
|
+
readonly type: "number";
|
|
2985
|
+
readonly default: 60000;
|
|
2986
|
+
};
|
|
2971
2987
|
readonly "hindsight.mentalModelsEnabled": {
|
|
2972
2988
|
readonly type: "boolean";
|
|
2973
2989
|
readonly default: true;
|
|
@@ -53,4 +53,23 @@ export declare class DapClient {
|
|
|
53
53
|
sendResponse(request: DapRequestMessage, success: boolean, body?: unknown, message?: string): Promise<void>;
|
|
54
54
|
dispose(): Promise<void>;
|
|
55
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* Give the adapter a chance to announce it is listening on `port` before the
|
|
58
|
+
* first connect. vscode-js-debug prints `Debug server listening at HOST:PORT`
|
|
59
|
+
* to stdout from inside its `listen()` callback; waiting for the port to appear
|
|
60
|
+
* there means we only connect once the child genuinely owns the reserved port,
|
|
61
|
+
* which closes the WSL2-mirrored ghost-accept window (issue #6055) at its root.
|
|
62
|
+
*
|
|
63
|
+
* Best-effort: resolves on the banner, on process exit, or on timeout — the
|
|
64
|
+
* subsequent connect loop and `proc.exitCode` checks surface real failures, so
|
|
65
|
+
* an adapter that never prints a banner still proceeds (just without the gate).
|
|
66
|
+
* Also drains stdout for the wait's duration: in tcp mode the DAP protocol
|
|
67
|
+
* flows over the socket, so nothing else consumes the adapter's stdout.
|
|
68
|
+
*
|
|
69
|
+
* Exported so tests can drive the gate deterministically with a synthetic stdout.
|
|
70
|
+
*/
|
|
71
|
+
export declare function waitForTcpServerListening(proc: {
|
|
72
|
+
stdout: ReadableStream<Uint8Array>;
|
|
73
|
+
exitCode: number | null;
|
|
74
|
+
}, port: number, timeoutMs: number): Promise<void>;
|
|
56
75
|
export {};
|
|
@@ -54,8 +54,10 @@ export type SwitchSessionHandler = (sessionPath: string) => Promise<{
|
|
|
54
54
|
}>;
|
|
55
55
|
export type ShutdownHandler = () => void;
|
|
56
56
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
57
|
+
* Emit `session_shutdown` and clear timers owned by an extension runner.
|
|
58
|
+
*
|
|
59
|
+
* Returns whether any shutdown handlers were present. Timer cleanup runs even
|
|
60
|
+
* when a handler fails so extension background work cannot outlive its host.
|
|
59
61
|
*/
|
|
60
62
|
export declare function emitSessionShutdownEvent(extensionRunner: ExtensionRunner | undefined): Promise<boolean>;
|
|
61
63
|
export declare class ExtensionRunner {
|
|
@@ -398,6 +398,9 @@ export interface ToolDefinition<TParams extends TSchema = TSchema, TDetails = un
|
|
|
398
398
|
/** Tool approval tier. Defaults to `"exec"` when omitted.
|
|
399
399
|
* `"read"`: read-only operations. `"write"`: mutations. `"exec"`: code execution. */
|
|
400
400
|
approval?: ToolApproval;
|
|
401
|
+
/** Structured-output strict grammar opt-in/out. `false` is meaningful: OpenAI-family
|
|
402
|
+
* serializers preserve an explicit `strict: false` on the wire (#4336/#4340). */
|
|
403
|
+
strict?: boolean;
|
|
401
404
|
/** MCP server name for discovery/search metadata when this tool fronts an MCP server. */
|
|
402
405
|
mcpServerName?: string;
|
|
403
406
|
/** Original MCP tool name for discovery/search metadata. */
|
|
@@ -33,6 +33,8 @@ export type TOptional<_E extends ArkSchema> = ArkSchema;
|
|
|
33
33
|
export type TUnion<_T extends readonly ArkSchema[] = readonly ArkSchema[]> = ArkSchema;
|
|
34
34
|
export type TEnum<_T extends readonly (string | number)[] = readonly (string | number)[]> = ArkSchema;
|
|
35
35
|
export type TRecord<_K extends ArkSchema, _V extends ArkSchema> = ArkSchema;
|
|
36
|
+
/** TypeBox-compatible wrapper for raw JSON Schema documents. */
|
|
37
|
+
export type TUnsafe<_T = unknown> = ArkSchema;
|
|
36
38
|
declare const VALIDATION_FAILURE: unique symbol;
|
|
37
39
|
interface ValidationFailure {
|
|
38
40
|
message: string;
|
|
@@ -126,6 +128,7 @@ export declare const Type: {
|
|
|
126
128
|
readonly Null: typeof tNull;
|
|
127
129
|
readonly Any: typeof tAny;
|
|
128
130
|
readonly Unknown: typeof tUnknown;
|
|
131
|
+
readonly Unsafe: <T = unknown>(jsonSchema?: Record<string, unknown>) => TUnsafe<T>;
|
|
129
132
|
readonly Never: typeof tNever;
|
|
130
133
|
readonly Literal: typeof tLiteral;
|
|
131
134
|
readonly Union: typeof tUnion;
|
|
@@ -155,6 +158,7 @@ declare const _default: {
|
|
|
155
158
|
readonly Null: typeof tNull;
|
|
156
159
|
readonly Any: typeof tAny;
|
|
157
160
|
readonly Unknown: typeof tUnknown;
|
|
161
|
+
readonly Unsafe: <T = unknown>(jsonSchema?: Record<string, unknown>) => TUnsafe<T>;
|
|
158
162
|
readonly Never: typeof tNever;
|
|
159
163
|
readonly Literal: typeof tLiteral;
|
|
160
164
|
readonly Union: typeof tUnion;
|
|
@@ -12,10 +12,20 @@ export type Budget = "low" | "mid" | "high" | string;
|
|
|
12
12
|
export type TagsMatch = "any" | "all" | "any_strict" | "all_strict";
|
|
13
13
|
export type UpdateMode = "replace" | "append";
|
|
14
14
|
export type ConsolidationState = "failed" | "pending" | "done";
|
|
15
|
+
/** Per-operation request deadlines (ms). Each falls back to a built-in default. */
|
|
16
|
+
export interface HindsightTimeouts {
|
|
17
|
+
/** Default deadline for ops without a specific override. */
|
|
18
|
+
request?: number;
|
|
19
|
+
reflect?: number;
|
|
20
|
+
recall?: number;
|
|
21
|
+
retain?: number;
|
|
22
|
+
}
|
|
15
23
|
export interface HindsightApiOptions {
|
|
16
24
|
baseUrl: string;
|
|
17
25
|
apiKey?: string;
|
|
18
26
|
userAgent?: string;
|
|
27
|
+
/** Per-op deadlines; unset entries fall back to built-in defaults. */
|
|
28
|
+
timeouts?: HindsightTimeouts;
|
|
19
29
|
}
|
|
20
30
|
/** Caller cancellation shared by Hindsight request option bags. */
|
|
21
31
|
export interface HindsightRequestOptions {
|
|
@@ -32,6 +32,14 @@ export interface HindsightConfig {
|
|
|
32
32
|
recallMaxQueryChars: number;
|
|
33
33
|
recallPromptPreamble: string;
|
|
34
34
|
debug: boolean;
|
|
35
|
+
/** Default per-request client deadline (ms) for ops without a specific override. */
|
|
36
|
+
requestTimeoutMs: number;
|
|
37
|
+
/** Client deadline (ms) for reflect (agentic synthesis; costlier than a metadata fetch). */
|
|
38
|
+
reflectTimeoutMs: number;
|
|
39
|
+
/** Client deadline (ms) for recall. */
|
|
40
|
+
recallTimeoutMs: number;
|
|
41
|
+
/** Client deadline (ms) for retain / retainBatch. */
|
|
42
|
+
retainTimeoutMs: number;
|
|
35
43
|
mentalModelsEnabled: boolean;
|
|
36
44
|
mentalModelAutoSeed: boolean;
|
|
37
45
|
mentalModelRefreshIntervalMs: number;
|
|
@@ -59,6 +59,13 @@ export declare class MCPTool implements CustomTool<TSchema, MCPToolDetails> {
|
|
|
59
59
|
readonly approval: "write";
|
|
60
60
|
/** Render completed MCP calls with the result header replacing the pending call header. */
|
|
61
61
|
readonly mergeCallAndResult = true;
|
|
62
|
+
/**
|
|
63
|
+
* MCP-backed tools opt out of strict structured-output grammar. The server
|
|
64
|
+
* owns validation, and strict mode makes OpenAI-family models over-fill
|
|
65
|
+
* mutually exclusive optional fields (#4336/#4340). Serializers preserve an
|
|
66
|
+
* explicit `false`; an omitted flag would leave nothing to preserve.
|
|
67
|
+
*/
|
|
68
|
+
readonly strict: false;
|
|
62
69
|
/** Create MCPTool instances for all tools from an MCP server connection */
|
|
63
70
|
static fromTools(connection: MCPServerConnection, tools: MCPToolDefinition[], reconnect?: MCPReconnect): MCPTool[];
|
|
64
71
|
constructor(connection: MCPServerConnection, tool: MCPToolDefinition, reconnect?: MCPReconnect | undefined);
|
|
@@ -86,6 +93,8 @@ export declare class DeferredMCPTool implements CustomTool<TSchema, MCPToolDetai
|
|
|
86
93
|
readonly approval: "write";
|
|
87
94
|
/** Render completed MCP calls with the result header replacing the pending call header. */
|
|
88
95
|
readonly mergeCallAndResult = true;
|
|
96
|
+
/** See {@link MCPTool.strict}: MCP servers own validation, so stay non-strict. */
|
|
97
|
+
readonly strict: false;
|
|
89
98
|
/** Create DeferredMCPTool instances for all tools from an MCP server */
|
|
90
99
|
static fromTools(serverName: string, tools: MCPToolDefinition[], getConnection: () => Promise<MCPServerConnection>, source?: SourceMeta, reconnect?: MCPReconnect): DeferredMCPTool[];
|
|
91
100
|
constructor(serverName: string, tool: MCPToolDefinition, getConnection: () => Promise<MCPServerConnection>, source?: SourceMeta, reconnect?: MCPReconnect | undefined);
|
|
@@ -74,6 +74,7 @@ export interface MnemopiSessionStateOptions {
|
|
|
74
74
|
hasRecalledForFirstTurn?: boolean;
|
|
75
75
|
}
|
|
76
76
|
export declare class MnemopiSessionState {
|
|
77
|
+
#private;
|
|
77
78
|
sessionId: string;
|
|
78
79
|
readonly config: MnemopiBackendConfig;
|
|
79
80
|
readonly session: AgentSession;
|
|
@@ -124,6 +125,7 @@ export declare class MnemopiSessionState {
|
|
|
124
125
|
content: string;
|
|
125
126
|
}>, sourceId: string, options?: {
|
|
126
127
|
extract?: boolean;
|
|
128
|
+
retainedThroughUserTurn?: number;
|
|
127
129
|
}): Promise<void>;
|
|
128
130
|
attachSessionListeners(): void;
|
|
129
131
|
maybeRecallOnAgentStart(): Promise<void>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Container } from "@oh-my-pi/pi-tui";
|
|
1
|
+
import { type Component, Container } from "@oh-my-pi/pi-tui";
|
|
2
2
|
/**
|
|
3
3
|
* Component that renders a user message
|
|
4
4
|
*/
|
|
@@ -7,3 +7,27 @@ export declare class UserMessageComponent extends Container {
|
|
|
7
7
|
constructor(text: string, synthetic?: boolean, imageLinks?: readonly (string | undefined)[]);
|
|
8
8
|
render(width: number): readonly string[];
|
|
9
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Collapsed placeholder for a synthetic (agent-attributed) user input in the
|
|
12
|
+
* file/remote-backed transcript viewer — chiefly the advisor's `Session update`
|
|
13
|
+
* replay dumps, which can each be hundreds of KiB of Markdown and, on cold open,
|
|
14
|
+
* blocked the TUI for tens of seconds while every historical body was laid out
|
|
15
|
+
* before the viewport clip (issue #6308).
|
|
16
|
+
*
|
|
17
|
+
* Collapsed by default: renders one dim summary row (label · size · line count ·
|
|
18
|
+
* expand hint) and builds NO Markdown. The heavy {@link UserMessageComponent} is
|
|
19
|
+
* constructed lazily only when expanded via `ctrl+o`, so blocks above the
|
|
20
|
+
* viewport never pay layout cost until the reader asks to see them. The raw
|
|
21
|
+
* observability data stays intact in `__advisor.jsonl`.
|
|
22
|
+
*/
|
|
23
|
+
export declare class CollapsedSyntheticMessageComponent implements Component {
|
|
24
|
+
#private;
|
|
25
|
+
private readonly text;
|
|
26
|
+
private readonly imageLinks?;
|
|
27
|
+
constructor(text: string, imageLinks?: readonly (string | undefined)[] | undefined);
|
|
28
|
+
/** ctrl+o toggle: reveal/hide the full Markdown body. */
|
|
29
|
+
setExpanded(expanded: boolean): void;
|
|
30
|
+
invalidate(): void;
|
|
31
|
+
dispose(): void;
|
|
32
|
+
render(width: number): readonly string[];
|
|
33
|
+
}
|
|
@@ -12,6 +12,14 @@ export declare class ExtensionUiController {
|
|
|
12
12
|
* Initialize the hook system with TUI-based UI context.
|
|
13
13
|
*/
|
|
14
14
|
initHooksAndCustomTools(): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* The `ExtensionUIContext` built in `initHooksAndCustomTools()` — the same
|
|
17
|
+
* picker/dialog primitives passed as `context.ui` for every live tool
|
|
18
|
+
* call. `/tree` `ask` re-answer (issue #5642) reuses this to drive a
|
|
19
|
+
* standalone `AskTool.execute()` call outside a normal agent turn.
|
|
20
|
+
* `undefined` before hooks have initialized.
|
|
21
|
+
*/
|
|
22
|
+
getToolUIContext(): ExtensionUIContext | undefined;
|
|
15
23
|
setHookWidget(key: string, content: ExtensionWidgetContent, options?: ExtensionWidgetOptions): void;
|
|
16
24
|
initializeHookRunner(uiContext: ExtensionUIContext, _hasUI: boolean): void;
|
|
17
25
|
/**
|
|
@@ -128,6 +128,7 @@ export declare class InteractiveMode implements InteractiveModeContext {
|
|
|
128
128
|
proseOnlyThinking: boolean;
|
|
129
129
|
compactionQueuedMessages: CompactionQueuedMessage[];
|
|
130
130
|
pendingTools: Map<string, ToolExecutionHandle>;
|
|
131
|
+
transcriptMessageComponents: WeakMap<AgentMessage, Component>;
|
|
131
132
|
pendingBashComponents: BashExecutionComponent[];
|
|
132
133
|
bashComponent: BashExecutionComponent | undefined;
|
|
133
134
|
pendingPythonComponents: EvalExecutionComponent[];
|
|
@@ -228,7 +229,9 @@ export declare class InteractiveMode implements InteractiveModeContext {
|
|
|
228
229
|
syncRunningSubagentBadge(options?: {
|
|
229
230
|
requestRender?: boolean;
|
|
230
231
|
}): void;
|
|
231
|
-
rebuildChatFromMessages(
|
|
232
|
+
rebuildChatFromMessages(options?: {
|
|
233
|
+
reuseSettledComponents?: boolean;
|
|
234
|
+
}): void;
|
|
232
235
|
/**
|
|
233
236
|
* Render the ctrl+p model-role cycle chip track into its own anchored
|
|
234
237
|
* container (just above the editor), mirroring the todo HUD: the container is
|
|
@@ -301,10 +304,12 @@ export declare class InteractiveMode implements InteractiveModeContext {
|
|
|
301
304
|
addMessageToChat(message: AgentMessage, options?: {
|
|
302
305
|
populateHistory?: boolean;
|
|
303
306
|
imageLinks?: readonly (string | undefined)[];
|
|
307
|
+
reuseSettledComponent?: boolean;
|
|
304
308
|
}): Component[];
|
|
305
309
|
renderSessionContext(sessionContext: SessionContext, options?: {
|
|
306
310
|
updateFooter?: boolean;
|
|
307
311
|
populateHistory?: boolean;
|
|
312
|
+
reuseSettledComponents?: boolean;
|
|
308
313
|
}): void;
|
|
309
314
|
renderInitialMessages(options?: {
|
|
310
315
|
preserveExistingChat?: boolean;
|
|
@@ -399,6 +404,7 @@ export declare class InteractiveMode implements InteractiveModeContext {
|
|
|
399
404
|
openExternalEditor(): void;
|
|
400
405
|
registerExtensionShortcuts(): void;
|
|
401
406
|
initHooksAndCustomTools(): Promise<void>;
|
|
407
|
+
getToolUIContext(): ExtensionUIContext | undefined;
|
|
402
408
|
emitCustomToolSessionEvent(reason: "start" | "switch" | "branch" | "tree" | "shutdown", previousSessionFile?: string): Promise<void>;
|
|
403
409
|
setHookWidget(key: string, content: ExtensionWidgetContent, options?: ExtensionWidgetOptions): void;
|
|
404
410
|
setHookStatus(key: string, text: string | undefined): void;
|
|
@@ -156,6 +156,8 @@ export interface InteractiveModeContext {
|
|
|
156
156
|
noteDisplayableThinkingContent(message: AgentMessage): boolean;
|
|
157
157
|
proseOnlyThinking: boolean;
|
|
158
158
|
compactionQueuedMessages: CompactionQueuedMessage[];
|
|
159
|
+
/** Settled user/assistant components reusable across post-compaction transcript rebuilds. */
|
|
160
|
+
transcriptMessageComponents: WeakMap<AgentMessage, Component>;
|
|
159
161
|
pendingTools: Map<string, ToolExecutionHandle>;
|
|
160
162
|
pendingBashComponents: BashExecutionComponent[];
|
|
161
163
|
bashComponent: BashExecutionComponent | undefined;
|
|
@@ -280,10 +282,12 @@ export interface InteractiveModeContext {
|
|
|
280
282
|
addMessageToChat(message: AgentMessage, options?: {
|
|
281
283
|
populateHistory?: boolean;
|
|
282
284
|
imageLinks?: readonly (string | undefined)[];
|
|
285
|
+
reuseSettledComponent?: boolean;
|
|
283
286
|
}): Component[];
|
|
284
287
|
renderSessionContext(sessionContext: SessionContext, options?: {
|
|
285
288
|
updateFooter?: boolean;
|
|
286
289
|
populateHistory?: boolean;
|
|
290
|
+
reuseSettledComponents?: boolean;
|
|
287
291
|
}): void;
|
|
288
292
|
renderInitialMessages(options?: {
|
|
289
293
|
preserveExistingChat?: boolean;
|
|
@@ -295,7 +299,9 @@ export interface InteractiveModeContext {
|
|
|
295
299
|
/** Refresh the running-subagents status badge from the active local or collab registry. */
|
|
296
300
|
syncRunningSubagentBadge(): void;
|
|
297
301
|
updateEditorBorderColor(): void;
|
|
298
|
-
rebuildChatFromMessages(
|
|
302
|
+
rebuildChatFromMessages(options?: {
|
|
303
|
+
reuseSettledComponents?: boolean;
|
|
304
|
+
}): void;
|
|
299
305
|
setTodos(todos: TodoItem[] | TodoPhase[]): void;
|
|
300
306
|
reloadTodos(): Promise<void>;
|
|
301
307
|
toggleTodoExpansion(): void;
|
|
@@ -396,6 +402,13 @@ export interface InteractiveModeContext {
|
|
|
396
402
|
handlePlanApproval(details: PlanApprovalDetails): Promise<void>;
|
|
397
403
|
openPlanReview(): Promise<void>;
|
|
398
404
|
initHooksAndCustomTools(): Promise<void>;
|
|
405
|
+
/**
|
|
406
|
+
* The live `ExtensionUIContext` (picker/dialog primitives) used for tool
|
|
407
|
+
* execution, `undefined` before hooks have initialized. `/tree` `ask`
|
|
408
|
+
* re-answer (issue #5642) reuses it to drive a standalone
|
|
409
|
+
* `AskTool.execute()` call.
|
|
410
|
+
*/
|
|
411
|
+
getToolUIContext(): ExtensionUIContext | undefined;
|
|
399
412
|
emitCustomToolSessionEvent(reason: "start" | "switch" | "branch" | "tree" | "shutdown", previousSessionFile?: string): Promise<void>;
|
|
400
413
|
setHookWidget(key: string, content: ExtensionWidgetContent, options?: ExtensionWidgetOptions): void;
|
|
401
414
|
setHookStatus(key: string, text: string | undefined): void;
|
|
@@ -7,6 +7,16 @@ interface RenderInitialMessagesOptions {
|
|
|
7
7
|
preserveExistingChat?: boolean;
|
|
8
8
|
clearTerminalHistory?: boolean;
|
|
9
9
|
}
|
|
10
|
+
type AddMessageOptions = {
|
|
11
|
+
populateHistory?: boolean;
|
|
12
|
+
imageLinks?: readonly (string | undefined)[];
|
|
13
|
+
reuseSettledComponent?: boolean;
|
|
14
|
+
};
|
|
15
|
+
type RenderSessionContextOptions = {
|
|
16
|
+
updateFooter?: boolean;
|
|
17
|
+
populateHistory?: boolean;
|
|
18
|
+
reuseSettledComponents?: boolean;
|
|
19
|
+
};
|
|
10
20
|
export declare class UiHelpers {
|
|
11
21
|
#private;
|
|
12
22
|
private ctx;
|
|
@@ -22,20 +32,14 @@ export declare class UiHelpers {
|
|
|
22
32
|
showStatus(message: string, options?: {
|
|
23
33
|
dim?: boolean;
|
|
24
34
|
}): void;
|
|
25
|
-
addMessageToChat(message: AgentMessage, options?:
|
|
26
|
-
populateHistory?: boolean;
|
|
27
|
-
imageLinks?: readonly (string | undefined)[];
|
|
28
|
-
}): Component[];
|
|
35
|
+
addMessageToChat(message: AgentMessage, options?: AddMessageOptions): Component[];
|
|
29
36
|
/**
|
|
30
37
|
* Render session context to chat. Used for initial load and rebuild after compaction.
|
|
31
38
|
* @param sessionContext Session context to render
|
|
32
39
|
* @param options.updateFooter Update footer state
|
|
33
40
|
* @param options.populateHistory Add user messages to editor history
|
|
34
41
|
*/
|
|
35
|
-
renderSessionContext(sessionContext: SessionContext, options?:
|
|
36
|
-
updateFooter?: boolean;
|
|
37
|
-
populateHistory?: boolean;
|
|
38
|
-
}): void;
|
|
42
|
+
renderSessionContext(sessionContext: SessionContext, options?: RenderSessionContextOptions): void;
|
|
39
43
|
renderInitialMessages(options?: RenderInitialMessagesOptions): void;
|
|
40
44
|
clearEditor(): void;
|
|
41
45
|
showError(errorMessage: string): void;
|
package/dist/types/sdk.d.ts
CHANGED
|
@@ -359,6 +359,7 @@ export interface BuildSystemPromptOptions {
|
|
|
359
359
|
* as separate entries so providers can cache prompt prefixes without concatenating blocks.
|
|
360
360
|
*/
|
|
361
361
|
export declare function buildSystemPrompt(options?: BuildSystemPromptOptions): Promise<BuildSystemPromptResult>;
|
|
362
|
+
export declare function customToolToDefinition(tool: CustomTool): ToolDefinition;
|
|
362
363
|
/** Dependencies used to construct an isolated auto-learn capture agent. */
|
|
363
364
|
export interface AutoLearnCaptureRunnerOptions {
|
|
364
365
|
sourceAgent: Agent;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* Modes use this class and add their own I/O layer on top.
|
|
14
14
|
*/
|
|
15
15
|
import type { InMemorySnapshotStore } from "@oh-my-pi/hashline";
|
|
16
|
-
import { Agent, type AgentEvent, type AgentMessage, type AgentState, type AgentTool, type AgentToolResult, type StreamFn, ThinkingLevel, type ToolChoiceDirective } from "@oh-my-pi/pi-agent-core";
|
|
16
|
+
import { Agent, type AgentEvent, type AgentMessage, type AgentState, type AgentTool, type AgentToolContext, type AgentToolResult, type StreamFn, ThinkingLevel, type ToolChoiceDirective } from "@oh-my-pi/pi-agent-core";
|
|
17
17
|
import { type CompactionResult, type ShakeConfig } from "@oh-my-pi/pi-agent-core/compaction";
|
|
18
18
|
import type { AssistantMessage, Context, ImageContent, Message, MessageAttribution, Model, ProviderSessionState, ResetCreditAccountStatus, ResetCreditRedeemOutcome, ResetCreditTarget, ServiceTier, ServiceTierByFamily, ServiceTierFamily, SimpleStreamOptions, TextContent, ToolChoice, UsageReport } from "@oh-my-pi/pi-ai";
|
|
19
19
|
import { Effort } from "@oh-my-pi/pi-ai";
|
|
@@ -31,7 +31,7 @@ import { type BashResult } from "../exec/bash-executor.js";
|
|
|
31
31
|
import type { TtsrManager } from "../export/ttsr.js";
|
|
32
32
|
import type { LoadedCustomCommand } from "../extensibility/custom-commands/index.js";
|
|
33
33
|
import type { CustomTool } from "../extensibility/custom-tools/types.js";
|
|
34
|
-
import type { ExtensionRunner } from "../extensibility/extensions/index.js";
|
|
34
|
+
import type { ExtensionRunner, ExtensionUIContext } from "../extensibility/extensions/index.js";
|
|
35
35
|
import type { CompactOptions, ContextUsage } from "../extensibility/extensions/types.js";
|
|
36
36
|
import type { RecoveredRetryError } from "../extensibility/shared-events.js";
|
|
37
37
|
import { type Skill, type SkillWarning } from "../extensibility/skills.js";
|
|
@@ -45,6 +45,7 @@ import { type PlanApprovalDetails } from "../plan-mode/approved-plan.js";
|
|
|
45
45
|
import type { PlanModeState } from "../plan-mode/state.js";
|
|
46
46
|
import { type SecretObfuscator } from "../secrets/obfuscator.js";
|
|
47
47
|
import { type ConfiguredThinkingLevel } from "../thinking.js";
|
|
48
|
+
import { type AskToolDetails, type AskToolInput } from "../tools/ask.js";
|
|
48
49
|
import type { CheckpointState, CompletedRewindState } from "../tools/checkpoint.js";
|
|
49
50
|
import { type PlanProposalHandler } from "../tools/resolve.js";
|
|
50
51
|
import { type TodoItem, type TodoPhase } from "../tools/todo.js";
|
|
@@ -180,6 +181,15 @@ export interface PlanYolo {
|
|
|
180
181
|
target: Model;
|
|
181
182
|
thinkingLevel?: ConfiguredThinkingLevel;
|
|
182
183
|
}
|
|
184
|
+
/** Identifies a retry fallback chain already entered during startup model resolution. */
|
|
185
|
+
export interface InitialRetryFallbackState {
|
|
186
|
+
/** Role whose configured primary was unavailable. */
|
|
187
|
+
role: string;
|
|
188
|
+
/** Configured primary selector retained for restoration when it becomes available. */
|
|
189
|
+
originalSelector: string;
|
|
190
|
+
/** Thinking selector configured for the unavailable primary. */
|
|
191
|
+
originalThinkingLevel: ConfiguredThinkingLevel | undefined;
|
|
192
|
+
}
|
|
183
193
|
export interface AgentSessionConfig {
|
|
184
194
|
agent: Agent;
|
|
185
195
|
sessionManager: SessionManager;
|
|
@@ -193,6 +203,8 @@ export interface AgentSessionConfig {
|
|
|
193
203
|
}>;
|
|
194
204
|
/** Initial session thinking selector. */
|
|
195
205
|
thinkingLevel?: ConfiguredThinkingLevel;
|
|
206
|
+
/** Retry chain ownership when startup selected one of its fallback entries. */
|
|
207
|
+
initialRetryFallback?: InitialRetryFallbackState;
|
|
196
208
|
/** Prewalk from the starting model to a fast/cheap target at the first edit/write once the todo list exists. */
|
|
197
209
|
prewalk?: Prewalk;
|
|
198
210
|
/** Force read-only plan mode at start, auto-approve on the model's first
|
|
@@ -520,6 +532,15 @@ export type RestoredQueuedMessage = {
|
|
|
520
532
|
text: string;
|
|
521
533
|
images?: ImageContent[];
|
|
522
534
|
};
|
|
535
|
+
/**
|
|
536
|
+
* Emit a warn-level log for a turn that ended in a provider error so recurring
|
|
537
|
+
* stream failures are diagnosable from the main log alone. The `agent_end`
|
|
538
|
+
* routing trace is debug-only and omits the error fields; without this a
|
|
539
|
+
* session dying on provider errors leaves only `stopReason:"error"` debug lines
|
|
540
|
+
* and the real cause lives solely in the session transcript (issue #6177).
|
|
541
|
+
* No-op for any non-error stop reason.
|
|
542
|
+
*/
|
|
543
|
+
export declare function logProviderTurnError(msg: AssistantMessage): void;
|
|
523
544
|
type SessionNameTrigger = "replan";
|
|
524
545
|
export declare class AgentSession {
|
|
525
546
|
#private;
|
|
@@ -1215,6 +1236,16 @@ export declare class AgentSession {
|
|
|
1215
1236
|
/**
|
|
1216
1237
|
* Manually retry the last failed assistant turn.
|
|
1217
1238
|
* Removes the error message from agent state and re-attempts with a fresh retry budget.
|
|
1239
|
+
*
|
|
1240
|
+
* A stream that stalls or aborts mid-tool-call ends the turn with
|
|
1241
|
+
* `stopReason: "error" | "aborted"` and then appends one synthetic
|
|
1242
|
+
* {@link isSyntheticToolResultMessage tool_result} per emitted tool call to
|
|
1243
|
+
* preserve the provider's tool_use/tool_result pairing (see
|
|
1244
|
+
* `createAbortedToolResult` in `agent-loop.ts`). Those placeholders trail the
|
|
1245
|
+
* failed assistant turn, so the retry lookback walks back over them before
|
|
1246
|
+
* checking the assistant message; it strips both the placeholders and the
|
|
1247
|
+
* failed turn before re-attempting.
|
|
1248
|
+
*
|
|
1218
1249
|
* @returns true if retry was initiated, false if no failed turn to retry or agent is busy
|
|
1219
1250
|
*/
|
|
1220
1251
|
retry(): Promise<boolean>;
|
|
@@ -1380,6 +1411,26 @@ export declare class AgentSession {
|
|
|
1380
1411
|
navigateTree(targetId: string, options?: {
|
|
1381
1412
|
summarize?: boolean;
|
|
1382
1413
|
customInstructions?: string;
|
|
1414
|
+
/**
|
|
1415
|
+
* Opts into the two-phase `ask` toolResult re-answer protocol
|
|
1416
|
+
* (issue #5642): set only by the interactive `/tree` selector, which
|
|
1417
|
+
* knows how to re-open the picker on `reopenAsk` and complete the
|
|
1418
|
+
* navigation with `reanswerAskResult`. Every other public caller
|
|
1419
|
+
* (extensions, hooks, ACP, session-extension actions) leaves this
|
|
1420
|
+
* unset and gets the pre-#5642 plain leaf move onto `ask`
|
|
1421
|
+
* toolResults instead — they have no picker to re-open and would
|
|
1422
|
+
* otherwise report a successful no-op navigation (roboomp review on
|
|
1423
|
+
* #5895).
|
|
1424
|
+
*/
|
|
1425
|
+
allowAskReopen?: boolean;
|
|
1426
|
+
/**
|
|
1427
|
+
* Completes an in-progress `ask` re-answer (issue #5642): the caller
|
|
1428
|
+
* already received `reopenAsk` from a prior call on the same
|
|
1429
|
+
* `targetId`, re-opened the picker, and is handing back the fresh
|
|
1430
|
+
* answer. Branches a new toolResult sibling instead of landing on
|
|
1431
|
+
* the original one.
|
|
1432
|
+
*/
|
|
1433
|
+
reanswerAskResult?: AgentToolResult<AskToolDetails>;
|
|
1383
1434
|
}): Promise<{
|
|
1384
1435
|
editorText?: string;
|
|
1385
1436
|
cancelled: boolean;
|
|
@@ -1387,7 +1438,32 @@ export declare class AgentSession {
|
|
|
1387
1438
|
summaryEntry?: BranchSummaryEntry;
|
|
1388
1439
|
/** Raw session context built during navigation — pass to renderInitialMessages to skip a second O(N) walk. */
|
|
1389
1440
|
sessionContext?: SessionContext;
|
|
1441
|
+
/**
|
|
1442
|
+
* Set when `targetId` is an `ask` toolResult, `options.allowAskReopen`
|
|
1443
|
+
* was set, and `options.reanswerAskResult` was not supplied: nothing was
|
|
1444
|
+
* mutated. The caller must re-open the ask picker with these
|
|
1445
|
+
* `questions`, then call `navigateTree(targetId, { ...options,
|
|
1446
|
+
* reanswerAskResult })` with the produced result to actually branch
|
|
1447
|
+
* (issue #5642).
|
|
1448
|
+
*/
|
|
1449
|
+
reopenAsk?: {
|
|
1450
|
+
toolCallId: string;
|
|
1451
|
+
questions: AskToolInput["questions"];
|
|
1452
|
+
};
|
|
1390
1453
|
}>;
|
|
1454
|
+
/**
|
|
1455
|
+
* Build a standalone `AgentToolContext` for running `AskTool.execute()`
|
|
1456
|
+
* outside a normal agent turn, for `/tree` `ask` re-answer (issue #5642).
|
|
1457
|
+
* `SelectorController` has no reachable `ToolContextStore` (that store is
|
|
1458
|
+
* built inside `sdk.ts` and never threaded through to mode controllers),
|
|
1459
|
+
* so this mirrors `refreshMCPTools()`'s `getCustomToolContext` factory
|
|
1460
|
+
* with real session state instead of a `{ ... } as unknown as
|
|
1461
|
+
* AgentToolContext` cast that could silently compile with an incomplete
|
|
1462
|
+
* context (roboomp review on #5895) — every `CustomToolContext` field is
|
|
1463
|
+
* backed by live session state, so a future required field fails to
|
|
1464
|
+
* compile here instead of surfacing as `undefined` at runtime.
|
|
1465
|
+
*/
|
|
1466
|
+
buildAskReanswerContext(uiContext: ExtensionUIContext): AgentToolContext;
|
|
1391
1467
|
/**
|
|
1392
1468
|
* Get all user messages from session for branch selector.
|
|
1393
1469
|
*/
|
|
@@ -219,6 +219,16 @@ export declare const SUBAGENT_WARNING_MISSING_YIELD = "SYSTEM WARNING: Subagent
|
|
|
219
219
|
export declare function finalizeSubprocessOutput(args: FinalizeSubprocessOutputArgs): FinalizeSubprocessOutputResult;
|
|
220
220
|
/**
|
|
221
221
|
* Create proxy tools that reuse the parent's MCP connections.
|
|
222
|
+
*
|
|
223
|
+
* Each proxy delegates to the current source `MCPTool`/`DeferredMCPTool` rather
|
|
224
|
+
* than rebuilding a raw `tools/call` request, so the Task/subagent path shares
|
|
225
|
+
* the source tool's authoritative outbound boundary: harness-intent (`i`)
|
|
226
|
+
* stripping, optional-placeholder pruning, local-URL resolution, reconnect
|
|
227
|
+
* retry, abort handling, and result/provider metadata. The source tool is
|
|
228
|
+
* re-resolved on every call by raw MCP server/tool metadata (not the normalized
|
|
229
|
+
* display name), so a reconnect that swaps the instance in `getTools()` is
|
|
230
|
+
* always honored. The proxy adds only the Task-specific 60s call timeout,
|
|
231
|
+
* combining its abort signal with the caller's around source execution.
|
|
222
232
|
*/
|
|
223
233
|
export declare function createMCPProxyTools(mcpManager: MCPManager): CustomTool[];
|
|
224
234
|
export declare function createSubagentSettings(baseSettings: Settings, overrides?: Partial<Record<SettingPath, unknown>>, inheritedServiceTier?: ServiceTierByFamily | null): Settings;
|
|
@@ -66,6 +66,7 @@ export declare class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskT
|
|
|
66
66
|
readonly summary = "Spawn subagents to complete delegated tasks";
|
|
67
67
|
readonly strict = false;
|
|
68
68
|
readonly loadMode = "essential";
|
|
69
|
+
readonly lenientArgValidation = true;
|
|
69
70
|
readonly renderResult: typeof renderResult;
|
|
70
71
|
readonly mergeCallAndResult = true;
|
|
71
72
|
get parameters(): TaskToolSchemaInstance;
|
|
@@ -35,6 +35,16 @@ declare const askSchema: import("arktype/internal/variants/object.ts").ObjectTyp
|
|
|
35
35
|
}[];
|
|
36
36
|
}, {}>;
|
|
37
37
|
export type AskToolInput = typeof askSchema.infer;
|
|
38
|
+
/**
|
|
39
|
+
* Recover a validated `questions` payload from a persisted `ask` toolCall's
|
|
40
|
+
* `arguments`. Used by `/tree` re-answer (issue #5642): selecting a past
|
|
41
|
+
* `ask` toolResult re-opens the picker with the *original* questions, so the
|
|
42
|
+
* new answer branches as a sibling instead of mutating the old one. Runs the
|
|
43
|
+
* same schema the live tool call validated against — legacy/corrupted
|
|
44
|
+
* persisted args fail closed (`undefined`) rather than feeding malformed
|
|
45
|
+
* data back into the picker.
|
|
46
|
+
*/
|
|
47
|
+
export declare function recoverAskQuestions(toolCallArguments: unknown): AskToolInput["questions"] | undefined;
|
|
38
48
|
/** Result for a single question */
|
|
39
49
|
export interface QuestionResult {
|
|
40
50
|
id: string;
|
|
@@ -46,6 +46,12 @@ export declare const TOOL_TIMEOUTS: {
|
|
|
46
46
|
export type ToolWithTimeout = keyof typeof TOOL_TIMEOUTS;
|
|
47
47
|
/**
|
|
48
48
|
* Clamp a raw timeout to the allowed range for a tool.
|
|
49
|
-
*
|
|
49
|
+
*
|
|
50
|
+
* When `rawTimeout` is undefined the tool's `default` is used. A positive
|
|
51
|
+
* `maxTimeout` (the `tools.maxTimeout` global ceiling) caps the *resolved*
|
|
52
|
+
* value — including the default-fallback path — before the per-tool `min`/`max`
|
|
53
|
+
* floor and ceiling apply, so a configured global cap governs calls where the
|
|
54
|
+
* agent omits `timeout`, not only explicitly-passed values. `maxTimeout <= 0`
|
|
55
|
+
* means no global cap.
|
|
50
56
|
*/
|
|
51
|
-
export declare function clampTimeout(tool: ToolWithTimeout, rawTimeout?: number): number;
|
|
57
|
+
export declare function clampTimeout(tool: ToolWithTimeout, rawTimeout?: number, maxTimeout?: number): number;
|
|
@@ -23,13 +23,11 @@ export interface StartupChangelogSelection {
|
|
|
23
23
|
selectedEntries: number;
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
|
-
* Parse changelog entries from
|
|
27
|
-
*
|
|
26
|
+
* Parse changelog entries from omp's package asset when available, falling back
|
|
27
|
+
* to the copy embedded in compiled binaries.
|
|
28
28
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* synthesize a fallback path from the host project's cwd; doing so caused issue
|
|
32
|
-
* #1423 (the host project's `CHANGELOG.md` was rendered as omp's).
|
|
29
|
+
* The embedded fallback keeps standalone binaries self-contained without
|
|
30
|
+
* resolving relative to the host project's cwd, which caused issue #1423.
|
|
33
31
|
*/
|
|
34
32
|
export declare function parseChangelog(changelogPath: string | undefined): Promise<ChangelogEntry[]>;
|
|
35
33
|
/**
|