@code-yeongyu/senpi 2026.10.16-2 → 2026.10.16-3

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 (82) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/bundle/chunks/chunk-74YFRVGQ.js +2 -0
  3. package/dist/bundle/chunks/{chunk-KRAABTZY.js → chunk-AVALXFDW.js} +2 -2
  4. package/dist/bundle/chunks/{chunk-V5JFWWGJ.js → chunk-FMYLLJBQ.js} +1 -1
  5. package/dist/bundle/chunks/{chunk-VY43SSYL.js → chunk-HJPX7PBL.js} +30 -27
  6. package/dist/bundle/chunks/{chunk-QQUHMCOM.js → chunk-I5ZJEXTM.js} +1 -1
  7. package/dist/bundle/chunks/chunk-K2EVQGGT.js +31 -0
  8. package/dist/bundle/chunks/chunk-WL4Y6XN6.js +18 -0
  9. package/dist/bundle/chunks/{chunk-Q7RD3NOC.js → chunk-X5VCHHXR.js} +1 -1
  10. package/dist/bundle/chunks/{cli-main-JDL52ADK.js → cli-main-JVPFJGP5.js} +1 -1
  11. package/dist/bundle/chunks/google-generative-ai-AI6PAUPA.js +2 -0
  12. package/dist/bundle/chunks/google-vertex-USNRIFF7.js +2 -0
  13. package/dist/bundle/chunks/google-vertex-adc-JZURL4XM.js +2 -0
  14. package/dist/bundle/chunks/{interactive-mode-7IM7YJYH.js → interactive-mode-BROZRY34.js} +1 -1
  15. package/dist/bundle/chunks/{multi-session-host-3MEEUMYU.js → multi-session-host-SMQR5SCJ.js} +2 -2
  16. package/dist/bundle/chunks/{openai-codex-responses-T26WW2RE.js → openai-codex-responses-NV27Q6VV.js} +1 -1
  17. package/dist/bundle/chunks/{package-manager-cli-UCHXVBQ2.js → package-manager-cli-2QFJY2AS.js} +1 -1
  18. package/dist/bundle/chunks/{rpc-mode-D4BJKWFL.js → rpc-mode-Z45T3NZO.js} +1 -1
  19. package/dist/bundle/chunks/{session-control-endpoint-NBSRSAJS.js → session-control-endpoint-H7FFWF2A.js} +1 -1
  20. package/dist/bundle/chunks/{session-picker-6TSBGWOA.js → session-picker-2O2BNBVE.js} +1 -1
  21. package/dist/bundle/chunks/session-worker.js +36 -33
  22. package/dist/bundle/cli.js +2 -2
  23. package/dist/bundle/index.js +1 -1
  24. package/dist/bundle/rpc-entry.js +1 -1
  25. package/dist/bundle/runtime-manifest.json +1 -1
  26. package/dist/core/agent-session.d.ts +16 -0
  27. package/dist/core/agent-session.js +46 -2
  28. package/dist/core/dynamic-prompt/intent-gate.d.ts +3 -0
  29. package/dist/core/dynamic-prompt/intent-gate.js +4 -3
  30. package/dist/core/dynamic-prompt/policies.d.ts +4 -1
  31. package/dist/core/dynamic-prompt/policies.js +3 -2
  32. package/dist/core/dynamic-prompt/working-task.d.ts +4 -1
  33. package/dist/core/dynamic-prompt/working-task.js +3 -2
  34. package/dist/core/dynamic-prompt/workstation.d.ts +4 -3
  35. package/dist/core/dynamic-prompt/workstation.js +1 -0
  36. package/dist/core/extensions/builtin/goal/index.js +18 -8
  37. package/dist/core/extensions/builtin/goal/monitor-continuation.js +7 -0
  38. package/dist/core/extensions/builtin/goal/reload-reengagement.js +5 -0
  39. package/dist/core/extensions/builtin/index.js +3 -0
  40. package/dist/core/extensions/builtin/prompt-preset/contract.js +6 -1
  41. package/dist/core/extensions/builtin/prompt-preset/gemini-4-argon.d.ts +7 -0
  42. package/dist/core/extensions/builtin/prompt-preset/gemini-4-argon.js +83 -0
  43. package/dist/core/extensions/builtin/prompt-preset/matchers.d.ts +2 -0
  44. package/dist/core/extensions/builtin/prompt-preset/matchers.js +12 -0
  45. package/dist/core/extensions/builtin/prompt-preset/presets.js +3 -0
  46. package/dist/core/extensions/builtin/prompt-preset/settings.d.ts +1 -1
  47. package/dist/core/extensions/builtin/prompt-preset/settings.js +1 -0
  48. package/dist/core/extensions/builtin/vertex-model-garden/auth.d.ts +16 -0
  49. package/dist/core/extensions/builtin/vertex-model-garden/auth.js +19 -0
  50. package/dist/core/extensions/builtin/vertex-model-garden/index.d.ts +6 -0
  51. package/dist/core/extensions/builtin/vertex-model-garden/index.js +27 -0
  52. package/dist/core/extensions/builtin/vertex-model-garden/models.d.ts +3 -0
  53. package/dist/core/extensions/builtin/vertex-model-garden/models.js +34 -0
  54. package/dist/core/extensions/builtin/vertex-model-garden/transport.d.ts +14 -0
  55. package/dist/core/extensions/builtin/vertex-model-garden/transport.js +35 -0
  56. package/dist/core/extensions/types.d.ts +32 -1
  57. package/dist/core/provider-api-key-auth.d.ts +9 -1
  58. package/dist/core/provider-api-key-auth.js +34 -0
  59. package/dist/core/provider-composer.d.ts +23 -0
  60. package/dist/core/settings-manager.d.ts +4 -0
  61. package/dist/core/settings-manager.js +6 -0
  62. package/dist/core/settings-shapes.d.ts +4 -0
  63. package/dist/core/turn-deadline.d.ts +92 -0
  64. package/dist/core/turn-deadline.js +179 -0
  65. package/dist/modes/rpc/client-admission-record.d.ts +1 -0
  66. package/dist/modes/rpc/client-admissions.d.ts +6 -3
  67. package/dist/modes/rpc/client-admissions.js +9 -4
  68. package/dist/modes/rpc/connection-handler.js +8 -3
  69. package/dist/modes/rpc/effect-commands.d.ts +1 -1
  70. package/dist/modes/rpc/effect-commands.js +2 -2
  71. package/dist/modes/rpc/effect-outcome-copy.d.ts +4 -4
  72. package/dist/modes/rpc/effect-outcome-copy.js +4 -4
  73. package/dist/modes/rpc/effect-record.d.ts +2 -0
  74. package/dist/modes/rpc/effect-record.js +2 -0
  75. package/dist/modes/rpc/effect-status.js +1 -1
  76. package/dist/modes/rpc/session-unload.js +4 -1
  77. package/docs/rpc.md +4 -1
  78. package/docs/settings.md +3 -1
  79. package/package.json +6 -6
  80. package/dist/bundle/chunks/chunk-7ASXJ4AD.js +0 -47
  81. package/dist/bundle/chunks/google-generative-ai-YNIOL5FT.js +0 -2
  82. package/dist/bundle/chunks/google-vertex-CF6AYVXL.js +0 -2
@@ -47,6 +47,7 @@ import toolPairGuardExtension from "./tool-pair-guard/index.js";
47
47
  import toolSearchExtension from "./tool-search/index.js";
48
48
  import tpsExtension from "./tps.js";
49
49
  import ttsrExtension from "./ttsr/index.js";
50
+ import vertexModelGardenExtension from "./vertex-model-garden/index.js";
50
51
  import videoInExtension from "./video-in/index.js";
51
52
  import webfetchExtension from "./webfetch/index.js";
52
53
  import websearchExtension from "./websearch/index.js";
@@ -117,6 +118,8 @@ export const builtinExtensions = [
117
118
  { id: "claude-sdk-oauth", factory: anthropicSubscriptionExtension },
118
119
  // Registers unconditionally and reports executable/auth state through its oauth check, so it stays beside the other provider lane.
119
120
  { id: "cursor-cli-oauth", factory: cursorCliOauthExtension },
121
+ // Provider-only lane beside the other provider registrations; no hooks, so order is not load-bearing.
122
+ { id: "vertex-model-garden", factory: vertexModelGardenExtension },
120
123
  // Config reload follows settings-dependent builtins so reloads rebuild their resolved settings before catalog feeders observe them.
121
124
  { id: "config-reload", factory: configReloadExtension },
122
125
  // Shared catalog wiring loads before MCP, which feeds its tools into the shared catalog as the final builtin.
@@ -1,4 +1,4 @@
1
- import { extractClaudeOpusVersion, extractGpt5Version, isClaudeFable5Model, isClaudeFable51Model, isClaudeHaiku55Model, isClaudeOpus5Model, isClaudeOpus55Model, isClaudeSonnet55Model, isDeepseekV4Flash0731Model, isDeepseekV4FlashModel, isDeepseekV4ProModel, isDeepseekV41FlashModel, isGlm52Model, isGlm53Model, isGpt6FamilyModel, isGrok45Model, isGrok46Model, isGrok47Model, isKimiK3Model, isKimiK26Model, isKimiK27Model, isKimiK28Model, isSWE2Model, } from "./matchers.js";
1
+ import { extractClaudeOpusVersion, extractGpt5Version, isClaudeFable5Model, isClaudeFable51Model, isClaudeHaiku55Model, isClaudeOpus5Model, isClaudeOpus55Model, isClaudeSonnet55Model, isDeepseekV4Flash0731Model, isDeepseekV4FlashModel, isDeepseekV4ProModel, isDeepseekV41FlashModel, isGemini4ArgonModel, isGlm52Model, isGlm53Model, isGpt6FamilyModel, isGrok45Model, isGrok46Model, isGrok47Model, isKimiK3Model, isKimiK26Model, isKimiK27Model, isKimiK28Model, isSWE2Model, } from "./matchers.js";
2
2
  export function resolvePresetName(input) {
3
3
  const model = { id: input.modelID, provider: input.providerID, name: input.name };
4
4
  if (isGpt6FamilyModel(model)) {
@@ -72,6 +72,9 @@ export function resolvePresetName(input) {
72
72
  if (isGrok45Model(model)) {
73
73
  return "grok-4.5";
74
74
  }
75
+ if (isGemini4ArgonModel(model)) {
76
+ return "gemini-4-argon";
77
+ }
75
78
  return undefined;
76
79
  }
77
80
  export const PROMPT_PRESET_MODEL_CASES = [
@@ -104,6 +107,7 @@ export const PROMPT_PRESET_MODEL_CASES = [
104
107
  { providerID: "xai", modelID: "grok-4.7", preset: "grok-4.7" },
105
108
  { providerID: "xai", modelID: "grok-4.6", preset: "grok-4.6" },
106
109
  { providerID: "xai", modelID: "grok-4.5", preset: "grok-4.5" },
110
+ { providerID: "google", modelID: "gemini-4-argon", preset: "gemini-4-argon" },
107
111
  ];
108
112
  // Presets a model id can auto-resolve to. gpt-5 is a manual-only preset (settings union +
109
113
  // buildPreset, no model matcher), so it is intentionally absent here: a model-driven parity check
@@ -138,5 +142,6 @@ export const AUTO_RESOLVED_PRESET_NAMES = [
138
142
  "claude-opus-4-7",
139
143
  "claude-opus-4-6",
140
144
  "claude-opus-4-5",
145
+ "gemini-4-argon",
141
146
  ];
142
147
  //# sourceMappingURL=contract.js.map
@@ -0,0 +1,7 @@
1
+ import { type BuildDynamicSystemPromptOptions } from "../../../dynamic-prompt/build.ts";
2
+ export declare const GEMINI_4_ARGON_ROUTING_LINE_RULE = "The line is plain prose, and the tool calls that start the work follow it in the same response";
3
+ export declare const GEMINI_4_ARGON_WORKING_TASK_OPENING = "Writing code is your superpower. A step is solved by writing one `eval` cell that does the work, not by a parade of one-off tool calls: every session tool is reachable from the cell as `tool.<name>(...)`, so the cell reads, searches, inspects, runs commands, and edits files with real control flow - a `for` over every target, an `if`/`else` per case, a `try`/`catch` per item - and fires every independent lookup AT ONCE through `parallel(thunks)`. Bias toward breadth when context is thin: pull in anything even loosely relevant in that wave instead of serially later, since wasted reads cost almost nothing and stale assumptions cost the turn. Reduce in the kernel to the facts the decision needs, keeping every failed or missing item verbatim; a result that hides a failure or a truncated tail is not evidence.\n\nSort the step before you write the cell: independent reads, searches, probes, and edits share one cell; a call whose input is a result you have not seen yet, a deploy, an approval, or a destructive command runs ONE ACTION AT A TIME, each observed before the next. Name the state a cell should produce before it runs and compare the return with that state. When the result must be SEEN rather than read - a page, an image, a layout - make one change, render it, look, then make the next. A direct tool call is the exception, for a single call that settles the step or an action that needs approval; files are read, searched, and edited through the cell's tool calls, never through shell text processing or inline scripts inside a command. Never fill missing parameters with placeholders.";
4
+ export declare const GEMINI_4_ARGON_ERROR_RULE = "Never silently swallow errors. Retry a transient failure (timeout, rate limit, \"try again\") as is; on any other failure change the strategy or the arguments - never repeat the same failed call, and never shotgun-debug with unrelated edits.";
5
+ export declare const GEMINI_4_ARGON_SEARCH_GROUNDING = "## Search Grounding\n\nToday's date is in the environment context and your training data ends before it: when a query is time-sensitive, form search queries from that date, and search before answering about anything \"latest\"; facts that cannot change need no search.";
6
+ export declare function buildGemini4ArgonPrompt(options: BuildDynamicSystemPromptOptions): string;
7
+ //# sourceMappingURL=gemini-4-argon.d.ts.map
@@ -0,0 +1,83 @@
1
+ // Argon system prompt (senpi#3385).
2
+ //
3
+ // 2026-10-15. The provider's published guidance for the previous generation, which
4
+ // Argon continues (model docs: latest-model, prompting-strategies and "Agentic
5
+ // workflows", function-calling "Workarounds for pre-tool text", FAQ 8),
6
+ // says the model answers direct, concise instructions best and over-analyzes the
7
+ // shouting style older prompts used; structured text demanded right before a tool
8
+ // call can fail the call; the Pro line reaches for shell commands over custom
9
+ // tools; the newer releases run diagnostic code before changing anything. The
10
+ // default dynamic core already carries one home per rule, so this preset keeps
11
+ // every default section and changes four spots at their source (prompt-engineering
12
+ // A/B/C, no appended rule), plus the plain `gemini` workstation dialect:
13
+ // - identity names the model, as the Grok preset does (C: only the harness knows
14
+ // which model is loaded).
15
+ // - Intent Gate (terminal): the routing line is plain prose and the tool calls that
16
+ // start the work follow in the same response (B: the pre-tool-text warning and
17
+ // the previous generation's "narrates instead of calling" failure the 2026-02-22 omo
18
+ // overlays and oh-my-pi's reasoning-stall interrupt both guard against).
19
+ // - Working the Task opening, only when `eval` is a session tool: writing code is
20
+ // the model's superpower, one eval cell per step with real control flow and
21
+ // `parallel(thunks)`, one action at a time only for unseen-input, deploy,
22
+ // approval and destructive calls (owner steer 2026-10-15; voice of the ultrawork
23
+ // skill's "Parallel execution" section; Google: 10-20 active tools, parallel
24
+ // calls when independent, code-first inspection).
25
+ // - Policies: transient failures retry as is, other failures change strategy and
26
+ // never repeat the same call (B: the Agentic workflows template, rule 8.2).
27
+ // - `## Search Grounding`, only when `web_search` is a session tool (C: the
28
+ // prompting-strategies "current day" clause; the date itself stays in the
29
+ // environment-context message, senpi#2093).
30
+ // Byte-identical to the default everywhere else; prompt-presets-gemini-4-argon.test.ts
31
+ // checks that section by section.
32
+ import { APP_NAME } from "../../../../config.js";
33
+ import { buildDynamicSystemPrompt, } from "../../../dynamic-prompt/build.js";
34
+ import { buildHandoffSection } from "../../../dynamic-prompt/handoff.js";
35
+ import { buildIntentGate } from "../../../dynamic-prompt/intent-gate.js";
36
+ import { buildPoliciesSection } from "../../../dynamic-prompt/policies.js";
37
+ import { buildStyleSection } from "../../../dynamic-prompt/style.js";
38
+ import { buildVerificationSection } from "../../../dynamic-prompt/verification.js";
39
+ import { buildWorkingTaskSection } from "../../../dynamic-prompt/working-task.js";
40
+ export const GEMINI_4_ARGON_ROUTING_LINE_RULE = "The line is plain prose, and the tool calls that start the work follow it in the same response";
41
+ export const GEMINI_4_ARGON_WORKING_TASK_OPENING = `Writing code is your superpower. A step is solved by writing one \`eval\` cell that does the work, not by a parade of one-off tool calls: every session tool is reachable from the cell as \`tool.<name>(...)\`, so the cell reads, searches, inspects, runs commands, and edits files with real control flow - a \`for\` over every target, an \`if\`/\`else\` per case, a \`try\`/\`catch\` per item - and fires every independent lookup AT ONCE through \`parallel(thunks)\`. Bias toward breadth when context is thin: pull in anything even loosely relevant in that wave instead of serially later, since wasted reads cost almost nothing and stale assumptions cost the turn. Reduce in the kernel to the facts the decision needs, keeping every failed or missing item verbatim; a result that hides a failure or a truncated tail is not evidence.
42
+
43
+ Sort the step before you write the cell: independent reads, searches, probes, and edits share one cell; a call whose input is a result you have not seen yet, a deploy, an approval, or a destructive command runs ONE ACTION AT A TIME, each observed before the next. Name the state a cell should produce before it runs and compare the return with that state. When the result must be SEEN rather than read - a page, an image, a layout - make one change, render it, look, then make the next. A direct tool call is the exception, for a single call that settles the step or an action that needs approval; files are read, searched, and edited through the cell's tool calls, never through shell text processing or inline scripts inside a command. Never fill missing parameters with placeholders.`;
44
+ export const GEMINI_4_ARGON_ERROR_RULE = 'Never silently swallow errors. Retry a transient failure (timeout, rate limit, "try again") as is; on any other failure change the strategy or the arguments - never repeat the same failed call, and never shotgun-debug with unrelated edits.';
45
+ export const GEMINI_4_ARGON_SEARCH_GROUNDING = `## Search Grounding
46
+
47
+ Today's date is in the environment context and your training data ends before it: when a query is time-sensitive, form search queries from that date, and search before answering about anything "latest"; facts that cannot change need no search.`;
48
+ function hasTool(context, name) {
49
+ return context.tools.some((tool) => tool.name === name);
50
+ }
51
+ function buildGemini4ArgonCore(context) {
52
+ const appName = context.appName ?? APP_NAME;
53
+ return [
54
+ `You are ${appName}, a coding agent running on Gemini 4 Argon. Your work should be indistinguishable from a careful senior engineer's.`,
55
+ "",
56
+ buildIntentGate({
57
+ tools: context.tools,
58
+ surface: context.surface,
59
+ routingLineRule: GEMINI_4_ARGON_ROUTING_LINE_RULE,
60
+ }),
61
+ "",
62
+ buildWorkingTaskSection(hasTool(context, "eval") ? { opening: GEMINI_4_ARGON_WORKING_TASK_OPENING } : {}),
63
+ "",
64
+ buildVerificationSection({ surface: context.surface }),
65
+ "",
66
+ context.toolSection,
67
+ "",
68
+ buildPoliciesSection({ errorRule: GEMINI_4_ARGON_ERROR_RULE }),
69
+ "",
70
+ buildHandoffSection({ surface: context.surface }),
71
+ "",
72
+ buildStyleSection({ surface: context.surface }),
73
+ ].join("\n");
74
+ }
75
+ export function buildGemini4ArgonPrompt(options) {
76
+ return buildDynamicSystemPrompt({
77
+ ...options,
78
+ corePrompt: buildGemini4ArgonCore,
79
+ ...(options.selectedTools.includes("web_search") ? { tuningSection: GEMINI_4_ARGON_SEARCH_GROUNDING } : {}),
80
+ workstationDialect: "gemini",
81
+ });
82
+ }
83
+ //# sourceMappingURL=gemini-4-argon.js.map
@@ -51,6 +51,8 @@ export declare const CLAUDE_SONNET_55_MARKERS: readonly ["sonnet-5-5", "sonnet-5
51
51
  export declare function isClaudeSonnet55Model(modelId: string): boolean;
52
52
  export declare const CLAUDE_HAIKU_55_MARKERS: readonly ["haiku-5-5", "haiku-5.5"];
53
53
  export declare function isClaudeHaiku55Model(modelId: string): boolean;
54
+ export declare function hasGemini4ArgonSignal(value: string): boolean;
55
+ export declare function isGemini4ArgonModel(model: ModelWithPromptPresetMetadata): boolean;
54
56
  export type ClaudeOpusVersion = "claude-opus-4-8" | "claude-opus-4-7" | "claude-opus-4-6" | "claude-opus-4-5";
55
57
  export declare function extractClaudeOpusVersion(modelId: string): ClaudeOpusVersion | undefined;
56
58
  //# sourceMappingURL=matchers.d.ts.map
@@ -191,6 +191,18 @@ export function isClaudeHaiku55Model(modelId) {
191
191
  const normalized = normalizeModelId(modelId);
192
192
  return CLAUDE_HAIKU_55_MARKERS.some((marker) => normalized.includes(marker));
193
193
  }
194
+ // Argon id shapes verified against the generated catalogs (2026-10-15):
195
+ // gemini-4-argon (google, google-vertex, github-copilot, opencode, venice),
196
+ // google/gemini-4-argon and its :batch row (openrouter, vercel-ai-gateway),
197
+ // opencode-go's gemini-4-argon-contributor, the Antigravity -low/-medium/-high
198
+ // SKUs, and the catalog display names of the plain and batch rows.
199
+ // Bare gemini-4, other generations of the family and unknown siblings stay out.
200
+ export function hasGemini4ArgonSignal(value) {
201
+ return /(?:^|[/@:._-])gemini[._-]?4[._-]argon(?:$|[/@:._-])/.test(normalizeModelId(value));
202
+ }
203
+ export function isGemini4ArgonModel(model) {
204
+ return hasGemini4ArgonSignal(model.id) || (model.name !== undefined && hasGemini4ArgonSignal(model.name));
205
+ }
194
206
  export function extractClaudeOpusVersion(modelId) {
195
207
  const normalized = normalizeModelId(modelId);
196
208
  if (normalized.includes("opus-4-8")) {
@@ -13,6 +13,7 @@ import { buildDeepseekV41FlashPrompt } from "./deepseek-v4-1-flash.js";
13
13
  import { buildDeepseekV4FlashPrompt } from "./deepseek-v4-flash.js";
14
14
  import { buildDeepseekV4Flash0731Prompt } from "./deepseek-v4-flash-0731.js";
15
15
  import { buildDeepseekV4ProPrompt } from "./deepseek-v4-pro.js";
16
+ import { buildGemini4ArgonPrompt } from "./gemini-4-argon.js";
16
17
  import { buildGlm52Prompt } from "./glm-5-2.js";
17
18
  import { buildGlm53Prompt } from "./glm-5-3.js";
18
19
  import { buildGpt52Prompt } from "./gpt-5.2.js";
@@ -74,6 +75,8 @@ export function buildPreset(name, options) {
74
75
  return { name, prompt: buildGrok46Prompt(options) };
75
76
  case "grok-4.5":
76
77
  return { name, prompt: buildGrok45Prompt(options) };
78
+ case "gemini-4-argon":
79
+ return { name, prompt: buildGemini4ArgonPrompt(options) };
77
80
  case "kimi-k3":
78
81
  return { name, prompt: buildKimiK3Prompt(options) };
79
82
  case "kimi-k2-8":
@@ -1,5 +1,5 @@
1
1
  import type { SettingsManager } from "../../../settings-manager.ts";
2
- export type PromptPresetName = "auto" | "claude-fable-5" | "claude-fable-5-1" | "claude-opus-5-5" | "claude-opus-5" | "claude-sonnet-5-5" | "claude-haiku-5-5" | "claude-opus-4-8" | "claude-opus-4-7" | "claude-opus-4-6" | "claude-opus-4-5" | "deepseek-v4-flash" | "deepseek-v4-flash-0731" | "deepseek-v4-1-flash" | "deepseek-v4-pro" | "glm-5.2" | "glm-5.3" | "grok-4.5" | "grok-4.6" | "grok-4.7" | "kimi-k3" | "kimi-k2-8" | "kimi-k2-7" | "kimi-k2-6" | "gpt-5" | "gpt-5.2" | "gpt-5.3-codex" | "gpt-5.4" | "gpt-5.5" | "gpt-5.6" | "gpt-6-astra";
2
+ export type PromptPresetName = "auto" | "claude-fable-5" | "claude-fable-5-1" | "claude-opus-5-5" | "claude-opus-5" | "claude-sonnet-5-5" | "claude-haiku-5-5" | "claude-opus-4-8" | "claude-opus-4-7" | "claude-opus-4-6" | "claude-opus-4-5" | "deepseek-v4-flash" | "deepseek-v4-flash-0731" | "deepseek-v4-1-flash" | "deepseek-v4-pro" | "glm-5.2" | "glm-5.3" | "gemini-4-argon" | "grok-4.5" | "grok-4.6" | "grok-4.7" | "kimi-k3" | "kimi-k2-8" | "kimi-k2-7" | "kimi-k2-6" | "gpt-5" | "gpt-5.2" | "gpt-5.3-codex" | "gpt-5.4" | "gpt-5.5" | "gpt-5.6" | "gpt-6-astra";
3
3
  export interface PromptPresetSettings {
4
4
  promptPreset: PromptPresetName;
5
5
  }
@@ -16,6 +16,7 @@ export const VALID_PRESETS = new Set([
16
16
  "deepseek-v4-pro",
17
17
  "glm-5.2",
18
18
  "glm-5.3",
19
+ "gemini-4-argon",
19
20
  "grok-4.5",
20
21
  "grok-4.6",
21
22
  "grok-4.7",
@@ -0,0 +1,16 @@
1
+ import type { AuthContext, AuthResult } from "@earendil-works/pi-ai";
2
+ /** The ADC file `gcloud auth application-default login` writes, same as the builtin google-vertex provider. */
3
+ export declare const VERTEX_MODEL_GARDEN_ADC_PATH = "~/.config/gcloud/application_default_credentials.json";
4
+ export declare const VERTEX_MODEL_GARDEN_ADC_SOURCE = "gcloud application default credentials";
5
+ /**
6
+ * Availability through the shared Google Application Default Credentials chain.
7
+ * This is deliberately ambient (senpi#2327): the credentials exist for other
8
+ * gcloud tooling too, so the lane is selectable but never outranks a provider the
9
+ * user configured, and it reports nothing while the chain is absent — the failure
10
+ * belongs at selection time, not at the first request.
11
+ */
12
+ export declare function resolveVertexModelGardenAmbient(input: {
13
+ ctx: AuthContext;
14
+ signal: AbortSignal;
15
+ }): Promise<AuthResult | undefined>;
16
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1,19 @@
1
+ /** The ADC file `gcloud auth application-default login` writes, same as the builtin google-vertex provider. */
2
+ export const VERTEX_MODEL_GARDEN_ADC_PATH = "~/.config/gcloud/application_default_credentials.json";
3
+ export const VERTEX_MODEL_GARDEN_ADC_SOURCE = "gcloud application default credentials";
4
+ /**
5
+ * Availability through the shared Google Application Default Credentials chain.
6
+ * This is deliberately ambient (senpi#2327): the credentials exist for other
7
+ * gcloud tooling too, so the lane is selectable but never outranks a provider the
8
+ * user configured, and it reports nothing while the chain is absent — the failure
9
+ * belongs at selection time, not at the first request.
10
+ */
11
+ export async function resolveVertexModelGardenAmbient(input) {
12
+ input.signal.throwIfAborted();
13
+ const path = (await input.ctx.env("GOOGLE_APPLICATION_CREDENTIALS")) ?? VERTEX_MODEL_GARDEN_ADC_PATH;
14
+ input.signal.throwIfAborted();
15
+ if (!(await input.ctx.fileExists(path)))
16
+ return undefined;
17
+ return { auth: {}, source: VERTEX_MODEL_GARDEN_ADC_SOURCE, ambient: true };
18
+ }
19
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1,6 @@
1
+ import type { ExtensionAPI } from "../../types.ts";
2
+ import { type ResolveVertexAccess } from "./transport.ts";
3
+ export declare const VERTEX_MODEL_GARDEN_PROVIDER_ID = "vertex-garden";
4
+ export declare function registerVertexModelGarden(pi: ExtensionAPI, resolveAccess?: ResolveVertexAccess): void;
5
+ export default function vertexModelGardenExtension(pi: ExtensionAPI): void;
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,27 @@
1
+ import { resolveVertexModelGardenAmbient } from "./auth.js";
2
+ import { VERTEX_MODEL_GARDEN_MODELS } from "./models.js";
3
+ import { defaultResolveVertexAccess, streamVertexModelGarden } from "./transport.js";
4
+ export const VERTEX_MODEL_GARDEN_PROVIDER_ID = "vertex-garden";
5
+ // The request URL is built per call from the ADC-resolved project; this only satisfies registration.
6
+ const REGISTRATION_BASE_URL = "https://aiplatform.googleapis.com/v1";
7
+ export function registerVertexModelGarden(pi, resolveAccess = defaultResolveVertexAccess) {
8
+ pi.registerProvider(VERTEX_MODEL_GARDEN_PROVIDER_ID, {
9
+ name: "Vertex AI Model Garden",
10
+ api: "openai-completions",
11
+ baseUrl: REGISTRATION_BASE_URL,
12
+ // Ambient like the builtin google-vertex ADC lane (senpi#2327): available
13
+ // while the ADC chain is present, never an explicitly configured provider,
14
+ // and never the automatic default over one the user configured.
15
+ ambientAuth: {
16
+ name: "Google Cloud credentials (ADC)",
17
+ resolve: resolveVertexModelGardenAmbient,
18
+ },
19
+ models: VERTEX_MODEL_GARDEN_MODELS,
20
+ streamSimple: (model, context, options) => streamVertexModelGarden(model, context, options, resolveAccess),
21
+ fallbackEligible: () => false,
22
+ });
23
+ }
24
+ export default function vertexModelGardenExtension(pi) {
25
+ registerVertexModelGarden(pi);
26
+ }
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,3 @@
1
+ import type { ProviderModelConfig } from "../../types.ts";
2
+ export declare const VERTEX_MODEL_GARDEN_MODELS: ProviderModelConfig[];
3
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1,34 @@
1
+ // This starter list covers open models through the global OpenAI-compatible endpoint.
2
+ // Marketplace partner models are excluded: they are card-billed and promotional credits do not apply.
3
+ // Prices are the model card's published MaaS list prices, USD per million tokens
4
+ // (https://cloud.google.com/gemini-enterprise-agent-platform/generative-ai/pricing,
5
+ // "Deepseek's models" and "GLM's models"); DeepSeek V4.1 Flash is listed at no charge through 2026-10-16.
6
+ // These endpoints accept no thinking parameters, so no level may be offered as steerable.
7
+ const NO_THINKING_CONTROLS = {
8
+ off: null,
9
+ minimal: null,
10
+ low: null,
11
+ medium: null,
12
+ high: null,
13
+ xhigh: null,
14
+ max: null,
15
+ };
16
+ const OPENAPI_COMPAT = { supportsDeveloperRole: false, supportsReasoningEffort: false };
17
+ function garden(id, name, cost, contextWindow) {
18
+ return {
19
+ id,
20
+ name,
21
+ reasoning: true,
22
+ thinkingLevelMap: NO_THINKING_CONTROLS,
23
+ input: ["text"],
24
+ cost,
25
+ contextWindow,
26
+ maxTokens: 32_000,
27
+ compat: OPENAPI_COMPAT,
28
+ };
29
+ }
30
+ export const VERTEX_MODEL_GARDEN_MODELS = [
31
+ garden("deepseek-ai/deepseek-v4.1-flash-maas", "DeepSeek V4.1 Flash (Vertex)", { input: 0.3, output: 1.2, cacheRead: 0.03, cacheWrite: 0 }, 1_000_000),
32
+ garden("zai-org/glm-5.2-maas", "GLM 5.2 (Vertex)", { input: 1.4, output: 4.4, cacheRead: 0.14, cacheWrite: 0 }, 200_000),
33
+ ];
34
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1,14 @@
1
+ import { type Api, type AssistantMessageEventStream, type Model, type SimpleStreamOptions, type TranscriptContext } from "@earendil-works/pi-ai";
2
+ import { type VertexAdcAccess } from "@earendil-works/pi-ai/api/google-vertex-adc.lazy";
3
+ export declare const VERTEX_MODEL_GARDEN_LOCATION = "global";
4
+ export type ResolveVertexAccess = (options?: SimpleStreamOptions) => Promise<VertexAdcAccess>;
5
+ /**
6
+ * The project comes from its own environment (`options.env`, then the ADC quota
7
+ * project, then `getProjectId()`), never from the API-key slot: a stored secret
8
+ * must not end up in the request URL, and the project may legitimately come from
9
+ * ADC alone.
10
+ */
11
+ export declare const defaultResolveVertexAccess: ResolveVertexAccess;
12
+ export declare function vertexHost(location: string): string;
13
+ export declare function streamVertexModelGarden(model: Model<Api>, context: TranscriptContext, options: SimpleStreamOptions | undefined, resolveAccess?: ResolveVertexAccess): AssistantMessageEventStream;
14
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1,35 @@
1
+ import { getApiProvider, } from "@earendil-works/pi-ai";
2
+ import { getVertexAdcAccess } from "@earendil-works/pi-ai/api/google-vertex-adc.lazy";
3
+ import { lazyStream } from "@earendil-works/pi-ai/api/lazy";
4
+ export const VERTEX_MODEL_GARDEN_LOCATION = "global";
5
+ /**
6
+ * The project comes from its own environment (`options.env`, then the ADC quota
7
+ * project, then `getProjectId()`), never from the API-key slot: a stored secret
8
+ * must not end up in the request URL, and the project may legitimately come from
9
+ * ADC alone.
10
+ */
11
+ export const defaultResolveVertexAccess = (options) => getVertexAdcAccess({ env: options?.env });
12
+ export function vertexHost(location) {
13
+ return location === "global" ? "aiplatform.googleapis.com" : `${location}-aiplatform.googleapis.com`;
14
+ }
15
+ function buildVertexOpenApiBaseUrl(project, location = VERTEX_MODEL_GARDEN_LOCATION) {
16
+ return `https://${vertexHost(location)}/v1/projects/${encodeURIComponent(project)}/locations/${location}/endpoints/openapi`;
17
+ }
18
+ function requireApi(api) {
19
+ const provider = getApiProvider(api);
20
+ if (!provider)
21
+ throw new Error(`API provider ${api} is not registered`);
22
+ return provider;
23
+ }
24
+ export function streamVertexModelGarden(model, context, options, resolveAccess = defaultResolveVertexAccess) {
25
+ return lazyStream(model, async () => {
26
+ const access = await resolveAccess(options);
27
+ const target = { ...model, baseUrl: buildVertexOpenApiBaseUrl(access.project) };
28
+ return requireApi("openai-completions").streamSimple(target, context, {
29
+ ...options,
30
+ apiKey: access.accessToken,
31
+ headers: { ...options?.headers, "x-goog-user-project": access.quotaProject },
32
+ });
33
+ });
34
+ }
35
+ //# sourceMappingURL=transport.js.map
@@ -10,7 +10,7 @@
10
10
  import type { ContextEvent } from "./context-event.ts";
11
11
  export type { ContextEvent } from "./context-event.ts";
12
12
  import type { AgentMessage, AgentTool, AgentToolCallOutcome, AgentToolResult, AgentToolUpdateCallback, ThinkingLevel, ToolExecutionMode } from "@earendil-works/pi-agent-core";
13
- import type { AnyModel, Api, AssistantMessageEvent, AssistantMessageEventStream, ClassifierApi, ConstrainedSamplingConfig, Context, FreeformToolFormat, ImageApi, ImageContent, JsonValue, Message, Model, OAuthCredentials, OAuthLoginCallbacks, Provider, ProviderClassifier, ProviderHeaders, ProviderId, ProviderImages, RefreshModelsContext, SimpleStreamOptions, TextContent, ToolResultMessage, TranscriptContext, Usage } from "@earendil-works/pi-ai";
13
+ import type { AnyModel, Api, AssistantMessageEvent, AssistantMessageEventStream, AuthContext, AuthResult, ClassifierApi, ConstrainedSamplingConfig, Context, FreeformToolFormat, ImageApi, ImageContent, JsonValue, Message, Model, OAuthCredentials, OAuthLoginCallbacks, Provider, ProviderClassifier, ProviderHeaders, ProviderId, ProviderImages, RefreshModelsContext, SimpleStreamOptions, TextContent, ToolResultMessage, TranscriptContext, Usage } from "@earendil-works/pi-ai";
14
14
  import type { AutocompleteItem, AutocompleteProvider, Component, EditorComponent, EditorTheme, ImageProtocol, KeyId, OverlayHandle, OverlayOptions, TUI } from "@earendil-works/pi-tui";
15
15
  import type { Static, TSchema } from "typebox";
16
16
  import type { Theme } from "../../modes/interactive/theme/theme.ts";
@@ -1219,6 +1219,16 @@ export interface AgentEndEvent {
1219
1219
  willRetry?: boolean;
1220
1220
  /** Present when the host can attribute the abort to a user action or internal operation. */
1221
1221
  abortSource?: "user" | "system" | "provider";
1222
+ /**
1223
+ * Present on a system abort the turn deadline lease caused (`turn_inactivity_ms` or
1224
+ * `turn_max_runtime_ms`). A deadline stop is never auto-continued: goal continuations,
1225
+ * monitor backstops and hidden nudges hold off until admitted user input clears the hold.
1226
+ */
1227
+ deadline?: {
1228
+ kind: "inactivity" | "max_runtime";
1229
+ limitMs: number;
1230
+ elapsedMs: number;
1231
+ };
1222
1232
  }
1223
1233
  export type AgentActivityOutcome = "completed" | "aborted" | "error";
1224
1234
  export interface CustomEntryDraft {
@@ -2095,6 +2105,27 @@ export interface ProviderConfig {
2095
2105
  * Use context.publish({ persist: entry }) when the catalog should persist across sessions.
2096
2106
  */
2097
2107
  refreshModels?(context: RefreshModelsContext): Promise<ProviderModelConfig[]>;
2108
+ /**
2109
+ * Ambient api-key auth resolved from a shared cloud credential chain (Google
2110
+ * ADC, AWS env) rather than a credential configured for this provider. The
2111
+ * provider counts as configured only while `resolve` yields a result, and the
2112
+ * ambient marker keeps it from outranking a provider the user configured when
2113
+ * the automatic default model is chosen (senpi#2327). Ignored when `apiKey` or
2114
+ * credential headers already supply auth.
2115
+ */
2116
+ ambientAuth?: {
2117
+ /** Display name, e.g. "Google Cloud credentials". */
2118
+ name?: string;
2119
+ /**
2120
+ * Resolve from the ambient chain. `undefined` means the chain currently
2121
+ * supplies no credential, so the provider stays unavailable. A returned
2122
+ * result should carry `ambient: true`.
2123
+ */
2124
+ resolve(input: {
2125
+ ctx: AuthContext;
2126
+ signal: AbortSignal;
2127
+ }): Promise<AuthResult | undefined>;
2128
+ };
2098
2129
  /** OAuth provider for /login support. The `id` is set automatically from the provider name. */
2099
2130
  oauth?: {
2100
2131
  /** Display name for the provider in login UI. */
@@ -1,10 +1,18 @@
1
- import { type ApiKeyAuth, type ModelAuth, type Provider, type ProviderHeaders } from "@earendil-works/pi-ai";
1
+ import { type ApiKeyAuth, type AuthContext, type AuthResult, type ModelAuth, type Provider, type ProviderHeaders } from "@earendil-works/pi-ai";
2
2
  import type { ModelsJsonProvider } from "./model-config.ts";
3
+ interface AmbientAuthExtensionInput {
4
+ name?: string;
5
+ resolve(input: {
6
+ ctx: AuthContext;
7
+ signal: AbortSignal;
8
+ }): Promise<AuthResult | undefined>;
9
+ }
3
10
  interface ProviderAuthExtensionInput {
4
11
  apiKey?: string;
5
12
  headers?: Record<string, string>;
6
13
  authHeader?: boolean;
7
14
  oauth?: unknown;
15
+ ambientAuth?: AmbientAuthExtensionInput;
8
16
  }
9
17
  export declare function composeApiKeyAuth(providerId: string, base: Provider | undefined, config: ModelsJsonProvider | undefined, extension: ProviderAuthExtensionInput | undefined): ApiKeyAuth | undefined;
10
18
  export declare function configuredApiKey(config: ModelsJsonProvider | undefined, extension: ProviderAuthExtensionInput | undefined): string | undefined;
@@ -8,6 +8,14 @@ export function composeApiKeyAuth(providerId, base, config, extension) {
8
8
  const rawHeaders = configuredHeaders(config, extension);
9
9
  const headerSource = headerAuthResolutionSource(config?.headers, extension?.headers);
10
10
  const authHeader = extension?.authHeader ?? config?.authHeader ?? false;
11
+ const ambient = extension?.ambientAuth;
12
+ if (!inherited && rawKey === undefined && !headerSource && ambient) {
13
+ // A shared cloud credential chain (Google ADC, AWS env) owns the lane: an
14
+ // explicitly configured key, credential headers, or a base provider still
15
+ // win, and a resolution marked ambient never outranks a configured
16
+ // provider in automatic default selection (senpi#2327).
17
+ return ambientApiKeyAuth(providerId, ambient, rawHeaders, headerSource, authHeader);
18
+ }
11
19
  if (!inherited && rawKey === undefined && !headerSource && oauth) {
12
20
  // An OAuth provider with no key, no credential headers and no base normally
13
21
  // gets no api-key auth at all. Providers with ambient credentials still
@@ -101,6 +109,32 @@ function ambientOnlyAuth(providerId, oauth, rawHeaders, headerSource, authHeader
101
109
  resolve,
102
110
  };
103
111
  }
112
+ /**
113
+ * Api-key adapter for extension providers whose credentials live in a shared
114
+ * cloud credential chain (Google ADC, AWS env). No login is offered — the chain
115
+ * is the only source — and `Models.checkAuth` resolves this auth, so the
116
+ * `ambient` marker reaches the provider's auth status.
117
+ */
118
+ function ambientApiKeyAuth(providerId, ambient, rawHeaders, headerSource, authHeader) {
119
+ const resolve = async (input) => {
120
+ const result = await ambient.resolve({ ctx: input.ctx, signal: input.signal });
121
+ if (!result)
122
+ return undefined;
123
+ const explicitEnv = { ...(input.credential?.env ?? {}), ...(result.env ?? {}) };
124
+ const headerEnv = await configContextEnv(Object.values(rawHeaders ?? {}), input.ctx, explicitEnv);
125
+ const headers = await resolveHeadersOrThrow(rawHeaders, `provider "${providerId}"`, headerEnv);
126
+ return {
127
+ ...result,
128
+ auth: withConfiguredAuth(result.auth, headers, authHeader),
129
+ source: result.source ?? headerSource,
130
+ };
131
+ };
132
+ return {
133
+ name: ambient.name ?? "Ambient credentials",
134
+ ambientOnly: true,
135
+ resolve,
136
+ };
137
+ }
104
138
  export function configuredApiKey(config, extension) {
105
139
  return extension?.apiKey ?? config?.apiKey;
106
140
  }
@@ -80,6 +80,15 @@ export interface ProviderConfigInput {
80
80
  extraBody?: Record<string, unknown>;
81
81
  authHeader?: boolean;
82
82
  oauth?: ExtensionOAuthConfig;
83
+ /**
84
+ * Ambient api-key auth resolved from a shared cloud credential chain (Google
85
+ * ADC, AWS env) rather than a credential configured for this provider. The
86
+ * provider counts as configured only while `resolve` yields a result, and the
87
+ * ambient marker keeps it from outranking a provider the user configured when
88
+ * the automatic default model is chosen (senpi#2327). Ignored when `apiKey`,
89
+ * credential headers, or a base provider already supply auth.
90
+ */
91
+ ambientAuth?: ProviderAmbientAuth;
83
92
  retryPolicy?: RetryPolicyProfile;
84
93
  models?: ProviderModelConfig[];
85
94
  refreshModels?(context: RefreshModelsContext): Promise<ProviderModelConfig[]>;
@@ -92,6 +101,20 @@ export interface ProviderConfigInput {
92
101
  */
93
102
  fallbackEligible?(): boolean;
94
103
  }
104
+ /** Ambient api-key auth hook for extension providers (see `ProviderConfigInput.ambientAuth`). */
105
+ export interface ProviderAmbientAuth {
106
+ /** Display name, e.g. "Google Cloud credentials". */
107
+ name?: string;
108
+ /**
109
+ * Resolve from the ambient chain. `undefined` means the chain currently
110
+ * supplies no credential, so the provider stays unavailable. A returned
111
+ * result should carry `ambient: true`.
112
+ */
113
+ resolve(input: {
114
+ ctx: AuthContext;
115
+ signal: AbortSignal;
116
+ }): Promise<AuthResult | undefined>;
117
+ }
95
118
  export type AuthStatus = {
96
119
  configured: boolean;
97
120
  source?: "stored" | "runtime" | "environment" | "fallback" | "models_json_key" | "models_json_command" | HeaderAuthStatusSource;
@@ -108,6 +108,8 @@ export interface Settings {
108
108
  maxPerUserInput?: number;
109
109
  maxToolFreePerMinute?: number;
110
110
  };
111
+ turn_inactivity_ms?: number;
112
+ turn_max_runtime_ms?: number;
111
113
  todo?: TodoSettings;
112
114
  recommendedModels?: string[];
113
115
  favoriteModels?: string[];
@@ -274,6 +276,8 @@ export declare class SettingsManager {
274
276
  maxPerUserInput: number;
275
277
  maxToolFreePerMinute: number;
276
278
  };
279
+ getTurnInactivityMs(): number | undefined;
280
+ getTurnMaxRuntimeMs(): number | undefined;
277
281
  getTodoFirstTurnPlan(): TodoFirstTurnPlan;
278
282
  getTodoTurnEndBackstop(): boolean;
279
283
  isProjectTrusted(): boolean;
@@ -717,6 +717,12 @@ export class SettingsManager {
717
717
  maxToolFreePerMinute: limit(configured?.maxToolFreePerMinute, MAX_TOOL_FREE_ENGINE_TURNS_PER_WINDOW),
718
718
  };
719
719
  }
720
+ getTurnInactivityMs() {
721
+ return this.settings.turn_inactivity_ms;
722
+ }
723
+ getTurnMaxRuntimeMs() {
724
+ return this.settings.turn_max_runtime_ms;
725
+ }
720
726
  getTodoFirstTurnPlan() {
721
727
  const configured = this.settings.todo?.firstTurnPlan;
722
728
  return configured === "remind" || configured === "off" ? configured : "force";
@@ -49,4 +49,8 @@ export interface OpenAISettings {
49
49
  export interface ProviderConcurrencySettings {
50
50
  maxConcurrency?: number;
51
51
  }
52
+ export interface TurnDeadlineSettings {
53
+ turn_inactivity_ms?: number;
54
+ turn_max_runtime_ms?: number;
55
+ }
52
56
  //# sourceMappingURL=settings-shapes.d.ts.map