@oh-my-pi/pi-coding-agent 15.11.3 → 15.11.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/dist/cli.js +692 -607
  3. package/dist/types/cli/usage-cli.d.ts +10 -1
  4. package/dist/types/commands/usage.d.ts +9 -0
  5. package/dist/types/config/api-key-resolver.d.ts +9 -3
  6. package/dist/types/config/keybindings.d.ts +1 -1
  7. package/dist/types/config/model-discovery.d.ts +6 -4
  8. package/dist/types/config/model-registry.d.ts +7 -4
  9. package/dist/types/config/settings-schema.d.ts +508 -155
  10. package/dist/types/export/html/template.generated.d.ts +1 -1
  11. package/dist/types/mnemopi/config.d.ts +3 -1
  12. package/dist/types/modes/components/reset-usage-selector.d.ts +12 -0
  13. package/dist/types/modes/components/session-selector.d.ts +1 -1
  14. package/dist/types/modes/components/settings-defs.d.ts +9 -2
  15. package/dist/types/modes/components/settings-selector.d.ts +9 -4
  16. package/dist/types/modes/components/tool-execution.d.ts +26 -1
  17. package/dist/types/modes/components/transcript-container.d.ts +12 -0
  18. package/dist/types/modes/controllers/input-controller.d.ts +9 -1
  19. package/dist/types/modes/controllers/selector-controller.d.ts +1 -0
  20. package/dist/types/modes/interactive-mode.d.ts +10 -0
  21. package/dist/types/modes/session-observer-registry.d.ts +2 -0
  22. package/dist/types/modes/theme/theme.d.ts +23 -3
  23. package/dist/types/modes/types.d.ts +2 -0
  24. package/dist/types/modes/utils/context-usage.d.ts +6 -1
  25. package/dist/types/session/agent-session.d.ts +28 -8
  26. package/dist/types/session/auth-storage.d.ts +1 -1
  27. package/dist/types/session/codex-auto-reset.d.ts +107 -0
  28. package/dist/types/session/snapcompact-inline.d.ts +129 -0
  29. package/dist/types/slash-commands/helpers/active-oauth-account.d.ts +14 -0
  30. package/dist/types/slash-commands/helpers/reset-usage.d.ts +27 -0
  31. package/dist/types/system-prompt.d.ts +3 -1
  32. package/dist/types/task/render.d.ts +17 -6
  33. package/dist/types/tools/gh.d.ts +3 -0
  34. package/dist/types/tools/render-utils.d.ts +8 -16
  35. package/dist/types/tools/todo.d.ts +0 -11
  36. package/dist/types/utils/session-color.d.ts +15 -3
  37. package/dist/types/web/kagi.d.ts +1 -2
  38. package/dist/types/web/search/providers/codex.d.ts +1 -1
  39. package/dist/types/web/search/providers/gemini.d.ts +9 -6
  40. package/package.json +11 -11
  41. package/src/auto-thinking/classifier.ts +1 -5
  42. package/src/cli/usage-cli.ts +187 -16
  43. package/src/commands/usage.ts +8 -0
  44. package/src/commit/model-selection.ts +3 -6
  45. package/src/config/api-key-resolver.ts +10 -3
  46. package/src/config/keybindings.ts +1 -1
  47. package/src/config/model-discovery.ts +60 -46
  48. package/src/config/model-registry.ts +21 -8
  49. package/src/config/model-resolver.ts +57 -3
  50. package/src/config/settings-schema.ts +654 -153
  51. package/src/config/settings.ts +9 -0
  52. package/src/eval/completion-bridge.ts +1 -5
  53. package/src/export/html/template.generated.ts +1 -1
  54. package/src/export/html/template.js +13 -6
  55. package/src/internal-urls/docs-index.generated.ts +6 -6
  56. package/src/internal-urls/issue-pr-protocol.ts +10 -4
  57. package/src/memories/index.ts +2 -10
  58. package/src/mnemopi/backend.ts +30 -8
  59. package/src/mnemopi/config.ts +6 -1
  60. package/src/mnemopi/state.ts +6 -0
  61. package/src/modes/components/extensions/inspector-panel.ts +6 -2
  62. package/src/modes/components/plan-review-overlay.ts +15 -17
  63. package/src/modes/components/plugin-settings.ts +22 -5
  64. package/src/modes/components/reset-usage-selector.ts +161 -0
  65. package/src/modes/components/session-selector.ts +8 -2
  66. package/src/modes/components/settings-defs.ts +19 -4
  67. package/src/modes/components/settings-selector.ts +510 -95
  68. package/src/modes/components/status-line/component.ts +3 -1
  69. package/src/modes/components/status-line/segments.ts +3 -1
  70. package/src/modes/components/tool-execution.ts +87 -12
  71. package/src/modes/components/transcript-container.ts +49 -1
  72. package/src/modes/components/tree-selector.ts +16 -6
  73. package/src/modes/controllers/command-controller.ts +61 -8
  74. package/src/modes/controllers/event-controller.ts +1 -0
  75. package/src/modes/controllers/input-controller.ts +68 -6
  76. package/src/modes/controllers/selector-controller.ts +149 -61
  77. package/src/modes/interactive-mode.ts +63 -2
  78. package/src/modes/rpc/rpc-mode.ts +2 -1
  79. package/src/modes/session-observer-registry.ts +61 -3
  80. package/src/modes/shared.ts +2 -0
  81. package/src/modes/theme/theme.ts +102 -9
  82. package/src/modes/types.ts +2 -0
  83. package/src/modes/utils/context-usage.ts +78 -2
  84. package/src/modes/utils/hotkeys-markdown.ts +1 -1
  85. package/src/modes/utils/ui-helpers.ts +9 -5
  86. package/src/prompts/system/personalities/default.md +26 -0
  87. package/src/prompts/system/personalities/friendly.md +17 -0
  88. package/src/prompts/system/personalities/pragmatic.md +15 -0
  89. package/src/prompts/system/snapcompact-context-frames-note.md +1 -0
  90. package/src/prompts/system/snapcompact-context-stub.md +1 -0
  91. package/src/prompts/system/snapcompact-system-frames-note.md +1 -0
  92. package/src/prompts/system/snapcompact-system-stub.md +1 -0
  93. package/src/prompts/system/snapcompact-toolresult-note.md +1 -0
  94. package/src/prompts/system/system-prompt.md +5 -22
  95. package/src/prompts/tools/browser.md +33 -43
  96. package/src/prompts/tools/eval.md +27 -50
  97. package/src/prompts/tools/irc.md +29 -31
  98. package/src/prompts/tools/read.md +31 -37
  99. package/src/prompts/tools/task.md +3 -3
  100. package/src/prompts/tools/todo.md +1 -2
  101. package/src/sdk.ts +23 -1
  102. package/src/session/agent-session.ts +221 -29
  103. package/src/session/auth-storage.ts +4 -0
  104. package/src/session/codex-auto-reset.ts +190 -0
  105. package/src/session/session-dump-format.ts +8 -1
  106. package/src/session/session-manager.ts +5 -5
  107. package/src/session/snapcompact-inline.ts +524 -0
  108. package/src/slash-commands/builtin-registry.ts +145 -8
  109. package/src/slash-commands/helpers/active-oauth-account.ts +44 -0
  110. package/src/slash-commands/helpers/context-report.ts +28 -1
  111. package/src/slash-commands/helpers/reset-usage.ts +66 -0
  112. package/src/slash-commands/helpers/usage-report.ts +36 -3
  113. package/src/system-prompt.ts +15 -1
  114. package/src/task/index.ts +30 -7
  115. package/src/task/render.ts +57 -32
  116. package/src/tool-discovery/tool-index.ts +2 -0
  117. package/src/tools/bash.ts +10 -3
  118. package/src/tools/eval-render.ts +13 -8
  119. package/src/tools/gh.ts +39 -1
  120. package/src/tools/image-gen.ts +114 -78
  121. package/src/tools/inspect-image.ts +1 -5
  122. package/src/tools/job.ts +25 -5
  123. package/src/tools/read.ts +1 -57
  124. package/src/tools/render-utils.ts +29 -31
  125. package/src/tools/ssh.ts +3 -3
  126. package/src/tools/todo.ts +8 -128
  127. package/src/tools/tts.ts +40 -20
  128. package/src/utils/clipboard.ts +56 -4
  129. package/src/utils/commit-message-generator.ts +1 -5
  130. package/src/utils/session-color.ts +83 -9
  131. package/src/utils/title-generator.ts +1 -1
  132. package/src/web/kagi.ts +26 -27
  133. package/src/web/search/providers/codex.ts +42 -40
  134. package/src/web/search/providers/gemini.ts +42 -22
  135. package/src/web/search/providers/perplexity.ts +22 -10
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Snapcompact inline imaging: per-request transform that swaps the system
3
+ * prompt, loaded context-file instructions, and/or large historical tool
4
+ * results for dense PNG frames on vision-capable models.
5
+ * Runs inside the agent loop's `transformProviderContext` hook — after the
6
+ * persisted history is converted to the outgoing `Context`, before the
7
+ * provider stream call. It only ever builds NEW message objects/arrays; the
8
+ * input context shares `content` array references with the persisted
9
+ * `SessionMessageEntry` messages, so mutation would leak rendered images
10
+ * into session.jsonl.
11
+ *
12
+ * The swap policy (budget, savings gate, skip rules) lives in
13
+ * `planInlineSwaps`, shared by the transform and the `/context` savings
14
+ * estimate (`estimateInlineSavings`) so the two can never disagree.
15
+ */
16
+ import type { Context, Model } from "@oh-my-pi/pi-ai";
17
+ import * as snapcompact from "@oh-my-pi/snapcompact";
18
+ export type SnapcompactSystemPromptMode = "none" | "agents-md" | "all";
19
+ export interface SnapcompactInlineOptions {
20
+ renderSystemPrompt: SnapcompactSystemPromptMode;
21
+ renderToolResults: boolean;
22
+ }
23
+ /** Tool-result swap candidate, in context order. */
24
+ export interface InlineToolResultCandidate {
25
+ /** toolCallId — stable identity for render caching and application. */
26
+ id: string;
27
+ /** Token count of the joined text blocks (0 when empty or image-carrying). */
28
+ textTokens: number;
29
+ /** Frames needed to render the text (0 = empty or below the token floor). */
30
+ frames: number;
31
+ /** Already carries an image (screenshot etc.) — never re-imaged. */
32
+ hasImage: boolean;
33
+ }
34
+ export interface InlineSystemPromptCandidate {
35
+ textTokens: number;
36
+ frames: number;
37
+ }
38
+ export interface InlinePlanInput {
39
+ options: SnapcompactInlineOptions;
40
+ shape: snapcompact.Shape;
41
+ /** Provider image-count budget minus images already present in the context. */
42
+ budget: number;
43
+ /** All tool results in context order, INCLUDING the most recent one. */
44
+ toolResults: readonly InlineToolResultCandidate[];
45
+ /** Selected prompt text; undefined when system-prompt imaging is off or empty. */
46
+ systemPrompt: InlineSystemPromptCandidate | undefined;
47
+ /** Whether a user message exists to carry the prompt frames. */
48
+ hasUserMessage: boolean;
49
+ }
50
+ export interface InlineSwapPlan {
51
+ /** Tool results to swap, oldest first. */
52
+ toolResults: Array<{
53
+ id: string;
54
+ textTokens: number;
55
+ frames: number;
56
+ }>;
57
+ /** Set when the system prompt should swap to frames (uses leftover budget). */
58
+ systemPrompt: InlineSystemPromptCandidate | undefined;
59
+ }
60
+ /**
61
+ * Decide which content gets swapped for frames. Pure — the same rules drive
62
+ * the provider-request transform and the /context savings estimate.
63
+ */
64
+ export declare function planInlineSwaps(input: InlinePlanInput): InlineSwapPlan;
65
+ /**
66
+ * Minimal structural view of a history message — both pi-ai `Message`s (the
67
+ * outgoing context) and agent-core `AgentMessage`s (the live session) satisfy
68
+ * it, so the estimator can read session state without conversion.
69
+ */
70
+ export interface InlineMessageView {
71
+ role: string;
72
+ toolCallId?: string;
73
+ content?: unknown;
74
+ }
75
+ export interface SnapcompactSavingsEstimate {
76
+ /** Frames only ship on models that accept image input. */
77
+ visionCapable: boolean;
78
+ /** Present iff system-prompt imaging is enabled. */
79
+ systemPrompt?: {
80
+ applied: boolean;
81
+ /** Why the prompt stays text when `applied` is false. */
82
+ reason?: "empty" | "margin" | "budget";
83
+ textTokens: number;
84
+ frames: number;
85
+ /** Estimated billed tokens for the frames (0 when there are none). */
86
+ imageTokens: number;
87
+ savedTokens: number;
88
+ scope: Exclude<SnapcompactSystemPromptMode, "none">;
89
+ };
90
+ /** Present iff tool-result imaging is enabled. */
91
+ toolResults?: {
92
+ /** Tool results currently in history. */
93
+ total: number;
94
+ swapped: number;
95
+ /** Text tokens of the swapped results only. */
96
+ textTokens: number;
97
+ frames: number;
98
+ imageTokens: number;
99
+ savedTokens: number;
100
+ };
101
+ /** Net estimated wire savings for the next request. */
102
+ savedTokens: number;
103
+ }
104
+ /**
105
+ * Estimate what `SnapcompactInlineTransformer.transform` would save on the
106
+ * NEXT request, given the session's live system prompt and message history.
107
+ *
108
+ * Mirrors the transform exactly via `planInlineSwaps`, with one deliberate
109
+ * difference: `hasUserMessage` is assumed true, because the request being
110
+ * estimated is always triggered by a user prompt — even when the current
111
+ * history is still empty.
112
+ */
113
+ export declare function estimateInlineSavings(input: {
114
+ options: SnapcompactInlineOptions;
115
+ model: Model | undefined;
116
+ systemPrompt: readonly string[];
117
+ messages: readonly InlineMessageView[];
118
+ }): SnapcompactSavingsEstimate;
119
+ /**
120
+ * Stateless with respect to the model (passed per call, so mid-session model
121
+ * switches re-resolve shape and budget); stateful only for the render caches,
122
+ * which live as long as the session's Agent.
123
+ */
124
+ export declare class SnapcompactInlineTransformer {
125
+ #private;
126
+ private readonly options;
127
+ constructor(options: SnapcompactInlineOptions);
128
+ transform(context: Context, model: Model): Context;
129
+ }
@@ -0,0 +1,14 @@
1
+ import type { UsageLimit, UsageReport } from "@oh-my-pi/pi-ai";
2
+ import type { OAuthAccountIdentity } from "../../session/auth-storage";
3
+ /**
4
+ * True when a single usage-limit column belongs to the given OAuth identity.
5
+ *
6
+ * Single definition of the matching rules for both `/usage` renderers:
7
+ * - `accountId` ↔ report metadata `accountId`/`account_id` or `limit.scope.accountId`
8
+ * - `email` ↔ report metadata `email`
9
+ * - `projectId` ↔ report metadata `projectId` or `limit.scope.projectId`
10
+ * (Google-style providers key usage on the GCP project, not an account id)
11
+ */
12
+ export declare function limitMatchesActiveAccount(report: UsageReport, limit: UsageLimit, identity: OAuthAccountIdentity | undefined): boolean;
13
+ /** True when any limit column in `report` belongs to the given OAuth identity. */
14
+ export declare function reportMatchesActiveAccount(report: UsageReport, identity: OAuthAccountIdentity | undefined): boolean;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Shared helpers for the `/usage reset` command (TUI selector + ACP): turn the
3
+ * live per-account reset-credit status into selector rows, and map a redeem
4
+ * outcome code to a human message.
5
+ */
6
+ import type { ResetCreditAccountStatus, ResetCreditRedeemOutcome, ResetCreditTarget } from "../../session/auth-storage";
7
+ export declare const CODEX_PROVIDER_ID = "openai-codex";
8
+ /** One Codex account row for the reset-usage selector. */
9
+ export interface ResetUsageAccount {
10
+ /** Display label (email, else account id). */
11
+ label: string;
12
+ /** Saved resets redeemable for this account right now. */
13
+ availableCount: number;
14
+ /** Identifies the account when redeeming. */
15
+ target: ResetCreditTarget;
16
+ /** Whether this is the session's active Codex account. */
17
+ active: boolean;
18
+ /** Set when this account could not be reached (token/list failure). */
19
+ error?: string;
20
+ }
21
+ /**
22
+ * Map live per-account reset status to selector rows. Sorted with the active
23
+ * account first, then most-credits, then label.
24
+ */
25
+ export declare function toResetUsageAccounts(statuses: ResetCreditAccountStatus[]): ResetUsageAccount[];
26
+ /** Human-facing summary of a redeem outcome for status lines and ACP output. */
27
+ export declare function describeRedeemOutcome(outcome: ResetCreditRedeemOutcome, label: string): string;
@@ -2,7 +2,7 @@
2
2
  * System prompt construction and project context loading
3
3
  */
4
4
  import type { AgentTool } from "@oh-my-pi/pi-agent-core";
5
- import type { SkillsSettings } from "./config/settings";
5
+ import type { Personality, SkillsSettings } from "./config/settings";
6
6
  import { type Skill } from "./extensibility/skills";
7
7
  import { type WorkspaceTree } from "./workspace-tree";
8
8
  interface AlwaysApplyRule {
@@ -88,6 +88,8 @@ export interface BuildSystemPromptOptions {
88
88
  memoryRootEnabled?: boolean;
89
89
  /** Active model identifier (e.g. "anthropic/claude-opus-4") surfaced to the agent. */
90
90
  model?: string;
91
+ /** Personality preset rendered into the default system prompt. "none" omits the block. Default: "default" */
92
+ personality?: Personality;
91
93
  }
92
94
  /** Result of building provider-facing system prompt messages. */
93
95
  export interface BuildSystemPromptResult {
@@ -2,14 +2,24 @@ import type { Component } from "@oh-my-pi/pi-tui";
2
2
  import type { RenderResultOptions } from "../extensibility/custom-tools/types";
3
3
  import { type Theme } from "../modes/theme/theme";
4
4
  import type { TaskParams, TaskToolDetails } from "./types";
5
+ /** Render context threaded in from `ToolExecutionComponent.#buildRenderContext`. */
6
+ interface TaskRenderContext {
7
+ hasResult?: boolean;
8
+ /**
9
+ * The block left the transcript live region (detached spawn the transcript
10
+ * has moved past, or a sealed block): progress rows render static gray, so
11
+ * commit-eligible rows do not repaint after entering native scrollback.
12
+ */
13
+ frozen?: boolean;
14
+ }
15
+ type TaskRenderOptions = RenderResultOptions & {
16
+ renderContext?: TaskRenderContext;
17
+ };
18
+ export declare function formatTaskId(id: string): string;
5
19
  /**
6
20
  * Render the tool call arguments.
7
21
  */
8
- export declare function renderCall(args: TaskParams, options: RenderResultOptions & {
9
- renderContext?: {
10
- hasResult?: boolean;
11
- };
12
- }, theme: Theme): Component;
22
+ export declare function renderCall(args: TaskParams, options: TaskRenderOptions, theme: Theme): Component;
13
23
  /**
14
24
  * Render the tool result.
15
25
  */
@@ -20,9 +30,10 @@ export declare function renderResult(result: {
20
30
  }>;
21
31
  details?: TaskToolDetails;
22
32
  isError?: boolean;
23
- }, options: RenderResultOptions, theme: Theme, args?: TaskParams): Component;
33
+ }, options: TaskRenderOptions, theme: Theme, args?: TaskParams): Component;
24
34
  export declare const taskToolRenderer: {
25
35
  renderCall: typeof renderCall;
26
36
  renderResult: typeof renderResult;
27
37
  mergeCallAndResult: boolean;
28
38
  };
39
+ export {};
@@ -1,9 +1,12 @@
1
1
  import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback, ToolApprovalDecision } from "@oh-my-pi/pi-agent-core";
2
2
  import * as z from "zod/v4";
3
3
  import type { Settings } from "../config/settings";
4
+ import * as git from "../utils/git";
4
5
  import type { ToolSession } from ".";
5
6
  import { type CacheStatus } from "./github-cache";
6
7
  import type { OutputMeta } from "./output-meta";
8
+ /** Runs `gh --json` for issue data, retrying without optional stateReason on older gh releases. */
9
+ export declare function githubIssueJsonWithStateReasonFallback<T>(cwd: string, args: readonly string[], signal: AbortSignal | undefined, options?: git.GhCommandOptions): Promise<T>;
7
10
  declare const githubSchema: z.ZodObject<{
8
11
  op: z.ZodEnum<{
9
12
  pr_checkout: "pr_checkout";
@@ -76,24 +76,16 @@ export declare function formatBadge(label: string, color: ToolUIColor, theme: Th
76
76
  * Uses consistent wording pattern.
77
77
  */
78
78
  export declare function formatMoreItems(remaining: number, itemType: string): string;
79
+ /** Tail-window height for collapsed command/code previews. */
80
+ export declare function previewWindowRows(): number;
79
81
  /**
80
- * Maximum rows a tool's streaming/pending *call* preview may render before it is
81
- * capped. This is intentionally conservative: the preview still sits inside a
82
- * transcript that already consumed some viewport rows, and tool blocks carry
83
- * extra chrome (status/header/border/"more lines"), so a "reasonable" raw code
84
- * or command preview like 10-12 lines can still overflow and strand its top
85
- * while the block is volatile. Keeping the live call window short avoids that
86
- * across terminals without turning the transcript into an interactive scroller.
87
- */
88
- export declare const CALL_PREVIEW_MAX_LINES = 6;
89
- /**
90
- * Cap a pre-rendered pending/call preview to a bounded window. When truncated,
91
- * show both the head and the live tail so the user can still see what the tool
92
- * is currently writing while the volatile block stays short enough not to strand
93
- * its top above the viewport. `Ctrl+O` widens the bounded window, but does not
94
- * fully uncap live tool previews for the same reason.
82
+ * Cap a pre-rendered command preview to a viewport-sized tail window: the end
83
+ * of the command stays visible (it is the live edge while args stream) behind
84
+ * an "… N earlier lines" marker on top. The same window applies while
85
+ * streaming and after completion so the block never jumps; only `expanded`
86
+ * (ctrl+o) uncaps it.
95
87
  *
96
- * `prefix` (raw, e.g. a dim tree gutter) is prepended to the summary line so
88
+ * `prefix` (raw, e.g. a dim tree gutter) is prepended to the marker line so
97
89
  * nested previews stay aligned.
98
90
  */
99
91
  export declare function capPreviewLines(lines: string[], theme: Theme, options?: {
@@ -9,13 +9,6 @@ export type TodoStatus = "pending" | "in_progress" | "completed" | "abandoned";
9
9
  export interface TodoItem {
10
10
  content: string;
11
11
  status: TodoStatus;
12
- /**
13
- * Append-only list of freeform notes attached by `op: "note"`.
14
- * Each element is one note and may itself be multi-line.
15
- * Rendered as text only when the task is in_progress; otherwise shown as a
16
- * dim marker indicating the task has notes.
17
- */
18
- notes?: string[];
19
12
  }
20
13
  export interface TodoPhase {
21
14
  name: string;
@@ -37,7 +30,6 @@ declare const todoSchema: z.ZodObject<{
37
30
  done: "done";
38
31
  drop: "drop";
39
32
  init: "init";
40
- note: "note";
41
33
  rm: "rm";
42
34
  start: "start";
43
35
  view: "view";
@@ -49,7 +41,6 @@ declare const todoSchema: z.ZodObject<{
49
41
  task: z.ZodOptional<z.ZodString>;
50
42
  phase: z.ZodOptional<z.ZodString>;
51
43
  items: z.ZodOptional<z.ZodArray<z.ZodString>>;
52
- text: z.ZodOptional<z.ZodString>;
53
44
  }, z.core.$strip>>;
54
45
  }, z.core.$strip>;
55
46
  type TodoParams = z.infer<typeof todoSchema>;
@@ -111,7 +102,6 @@ export declare class TodoTool implements AgentTool<typeof todoSchema, TodoToolDe
111
102
  done: "done";
112
103
  drop: "drop";
113
104
  init: "init";
114
- note: "note";
115
105
  rm: "rm";
116
106
  start: "start";
117
107
  view: "view";
@@ -123,7 +113,6 @@ export declare class TodoTool implements AgentTool<typeof todoSchema, TodoToolDe
123
113
  task: z.ZodOptional<z.ZodString>;
124
114
  phase: z.ZodOptional<z.ZodString>;
125
115
  items: z.ZodOptional<z.ZodArray<z.ZodString>>;
126
- text: z.ZodOptional<z.ZodString>;
127
116
  }, z.core.$strip>>;
128
117
  }, z.core.$strip>;
129
118
  readonly concurrency = "exclusive";
@@ -1,13 +1,25 @@
1
1
  /**
2
- * Derive a stable CSS hex accent color from a session name.
2
+ * Derive a stable CSS hex accent color from a session name and the active theme.
3
+ *
4
+ * Picks a hue from a **dark/light-specific range** so the accent feels natural
5
+ * for the theme type (warm on dark, cool on light). The session name hash
6
+ * determines the exact hue within the range. The result is checked against
7
+ * all theme color hues and shifted if it lands within {@link MIN_HUE_DISTANCE}
8
+ * of an existing theme hue, but is clamped to the hue band so it never
9
+ * drifts into an unrelated part of the spectrum.
3
10
  *
4
11
  * On dark themes (`surfaceLuminance` undefined) the accent is vivid (high
5
12
  * saturation, high lightness). On light themes the lightness is reduced until the
6
13
  * accent's perceived luminance clears {@link ACCENT_MIN_CONTRAST} against the
7
14
  * actual surface it renders on — so it stays legible on near-white *and* mid-light
8
- * backgrounds — while keeping the same per-session hue.
15
+ * backgrounds.
16
+ *
17
+ * @param name — session name for per-session uniqueness.
18
+ * @param themeColorHexes — all theme colors to check collision against.
19
+ * @param surfaceLuminance — undefined on dark themes; WCAG luminance of the
20
+ * status-line background on light themes.
9
21
  */
10
- export declare function getSessionAccentHex(name: string, surfaceLuminance?: number): string;
22
+ export declare function getSessionAccentHex(name: string, themeColorHexes: string[], surfaceLuminance?: number): string;
11
23
  /**
12
24
  * Convert a hex accent color to an ANSI-16m foreground escape sequence.
13
25
  * Returns `undefined` if `hex` is nullish or Bun.color conversion fails.
@@ -6,7 +6,7 @@
6
6
  * through the shared {@link AuthStorage} broker (Bearer token), and responses
7
7
  * are categorized result buckets rather than the legacy flat object array.
8
8
  */
9
- import type { AuthStorage, FetchImpl } from "@oh-my-pi/pi-ai";
9
+ import { type AuthStorage, type FetchImpl } from "@oh-my-pi/pi-ai";
10
10
  /** V1 search request body. */
11
11
  export interface KagiSearchRequest {
12
12
  query: string;
@@ -96,5 +96,4 @@ export interface KagiSearchResult {
96
96
  relatedQuestions: string[];
97
97
  answer?: string;
98
98
  }
99
- export declare function findKagiApiKey(authStorage: AuthStorage, sessionId?: string, signal?: AbortSignal): Promise<string | null>;
100
99
  export declare function searchWithKagi(query: string, options: KagiSearchOptions | undefined, authStorage: AuthStorage): Promise<KagiSearchResult>;
@@ -1,4 +1,4 @@
1
- import type { AuthStorage, FetchImpl } from "@oh-my-pi/pi-ai";
1
+ import { type AuthStorage, type FetchImpl } from "@oh-my-pi/pi-ai";
2
2
  import type { SearchResponse } from "../../../web/search/types";
3
3
  import type { SearchParams } from "./base";
4
4
  import { SearchProvider } from "./base";
@@ -8,10 +8,12 @@
8
8
  * sibling SQLite store and never POSTs the broker sentinel to a Google token
9
9
  * endpoint.
10
10
  */
11
- import type { AuthStorage, FetchImpl } from "@oh-my-pi/pi-ai";
11
+ import { type AuthStorage, type FetchImpl, type OAuthAccess } from "@oh-my-pi/pi-ai";
12
12
  import type { SearchResponse } from "../../../web/search/types";
13
13
  import type { SearchParams } from "./base";
14
14
  import { SearchProvider } from "./base";
15
+ declare const GEMINI_PROVIDERS: readonly ["google-gemini-cli", "google-antigravity"];
16
+ type GeminiProviderId = (typeof GEMINI_PROVIDERS)[number];
15
17
  interface GeminiToolParams {
16
18
  google_search?: Record<string, unknown>;
17
19
  code_execution?: Record<string, unknown>;
@@ -31,19 +33,20 @@ export interface GeminiSearchParams extends GeminiToolParams {
31
33
  fetch?: FetchImpl;
32
34
  }
33
35
  export declare function buildGeminiRequestTools(params: GeminiToolParams): Array<Record<string, Record<string, unknown>>>;
34
- /** Resolved auth for a Gemini API request. */
35
- interface GeminiAuth {
36
- accessToken: string;
36
+ /** First configured Gemini OAuth provider plus its pre-resolved access. */
37
+ interface GeminiAuthSeed {
38
+ provider: GeminiProviderId;
39
+ access: OAuthAccess;
37
40
  projectId: string;
38
- isAntigravity: boolean;
39
41
  }
40
42
  /**
41
43
  * Walks the configured Gemini OAuth providers in deterministic order and
42
44
  * returns the first one that yields a usable access token + projectId via
43
45
  * {@link AuthStorage.getOAuthAccess}. AuthStorage handles refresh + broker
44
46
  * routing internally; this helper never touches refresh tokens directly.
47
+ * The resolved access seeds `withOAuthAccess` so the happy path resolves once.
45
48
  */
46
- export declare function findGeminiAuth(authStorage: AuthStorage, sessionId: string | undefined, signal: AbortSignal | undefined): Promise<GeminiAuth | null>;
49
+ export declare function findGeminiAuth(authStorage: AuthStorage, sessionId: string | undefined, signal: AbortSignal | undefined): Promise<GeminiAuthSeed | null>;
47
50
  /**
48
51
  * Executes a web search using Google Gemini with Google Search grounding.
49
52
  */
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": "15.11.3",
4
+ "version": "15.11.6",
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",
@@ -47,16 +47,16 @@
47
47
  "@agentclientprotocol/sdk": "0.22.1",
48
48
  "@babel/parser": "^7.29.7",
49
49
  "@mozilla/readability": "^0.6.0",
50
- "@oh-my-pi/hashline": "15.11.3",
51
- "@oh-my-pi/omp-stats": "15.11.3",
52
- "@oh-my-pi/pi-agent-core": "15.11.3",
53
- "@oh-my-pi/pi-ai": "15.11.3",
54
- "@oh-my-pi/pi-catalog": "15.11.3",
55
- "@oh-my-pi/pi-mnemopi": "15.11.3",
56
- "@oh-my-pi/pi-natives": "15.11.3",
57
- "@oh-my-pi/pi-tui": "15.11.3",
58
- "@oh-my-pi/pi-utils": "15.11.3",
59
- "@oh-my-pi/snapcompact": "15.11.3",
50
+ "@oh-my-pi/hashline": "15.11.6",
51
+ "@oh-my-pi/omp-stats": "15.11.6",
52
+ "@oh-my-pi/pi-agent-core": "15.11.6",
53
+ "@oh-my-pi/pi-ai": "15.11.6",
54
+ "@oh-my-pi/pi-catalog": "15.11.6",
55
+ "@oh-my-pi/pi-mnemopi": "15.11.6",
56
+ "@oh-my-pi/pi-natives": "15.11.6",
57
+ "@oh-my-pi/pi-tui": "15.11.6",
58
+ "@oh-my-pi/pi-utils": "15.11.6",
59
+ "@oh-my-pi/snapcompact": "15.11.6",
60
60
  "@opentelemetry/api": "^1.9.1",
61
61
  "@opentelemetry/context-async-hooks": "^2.7.1",
62
62
  "@opentelemetry/exporter-trace-otlp-proto": "^0.218.0",
@@ -83,11 +83,7 @@ async function classifyOnline(input: string, deps: ClassifyDifficultyDeps): Prom
83
83
  messages: [{ role: "user", content: input, timestamp: Date.now() }],
84
84
  },
85
85
  {
86
- apiKey: deps.registry.resolver(model.provider, {
87
- sessionId: deps.sessionId,
88
- baseUrl: model.baseUrl,
89
- modelId: model.id,
90
- }),
86
+ apiKey: deps.registry.resolver(model, deps.sessionId),
91
87
  maxTokens,
92
88
  disableReasoning: true,
93
89
  metadata,