@oh-my-pi/pi-coding-agent 17.2.12 → 17.2.13
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 +57 -0
- package/dist/{CHANGELOG-k9ghy5sn.md → CHANGELOG-d8xh7keh.md} +57 -0
- package/dist/cli.js +3069 -3047
- package/dist/types/advisor/delta-split.d.ts +24 -0
- package/dist/types/advisor/runtime.d.ts +2 -2
- package/dist/types/async/job-manager.d.ts +8 -1
- package/dist/types/cli/update-cli.d.ts +53 -1
- package/dist/types/config/keybindings.d.ts +10 -0
- package/dist/types/config/model-resolver.d.ts +15 -2
- package/dist/types/config/settings-schema.d.ts +4 -0
- package/dist/types/discovery/agents-md.d.ts +10 -1
- package/dist/types/eval/runner-cache.d.ts +12 -0
- package/dist/types/extensibility/extensions/runner.d.ts +12 -3
- package/dist/types/extensibility/extensions/types.d.ts +15 -4
- package/dist/types/extensibility/plugins/marketplace/manager.d.ts +4 -1
- package/dist/types/lib/xai-http.d.ts +0 -1
- package/dist/types/mcp/tool-bridge.d.ts +8 -5
- package/dist/types/modes/components/agent-hub-renderer.d.ts +6 -1
- package/dist/types/modes/components/status-line/types.d.ts +4 -0
- package/dist/types/modes/controllers/extension-ui-controller.d.ts +2 -4
- package/dist/types/modes/interactive-mode.d.ts +17 -8
- package/dist/types/modes/types.d.ts +7 -10
- package/dist/types/modes/utils/hotkeys-markdown.d.ts +1 -1
- package/dist/types/session/agent-session-types.d.ts +2 -0
- package/dist/types/session/agent-session.d.ts +22 -3
- package/dist/types/session/messages.d.ts +20 -0
- package/dist/types/session/retry-fallback-chains.d.ts +13 -0
- package/dist/types/session/session-advisors.d.ts +1 -1
- package/dist/types/session/session-history-format.d.ts +10 -0
- package/dist/types/session/session-maintenance.d.ts +1 -1
- package/dist/types/session/session-tools.d.ts +24 -5
- package/dist/types/session/turn-recovery.d.ts +34 -5
- package/dist/types/slash-commands/types.d.ts +5 -1
- package/dist/types/task/executor.d.ts +1 -1
- package/dist/types/tools/approval.d.ts +7 -0
- package/dist/types/tools/todo.d.ts +14 -15
- package/dist/types/tools/write.d.ts +2 -2
- package/dist/types/utils/local-date.d.ts +2 -0
- package/dist/types/vibe/runtime.d.ts +1 -1
- package/dist/types/web/parallel.d.ts +1 -0
- package/dist/types/web/search/providers/brave.d.ts +8 -3
- package/dist/types/web/search/providers/codex.d.ts +6 -0
- package/dist/types/web/search/providers/firecrawl.d.ts +3 -2
- package/dist/types/web/search/providers/jina.d.ts +3 -3
- package/dist/types/web/search/providers/parallel.d.ts +1 -0
- package/dist/types/web/search/providers/perplexity.d.ts +4 -0
- package/dist/types/web/search/providers/tinyfish.d.ts +2 -0
- package/package.json +13 -13
- package/src/advisor/delta-split.ts +98 -0
- package/src/advisor/runtime.ts +321 -69
- package/src/async/job-manager.ts +14 -3
- package/src/cli/plugin-cli.ts +30 -2
- package/src/cli/update-cli.ts +259 -24
- package/src/config/keybindings.ts +52 -9
- package/src/config/model-resolver.ts +19 -3
- package/src/config/settings-schema.ts +5 -0
- package/src/cursor.ts +10 -5
- package/src/discovery/agents-md.ts +61 -23
- package/src/eval/jl/kernel.ts +2 -20
- package/src/eval/py/kernel.ts +2 -20
- package/src/eval/rb/kernel.ts +2 -20
- package/src/eval/runner-cache.ts +41 -0
- package/src/exec/non-interactive-env.ts +14 -3
- package/src/extensibility/extensions/loader.ts +5 -2
- package/src/extensibility/extensions/runner.ts +184 -66
- package/src/extensibility/extensions/types.ts +26 -2
- package/src/extensibility/extensions/wrapper.ts +13 -7
- package/src/extensibility/plugins/marketplace/manager.ts +6 -2
- package/src/hindsight/client.ts +1 -1
- package/src/lib/xai-http.ts +0 -4
- package/src/lsp/client.ts +2 -0
- package/src/lsp/servers.ts +1 -1
- package/src/mcp/tool-bridge.ts +15 -6
- package/src/modes/components/agent-hub-renderer.ts +9 -3
- package/src/modes/components/agent-hub.ts +2 -1
- package/src/modes/components/status-line/component.ts +58 -6
- package/src/modes/components/status-line/segments.ts +12 -1
- package/src/modes/components/status-line/types.ts +1 -0
- package/src/modes/components/user-message.ts +20 -5
- package/src/modes/controllers/event-controller.ts +48 -0
- package/src/modes/controllers/extension-ui-controller.ts +14 -7
- package/src/modes/controllers/input-controller.ts +25 -6
- package/src/modes/interactive-mode.ts +315 -129
- package/src/modes/rpc/rpc-frame.ts +13 -5
- package/src/modes/theme/tui-adapters.ts +4 -5
- package/src/modes/types.ts +13 -7
- package/src/modes/utils/hotkeys-markdown.ts +10 -6
- package/src/prompts/system/system-prompt.md +1 -1
- package/src/registry/persisted-agents.ts +43 -8
- package/src/sdk.ts +139 -8
- package/src/session/agent-session-types.ts +2 -0
- package/src/session/agent-session.ts +66 -10
- package/src/session/messages.ts +98 -28
- package/src/session/retry-fallback-chains.ts +14 -0
- package/src/session/session-advisors.ts +32 -15
- package/src/session/session-history-format.ts +15 -1
- package/src/session/session-maintenance.ts +8 -8
- package/src/session/session-manager.ts +6 -2
- package/src/session/session-tools.ts +321 -184
- package/src/session/turn-recovery.ts +225 -47
- package/src/slash-commands/builtin-modes.ts +41 -12
- package/src/slash-commands/types.ts +5 -1
- package/src/task/executor.ts +92 -45
- package/src/task/structured-subagent.ts +5 -5
- package/src/tools/approval.ts +44 -10
- package/src/tools/fetch.ts +21 -2
- package/src/tools/image-gen.ts +6 -8
- package/src/tools/todo.ts +70 -26
- package/src/tools/tts.ts +3 -2
- package/src/tools/write.ts +7 -3
- package/src/utils/local-date.ts +13 -0
- package/src/utils/tools-manager.ts +2 -2
- package/src/vibe/runtime.ts +22 -14
- package/src/web/kagi.ts +91 -34
- package/src/web/parallel.ts +11 -2
- package/src/web/scrapers/crates-io.ts +2 -2
- package/src/web/scrapers/discogs.ts +2 -2
- package/src/web/scrapers/docs-rs.ts +2 -2
- package/src/web/scrapers/github.ts +2 -2
- package/src/web/scrapers/musicbrainz.ts +1 -2
- package/src/web/scrapers/pubmed.ts +2 -2
- package/src/web/scrapers/sec-edgar.ts +2 -2
- package/src/web/search/providers/brave.ts +121 -46
- package/src/web/search/providers/codex.ts +88 -12
- package/src/web/search/providers/exa.ts +45 -10
- package/src/web/search/providers/firecrawl.ts +53 -11
- package/src/web/search/providers/gemini.ts +139 -27
- package/src/web/search/providers/jina.ts +48 -25
- package/src/web/search/providers/parallel.ts +23 -9
- package/src/web/search/providers/perplexity.ts +24 -7
- package/src/web/search/providers/searxng.ts +77 -1
- package/src/web/search/providers/tavily.ts +23 -22
- package/src/web/search/providers/tinyfish.ts +44 -10
- package/src/web/search/providers/xai.ts +85 -14
|
@@ -37,6 +37,19 @@ export interface ActiveRetryFallbackState {
|
|
|
37
37
|
originalThinkingLevel: ConfiguredThinkingLevel | undefined;
|
|
38
38
|
lastAppliedFallbackThinkingLevel: ConfiguredThinkingLevel | undefined;
|
|
39
39
|
pinned: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Set once a turn on the fallback target settles successfully. Until then the
|
|
42
|
+
* switch is only a routing decision — nothing has been produced by the new
|
|
43
|
+
* model, so no observer may report the run as having used it.
|
|
44
|
+
*/
|
|
45
|
+
served?: boolean;
|
|
46
|
+
}
|
|
47
|
+
/** Model a session's produced work is attributed to. */
|
|
48
|
+
export interface ServingModel {
|
|
49
|
+
/** Full selector including routing and thinking level. */
|
|
50
|
+
selector: string;
|
|
51
|
+
/** Whether fallback routing, rather than the configured primary, owns it. */
|
|
52
|
+
isFallback: boolean;
|
|
40
53
|
}
|
|
41
54
|
/** Calculates capped exponential retry delay with downward jitter. */
|
|
42
55
|
export declare function calculateRetryBackoffDelayMs(baseDelayMs: number, attempt: number): number;
|
|
@@ -180,7 +180,7 @@ export declare class SessionAdvisors {
|
|
|
180
180
|
*/
|
|
181
181
|
refreshProviderIdentity(): void;
|
|
182
182
|
/** Re-primes advisor transcript views after an in-conversation history rewrite. */
|
|
183
|
-
resetAllRuntimes(): void;
|
|
183
|
+
resetAllRuntimes(reason?: string): void;
|
|
184
184
|
/** Whether live runtimes still match the resolved advisor configuration. */
|
|
185
185
|
runtimeMatchesCurrentConfig(): boolean;
|
|
186
186
|
/** Whether concern/blocker delivery is inside the post-interrupt immunity window. */
|
|
@@ -34,6 +34,16 @@ export interface HistoryFormatOptions {
|
|
|
34
34
|
*/
|
|
35
35
|
toolResultIndex?: ReadonlyMap<string, ToolResultMessage>;
|
|
36
36
|
consumedToolCallIds?: Set<string>;
|
|
37
|
+
/**
|
|
38
|
+
* Chunked rendering state: a mutable holder for the watched-role label
|
|
39
|
+
* (`**user**:` / `**agent**:`) that ended the previous chunk. Lets a caller
|
|
40
|
+
* formatting one logical transcript across several calls (advisor
|
|
41
|
+
* multi-message split) keep consecutive same-role collapsing byte-identical
|
|
42
|
+
* to the single-block render: pass one object across all chunk calls.
|
|
43
|
+
*/
|
|
44
|
+
watchedRoleState?: {
|
|
45
|
+
lastLabel: string | undefined;
|
|
46
|
+
};
|
|
37
47
|
}
|
|
38
48
|
export declare function formatExecutionSourcePreview(source: string): string;
|
|
39
49
|
/** Pick the most informative scalar argument of a tool call. */
|
|
@@ -85,7 +85,7 @@ export interface SessionMaintenanceHost {
|
|
|
85
85
|
resetCodexProviderAfterCompaction(compaction: CodexCompactionContext): void;
|
|
86
86
|
resetPlanReference(): void;
|
|
87
87
|
syncTodoPhasesFromBranch(): void;
|
|
88
|
-
resetAdvisorRuntimes(): void;
|
|
88
|
+
resetAdvisorRuntimes(reason?: string): void;
|
|
89
89
|
rebaseAfterCompaction(): void;
|
|
90
90
|
recordAnchoredHistoryRewrite(tokensRemoved: number): void;
|
|
91
91
|
getContextBreakdown(options?: {
|
|
@@ -47,6 +47,8 @@ interface SessionToolsOptions {
|
|
|
47
47
|
createInspectImageTool?: () => Promise<AgentTool | null>;
|
|
48
48
|
builtInToolNames?: Iterable<string>;
|
|
49
49
|
presentationPinnedToolNames?: ReadonlySet<string>;
|
|
50
|
+
/** MCP tool names whose current registry entries came from the manager snapshot. */
|
|
51
|
+
mcpManagerToolNames?: Iterable<string>;
|
|
50
52
|
ensureWriteRegistered?: () => Promise<boolean>;
|
|
51
53
|
rebuildSystemPrompt?: (toolNames: string[], tools: Map<string, AgentTool>) => Promise<{
|
|
52
54
|
systemPrompt: string[];
|
|
@@ -138,6 +140,20 @@ export declare class SessionTools {
|
|
|
138
140
|
getToolByName(name: string): AgentTool | undefined;
|
|
139
141
|
/** Whether a registry entry came from a built-in factory. */
|
|
140
142
|
hasBuiltInTool(name: string): boolean;
|
|
143
|
+
/** Updates source provenance when a live registry entry is replaced or restored. */
|
|
144
|
+
setToolBuiltIn(name: string, builtIn: boolean): void;
|
|
145
|
+
/** Whether the live registry entry is owned by the RPC host. */
|
|
146
|
+
hasRpcHostTool(name: string): boolean;
|
|
147
|
+
/** Whether the current MCP entry came from the manager snapshot. */
|
|
148
|
+
hasMCPManagerTool(name: string): boolean;
|
|
149
|
+
/** Restores manager ownership after a lifecycle registration rollback. */
|
|
150
|
+
setMCPManagerTool(name: string, managerOwned: boolean): void;
|
|
151
|
+
/** Current extension-owned MCP entry retained across manager refreshes. */
|
|
152
|
+
getExtensionMCPTool(name: string): AgentTool | undefined;
|
|
153
|
+
/** Updates extension ownership when a lifecycle registration commits or rolls back. */
|
|
154
|
+
setExtensionMCPTool(name: string, tool: AgentTool | undefined): void;
|
|
155
|
+
/** Serializes every registry and presentation mutation for this session. */
|
|
156
|
+
runToolRegistryMutation<T>(mutation: () => Promise<T>, signal?: AbortSignal): Promise<T>;
|
|
141
157
|
/** Names of every registered tool. */
|
|
142
158
|
getAllToolNames(): string[];
|
|
143
159
|
/**
|
|
@@ -162,7 +178,7 @@ export declare class SessionTools {
|
|
|
162
178
|
/** Enabled MCP tools in their current presentation partition. */
|
|
163
179
|
getSelectedMCPToolNames(): string[];
|
|
164
180
|
/** Applies an enabled tool set and reconciles its `xd://` partition. */
|
|
165
|
-
applyActiveToolsByName(toolNames: string[]): Promise<void>;
|
|
181
|
+
applyActiveToolsByName(toolNames: string[], forcePromptRefresh?: boolean, signal?: AbortSignal): Promise<void>;
|
|
166
182
|
/**
|
|
167
183
|
* Forget the announced-mount baseline for a replaced transcript. Called when
|
|
168
184
|
* session history is swapped wholesale (`/new`, `switchSession`, `branch`): the
|
|
@@ -192,11 +208,14 @@ export declare class SessionTools {
|
|
|
192
208
|
* `xd://` remain mount-eligible, even when the live mount set has drifted.
|
|
193
209
|
*
|
|
194
210
|
* Names outside `mountedToolNames` are pinned top-level for this application;
|
|
195
|
-
* names in the mounted subset remain eligible for xdev mounting.
|
|
196
|
-
*
|
|
197
|
-
*
|
|
211
|
+
* names in the mounted subset remain eligible for xdev mounting. Set
|
|
212
|
+
* `forcePromptRefresh` when an enabled tool's schema or prompt-visible metadata
|
|
213
|
+
* changed without changing its name or presentation.
|
|
214
|
+
*
|
|
215
|
+
* Delegates the actual apply through {@link applyActiveToolsByName} and restores
|
|
216
|
+
* the prior runtime selection if that apply throws.
|
|
198
217
|
*/
|
|
199
|
-
setActiveToolPresentation(toolNames: string[], mountedToolNames: string[]): Promise<void>;
|
|
218
|
+
setActiveToolPresentation(toolNames: string[], mountedToolNames: string[], forcePromptRefresh?: boolean, signal?: AbortSignal): Promise<void>;
|
|
200
219
|
/** Replaces memory-backend tools while preserving unrelated selections. */
|
|
201
220
|
replaceMemoryTools(tools: AgentTool[]): Promise<void>;
|
|
202
221
|
/**
|
|
@@ -5,7 +5,7 @@ import type { Settings } from "../config/settings.js";
|
|
|
5
5
|
import { type ConfiguredThinkingLevel } from "../thinking.js";
|
|
6
6
|
import type { AgentSessionEvent } from "./agent-session-events.js";
|
|
7
7
|
import type { InitialRetryFallbackState, UsageFallbackConfirmer } from "./agent-session-types.js";
|
|
8
|
-
import { type RetryFallbackSelector } from "./retry-fallback-chains.js";
|
|
8
|
+
import { type RetryFallbackSelector, type ServingModel } from "./retry-fallback-chains.js";
|
|
9
9
|
import type { SessionManager } from "./session-manager.js";
|
|
10
10
|
/** Result shape shared with automatic maintenance recovery. */
|
|
11
11
|
export interface RecoveryCompactionResult {
|
|
@@ -77,13 +77,42 @@ export declare class TurnRecovery {
|
|
|
77
77
|
get attempt(): number;
|
|
78
78
|
/** Promise settled when the active retry saga finishes. */
|
|
79
79
|
get retryPromise(): Promise<void> | undefined;
|
|
80
|
-
/**
|
|
81
|
-
|
|
80
|
+
/**
|
|
81
|
+
* Model this session's produced work is attributed to.
|
|
82
|
+
*
|
|
83
|
+
* A model switch is a routing decision, not evidence the target can produce
|
|
84
|
+
* anything: a candidate that errors on its first request produced none of the
|
|
85
|
+
* turns already in this session. So attribution only ever names a model that
|
|
86
|
+
* has settled a turn here, and a switch — into a fallback, back to a restored
|
|
87
|
+
* primary, or anywhere else — moves it only once the new model answers.
|
|
88
|
+
*
|
|
89
|
+
* Before anything has served there is no earlier work to miscredit, so the
|
|
90
|
+
* configured model is both the only available answer and a safe one.
|
|
91
|
+
*/
|
|
92
|
+
get servingModel(): ServingModel | undefined;
|
|
93
|
+
/**
|
|
94
|
+
* Carries attribution onto a new session id that continues this conversation.
|
|
95
|
+
*
|
|
96
|
+
* The session-id anchor assumes a new id means an unrelated transcript, which
|
|
97
|
+
* holds for `/new` and for resuming something else. A fork breaks that
|
|
98
|
+
* assumption on purpose: it clones the transcript and keeps running the same
|
|
99
|
+
* recovery state under a fresh id. Dropping attribution there would bootstrap
|
|
100
|
+
* an unproven fallback as the primary and re-credit it with the work the
|
|
101
|
+
* previous model did — the very bug the anchor exists to prevent.
|
|
102
|
+
*
|
|
103
|
+
* Only state belonging to `previousSessionId` moves, so an id left behind by
|
|
104
|
+
* an earlier switch stays expired.
|
|
105
|
+
*/
|
|
106
|
+
reanchorServedAttribution(previousSessionId: string): void;
|
|
82
107
|
/** Resets per-prompt recovery counters and terminal-stop acceptance. */
|
|
83
108
|
resetForNewPrompt(): void;
|
|
84
109
|
/** Sets whether one terminal empty stop is accepted for the current prompt. */
|
|
85
110
|
setAcceptTerminalEmptyStop(accept: boolean): void;
|
|
86
|
-
/**
|
|
111
|
+
/**
|
|
112
|
+
* Records which model produced this turn, marks an active fallback as having
|
|
113
|
+
* served, then closes a successful retry saga and annotates recovered
|
|
114
|
+
* persisted errors.
|
|
115
|
+
*/
|
|
87
116
|
onAssistantSettledSuccessfully(message: AssistantMessage): Promise<void>;
|
|
88
117
|
/** Closes a failed retry saga when no compaction continuation took ownership. */
|
|
89
118
|
onErrorSettledWithoutRetry(message: AssistantMessage, compaction: RecoveryCompactionResult): Promise<void>;
|
|
@@ -170,7 +199,7 @@ export declare class TurnRecovery {
|
|
|
170
199
|
classifyResolvedInterruptedToolTurn(message: AssistantMessage): "reasonless-abort" | "stream-stall" | undefined;
|
|
171
200
|
/** Checks whether a provider error represents a classifier refusal. */
|
|
172
201
|
isClassifierRefusal(message: AssistantMessage): boolean;
|
|
173
|
-
/** Clears fallback ownership after an explicit model change. */
|
|
202
|
+
/** Clears fallback ownership after an explicit model change or a restore. */
|
|
174
203
|
clearActiveRetryFallback(): void;
|
|
175
204
|
/** Checks whether a fallback selector remains in cooldown. */
|
|
176
205
|
isRetryFallbackSelectorSuppressed(selector: RetryFallbackSelector): boolean;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Settings } from "../config/settings.js";
|
|
2
|
-
import type { InteractiveModeContext } from "../modes/types.js";
|
|
2
|
+
import type { InteractiveModeContext, SubmittedUserInput } from "../modes/types.js";
|
|
3
3
|
import type { AgentSession } from "../session/agent-session.js";
|
|
4
4
|
import type { SessionManager } from "../session/session-manager.js";
|
|
5
5
|
/** Declarative subcommand definition for commands like /mcp. */
|
|
@@ -81,6 +81,10 @@ export interface SlashCommandRuntime {
|
|
|
81
81
|
*/
|
|
82
82
|
export interface TuiSlashCommandRuntime {
|
|
83
83
|
ctx: InteractiveModeContext;
|
|
84
|
+
/** Post-extension-hook attachments belonging to the submitted slash draft. */
|
|
85
|
+
input?: Pick<SubmittedUserInput, "images" | "imageLinks">;
|
|
86
|
+
/** The editor snapshot was cleared before asynchronous input hooks ran. */
|
|
87
|
+
draftDetached?: boolean;
|
|
84
88
|
}
|
|
85
89
|
/** Unified slash-command spec consumed by both TUI and ACP dispatchers. */
|
|
86
90
|
export interface SlashCommandSpec extends BuiltinSlashCommand {
|
|
@@ -253,7 +253,7 @@ export declare function finalizeSubprocessOutput(args: FinalizeSubprocessOutputA
|
|
|
253
253
|
*/
|
|
254
254
|
export declare function createMCPProxyTools(mcpManager: MCPManager): CustomTool[];
|
|
255
255
|
export declare function createSubagentSettings(baseSettings: Settings, overrides?: Partial<Record<SettingPath, unknown>>, inheritedServiceTier?: ServiceTierByFamily | null): Settings;
|
|
256
|
-
export type AbortReason = "signal" | "terminate" | "timeout" | "budget";
|
|
256
|
+
export type AbortReason = "signal" | "shutdown" | "terminate" | "timeout" | "budget";
|
|
257
257
|
/** Inputs for {@link attachIrcWakeTurnMonitor}. */
|
|
258
258
|
export interface IrcWakeTurnMonitorOptions {
|
|
259
259
|
/** Registry id of the kept-alive subagent whose autonomous IRC wake turns are monitored. */
|
|
@@ -17,6 +17,8 @@ export interface ResolvedApproval {
|
|
|
17
17
|
reason?: string;
|
|
18
18
|
override: boolean;
|
|
19
19
|
source?: "tool" | "user" | "mode";
|
|
20
|
+
/** User-policy key that produced `source: "user"` (defaults to the tool name). */
|
|
21
|
+
policyKey?: string;
|
|
20
22
|
}
|
|
21
23
|
/**
|
|
22
24
|
* Evaluate a tool's own approval declaration against `args` and return the
|
|
@@ -31,6 +33,11 @@ export declare function resolveToolTier(tool: ApprovalSubject, args: unknown): T
|
|
|
31
33
|
*
|
|
32
34
|
* Resolution order:
|
|
33
35
|
* 1. Tool `approval(args)` decision, defaulting to tier "exec" when omitted.
|
|
36
|
+
* A decision may carry a `policyKey` — `tools.approval.<policyKey>` is then
|
|
37
|
+
* the user override consulted instead of `tools.approval.<tool.name>`, with
|
|
38
|
+
* the invoking tool's own policy as the fallback when the user set none for
|
|
39
|
+
* the keyed sub-tool (e.g. an `xd://` device dispatch without a device
|
|
40
|
+
* policy still honors `tools.approval.write`).
|
|
34
41
|
* 2. User per-tool override, if set and valid.
|
|
35
42
|
* 3. Active mode tier comparison.
|
|
36
43
|
*
|
|
@@ -74,6 +74,12 @@ export declare function getLatestTodoPhasesFromEntries(entries: SessionEntry[]):
|
|
|
74
74
|
* the contained side.
|
|
75
75
|
*/
|
|
76
76
|
export declare function todoMatchesAnyDescription(content: string, descriptions: readonly string[]): boolean;
|
|
77
|
+
/** Whether a todo is settled: completed or deliberately abandoned. Shared so
|
|
78
|
+
* the collapsed viewport, the HUD progress counters, and the HUD's closed-todo
|
|
79
|
+
* auto-clear can never disagree about what "done" hides. */
|
|
80
|
+
export declare function isClosedTodo<T extends {
|
|
81
|
+
status: TodoStatus;
|
|
82
|
+
}>(task: T): boolean;
|
|
77
83
|
/** Result of {@link selectCollapsedTodos}: the rows to render plus an optional
|
|
78
84
|
* summary line (empty string ⇒ no summary row). */
|
|
79
85
|
export interface CollapsedTodoSelection<T> {
|
|
@@ -83,22 +89,15 @@ export interface CollapsedTodoSelection<T> {
|
|
|
83
89
|
/**
|
|
84
90
|
* Walking-viewport selection for a phase's collapsed todo preview (#5873).
|
|
85
91
|
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* an ordinary window.
|
|
93
|
-
* 3. Remaining rows up to `cap` are filled with the pending tasks that follow
|
|
94
|
-
* the first active one, in todo order (falling back to leading pending tasks
|
|
95
|
-
* when no active task exists), so a freshly-promoted task leads the preview.
|
|
96
|
-
* 4. When active tasks alone exceed `cap`, only the first `cap` active tasks are
|
|
97
|
-
* shown and the summary counts the hidden *active* todos, never replacing
|
|
98
|
-
* them with unrelated pending rows.
|
|
92
|
+
* Applied to `tasks` in todo order: the open tasks run through
|
|
93
|
+
* {@link selectWithinCap}, led by the last {@link COLLAPSED_CLOSED_CONTEXT}
|
|
94
|
+
* closed tasks in todo order so a checked row remains visible even when callers
|
|
95
|
+
* complete work out of sequence. The lead is additive — it never costs an open
|
|
96
|
+
* row — and a phase with no open work left falls back to its closed tasks so the
|
|
97
|
+
* sticky HUD's closed-todo persistence still has something to render.
|
|
99
98
|
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
99
|
+
* `summary` counts the open tasks that did not fit; the closed lead is context,
|
|
100
|
+
* not part of the budget.
|
|
102
101
|
*/
|
|
103
102
|
export declare function selectCollapsedTodos<T extends {
|
|
104
103
|
status: TodoStatus;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback,
|
|
1
|
+
import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback, ToolApprovalDecision } from "@oh-my-pi/pi-agent-core";
|
|
2
2
|
import { type Component } from "@oh-my-pi/pi-tui";
|
|
3
3
|
import type { RenderResultOptions } from "../extensibility/custom-tools/types.js";
|
|
4
4
|
import { type FileDiagnosticsResult } from "../lsp/index.js";
|
|
@@ -36,7 +36,7 @@ export declare class WriteTool implements AgentTool<typeof writeSchema, WriteToo
|
|
|
36
36
|
#private;
|
|
37
37
|
private readonly session;
|
|
38
38
|
readonly name = "write";
|
|
39
|
-
readonly approval: (args: unknown) =>
|
|
39
|
+
readonly approval: (args: unknown) => ToolApprovalDecision;
|
|
40
40
|
readonly formatApprovalDetails: (args: unknown) => string[];
|
|
41
41
|
readonly label = "Write";
|
|
42
42
|
readonly description: string;
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
/** formatLocalCalendarDate formats a Date as YYYY-MM-DD in the host local timezone. */
|
|
2
2
|
export declare function formatLocalCalendarDate(date?: Date): string;
|
|
3
|
+
/** Format a local date and minute with a compact numeric UTC offset. */
|
|
4
|
+
export declare function formatLocalDateTimeWithOffset(date: Date): string;
|
|
@@ -7,7 +7,7 @@ export type VibeCli = "fast" | "good";
|
|
|
7
7
|
* CLI flavor → bundled agent type. This IS the model-tier mapping: `sonic`
|
|
8
8
|
* carries `model: "@smol"` (the configured fast/low-latency role) and `task`
|
|
9
9
|
* carries `model: "@task"` (inherits the session's strong model).
|
|
10
|
-
* Resolution goes through {@link
|
|
10
|
+
* Resolution goes through {@link resolveAgentModelSelection} exactly like a
|
|
11
11
|
* `task` spawn, so `task.agentModelOverrides` and model-role settings apply.
|
|
12
12
|
*/
|
|
13
13
|
export declare const VIBE_CLI_AGENT: Record<VibeCli, string>;
|
|
@@ -58,6 +58,7 @@ export declare class ParallelApiError extends Error {
|
|
|
58
58
|
constructor(message: string, statusCode?: number);
|
|
59
59
|
}
|
|
60
60
|
export declare function parseParallelErrorResponse(statusCode: number, responseText: string): ParallelApiError;
|
|
61
|
+
export declare function parseParallelJsonResponse(response: Response, operation: "search" | "extract"): Promise<unknown>;
|
|
61
62
|
export declare function parseParallelSearchPayload(payload: unknown, options?: {
|
|
62
63
|
parseMetadata?: boolean;
|
|
63
64
|
}): ParallelSearchResult;
|
|
@@ -14,18 +14,23 @@ export interface BraveSearchParams {
|
|
|
14
14
|
num_results?: number;
|
|
15
15
|
recency?: "day" | "week" | "month" | "year";
|
|
16
16
|
parsedQuery?: StructuredQuery;
|
|
17
|
+
/** Two-letter market code, or `ALL`. */
|
|
18
|
+
country?: string;
|
|
19
|
+
/** Brave search language code, such as `en` or `zh-hans`. */
|
|
20
|
+
search_lang?: string;
|
|
21
|
+
safesearch?: "off" | "moderate" | "strict";
|
|
22
|
+
authStorage: AuthStorage;
|
|
23
|
+
sessionId?: string;
|
|
17
24
|
signal?: AbortSignal;
|
|
18
25
|
timeoutMs?: number;
|
|
19
26
|
fetch?: FetchImpl;
|
|
20
27
|
}
|
|
21
|
-
/** Find BRAVE_API_KEY from environment or .env files. */
|
|
22
|
-
export declare function findApiKey(): string | null;
|
|
23
28
|
/** Execute Brave web search. */
|
|
24
29
|
export declare function searchBrave(params: BraveSearchParams): Promise<SearchResponse>;
|
|
25
30
|
/** Search provider for Brave web search. */
|
|
26
31
|
export declare class BraveProvider extends SearchProvider {
|
|
27
32
|
readonly id = "brave";
|
|
28
33
|
readonly label = "Brave";
|
|
29
|
-
isAvailable(
|
|
34
|
+
isAvailable(authStorage: AuthStorage): boolean;
|
|
30
35
|
search(params: SearchParams): Promise<SearchResponse>;
|
|
31
36
|
}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI Codex Web Search Provider
|
|
3
|
+
*
|
|
4
|
+
* Uses the configured Codex Responses transport for proxy/API-key setups and
|
|
5
|
+
* the official ChatGPT backend for OAuth logins.
|
|
6
|
+
*/
|
|
1
7
|
import { type AuthStorage, type FetchImpl } from "@oh-my-pi/pi-ai";
|
|
2
8
|
import type { SearchResponse } from "../../../web/search/types.js";
|
|
3
9
|
import type { SearchParams } from "./base.js";
|
|
@@ -27,8 +27,9 @@ export declare class FirecrawlProvider extends SearchProvider {
|
|
|
27
27
|
readonly id = "firecrawl";
|
|
28
28
|
readonly label = "Firecrawl";
|
|
29
29
|
/**
|
|
30
|
-
* Auto-chain admission
|
|
31
|
-
*
|
|
30
|
+
* Auto-chain admission requires either a credential or an explicitly
|
|
31
|
+
* configured self-hosted endpoint. Hosted keyless mode remains explicit-only
|
|
32
|
+
* so it does not displace providers the user configured.
|
|
32
33
|
*/
|
|
33
34
|
isAvailable(authStorage: AuthStorage): boolean;
|
|
34
35
|
/**
|
|
@@ -13,6 +13,8 @@ type SearchParamsWithFetch = SearchParams & {
|
|
|
13
13
|
};
|
|
14
14
|
export interface JinaSearchParams {
|
|
15
15
|
query: string;
|
|
16
|
+
authStorage: AuthStorage;
|
|
17
|
+
sessionId?: string;
|
|
16
18
|
num_results?: number;
|
|
17
19
|
/** Single bare host for Jina's `X-Site` in-site search header. */
|
|
18
20
|
site?: string;
|
|
@@ -20,15 +22,13 @@ export interface JinaSearchParams {
|
|
|
20
22
|
timeoutMs?: number;
|
|
21
23
|
fetch?: FetchImpl;
|
|
22
24
|
}
|
|
23
|
-
/** Find JINA_API_KEY from environment or .env files. */
|
|
24
|
-
export declare function findApiKey(): string | null;
|
|
25
25
|
/** Execute Jina web search. */
|
|
26
26
|
export declare function searchJina(params: JinaSearchParams): Promise<SearchResponse>;
|
|
27
27
|
/** Search provider for Jina Reader. */
|
|
28
28
|
export declare class JinaProvider extends SearchProvider {
|
|
29
29
|
readonly id = "jina";
|
|
30
30
|
readonly label = "Jina";
|
|
31
|
-
isAvailable(
|
|
31
|
+
isAvailable(authStorage: AuthStorage): boolean;
|
|
32
32
|
search(params: SearchParamsWithFetch): Promise<SearchResponse>;
|
|
33
33
|
}
|
|
34
34
|
export {};
|
|
@@ -19,7 +19,11 @@ export interface PerplexitySearchParams {
|
|
|
19
19
|
system_prompt?: string;
|
|
20
20
|
/** Pre-parsed view of `query` from the search pipeline; parsed locally when absent. */
|
|
21
21
|
parsedQuery?: StructuredQuery;
|
|
22
|
+
/** Direct API model. Defaults to `PI_PERPLEXITY_API_MODEL`, then `sonar-pro`. */
|
|
23
|
+
api_model?: string;
|
|
22
24
|
search_recency_filter?: "hour" | "day" | "week" | "month" | "year";
|
|
25
|
+
/** Consumer subscription model preference. Defaults to `PI_PERPLEXITY_MODEL`, then Sonar (`experimental`). */
|
|
26
|
+
subscription_model?: string;
|
|
23
27
|
num_results?: number;
|
|
24
28
|
/** Maximum output tokens. Defaults to 8192. */
|
|
25
29
|
max_tokens?: number;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-coding-agent",
|
|
4
|
-
"version": "17.2.
|
|
4
|
+
"version": "17.2.13",
|
|
5
5
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -50,18 +50,18 @@
|
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@babel/parser": "^7.29.7",
|
|
53
|
-
"@oh-my-pi/hashline": "17.2.
|
|
54
|
-
"@oh-my-pi/omp-stats": "17.2.
|
|
55
|
-
"@oh-my-pi/omptype": "17.2.
|
|
56
|
-
"@oh-my-pi/pi-agent-core": "17.2.
|
|
57
|
-
"@oh-my-pi/pi-ai": "17.2.
|
|
58
|
-
"@oh-my-pi/pi-catalog": "17.2.
|
|
59
|
-
"@oh-my-pi/pi-mnemopi": "17.2.
|
|
60
|
-
"@oh-my-pi/pi-natives": "17.2.
|
|
61
|
-
"@oh-my-pi/pi-tui": "17.2.
|
|
62
|
-
"@oh-my-pi/pi-utils": "17.2.
|
|
63
|
-
"@oh-my-pi/pi-wire": "17.2.
|
|
64
|
-
"@oh-my-pi/snapcompact": "17.2.
|
|
53
|
+
"@oh-my-pi/hashline": "17.2.13",
|
|
54
|
+
"@oh-my-pi/omp-stats": "17.2.13",
|
|
55
|
+
"@oh-my-pi/omptype": "17.2.13",
|
|
56
|
+
"@oh-my-pi/pi-agent-core": "17.2.13",
|
|
57
|
+
"@oh-my-pi/pi-ai": "17.2.13",
|
|
58
|
+
"@oh-my-pi/pi-catalog": "17.2.13",
|
|
59
|
+
"@oh-my-pi/pi-mnemopi": "17.2.13",
|
|
60
|
+
"@oh-my-pi/pi-natives": "17.2.13",
|
|
61
|
+
"@oh-my-pi/pi-tui": "17.2.13",
|
|
62
|
+
"@oh-my-pi/pi-utils": "17.2.13",
|
|
63
|
+
"@oh-my-pi/pi-wire": "17.2.13",
|
|
64
|
+
"@oh-my-pi/snapcompact": "17.2.13",
|
|
65
65
|
"@opentelemetry/api": "^1.9.1",
|
|
66
66
|
"@opentelemetry/api-logs": "^0.220.0",
|
|
67
67
|
"@opentelemetry/context-async-hooks": "^2.9.0",
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// Candidate 4 (multi-message split) pure renderer, extracted for direct unit
|
|
2
|
+
// testing. Renders an advisor delta as MULTIPLE user messages — one per source
|
|
3
|
+
// message — instead of one ever-growing user message, so the provider prompt
|
|
4
|
+
// cache can incrementally hit each appended message. Provider caches are
|
|
5
|
+
// prefix-based: a single user message whose text keeps growing invalidates the
|
|
6
|
+
// whole message on every turn, pinning cache_read at the instructions/tools
|
|
7
|
+
// boundary (observed 14491 in production, 11066 in tests). Splitting into
|
|
8
|
+
// per-source user messages grows cache_read with the session (verified
|
|
9
|
+
// experimentally: 11066 → 11091 → 11112).
|
|
10
|
+
//
|
|
11
|
+
// Each source message is rendered INDEPENDENTLY via formatSessionHistoryMarkdown
|
|
12
|
+
// in chunked mode (shared toolResultIndex + consumedToolCallIds + watchedRoleState
|
|
13
|
+
// over the WHOLE delta), so toolCall/toolResult pairings resolve across chunk
|
|
14
|
+
// boundaries and consecutive same-role collapsing is byte-identical to the old
|
|
15
|
+
// single-block render. Concatenating the chunk texts reproduces the old advisor
|
|
16
|
+
// context exactly (equivalence-tested).
|
|
17
|
+
//
|
|
18
|
+
// The heading stays on the FIRST chunk; the WIP marker stays on the LAST chunk
|
|
19
|
+
// (candidate 3) so a wip/final flip never changes the stable prefix.
|
|
20
|
+
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
21
|
+
import type { TextContent, ToolResultMessage } from "@oh-my-pi/pi-ai";
|
|
22
|
+
import { formatSessionHistoryMarkdown } from "../session/session-history-format";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Obfuscation surface the split renderer needs: a single text redaction pass.
|
|
26
|
+
* Narrowed from the full SecretObfuscator class to the method actually
|
|
27
|
+
* consumed, so tests can satisfy the contract with a typed helper instead of
|
|
28
|
+
* an `as any` escape. A SecretObfuscator instance is structurally assignable.
|
|
29
|
+
*/
|
|
30
|
+
export interface AdvisorObfuscator {
|
|
31
|
+
obfuscate(text: string, sharedRegexSecretValues?: ReadonlySet<string>): string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Render options shared by the advisor single-block and multi-message paths. */
|
|
35
|
+
export const ADVISOR_RENDER_OPTIONS = {
|
|
36
|
+
includeToolIntent: true,
|
|
37
|
+
watchedRoles: true,
|
|
38
|
+
expandPrimaryContext: true,
|
|
39
|
+
expandEditDiffs: true,
|
|
40
|
+
} as const;
|
|
41
|
+
|
|
42
|
+
export interface RenderAdvisorDeltaChunksOptions {
|
|
43
|
+
wip: boolean;
|
|
44
|
+
includeThinking: boolean;
|
|
45
|
+
obfuscator?: AdvisorObfuscator;
|
|
46
|
+
advisorRegexSecretValues: ReadonlySet<string>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function renderAdvisorDeltaChunks(
|
|
50
|
+
delta: AgentMessage[],
|
|
51
|
+
opts: RenderAdvisorDeltaChunksOptions,
|
|
52
|
+
): AgentMessage[] | null {
|
|
53
|
+
if (delta.length === 0) return null;
|
|
54
|
+
|
|
55
|
+
const resultsByCallId = new Map<string, ToolResultMessage>();
|
|
56
|
+
for (const msg of delta) {
|
|
57
|
+
if (msg.role === "toolResult") resultsByCallId.set(msg.toolCallId, msg);
|
|
58
|
+
}
|
|
59
|
+
const consumed = new Set<string>();
|
|
60
|
+
const watchedRoleState = { lastLabel: undefined as string | undefined };
|
|
61
|
+
|
|
62
|
+
const renderChunk = (chunk: AgentMessage[]): string =>
|
|
63
|
+
formatSessionHistoryMarkdown(chunk, {
|
|
64
|
+
...ADVISOR_RENDER_OPTIONS,
|
|
65
|
+
includeThinking: opts.includeThinking,
|
|
66
|
+
toolResultIndex: resultsByCallId,
|
|
67
|
+
consumedToolCallIds: consumed,
|
|
68
|
+
watchedRoleState,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const heading = "### Session update";
|
|
72
|
+
// Concrete local chunk type: content blocks are minted here, so the WIP
|
|
73
|
+
// marker append below is a plain field access (no double-cast).
|
|
74
|
+
const chunks: { role: "user"; content: TextContent[]; timestamp: number }[] = [];
|
|
75
|
+
for (let i = 0; i < delta.length; i++) {
|
|
76
|
+
const text = renderChunk([delta[i]]);
|
|
77
|
+
if (!text.trim()) continue;
|
|
78
|
+
chunks.push({ role: "user", content: [{ type: "text", text }], timestamp: Date.now() });
|
|
79
|
+
}
|
|
80
|
+
if (chunks.length === 0) return null;
|
|
81
|
+
if (opts.obfuscator) {
|
|
82
|
+
const fullText = chunks.map(chunk => chunk.content[0].text).join("\n");
|
|
83
|
+
const individuallyObfuscated = chunks.map(chunk =>
|
|
84
|
+
opts.obfuscator!.obfuscate(chunk.content[0].text, opts.advisorRegexSecretValues),
|
|
85
|
+
);
|
|
86
|
+
if (opts.obfuscator.obfuscate(fullText, opts.advisorRegexSecretValues) !== individuallyObfuscated.join("\n")) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
for (let i = 0; i < chunks.length; i++) chunks[i].content[0].text = individuallyObfuscated[i];
|
|
90
|
+
}
|
|
91
|
+
chunks[0].content[0].text = `${heading}\n\n${chunks[0].content[0].text}`;
|
|
92
|
+
if (chunks.length === 0) return null;
|
|
93
|
+
if (opts.wip) {
|
|
94
|
+
const last = chunks[chunks.length - 1];
|
|
95
|
+
last.content[0].text += `\n\n---\n\n[in progress — more steps follow]`;
|
|
96
|
+
}
|
|
97
|
+
return chunks as AgentMessage[];
|
|
98
|
+
}
|