@oh-my-pi/pi-coding-agent 16.0.4 → 16.0.5

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 (71) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/cli.js +341 -261
  3. package/dist/types/advisor/advise-tool.d.ts +9 -0
  4. package/dist/types/cli/args.d.ts +1 -0
  5. package/dist/types/cli/bench-cli.d.ts +6 -0
  6. package/dist/types/commands/launch.d.ts +3 -0
  7. package/dist/types/config/settings-schema.d.ts +91 -2
  8. package/dist/types/extensibility/extensions/runner.d.ts +5 -2
  9. package/dist/types/extensibility/extensions/types.d.ts +8 -7
  10. package/dist/types/extensibility/shared-events.d.ts +22 -1
  11. package/dist/types/main.d.ts +1 -0
  12. package/dist/types/modes/components/status-line/component.d.ts +1 -1
  13. package/dist/types/modes/components/status-line/context-thresholds.d.ts +0 -1
  14. package/dist/types/modes/rpc/rpc-types.d.ts +1 -1
  15. package/dist/types/modes/utils/context-usage.d.ts +12 -0
  16. package/dist/types/sdk.d.ts +3 -1
  17. package/dist/types/session/agent-session.d.ts +20 -0
  18. package/dist/types/session/session-persistence.d.ts +4 -0
  19. package/dist/types/tools/read.d.ts +1 -0
  20. package/dist/types/tui/code-cell.d.ts +2 -0
  21. package/dist/types/utils/image-vision-fallback.d.ts +28 -0
  22. package/dist/types/web/search/providers/base.d.ts +1 -0
  23. package/dist/types/web/search/providers/gemini.d.ts +1 -0
  24. package/package.json +12 -12
  25. package/src/advisor/__tests__/advisor.test.ts +59 -0
  26. package/src/advisor/advise-tool.ts +13 -0
  27. package/src/cli/args.ts +1 -0
  28. package/src/cli/bench-cli.ts +30 -7
  29. package/src/cli/flag-tables.ts +8 -0
  30. package/src/collab/host.ts +2 -2
  31. package/src/commands/launch.ts +3 -0
  32. package/src/config/settings-schema.ts +84 -2
  33. package/src/eval/py/runner.py +44 -0
  34. package/src/extensibility/extensions/runner.ts +20 -2
  35. package/src/extensibility/extensions/types.ts +16 -5
  36. package/src/extensibility/shared-events.ts +24 -0
  37. package/src/internal-urls/docs-index.generated.ts +7 -7
  38. package/src/main.ts +12 -5
  39. package/src/modes/components/branch-summary-message.ts +1 -0
  40. package/src/modes/components/collab-prompt-message.ts +9 -7
  41. package/src/modes/components/compaction-summary-message.ts +1 -0
  42. package/src/modes/components/custom-message.ts +1 -0
  43. package/src/modes/components/footer.ts +6 -5
  44. package/src/modes/components/hook-message.ts +1 -0
  45. package/src/modes/components/read-tool-group.ts +9 -3
  46. package/src/modes/components/skill-message.ts +1 -0
  47. package/src/modes/components/status-line/component.ts +131 -14
  48. package/src/modes/components/status-line/context-thresholds.ts +0 -1
  49. package/src/modes/components/todo-reminder.ts +1 -0
  50. package/src/modes/components/ttsr-notification.ts +1 -0
  51. package/src/modes/components/user-message.ts +6 -6
  52. package/src/modes/controllers/event-controller.ts +2 -7
  53. package/src/modes/controllers/selector-controller.ts +10 -3
  54. package/src/modes/interactive-mode.ts +4 -2
  55. package/src/modes/rpc/rpc-types.ts +1 -1
  56. package/src/modes/utils/context-usage.ts +28 -15
  57. package/src/prompts/tools/image-attachment-describe-system.md +8 -0
  58. package/src/prompts/tools/image-attachment-describe.md +10 -0
  59. package/src/sdk.ts +14 -18
  60. package/src/session/agent-session.ts +564 -231
  61. package/src/session/session-loader.ts +19 -32
  62. package/src/session/session-persistence.ts +27 -11
  63. package/src/ssh/connection-manager.ts +3 -2
  64. package/src/task/executor.ts +1 -1
  65. package/src/tools/image-gen.ts +67 -25
  66. package/src/tools/read.ts +28 -6
  67. package/src/tui/code-cell.ts +44 -3
  68. package/src/utils/image-vision-fallback.ts +197 -0
  69. package/src/web/search/index.ts +12 -0
  70. package/src/web/search/providers/base.ts +1 -0
  71. package/src/web/search/providers/gemini.ts +56 -18
@@ -94,7 +94,7 @@ export function computeNonMessageTokens(session: AgentSession): number {
94
94
  * the status-line fast path intentionally uses the equivalent collapsed total
95
95
  * in `computeNonMessageTokens`.
96
96
  */
97
- function computeNonMessageBreakdown(session: AgentSession): {
97
+ export function computeNonMessageBreakdown(session: AgentSession): {
98
98
  skillsTokens: number;
99
99
  toolsTokens: number;
100
100
  systemContextTokens: number;
@@ -119,22 +119,37 @@ export function computeContextBreakdown(
119
119
  const model = session.model;
120
120
  const contextWindow = model?.contextWindow ?? 0;
121
121
 
122
+ const breakdown = typeof session.getContextBreakdown === "function" ? session.getContextBreakdown() : undefined;
123
+
122
124
  let messagesTokens = 0;
123
- const convo = session.messages;
124
- if (convo) {
125
- for (const message of convo) {
126
- messagesTokens += estimateTokens(message);
125
+ let skillsTokens = 0;
126
+ let toolsTokens = 0;
127
+ let systemContextTokens = 0;
128
+ let systemPromptTokens = 0;
129
+ let usedTokens = 0;
130
+
131
+ if (breakdown) {
132
+ messagesTokens = breakdown.messagesTokens;
133
+ skillsTokens = breakdown.skillsTokens;
134
+ toolsTokens = breakdown.systemToolsTokens;
135
+ systemContextTokens = breakdown.systemContextTokens;
136
+ systemPromptTokens = breakdown.systemPromptTokens;
137
+ usedTokens = breakdown.usedTokens;
138
+ } else {
139
+ const convo = session.messages;
140
+ if (convo) {
141
+ for (const message of convo) {
142
+ messagesTokens += estimateTokens(message);
143
+ }
127
144
  }
145
+ const nonMessage = computeNonMessageBreakdown(session);
146
+ skillsTokens = nonMessage.skillsTokens;
147
+ toolsTokens = nonMessage.toolsTokens;
148
+ systemContextTokens = nonMessage.systemContextTokens;
149
+ systemPromptTokens = nonMessage.systemPromptTokens;
150
+ usedTokens = skillsTokens + toolsTokens + systemContextTokens + systemPromptTokens + messagesTokens;
128
151
  }
129
152
 
130
- // The rendered system prompt already contains the skill descriptions and the
131
- // markdown tool descriptions. To present a non-overlapping breakdown:
132
- // System prompt = total system prompt text - skills section (tool descriptions stay)
133
- // Tools = JSON tool schema sent separately on the wire
134
- // Skills = the skill list embedded in the system prompt
135
- // Messages = conversation messages
136
- const { skillsTokens, toolsTokens, systemContextTokens, systemPromptTokens } = computeNonMessageBreakdown(session);
137
-
138
153
  const categories: CategoryInfo[] = [
139
154
  { id: "systemPrompt", label: "System prompt", tokens: systemPromptTokens, color: "accent", glyph: CELL_FILLED },
140
155
  { id: "systemTools", label: "System tools", tokens: toolsTokens, color: "warning", glyph: CELL_FILLED },
@@ -155,8 +170,6 @@ export function computeContextBreakdown(
155
170
  },
156
171
  ];
157
172
 
158
- const usedTokens = categories.reduce((sum, c) => sum + c.tokens, 0);
159
-
160
173
  let autoCompactBufferTokens = 0;
161
174
  if (contextWindow > 0) {
162
175
  const compactionSettings = session.settings.getGroup("compaction") as CompactionSettings;
@@ -0,0 +1,8 @@
1
+ You are an image-analysis assistant. The user attached an image to a model that cannot see images, so your description is injected into that model's context in place of the image. The downstream model relies entirely on your text — it never sees the pixels.
2
+
3
+ Core behavior:
4
+ - Be faithful and evidence-first: distinguish direct observations from inferences.
5
+ - Transcribe ALL visible text verbatim, preserving casing, punctuation, and layout order. Mark unreadable segments explicitly rather than guessing.
6
+ - NEVER fabricate occluded, blurry, or uncertain details — say what is uncertain.
7
+ - Be thorough but compact: prefer dense, information-rich prose over filler.
8
+ - Do not add meta commentary, preambles ("This image shows…"), or closing remarks. Output only the description.
@@ -0,0 +1,10 @@
1
+ Describe this image in enough detail that a model which cannot see it can reason about its content.
2
+
3
+ Cover, where present:
4
+ - The overall scene, subject, and what is happening.
5
+ - People, objects, and their relationships, positions, colors, and counts.
6
+ - All visible text, transcribed verbatim (OCR).
7
+ - UI/screenshot elements: labels, buttons, inputs, states, errors, highlighted or disabled controls.
8
+ - Diagrams, charts, tables: structure, axes, series, and the values they encode.
9
+
10
+ Flag anything ambiguous or unreadable. Output the description as plain prose only.
package/src/sdk.ts CHANGED
@@ -21,6 +21,7 @@ import {
21
21
  getOpenAICodexTransportDetails,
22
22
  prewarmOpenAICodexResponses,
23
23
  } from "@oh-my-pi/pi-ai/providers/openai-codex-responses";
24
+ import { FALLBACK_DIALECT, preferredDialect } from "@oh-my-pi/pi-catalog/identity";
24
25
  import type { Component } from "@oh-my-pi/pi-tui";
25
26
  import {
26
27
  $env,
@@ -40,7 +41,6 @@ import { AutoLearnController, buildAutoLearnInstructions } from "./autolearn/con
40
41
  import { loadCapability } from "./capability";
41
42
  import { type Rule, ruleCapability, setActiveRules } from "./capability/rule";
42
43
  import { bucketRules } from "./capability/rule-buckets";
43
- import { createApiKeyResolver } from "./config/api-key-resolver";
44
44
  import { shouldEnableAppendOnlyContext } from "./config/append-only-context-mode";
45
45
  import { ModelRegistry } from "./config/model-registry";
46
46
  import {
@@ -415,6 +415,8 @@ export interface CreateAgentSessionOptions {
415
415
  providerSessionId?: string;
416
416
  /** Optional provider-facing prompt cache key, distinct from request lineage. */
417
417
  providerPromptCacheKey?: string;
418
+ /** Absolute wall-clock deadline in Unix epoch milliseconds. */
419
+ deadline?: number;
418
420
 
419
421
  /** Custom tools to register (in addition to built-in tools). Accepts both CustomTool and ToolDefinition. */
420
422
  customTools?: (CustomTool | ToolDefinition)[];
@@ -567,10 +569,15 @@ export type DialectFormat = "auto" | "native" | Dialect;
567
569
 
568
570
  export function resolveDialect(
569
571
  format: DialectFormat,
570
- model: Pick<Model, "supportsTools"> | undefined,
572
+ model: (Pick<Model, "supportsTools"> & Partial<Pick<Model, "id">>) | undefined,
571
573
  ): Dialect | undefined {
572
574
  if (format === "native") return undefined;
573
- if (format === "auto") return model?.supportsTools === false ? "glm" : undefined;
575
+ if (format === "auto") {
576
+ if (model?.supportsTools !== false) return undefined;
577
+ if (!model.id) return "glm";
578
+ const preferred = preferredDialect(model.id);
579
+ return preferred === FALLBACK_DIALECT ? "glm" : preferred;
580
+ }
574
581
  return format;
575
582
  }
576
583
 
@@ -2458,6 +2465,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
2458
2465
  onResponse,
2459
2466
  sessionId: providerSessionId,
2460
2467
  promptCacheKey: options.providerPromptCacheKey,
2468
+ deadline: options.deadline,
2461
2469
  transformContext,
2462
2470
  transformProviderContext,
2463
2471
  steeringMode: settings.get("steeringMode") ?? "one-at-a-time",
@@ -2475,28 +2483,16 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
2475
2483
  kimiApiFormat: settings.get("providers.kimiApiFormat") ?? "anthropic",
2476
2484
  preferWebsockets: preferOpenAICodexWebsockets,
2477
2485
  getToolContext: tc => toolContextStore.getContext(tc),
2478
- getApiKey: async (provider, ctx) => {
2479
- // Read agent.sessionId at call time so credential selection stays aligned
2480
- // with metadataResolver after /new, fork, resume, or branch switches.
2481
- // Retry steps (ctx carries an auth error) drive the central a/b/c
2482
- // policy — force-refresh the same account, then rotate to a sibling —
2483
- // and may legitimately yield no key when every account is exhausted.
2484
- if (ctx?.error !== undefined) {
2485
- return createApiKeyResolver(modelRegistry, provider, { sessionId: agent.sessionId })(ctx);
2486
- }
2487
- const key = await modelRegistry.getApiKeyForProvider(provider, agent.sessionId);
2488
- if (!key) {
2489
- throw new Error(`No API key found for provider "${provider}"`);
2490
- }
2491
- return key;
2492
- },
2486
+ getApiKey: requestModel => modelRegistry.resolver(requestModel, agent.sessionId),
2493
2487
  streamFn: (streamModel, context, streamOptions) => {
2494
2488
  const openrouterRoutingPreset = settings.get("providers.openrouterVariant");
2495
2489
  const openrouterVariant =
2496
2490
  openrouterRoutingPreset && openrouterRoutingPreset !== "default" ? openrouterRoutingPreset : undefined;
2491
+ const antigravityEndpointMode = settings.get("providers.antigravityEndpoint");
2497
2492
  return streamSimple(streamModel, context, {
2498
2493
  ...streamOptions,
2499
2494
  openrouterVariant: streamOptions?.openrouterVariant ?? openrouterVariant,
2495
+ antigravityEndpointMode: streamOptions?.antigravityEndpointMode ?? antigravityEndpointMode,
2500
2496
  });
2501
2497
  },
2502
2498
  cursorExecHandlers,