@oh-my-pi/pi-coding-agent 15.1.2 → 15.1.4

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 (155) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/dist/types/async/job-manager.d.ts +3 -2
  3. package/dist/types/cli/auth-broker-cli.d.ts +25 -0
  4. package/dist/types/cli/auth-gateway-cli.d.ts +18 -0
  5. package/dist/types/cli/grievances-cli.d.ts +12 -0
  6. package/dist/types/commands/auth-broker.d.ts +54 -0
  7. package/dist/types/commands/auth-gateway.d.ts +32 -0
  8. package/dist/types/commands/grievances.d.ts +1 -1
  9. package/dist/types/commit/agentic/tools/propose-commit.d.ts +9 -1
  10. package/dist/types/commit/agentic/tools/schemas.d.ts +9 -1
  11. package/dist/types/commit/agentic/tools/split-commit.d.ts +9 -1
  12. package/dist/types/config/model-registry.d.ts +3 -0
  13. package/dist/types/config/models-config-schema.d.ts +1 -0
  14. package/dist/types/config/settings-schema.d.ts +46 -0
  15. package/dist/types/discovery/agents.d.ts +12 -1
  16. package/dist/types/edit/renderer.d.ts +3 -0
  17. package/dist/types/eval/index.d.ts +0 -2
  18. package/dist/types/goals/tools/goal-tool.d.ts +10 -2
  19. package/dist/types/index.d.ts +0 -1
  20. package/dist/types/internal-urls/index.d.ts +1 -1
  21. package/dist/types/internal-urls/{pi-protocol.d.ts → omp-protocol.d.ts} +3 -3
  22. package/dist/types/internal-urls/types.d.ts +1 -1
  23. package/dist/types/main.d.ts +11 -2
  24. package/dist/types/modes/acp/acp-agent.d.ts +2 -1
  25. package/dist/types/modes/acp/acp-event-mapper.d.ts +13 -1
  26. package/dist/types/modes/acp/acp-mode.d.ts +3 -1
  27. package/dist/types/modes/emoji-autocomplete.d.ts +16 -0
  28. package/dist/types/modes/interactive-mode.d.ts +1 -1
  29. package/dist/types/modes/prompt-action-autocomplete.d.ts +4 -0
  30. package/dist/types/plan-mode/approved-plan.d.ts +10 -4
  31. package/dist/types/sdk.d.ts +10 -3
  32. package/dist/types/session/agent-session.d.ts +7 -3
  33. package/dist/types/session/auth-broker-config.d.ts +13 -0
  34. package/dist/types/session/auth-storage.d.ts +1 -1
  35. package/dist/types/session/client-bridge.d.ts +3 -0
  36. package/dist/types/tools/eval.d.ts +41 -7
  37. package/dist/types/tools/irc.d.ts +8 -2
  38. package/dist/types/tools/report-tool-issue.d.ts +118 -1
  39. package/dist/types/tools/resolve.d.ts +8 -2
  40. package/examples/custom-tools/README.md +3 -12
  41. package/examples/extensions/README.md +2 -15
  42. package/examples/extensions/api-demo.ts +1 -7
  43. package/package.json +7 -7
  44. package/src/async/job-manager.ts +111 -13
  45. package/src/autoresearch/tools/init-experiment.ts +11 -33
  46. package/src/autoresearch/tools/log-experiment.ts +10 -24
  47. package/src/autoresearch/tools/run-experiment.ts +1 -1
  48. package/src/autoresearch/tools/update-notes.ts +2 -9
  49. package/src/cli/auth-broker-cli.ts +746 -0
  50. package/src/cli/auth-gateway-cli.ts +342 -0
  51. package/src/cli/grievances-cli.ts +109 -16
  52. package/src/cli/update-cli.ts +1 -5
  53. package/src/cli.ts +4 -2
  54. package/src/commands/auth-broker.ts +96 -0
  55. package/src/commands/auth-gateway.ts +61 -0
  56. package/src/commands/grievances.ts +13 -8
  57. package/src/commands/launch.ts +1 -1
  58. package/src/commit/agentic/agent.ts +2 -0
  59. package/src/commit/agentic/tools/analyze-file.ts +2 -2
  60. package/src/commit/agentic/tools/git-file-diff.ts +2 -2
  61. package/src/commit/agentic/tools/git-hunk.ts +3 -3
  62. package/src/commit/agentic/tools/git-overview.ts +2 -2
  63. package/src/commit/agentic/tools/propose-changelog.ts +1 -3
  64. package/src/commit/agentic/tools/recent-commits.ts +1 -1
  65. package/src/commit/agentic/tools/schemas.ts +1 -9
  66. package/src/config/model-equivalence.ts +279 -174
  67. package/src/config/model-registry.ts +37 -6
  68. package/src/config/model-resolver.ts +13 -8
  69. package/src/config/models-config-schema.ts +8 -0
  70. package/src/config/settings-schema.ts +52 -0
  71. package/src/cursor.ts +1 -1
  72. package/src/debug/log-formatting.ts +1 -1
  73. package/src/debug/log-viewer.ts +1 -1
  74. package/src/debug/profiler.ts +4 -0
  75. package/src/debug/raw-sse-buffer.ts +100 -59
  76. package/src/debug/raw-sse.ts +1 -1
  77. package/src/discovery/agents.ts +15 -4
  78. package/src/edit/modes/apply-patch.ts +1 -5
  79. package/src/edit/modes/patch.ts +5 -5
  80. package/src/edit/modes/replace.ts +5 -5
  81. package/src/edit/renderer.ts +2 -1
  82. package/src/edit/streaming.ts +1 -1
  83. package/src/eval/index.ts +0 -2
  84. package/src/eval/js/shared/runtime.ts +107 -2
  85. package/src/eval/py/kernel.ts +1 -1
  86. package/src/exa/researcher.ts +4 -4
  87. package/src/exa/search.ts +10 -22
  88. package/src/exa/websets.ts +33 -33
  89. package/src/extensibility/typebox.ts +44 -17
  90. package/src/goals/tools/goal-tool.ts +3 -3
  91. package/src/index.ts +0 -3
  92. package/src/internal-urls/docs-index.generated.ts +21 -18
  93. package/src/internal-urls/index.ts +1 -1
  94. package/src/internal-urls/{pi-protocol.ts → omp-protocol.ts} +10 -10
  95. package/src/internal-urls/router.ts +3 -3
  96. package/src/internal-urls/types.ts +1 -1
  97. package/src/lsp/types.ts +8 -11
  98. package/src/main.ts +216 -146
  99. package/src/mcp/tool-bridge.ts +3 -3
  100. package/src/modes/acp/acp-agent.ts +203 -57
  101. package/src/modes/acp/acp-client-bridge.ts +2 -1
  102. package/src/modes/acp/acp-event-mapper.ts +208 -32
  103. package/src/modes/acp/acp-mode.ts +11 -3
  104. package/src/modes/components/bash-execution.ts +1 -1
  105. package/src/modes/components/diff.ts +1 -2
  106. package/src/modes/components/eval-execution.ts +1 -1
  107. package/src/modes/components/oauth-selector.ts +38 -2
  108. package/src/modes/components/tool-execution.ts +1 -2
  109. package/src/modes/components/tree-selector.ts +26 -7
  110. package/src/modes/controllers/command-controller.ts +95 -34
  111. package/src/modes/controllers/input-controller.ts +4 -3
  112. package/src/modes/data/emojis.json +1 -0
  113. package/src/modes/emoji-autocomplete.ts +285 -0
  114. package/src/modes/interactive-mode.ts +92 -19
  115. package/src/modes/print-mode.ts +3 -3
  116. package/src/modes/prompt-action-autocomplete.ts +14 -0
  117. package/src/plan-mode/approved-plan.ts +30 -9
  118. package/src/prompts/system/system-prompt.md +1 -1
  119. package/src/prompts/system/ttsr-tool-reminder.md +5 -0
  120. package/src/prompts/tools/ask.md +4 -3
  121. package/src/prompts/tools/eval.md +25 -26
  122. package/src/prompts/tools/read.md +1 -1
  123. package/src/prompts/tools/resolve.md +1 -1
  124. package/src/prompts/tools/search.md +1 -1
  125. package/src/prompts/tools/web-search.md +1 -1
  126. package/src/sdk.ts +81 -8
  127. package/src/session/agent-session.ts +362 -131
  128. package/src/session/agent-storage.ts +7 -2
  129. package/src/session/auth-broker-config.ts +102 -0
  130. package/src/session/auth-storage.ts +7 -1
  131. package/src/session/client-bridge.ts +3 -0
  132. package/src/session/streaming-output.ts +1 -1
  133. package/src/task/types.ts +10 -35
  134. package/src/tools/bash-interactive.ts +4 -1
  135. package/src/tools/bash-pty-selection.ts +2 -2
  136. package/src/tools/browser.ts +12 -20
  137. package/src/tools/eval.ts +77 -100
  138. package/src/tools/gh.ts +21 -45
  139. package/src/tools/hindsight-recall.ts +1 -1
  140. package/src/tools/hindsight-reflect.ts +2 -2
  141. package/src/tools/hindsight-retain.ts +3 -7
  142. package/src/tools/index.ts +8 -1
  143. package/src/tools/inspect-image.ts +4 -1
  144. package/src/tools/irc.ts +4 -12
  145. package/src/tools/job.ts +3 -11
  146. package/src/tools/report-tool-issue.ts +462 -17
  147. package/src/tools/resolve.ts +2 -7
  148. package/src/tools/todo-write.ts +8 -15
  149. package/src/utils/title-generator.ts +3 -0
  150. package/src/web/search/index.ts +6 -6
  151. package/dist/types/eval/parse.d.ts +0 -28
  152. package/dist/types/eval/sniff.d.ts +0 -11
  153. package/src/eval/eval.lark +0 -36
  154. package/src/eval/parse.ts +0 -407
  155. package/src/eval/sniff.ts +0 -28
@@ -7,14 +7,20 @@ export interface PlanApprovalDetails {
7
7
  title: string;
8
8
  planExists: boolean;
9
9
  }
10
- /** Validate the agent-supplied plan title and derive the destination filename.
11
- * Filename uses the title with a `.md` suffix; characters are restricted to
12
- * letters, numbers, underscores, and hyphens so the value is safe to splice
13
- * into a `local://` URL without escaping. */
10
+ /** Validate and normalize the agent-supplied plan title into a safe filename stem.
11
+ * Spaces and other URL-safe punctuation are replaced with hyphens so models that
12
+ * produce natural-language titles (e.g. "My feature plan") still succeed.
13
+ * Characters that cannot be safely represented after replacement are dropped.
14
+ * The result is restricted to letters, numbers, underscores, and hyphens so it
15
+ * is safe to splice into a `local://` URL without escaping. */
14
16
  export declare function normalizePlanTitle(title: string): {
15
17
  title: string;
16
18
  fileName: string;
17
19
  };
20
+ /** Humanize a normalized plan title for use as a session display name.
21
+ * Replaces `-`/`_` separators with spaces and capitalizes the first letter.
22
+ * Returns an empty string when the input collapses to whitespace. */
23
+ export declare function humanizePlanTitle(title: string): string;
18
24
  interface RenameApprovedPlanFileOptions {
19
25
  planFilePath: string;
20
26
  finalPlanFilePath: string;
@@ -1,5 +1,5 @@
1
1
  import { type AgentTelemetryConfig, type ThinkingLevel } from "@oh-my-pi/pi-agent-core";
2
- import type { Model } from "@oh-my-pi/pi-ai";
2
+ import { type Model } from "@oh-my-pi/pi-ai";
3
3
  import { type Rule } from "./capability/rule";
4
4
  import { ModelRegistry } from "./config/model-registry";
5
5
  import { type PromptTemplate } from "./config/prompt-templates";
@@ -153,8 +153,15 @@ export type { Tool } from "./tools";
153
153
  export { buildDirectoryTree, buildWorkspaceTree, type DirectoryTree, type WorkspaceTree } from "./workspace-tree";
154
154
  export { BashTool, BUILTIN_TOOLS, createTools, EditTool, EvalTool, FindTool, HIDDEN_TOOLS, loadSshTool, ReadTool, ResolveTool, SearchTool, type ToolSession, WebSearchTool, WriteTool, };
155
155
  /**
156
- * Create an AuthStorage instance with fallback support.
157
- * Reads from primary path first, then falls back to legacy paths (.pi, .claude).
156
+ * Create an AuthStorage instance.
157
+ *
158
+ * Default: local SQLite store at `<agentDir>/agent.db`.
159
+ *
160
+ * Broker mode: when `OMP_AUTH_BROKER_URL` is set, credentials are pulled from
161
+ * a remote auth-broker over the wire. Refresh tokens never leave the broker;
162
+ * the client receives access tokens with `refresh = "__remote__"` and calls
163
+ * back into the broker through the {@link AuthStorageOptions.refreshOAuthCredential}
164
+ * override to re-mint access tokens when needed.
158
165
  */
159
166
  export declare function discoverAuthStorage(agentDir?: string): Promise<AuthStorage>;
160
167
  /**
@@ -15,7 +15,7 @@
15
15
  import { type Agent, type AgentEvent, type AgentMessage, type AgentState, type AgentTool, ThinkingLevel } from "@oh-my-pi/pi-agent-core";
16
16
  import { type CompactionResult } from "@oh-my-pi/pi-agent-core/compaction";
17
17
  import type { AssistantMessage, Effort, ImageContent, Message, MessageAttribution, Model, ProviderSessionState, ServiceTier, SimpleStreamOptions, TextContent, ToolChoice, UsageReport } from "@oh-my-pi/pi-ai";
18
- import { type AsyncJob, AsyncJobManager } from "../async";
18
+ import { type AsyncJob, type AsyncJobDeliveryState, AsyncJobManager } from "../async";
19
19
  import type { Rule } from "../capability/rule";
20
20
  import { type ModelRegistry } from "../config/model-registry";
21
21
  import { type ResolvedModelRoleValue } from "../config/model-resolver";
@@ -111,6 +111,7 @@ export type AsyncJobSnapshotItem = Pick<AsyncJob, "id" | "type" | "status" | "la
111
111
  export interface AsyncJobSnapshot {
112
112
  running: AsyncJobSnapshotItem[];
113
113
  recent: AsyncJobSnapshotItem[];
114
+ delivery: AsyncJobDeliveryState;
114
115
  }
115
116
  export interface AgentSessionConfig {
116
117
  agent: Agent;
@@ -347,6 +348,9 @@ export declare class AgentSession {
347
348
  get isStreaming(): boolean;
348
349
  /** Wait until streaming and deferred recovery work are fully settled. */
349
350
  waitForIdle(): Promise<void>;
351
+ drainAsyncJobDeliveriesForAcp(options?: {
352
+ timeoutMs?: number;
353
+ }): Promise<boolean>;
350
354
  /** Most recent assistant message in agent state. */
351
355
  getLastAssistantMessage(): AssistantMessage | undefined;
352
356
  /** Current effective system prompt blocks (includes any per-turn extension modifications) */
@@ -495,7 +499,7 @@ export declare class AgentSession {
495
499
  *
496
500
  * Handles three cases:
497
501
  * - Streaming: queue as steer/follow-up or store for next turn
498
- * - Not streaming + triggerTurn: appends to state/session, starts new turn
502
+ * - Not streaming + triggerTurn: appends to state/session, starts new turn unless the client cannot own it
499
503
  * - Not streaming + no trigger: appends to state/session, no turn
500
504
  */
501
505
  sendCustomMessage<T = unknown>(message: Pick<CustomMessage<T>, "customType" | "content" | "display" | "details" | "attribution">, options?: {
@@ -855,7 +859,7 @@ export declare class AgentSession {
855
859
  * otherwise estimates tokens for all messages.
856
860
  */
857
861
  getContextUsage(): ContextUsage | undefined;
858
- fetchUsageReports(): Promise<UsageReport[] | null>;
862
+ fetchUsageReports(signal?: AbortSignal): Promise<UsageReport[] | null>;
859
863
  /**
860
864
  * Export session to HTML.
861
865
  * @param outputPath Optional output path (defaults to session directory)
@@ -0,0 +1,13 @@
1
+ export interface AuthBrokerClientConfig {
2
+ url: string;
3
+ token: string;
4
+ }
5
+ /** Path to the local bearer token file. Created on the broker host by `omp auth-broker token`. */
6
+ export declare function getAuthBrokerTokenFilePath(): string;
7
+ /**
8
+ * Read broker configuration. Returns null when the URL is missing
9
+ * (broker disabled — local store is used). Throws when URL is set but no
10
+ * token is available — the caller cannot fall back silently because the
11
+ * user explicitly asked to use the broker.
12
+ */
13
+ export declare function resolveAuthBrokerConfig(): Promise<AuthBrokerClientConfig | null>;
@@ -3,4 +3,4 @@
3
3
  * All credential storage types and the AuthStorage class now live in the ai package.
4
4
  */
5
5
  export type { ApiKeyCredential, AuthCredential, AuthCredentialEntry, AuthCredentialStore, AuthStorageData, AuthStorageOptions, OAuthCredential, SerializedAuthStorage, StoredAuthCredential, } from "@oh-my-pi/pi-ai";
6
- export { AuthStorage } from "@oh-my-pi/pi-ai";
6
+ export { AuthBrokerClient, AuthStorage, REMOTE_REFRESH_SENTINEL, RemoteAuthCredentialStore, SqliteAuthCredentialStore, } from "@oh-my-pi/pi-ai";
@@ -23,6 +23,7 @@ export interface ClientBridgePermissionToolCall {
23
23
  toolName: string;
24
24
  title: string;
25
25
  kind?: string;
26
+ status?: "pending" | "in_progress" | "completed" | "failed";
26
27
  rawInput?: unknown;
27
28
  locations?: {
28
29
  path: string;
@@ -70,6 +71,8 @@ export interface ClientBridgeCreateTerminalParams {
70
71
  }
71
72
  export interface ClientBridge {
72
73
  readonly capabilities: ClientBridgeCapabilities;
74
+ /** ACP v1 clients cannot show server-initiated turns as busy after prompt response. */
75
+ readonly deferAgentInitiatedTurns?: boolean;
73
76
  readTextFile?(params: {
74
77
  path: string;
75
78
  line?: number;
@@ -6,8 +6,32 @@ import type { RenderResultOptions } from "../extensibility/custom-tools/types";
6
6
  import { type Theme } from "../modes/theme/theme";
7
7
  import { type ToolSession } from ".";
8
8
  export declare const EVAL_DEFAULT_PREVIEW_LINES = 10;
9
+ /**
10
+ * Per-cell input. Each cell runs in order; state persists within a language
11
+ * across cells and across tool calls.
12
+ */
13
+ declare const evalCellSchema: z.ZodObject<{
14
+ language: z.ZodEnum<{
15
+ js: "js";
16
+ py: "py";
17
+ }>;
18
+ code: z.ZodString;
19
+ title: z.ZodOptional<z.ZodString>;
20
+ timeout: z.ZodOptional<z.ZodNumber>;
21
+ reset: z.ZodOptional<z.ZodBoolean>;
22
+ }, z.core.$strip>;
23
+ export type EvalCellInput = z.infer<typeof evalCellSchema>;
9
24
  export declare const evalSchema: z.ZodObject<{
10
- input: z.ZodString;
25
+ cells: z.ZodArray<z.ZodObject<{
26
+ language: z.ZodEnum<{
27
+ js: "js";
28
+ py: "py";
29
+ }>;
30
+ code: z.ZodString;
31
+ title: z.ZodOptional<z.ZodString>;
32
+ timeout: z.ZodOptional<z.ZodNumber>;
33
+ reset: z.ZodOptional<z.ZodBoolean>;
34
+ }, z.core.$strip>>;
11
35
  }, z.core.$strip>;
12
36
  export type EvalToolParams = z.infer<typeof evalSchema>;
13
37
  export type EvalToolResult = {
@@ -35,20 +59,30 @@ export declare class EvalTool implements AgentTool<typeof evalSchema> {
35
59
  readonly label = "Eval";
36
60
  get description(): string;
37
61
  readonly parameters: z.ZodObject<{
38
- input: z.ZodString;
62
+ cells: z.ZodArray<z.ZodObject<{
63
+ language: z.ZodEnum<{
64
+ js: "js";
65
+ py: "py";
66
+ }>;
67
+ code: z.ZodString;
68
+ title: z.ZodOptional<z.ZodString>;
69
+ timeout: z.ZodOptional<z.ZodNumber>;
70
+ reset: z.ZodOptional<z.ZodBoolean>;
71
+ }, z.core.$strip>>;
39
72
  }, z.core.$strip>;
40
73
  readonly concurrency = "exclusive";
41
74
  readonly strict = true;
42
75
  readonly intent: (args: Partial<z.infer<typeof evalSchema>>) => string | undefined;
43
- get customFormat(): {
44
- syntax: "lark";
45
- definition: string;
46
- };
47
76
  constructor(session: ToolSession | null, options?: EvalToolOptions);
48
77
  execute(_toolCallId: string, params: z.infer<typeof evalSchema>, signal?: AbortSignal, onUpdate?: AgentToolUpdateCallback, _ctx?: AgentToolContext): Promise<AgentToolResult<EvalToolDetails | undefined>>;
49
78
  }
79
+ interface EvalRenderCellArg {
80
+ language?: string;
81
+ code?: string;
82
+ title?: string;
83
+ }
50
84
  interface EvalRenderArgs {
51
- input?: string;
85
+ cells?: EvalRenderCellArg[];
52
86
  __partialJson?: string;
53
87
  }
54
88
  interface EvalRenderContext {
@@ -21,7 +21,10 @@ import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallb
21
21
  import * as z from "zod/v4";
22
22
  import type { ToolSession } from ".";
23
23
  declare const ircSchema: z.ZodObject<{
24
- op: z.ZodUnion<readonly [z.ZodLiteral<"send">, z.ZodLiteral<"list">]>;
24
+ op: z.ZodEnum<{
25
+ list: "list";
26
+ send: "send";
27
+ }>;
25
28
  to: z.ZodOptional<z.ZodString>;
26
29
  message: z.ZodOptional<z.ZodString>;
27
30
  awaitReply: z.ZodOptional<z.ZodBoolean>;
@@ -59,7 +62,10 @@ export declare class IrcTool implements AgentTool<typeof ircSchema, IrcDetails>
59
62
  readonly summary = "Send and receive messages between agents over IRC-like channels";
60
63
  readonly description: string;
61
64
  readonly parameters: z.ZodObject<{
62
- op: z.ZodUnion<readonly [z.ZodLiteral<"send">, z.ZodLiteral<"list">]>;
65
+ op: z.ZodEnum<{
66
+ list: "list";
67
+ send: "send";
68
+ }>;
63
69
  to: z.ZodOptional<z.ZodString>;
64
70
  message: z.ZodOptional<z.ZodString>;
65
71
  awaitReply: z.ZodOptional<z.ZodBoolean>;
@@ -1,6 +1,123 @@
1
+ /**
2
+ * report_tool_issue — automated QA tool for tracking unexpected tool behavior.
3
+ *
4
+ * Enabled by default; gated behind PI_AUTO_QA=1 / `dev.autoqa` so a user
5
+ * who flips the setting off short-circuits injection entirely.
6
+ * Always injected into every agent (including subagents) regardless of tool selection.
7
+ * Records grievances to a local SQLite database; never throws.
8
+ *
9
+ * Before the first record lands, the user's consent is checked. If they've
10
+ * never been asked (`dev.autoqa.consent === "unset"`) the process-global
11
+ * consent handler — wired by `InteractiveMode` to a Yes/No popup — is
12
+ * invoked exactly once and the decision is persisted. Subsequent calls
13
+ * (including from subagents) read the cached decision without prompting.
14
+ *
15
+ * When the user grants consent, push is automatically active against the
16
+ * bundled endpoint (`dev.autoqaPush.endpoint`, default `qa.omp.sh`). Each
17
+ * insert schedules a background flush that POSTs pending rows and deletes
18
+ * them on HTTP 2xx. `PI_AUTO_QA_PUSH=1` forces push in non-interactive
19
+ * environments where the consent dialog never fires. Tool execution is
20
+ * never blocked on the network and never throws.
21
+ */
22
+ import { Database } from "bun:sqlite";
1
23
  import type { AgentTool } from "@oh-my-pi/pi-agent-core";
2
24
  import type { Settings } from "..";
3
25
  import type { ToolSession } from "./index";
4
26
  export declare function isAutoQaEnabled(settings?: Settings): boolean;
27
+ /**
28
+ * Resolver for the user's "share grievances?" consent.
29
+ *
30
+ * Return values:
31
+ * - `true` — user agreed; record + ship for this run and persist.
32
+ * - `false` — user declined; suppress for this run and persist.
33
+ * - `null` — user dismissed the dialog (ESC, click-away, …) without
34
+ * picking an option. The decision is NOT cached or persisted,
35
+ * so the next `report_tool_issue` invocation re-prompts.
36
+ *
37
+ * Persistence is the tool's job (so subagent invocations can persist into
38
+ * the disk-backed `Settings` instance the host registered alongside the
39
+ * handler), not the handler's. Implementations live in hosts that have UI
40
+ * affordances — today only `InteractiveMode`. When no handler is
41
+ * registered (CLI subcommands, tests, non-interactive runs) consent
42
+ * defaults to `false` — the explicit "don't collect by default" stance.
43
+ */
44
+ export type AutoQaConsentHandler = () => Promise<boolean | null>;
45
+ /**
46
+ * Register the consent handler and the persistent {@link Settings} instance
47
+ * the decision should be written to. Passing `null` clears the handler
48
+ * (e.g. on `InteractiveMode` teardown). Re-registration is authoritative.
49
+ */
50
+ export declare function setAutoQaConsentHandler(handler: AutoQaConsentHandler | null, persistentSettings?: Settings | null): void;
51
+ /** Test-only: clear consent cache + handler. Never call from production code. */
52
+ export declare function __resetAutoQaConsentForTests(): void;
53
+ /**
54
+ * Resolve the user's consent for `report_tool_issue` grievances.
55
+ *
56
+ * Precedence (highest first):
57
+ * 1. Process-global cache (set on first successful resolution).
58
+ * 2. Persistent setting (`dev.autoqa.consent` on the supplied `Settings`).
59
+ * 3. Persistent setting on the registered host `Settings`.
60
+ * 4. Consent handler popup (single-flight; persists the answer).
61
+ * 5. Default-deny when no handler is registered.
62
+ *
63
+ * Never throws — handler errors degrade to "denied for this call" without
64
+ * caching, so a subsequent invocation can re-prompt instead of being
65
+ * permanently locked into the false branch.
66
+ */
67
+ export declare function resolveAutoQaConsent(settings: Settings | undefined): Promise<boolean>;
5
68
  export declare function getAutoQaDbPath(): string;
6
- export declare function createReportToolIssueTool(session: ToolSession): AgentTool;
69
+ /**
70
+ * Open (or return the cached handle for) the auto-QA SQLite database at
71
+ * `~/.omp/agent/autoqa.db`. Idempotently runs schema creation, the
72
+ * `pushed`-column migration, and index setup so every consumer — tool
73
+ * execute path, manual `omp grievances push`, future debug scripts —
74
+ * sees the same prepared schema. Returns `null` only on a hard open
75
+ * failure (filesystem permissions, etc.); a missing file is created.
76
+ *
77
+ * Exported because the `omp grievances` CLI handlers need the migrated
78
+ * handle too — having a second `openDb` in the CLI led to the column
79
+ * never being added on the manual-push path.
80
+ */
81
+ export declare function openAutoQaDb(): Database | null;
82
+ export interface FlushResult {
83
+ pushed: number;
84
+ ok: boolean;
85
+ skipped?: boolean;
86
+ }
87
+ /**
88
+ * Optional per-flush controls. Used by `omp grievances push` to surface
89
+ * progress to a TTY and to skip the user-facing consent gate (manual
90
+ * pushes are the user's explicit intent, not a side effect of a tool call).
91
+ */
92
+ export interface FlushOptions {
93
+ /**
94
+ * Skip the `dev.autoqa.consent === "granted"` gate in
95
+ * {@link resolvePushConfig}. Endpoint configuration is still required.
96
+ * Reserved for explicit user-driven pushes (CLI `grievances push`,
97
+ * future debug recipes); never set from the tool's auto-flush path.
98
+ */
99
+ bypassConsent?: boolean;
100
+ /**
101
+ * Fires once at the start of the loop with the snapshot count of
102
+ * unpushed rows. Subsequent inserts won't be reflected (the count is
103
+ * a planning hint for progress reporters, not a live total).
104
+ */
105
+ onStart?: (totalUnpushed: number) => void;
106
+ /**
107
+ * Fires after every successfully shipped batch with the running pushed
108
+ * count. Reporters compare against the `totalUnpushed` they saw in
109
+ * `onStart` to advance their bar.
110
+ */
111
+ onProgress?: (pushedSoFar: number) => void;
112
+ }
113
+ /** Test-only: clear single-flight + cooldown state. Never call from production code. */
114
+ export declare function __resetAutoQaFlushStateForTests(): void;
115
+ /**
116
+ * Flush queued grievances to the configured backend.
117
+ *
118
+ * Single-flight: concurrent callers share the in-flight promise. After a
119
+ * failed push, retries are skipped for {@link FAILURE_COOLDOWN_MS} ms.
120
+ * Never throws — all errors are caught and routed to the logger.
121
+ */
122
+ export declare function flushGrievances(db?: Database, settings?: Settings, options?: FlushOptions): Promise<FlushResult>;
123
+ export declare function createReportToolIssueTool(session: ToolSession, activeBuiltinNames?: readonly string[]): AgentTool;
@@ -5,7 +5,10 @@ import type { RenderResultOptions } from "../extensibility/custom-tools/types";
5
5
  import type { Theme } from "../modes/theme/theme";
6
6
  import type { ToolSession } from ".";
7
7
  declare const resolveSchema: z.ZodObject<{
8
- action: z.ZodUnion<readonly [z.ZodLiteral<"apply">, z.ZodLiteral<"discard">]>;
8
+ action: z.ZodEnum<{
9
+ apply: "apply";
10
+ discard: "discard";
11
+ }>;
9
12
  reason: z.ZodString;
10
13
  extra: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
11
14
  }, z.core.$strip>;
@@ -54,7 +57,10 @@ export declare class ResolveTool implements AgentTool<typeof resolveSchema, Reso
54
57
  readonly hidden = true;
55
58
  readonly description: string;
56
59
  readonly parameters: z.ZodObject<{
57
- action: z.ZodUnion<readonly [z.ZodLiteral<"apply">, z.ZodLiteral<"discard">]>;
60
+ action: z.ZodEnum<{
61
+ apply: "apply";
62
+ discard: "discard";
63
+ }>;
58
64
  reason: z.ZodString;
59
65
  extra: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
60
66
  }, z.core.$strip>;
@@ -47,7 +47,6 @@ See [docs/custom-tools.md](../../docs/custom-tools.md) for full documentation.
47
47
  **Factory pattern:**
48
48
 
49
49
  ```typescript
50
- import { StringEnum } from "@oh-my-pi/pi-ai";
51
50
  import { Text } from "@oh-my-pi/pi-tui";
52
51
  import type { CustomToolFactory } from "@oh-my-pi/pi-coding-agent";
53
52
 
@@ -56,7 +55,7 @@ const factory: CustomToolFactory = (pi) => ({
56
55
  label: "My Tool",
57
56
  description: "Tool description for LLM",
58
57
  parameters: pi.zod.object({
59
- action: StringEnum(["list", "add"] as const),
58
+ action: pi.zod.enum(["list", "add"]),
60
59
  }),
61
60
 
62
61
  // Called on session start/switch/branch/clear
@@ -76,9 +75,6 @@ const factory: CustomToolFactory = (pi) => ({
76
75
 
77
76
  export default factory;
78
77
  ```
79
-
80
- **Legacy:** `parameters: pi.typebox.Type.Object({ ... })` still works; the injected `typebox` is a small Zod-backed shim, and schemas flow through the same Zod pipeline as `pi.zod` schemas.
81
-
82
78
  **Custom rendering:**
83
79
 
84
80
  ```typescript
@@ -97,17 +93,12 @@ renderResult(result, { expanded, isPartial }, theme) {
97
93
  },
98
94
  ```
99
95
 
100
- **Use `StringEnum` for discriminated string tool args** (required for Google API compatibility):
96
+ **Use `z.enum` for discriminated string tool args:**
101
97
 
102
98
  ```typescript
103
- import { StringEnum } from "@oh-my-pi/pi-ai";
104
-
105
99
  const { z } = pi.zod;
106
100
 
107
- // Good — Google-safe enum wiring
108
101
  parameters: z.object({
109
- action: StringEnum(["list", "add"] as const),
102
+ action: z.enum(["list", "add"]),
110
103
  });
111
-
112
- // Avoid raw union-of-literals patterns that don't degrade well for strict JSON Schema providers
113
104
  ```
@@ -108,29 +108,16 @@ export default function (pi: ExtensionAPI) {
108
108
  });
109
109
  }
110
110
  ```
111
-
112
- **Legacy TypeBox-style schemas** (`pi.typebox`) remain available for older extensions and are backed by a tiny Zod-shim — prefer `pi.zod` directly for new code.
113
-
114
- ```typescript
115
- const { Type } = pi.typebox;
116
- parameters: Type.Object({ name: Type.String() });
117
- ```
118
-
119
111
  ## Key Patterns
120
112
 
121
- **Use `StringEnum` for discriminated string tool args** (required for Google API compatibility):
113
+ **Use `z.enum` for discriminated string tool args:**
122
114
 
123
115
  ```typescript
124
- import { StringEnum } from "@oh-my-pi/pi-ai";
125
-
126
116
  const { z } = pi.zod;
127
117
 
128
- // Good — Google-safe enum wiring
129
118
  parameters: z.object({
130
- action: StringEnum(["list", "add"] as const),
119
+ action: z.enum(["list", "add"]),
131
120
  });
132
-
133
- // Avoid raw union-of-literals patterns that don't degrade well for strict JSON Schema providers
134
121
  ```
135
122
 
136
123
  **State persistence via details:**
@@ -10,9 +10,6 @@ import type { ExtensionAPI } from "@oh-my-pi/pi-coding-agent";
10
10
  export default function (pi: ExtensionAPI) {
11
11
  const { z } = pi.zod;
12
12
 
13
- // Access shared schema helpers from package exports (e.g. StringEnum for Google-safe enums)
14
- const { StringEnum } = pi.pi;
15
-
16
13
  // Access the logger for debugging
17
14
  pi.logger.debug("API demo extension loaded");
18
15
 
@@ -22,10 +19,7 @@ export default function (pi: ExtensionAPI) {
22
19
  description: "Demonstrates ExtensionAPI capabilities: logger, zod, and pi module access",
23
20
  parameters: z.object({
24
21
  message: z.string().describe("Test message"),
25
- logLevel: StringEnum(["error", "warn", "debug"], {
26
- description: "Log level to use",
27
- default: "debug",
28
- }),
22
+ logLevel: z.enum(["error", "warn", "debug"]).default("debug").describe("Log level to use"),
29
23
  }),
30
24
 
31
25
  async execute(_toolCallId, params, _onUpdate, ctx, _signal) {
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.1.2",
4
+ "version": "15.1.4",
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,12 +47,12 @@
47
47
  "@agentclientprotocol/sdk": "0.21.0",
48
48
  "@babel/parser": "^7.29.3",
49
49
  "@mozilla/readability": "^0.6.0",
50
- "@oh-my-pi/omp-stats": "15.1.2",
51
- "@oh-my-pi/pi-agent-core": "15.1.2",
52
- "@oh-my-pi/pi-ai": "15.1.2",
53
- "@oh-my-pi/pi-natives": "15.1.2",
54
- "@oh-my-pi/pi-tui": "15.1.2",
55
- "@oh-my-pi/pi-utils": "15.1.2",
50
+ "@oh-my-pi/omp-stats": "15.1.4",
51
+ "@oh-my-pi/pi-agent-core": "15.1.4",
52
+ "@oh-my-pi/pi-ai": "15.1.4",
53
+ "@oh-my-pi/pi-natives": "15.1.4",
54
+ "@oh-my-pi/pi-tui": "15.1.4",
55
+ "@oh-my-pi/pi-utils": "15.1.4",
56
56
  "@puppeteer/browsers": "^2.13.0",
57
57
  "@types/turndown": "5.0.6",
58
58
  "@xterm/headless": "^6.0.0",