@the-open-engine/zeroshot 6.22.0 → 6.24.0

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 (73) hide show
  1. package/docker/zeroshot-cluster/Dockerfile +7 -0
  2. package/lib/agent-cli-provider/adapters/omp.d.ts +3 -1
  3. package/lib/agent-cli-provider/adapters/omp.d.ts.map +1 -1
  4. package/lib/agent-cli-provider/adapters/omp.js +252 -269
  5. package/lib/agent-cli-provider/adapters/omp.js.map +1 -1
  6. package/lib/agent-cli-provider/contract-invoke.d.ts.map +1 -1
  7. package/lib/agent-cli-provider/contract-invoke.js +68 -14
  8. package/lib/agent-cli-provider/contract-invoke.js.map +1 -1
  9. package/lib/agent-cli-provider/contract-options.d.ts.map +1 -1
  10. package/lib/agent-cli-provider/contract-options.js +5 -3
  11. package/lib/agent-cli-provider/contract-options.js.map +1 -1
  12. package/lib/agent-cli-provider/index.d.ts +6 -0
  13. package/lib/agent-cli-provider/index.d.ts.map +1 -1
  14. package/lib/agent-cli-provider/index.js +12 -1
  15. package/lib/agent-cli-provider/index.js.map +1 -1
  16. package/lib/agent-cli-provider/omp-release.d.ts +6 -1
  17. package/lib/agent-cli-provider/omp-release.d.ts.map +1 -1
  18. package/lib/agent-cli-provider/omp-release.js +41 -2
  19. package/lib/agent-cli-provider/omp-release.js.map +1 -1
  20. package/lib/agent-cli-provider/omp-rpc-bounds.d.ts +7 -0
  21. package/lib/agent-cli-provider/omp-rpc-bounds.d.ts.map +1 -0
  22. package/lib/agent-cli-provider/omp-rpc-bounds.js +27 -0
  23. package/lib/agent-cli-provider/omp-rpc-bounds.js.map +1 -0
  24. package/lib/agent-cli-provider/omp-rpc-driver.d.ts +40 -0
  25. package/lib/agent-cli-provider/omp-rpc-driver.d.ts.map +1 -0
  26. package/lib/agent-cli-provider/omp-rpc-driver.js +494 -0
  27. package/lib/agent-cli-provider/omp-rpc-driver.js.map +1 -0
  28. package/lib/agent-cli-provider/omp-rpc-events.d.ts +28 -0
  29. package/lib/agent-cli-provider/omp-rpc-events.d.ts.map +1 -0
  30. package/lib/agent-cli-provider/omp-rpc-events.js +264 -0
  31. package/lib/agent-cli-provider/omp-rpc-events.js.map +1 -0
  32. package/lib/agent-cli-provider/omp-rpc-protocol.d.ts +1 -1
  33. package/lib/agent-cli-provider/omp-rpc-protocol.d.ts.map +1 -1
  34. package/lib/agent-cli-provider/omp-rpc-protocol.js +8 -3
  35. package/lib/agent-cli-provider/omp-rpc-protocol.js.map +1 -1
  36. package/lib/agent-cli-provider/omp-rpc-session.d.ts +17 -0
  37. package/lib/agent-cli-provider/omp-rpc-session.d.ts.map +1 -0
  38. package/lib/agent-cli-provider/omp-rpc-session.js +6 -0
  39. package/lib/agent-cli-provider/omp-rpc-session.js.map +1 -0
  40. package/lib/agent-cli-provider/provider-registry.d.ts +33 -17
  41. package/lib/agent-cli-provider/provider-registry.d.ts.map +1 -1
  42. package/lib/agent-cli-provider/provider-registry.js +63 -11
  43. package/lib/agent-cli-provider/provider-registry.js.map +1 -1
  44. package/lib/agent-cli-provider/types.d.ts +13 -11
  45. package/lib/agent-cli-provider/types.d.ts.map +1 -1
  46. package/lib/agent-cli-provider/types.js.map +1 -1
  47. package/lib/docker-config.js +122 -5
  48. package/package.json +2 -1
  49. package/src/agent/agent-lifecycle.js +12 -1
  50. package/src/agent/provider-session.js +1 -0
  51. package/src/agent-cli-provider/adapters/omp.ts +276 -329
  52. package/src/agent-cli-provider/contract-invoke.ts +86 -15
  53. package/src/agent-cli-provider/contract-options.ts +5 -3
  54. package/src/agent-cli-provider/index.ts +13 -0
  55. package/src/agent-cli-provider/omp-release.ts +50 -1
  56. package/src/agent-cli-provider/omp-rpc-bounds.ts +28 -0
  57. package/src/agent-cli-provider/omp-rpc-driver.ts +611 -0
  58. package/src/agent-cli-provider/omp-rpc-events.ts +318 -0
  59. package/src/agent-cli-provider/omp-rpc-protocol.ts +8 -3
  60. package/src/agent-cli-provider/omp-rpc-session.ts +20 -0
  61. package/src/agent-cli-provider/provider-registry.ts +118 -23
  62. package/src/agent-cli-provider/types.ts +14 -11
  63. package/src/command-cleanup-ownership.js +307 -0
  64. package/src/isolation-manager.js +535 -89
  65. package/src/omp-config-overlay.js +96 -0
  66. package/src/orchestrator.js +31 -6
  67. package/src/preflight.js +50 -5
  68. package/src/watcher-prompt-channel.js +209 -0
  69. package/task-lib/command-spec-cleanup.js +1 -262
  70. package/task-lib/provider-helper-runtime.js +6 -0
  71. package/task-lib/rpc-watcher.js +186 -0
  72. package/task-lib/runner.js +40 -6
  73. package/task-lib/watcher-output-runtime.js +32 -0
@@ -159,5 +159,12 @@ RUN if [ -n "$PROVIDER_INSTALL" ]; then sh -c "$PROVIDER_INSTALL"; fi
159
159
  # Switch to non-root user (required for --dangerously-skip-permissions)
160
160
  USER node
161
161
 
162
+ # Create a provider's config/overlay roots as the non-root container user (owner-only), so a
163
+ # provider whose credential surface is env/broker-only (no host mount) still gets a writable,
164
+ # private state directory. Registry-fed via PROVIDER_CONFIG_ROOTS (docker.configRoots); no
165
+ # provider name appears in this Dockerfile.
166
+ ARG PROVIDER_CONFIG_ROOTS=""
167
+ RUN if [ -n "$PROVIDER_CONFIG_ROOTS" ]; then for d in $PROVIDER_CONFIG_ROOTS; do mkdir -p "$d" && chmod 700 "$d"; done; fi
168
+
162
169
  # Default command (overridden by vibe)
163
170
  CMD ["bash"]
@@ -1,3 +1,5 @@
1
- import { type ProviderAdapter } from '../types';
1
+ import { type BuildProviderCommandOptions, type ProviderAdapter } from '../types';
2
+ /** Prompt text sent over the RPC `prompt` command — never part of argv for the rpc-stdio lane. */
3
+ export declare function buildOmpPrompt(context: string, options?: BuildProviderCommandOptions): string;
2
4
  export declare const ompAdapter: ProviderAdapter;
3
5
  //# sourceMappingURL=omp.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"omp.d.ts","sourceRoot":"","sources":["../../../src/agent-cli-provider/adapters/omp.ts"],"names":[],"mappings":"AAaA,OAAO,EAUL,KAAK,eAAe,EAIrB,MAAM,UAAU,CAAC;AAkZlB,eAAO,MAAM,UAAU,EAAE,eAkBxB,CAAC"}
1
+ {"version":3,"file":"omp.d.ts","sourceRoot":"","sources":["../../../src/agent-cli-provider/adapters/omp.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,KAAK,2BAA2B,EAQhC,KAAK,eAAe,EAKrB,MAAM,UAAU,CAAC;AAkOlB,kGAAkG;AAClG,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,2BAAgC,GAAG,MAAM,CAEjG;AA8HD,eAAO,MAAM,UAAU,EAAE,eAkBxB,CAAC"}
@@ -1,62 +1,169 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ompAdapter = void 0;
4
- const schema_1 = require("../schema");
4
+ exports.buildOmpPrompt = buildOmpPrompt;
5
5
  const contract_errors_1 = require("../contract-errors");
6
+ const errors_1 = require("../errors");
7
+ const schema_1 = require("../schema");
6
8
  const json_1 = require("../json");
9
+ const omp_release_1 = require("../omp-release");
10
+ const omp_rpc_events_1 = require("../omp-rpc-events");
11
+ const types_1 = require("../types");
7
12
  const common_1 = require("./common");
13
+ function isUnknownFunction(value) {
14
+ return typeof value === 'function';
15
+ }
16
+ function createOmpConfigOverlay() {
17
+ const overlayModule = require('../../../src/omp-config-overlay');
18
+ if (!(0, json_1.isRecord)(overlayModule) || !isUnknownFunction(overlayModule.createOmpConfigOverlay)) {
19
+ throw new Error('src/omp-config-overlay must export createOmpConfigOverlay.');
20
+ }
21
+ const overlay = overlayModule.createOmpConfigOverlay();
22
+ if (!(0, json_1.isRecord)(overlay) ||
23
+ typeof overlay.dir !== 'string' ||
24
+ typeof overlay.file !== 'string') {
25
+ throw new Error('createOmpConfigOverlay() must return { dir, file } strings.');
26
+ }
27
+ return { dir: overlay.dir, file: overlay.file };
28
+ }
8
29
  const MODEL_CATALOG = {};
9
30
  const LEVEL_MAPPING = {
10
- level1: { rank: 1, model: null, reasoningEffort: 'low' },
11
- level2: { rank: 2, model: null, reasoningEffort: 'medium' },
12
- level3: { rank: 3, model: null, reasoningEffort: 'high' },
31
+ level1: { rank: 1, model: '@smol' },
32
+ level2: { rank: 2, model: '@default' },
33
+ level3: { rank: 3, model: '@slow' },
13
34
  };
14
- const IGNORED_EVENT_TYPES = new Set([
15
- 'session',
16
- 'agent_start',
17
- 'agent_end',
18
- 'turn_start',
19
- 'queue_update',
20
- 'compaction_start',
21
- 'compaction_end',
22
- 'auto_retry_start',
23
- 'auto_retry_end',
24
- ]);
25
- function detectCliFeatures(helpText) {
35
+ // Verified against tagged v17.2.1 source: docs/environment-variables.md ("Model/provider
36
+ // authentication", "GitHub/Copilot tokens", "Auth broker", web-search credentials, Bedrock,
37
+ // Azure, Vertex sections) plus docs/providers.md's provider/env-var map. This is the full
38
+ // official host credential inventory OMP itself resolves credentials from — distinct from
39
+ // (and broader than) any narrower automatic Docker env-passthrough allowlist — because OMP
40
+ // routes to 70+ downstream model/search providers and every one of their credential env vars
41
+ // must be detected and redacted from Zeroshot logs/output, not just the handful Zeroshot's
42
+ // own cluster config commonly sets.
43
+ const CREDENTIAL_ENV_KEYS = [
44
+ 'AIMLAPI_API_KEY',
45
+ 'AI_GATEWAY_API_KEY',
46
+ 'ALIBABA_CODING_PLAN_API_KEY',
47
+ 'ALIBABA_TOKEN_PLAN_API_KEY',
48
+ 'ANTHROPIC_API_KEY',
49
+ 'ANTHROPIC_FOUNDRY_API_KEY',
50
+ 'ANTHROPIC_OAUTH_TOKEN',
51
+ 'ANTHROPIC_SEARCH_API_KEY',
52
+ 'AWS_ACCESS_KEY_ID',
53
+ 'AWS_BEARER_TOKEN_BEDROCK',
54
+ 'AWS_SECRET_ACCESS_KEY',
55
+ 'AZURE_OPENAI_API_KEY',
56
+ 'BAILIAN_TOKEN_PLAN_API_KEY',
57
+ 'BRAVE_API_KEY',
58
+ 'CEREBRAS_API_KEY',
59
+ 'CLAUDE_CODE_CLIENT_CERT',
60
+ 'CLAUDE_CODE_CLIENT_KEY',
61
+ 'CLOUDFLARE_AI_GATEWAY_API_KEY',
62
+ 'COPILOT_GITHUB_TOKEN',
63
+ 'CURSOR_ACCESS_TOKEN',
64
+ 'DEEPSEEK_API_KEY',
65
+ 'EXA_API_KEY',
66
+ 'FIREPASS_API_KEY',
67
+ 'FIREWORKS_API_KEY',
68
+ 'GEMINI_API_KEY',
69
+ 'GH_TOKEN',
70
+ 'GITHUB_TOKEN',
71
+ 'GITLAB_TOKEN',
72
+ 'GOOGLE_API_KEY',
73
+ 'GOOGLE_APPLICATION_CREDENTIALS',
74
+ 'GOOGLE_CLOUD_API_KEY',
75
+ 'GROQ_API_KEY',
76
+ 'HF_TOKEN',
77
+ 'HUGGINGFACE_HUB_TOKEN',
78
+ 'JINA_API_KEY',
79
+ 'KAGI_API_KEY',
80
+ 'KILO_API_KEY',
81
+ 'KIMI_SEARCH_API_KEY',
82
+ 'LITELLM_API_KEY',
83
+ 'LLAMA_CPP_API_KEY',
84
+ 'LM_STUDIO_API_KEY',
85
+ 'MINIMAX_API_KEY',
86
+ 'MINIMAX_CODE_API_KEY',
87
+ 'MINIMAX_CODE_CN_API_KEY',
88
+ 'MISTRAL_API_KEY',
89
+ 'MOONSHOT_API_KEY',
90
+ 'MOONSHOT_SEARCH_API_KEY',
91
+ 'NANO_GPT_API_KEY',
92
+ 'NOVITA_API_KEY',
93
+ 'NVIDIA_API_KEY',
94
+ 'OLLAMA_API_KEY',
95
+ 'OLLAMA_CLOUD_API_KEY',
96
+ 'OMP_AUTH_BROKER_TOKEN',
97
+ 'OPENAI_API_KEY',
98
+ 'OPENCODE_API_KEY',
99
+ 'OPENROUTER_API_KEY',
100
+ 'PARALLEL_API_KEY',
101
+ 'PERPLEXITY_API_KEY',
102
+ 'PERPLEXITY_COOKIES',
103
+ 'QIANFAN_API_KEY',
104
+ 'QWEN_OAUTH_TOKEN',
105
+ 'QWEN_PORTAL_API_KEY',
106
+ 'SEARXNG_BASIC_PASSWORD',
107
+ 'SEARXNG_TOKEN',
108
+ 'SILICONFLOW_API_KEY',
109
+ 'SILICONFLOW_CN_API_KEY',
110
+ 'SMITHERY_API_KEY',
111
+ 'SYNTHETIC_API_KEY',
112
+ 'TAVILY_API_KEY',
113
+ 'TOGETHER_API_KEY',
114
+ 'UMANS_AI_CODING_PLAN_API_KEY',
115
+ 'VENICE_API_KEY',
116
+ 'VLLM_API_KEY',
117
+ 'WAFER_SERVERLESS_API_KEY',
118
+ 'XAI_API_KEY',
119
+ 'XAI_OAUTH_TOKEN',
120
+ 'XIAOMI_API_KEY',
121
+ 'XIAOMI_TOKEN_PLAN_AMS_API_KEY',
122
+ 'XIAOMI_TOKEN_PLAN_CN_API_KEY',
123
+ 'XIAOMI_TOKEN_PLAN_SGP_API_KEY',
124
+ 'ZAI_API_KEY',
125
+ 'ZENMUX_API_KEY',
126
+ 'ZHIPU_API_KEY',
127
+ ];
128
+ const VERSION_TOKEN_PATTERN = /(?<![\w.])17\.2\.1(?![\w.])/;
129
+ const MODEL_ID_PATTERN = /^@?[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$/u;
130
+ function detectCliFeatures(helpText, versionText) {
26
131
  const help = helpText ?? '';
27
- const unknown = !help;
132
+ const version = (versionText ?? '').trim();
28
133
  return {
29
134
  provider: 'omp',
30
- supportsModeJson: unknown ? true : /--mode\b/.test(help) && /\bjson\b/.test(help),
31
- supportsPrint: unknown ? true : /-p\b/.test(help) || /--print\b/.test(help),
32
- supportsCwd: unknown ? true : /--cwd\b/.test(help),
33
- supportsAutoApprove: unknown ? true : /--auto-approve\b/.test(help),
34
- supportsModel: unknown ? true : /--model\b/.test(help),
35
- supportsThinking: unknown ? true : /--thinking\b/.test(help),
36
- supportsNoExtensions: unknown ? true : /--no-extensions\b/.test(help),
37
- supportsNoSkills: unknown ? true : /--no-skills\b/.test(help),
38
- supportsNoRules: unknown ? true : /--no-rules\b/.test(help),
39
- supportsNoTitle: unknown ? true : /--no-title\b/.test(help),
40
- unknown,
135
+ versionMatches: VERSION_TOKEN_PATTERN.test(version),
136
+ supportsRpcMode: /(^|\s)rpc(\s|$)/m.test(help),
137
+ supportsConfig: /--config\b/.test(help),
138
+ supportsModel: /--model\b/.test(help),
139
+ supportsThinking: /--thinking\b/.test(help),
140
+ supportsApprovalMode: /--approval-mode\b/.test(help),
141
+ supportsNoTitle: /--no-title\b/.test(help),
142
+ supportsNoSession: /--no-session\b/.test(help),
143
+ supportsSessionDir: /--session-dir\b/.test(help),
144
+ supportsResume: /--resume\b/.test(help),
145
+ unknown: !help,
41
146
  };
42
147
  }
43
148
  function assertRequiredOmpFeatures(options) {
44
149
  const features = (0, common_1.optionFeatures)(options);
45
150
  const required = [
46
- [features.supportsModeJson, '--mode json'],
47
- [features.supportsPrint, '-p/--print'],
48
- [features.supportsCwd, '--cwd'],
49
- [features.supportsAutoApprove, '--auto-approve'],
151
+ [features.versionMatches, `exact OMP version ${omp_release_1.OMP_SUPPORTED_VERSION}`],
152
+ [features.supportsRpcMode, '"rpc" mode'],
153
+ [features.supportsConfig, '--config'],
154
+ [features.supportsModel, '--model'],
155
+ [features.supportsApprovalMode, '--approval-mode'],
156
+ [features.supportsNoTitle, '--no-title'],
157
+ [features.supportsNoSession, '--no-session'],
50
158
  ];
51
- const missing = required.filter(([supported]) => supported === false).map(([, flag]) => flag);
159
+ const missing = required.filter(([supported]) => supported === false).map(([, label]) => label);
52
160
  if (missing.length === 0)
53
161
  return;
54
162
  throw (0, contract_errors_1.contractError)({
55
163
  code: 'unsupported-provider-cli',
56
164
  exitCode: 2,
57
- message: 'omp CLI is missing required non-interactive flag(s): ' +
58
- missing.join(', ') +
59
- '. Update/install @oh-my-pi/pi-coding-agent; Zeroshot will not silently fall back to Pi or another provider.',
165
+ message: `omp CLI is missing required evidence: ${missing.join(', ')}. ${omp_release_1.OMP_REMEDIATION} ` +
166
+ 'Zeroshot will not silently fall back to Pi or another provider.',
60
167
  });
61
168
  }
62
169
  function failClosedUnsupportedSessionControl(options) {
@@ -68,235 +175,64 @@ function failClosedUnsupportedSessionControl(options) {
68
175
  code: 'invalid-field',
69
176
  field,
70
177
  exitCode: 2,
71
- message: 'OMP CLI does not support resume/continue session control; fail closed and start a fresh run instead.',
178
+ message: 'OMP RPC lane runs sessionless (--no-session) in this slice; resume/continue session control is capability-gated off (sessionResume: false).',
72
179
  });
73
180
  }
74
- function addOptionalFlags(args, options) {
75
- const features = (0, common_1.optionFeatures)(options);
76
- if (features.supportsNoExtensions !== false)
77
- args.push('--no-extensions');
78
- if (features.supportsNoSkills !== false)
79
- args.push('--no-skills');
80
- if (features.supportsNoRules !== false)
81
- args.push('--no-rules');
82
- if (features.supportsNoTitle !== false)
83
- args.push('--no-title');
181
+ function rejectMcpConfig(options) {
182
+ if (!options.mcpConfig || options.mcpConfig.length === 0)
183
+ return;
184
+ throw new errors_1.UnsupportedProviderCapabilityError('omp', 'mcpServers', "OMP does not accept Zeroshot's --mcp-config surface; OMP's own discovered MCP/web tools remain governed by its own harness policy, not translated from Claude/Copilot MCP envelopes.");
84
185
  }
85
- function addModelArgs(args, options) {
86
- const features = (0, common_1.optionFeatures)(options);
87
- if (options.modelSpec?.model && features.supportsModel !== false) {
88
- args.push('--model', options.modelSpec.model);
89
- }
90
- if (options.modelSpec?.reasoningEffort && features.supportsThinking !== false) {
91
- args.push('--thinking', options.modelSpec.reasoningEffort);
92
- }
186
+ function resolveModelSelector(options) {
187
+ const model = options.modelSpec?.model;
188
+ if (typeof model === 'string' && model.length > 0)
189
+ return model;
190
+ throw (0, contract_errors_1.contractError)({
191
+ code: 'unsupported-provider-cli',
192
+ exitCode: 2,
193
+ message: 'omp requires a resolved --model selector; none was resolved for this run.',
194
+ });
93
195
  }
94
196
  function collectWarnings(options) {
95
- const features = (0, common_1.optionFeatures)(options);
96
- const warnings = [];
97
- if (options.jsonSchema) {
98
- warnings.push((0, common_1.warning)('omp', 'omp-jsonschema', 'OMP CLI does not support provider-native JSON schema; appending schema instructions to the prompt.'));
99
- }
100
- if (options.modelSpec?.model && features.supportsModel === false) {
101
- warnings.push((0, common_1.warning)('omp', 'omp-model-unsupported', "OMP CLI does not advertise --model; continuing with OMP's own configured model."));
102
- }
103
- if (options.modelSpec?.reasoningEffort && features.supportsThinking === false) {
104
- warnings.push((0, common_1.warning)('omp', 'omp-thinking-unsupported', 'OMP CLI does not advertise --thinking; continuing without a reasoning-effort override.'));
105
- }
106
- return warnings;
197
+ if (!options.jsonSchema)
198
+ return [];
199
+ return [
200
+ (0, common_1.warning)('omp', 'omp-jsonschema', 'OMP CLI does not support provider-native JSON schema; appending schema instructions to the prompt and validating locally.'),
201
+ ];
202
+ }
203
+ /** Prompt text sent over the RPC `prompt` command never part of argv for the rpc-stdio lane. */
204
+ function buildOmpPrompt(context, options = {}) {
205
+ return options.jsonSchema ? (0, schema_1.appendJsonSchemaPrompt)(context, options.jsonSchema) : context;
107
206
  }
108
- function buildCommand(context, options = {}) {
207
+ function buildCommand(_context, options = {}) {
109
208
  assertRequiredOmpFeatures(options);
110
209
  failClosedUnsupportedSessionControl(options);
111
- const finalContext = options.jsonSchema
112
- ? (0, schema_1.appendJsonSchemaPrompt)(context, options.jsonSchema)
113
- : context;
114
- const args = ['--mode', 'json', '-p'];
115
- if (options.cwd)
116
- args.push('--cwd', options.cwd);
117
- args.push('--auto-approve');
118
- addOptionalFlags(args, options);
119
- addModelArgs(args, options);
120
- args.push(finalContext);
210
+ rejectMcpConfig(options);
211
+ const modelSelector = resolveModelSelector(options);
212
+ const warnings = collectWarnings(options);
213
+ const overlay = createOmpConfigOverlay();
214
+ const args = ['--mode', 'rpc', '--no-session', '--model', modelSelector];
215
+ if (options.modelSpec?.reasoningEffort) {
216
+ args.push('--thinking', options.modelSpec.reasoningEffort);
217
+ }
218
+ args.push('--approval-mode', 'yolo', '--no-title', '--config', overlay.file);
121
219
  return (0, common_1.commandSpec)({
122
220
  binary: 'omp',
123
221
  args,
124
222
  env: {},
125
223
  ...(options.cwd === undefined ? {} : { cwd: options.cwd }),
126
- warnings: collectWarnings(options),
224
+ cleanup: [overlay.dir],
225
+ cleanupMetadata: [
226
+ { kind: 'temp-directory', provider: 'omp', path: overlay.dir, reason: 'isolated-config' },
227
+ ],
228
+ warnings,
127
229
  });
128
230
  }
129
231
  function createOmpState() {
130
- return {
131
- ...(0, common_1.createParserState)('omp'),
132
- lastAssistantText: '',
133
- lastAssistantThinking: '',
134
- };
135
- }
136
- function assistantSnapshot(message) {
137
- if ((0, json_1.getString)(message, 'role') !== 'assistant')
138
- return { text: '', thinking: '' };
139
- let text = '';
140
- let thinking = '';
141
- for (const item of (0, json_1.getArray)(message, 'content')) {
142
- if (!(0, json_1.isRecord)(item))
143
- continue;
144
- const type = (0, json_1.getString)(item, 'type');
145
- if (type === 'text') {
146
- text += (0, json_1.getString)(item, 'text') ?? '';
147
- }
148
- else if (type === 'thinking') {
149
- thinking += (0, json_1.getString)(item, 'thinking') ?? '';
150
- }
151
- }
152
- return { text, thinking };
153
- }
154
- function snapshotDelta(previous, current) {
155
- if (!current)
156
- return null;
157
- if (previous === current)
158
- return null;
159
- if (current.startsWith(previous))
160
- return current.slice(previous.length) || null;
161
- return current;
162
- }
163
- function emitAssistantSnapshot(message, state) {
164
- const snapshot = assistantSnapshot(message);
165
- const events = [];
166
- const textDelta = snapshotDelta(state.lastAssistantText ?? '', snapshot.text);
167
- if (textDelta)
168
- events.push({ type: 'text', text: textDelta });
169
- state.lastAssistantText = snapshot.text;
170
- const thinkingDelta = snapshotDelta(state.lastAssistantThinking ?? '', snapshot.thinking);
171
- if (thinkingDelta)
172
- events.push({ type: 'thinking', text: thinkingDelta });
173
- state.lastAssistantThinking = snapshot.thinking;
174
- return events;
175
- }
176
- function parseAssistantEvent(event, state) {
177
- const type = (0, json_1.getString)(event, 'type');
178
- if (type === 'text_delta') {
179
- const delta = (0, json_1.getString)(event, 'delta');
180
- if (!delta)
181
- return null;
182
- state.lastAssistantText += delta;
183
- return { type: 'text', text: delta };
184
- }
185
- if (type === 'thinking_delta') {
186
- const delta = (0, json_1.getString)(event, 'delta');
187
- if (!delta)
188
- return null;
189
- state.lastAssistantThinking += delta;
190
- return { type: 'thinking', text: delta };
191
- }
192
- return null;
193
- }
194
- function parseToolExecutionStart(event, state) {
195
- const toolId = (0, json_1.getOptionalString)(event, 'toolCallId');
196
- state.lastToolId = toolId;
197
- return {
198
- type: 'tool_call',
199
- toolName: (0, json_1.getOptionalString)(event, 'toolName'),
200
- toolId,
201
- input: event.args ?? {},
202
- };
203
- }
204
- function parseToolExecutionUpdate(event, state) {
205
- const toolId = (0, json_1.getOptionalString)(event, 'toolCallId') ?? state.lastToolId;
206
- if (toolId !== undefined)
207
- state.lastToolId = toolId;
208
- if (!Object.prototype.hasOwnProperty.call(event, 'partialResult'))
209
- return null;
210
- return {
211
- type: 'tool_result',
212
- toolId,
213
- content: event.partialResult,
214
- isError: false,
215
- };
216
- }
217
- function parseToolExecutionEnd(event, state) {
218
- const toolId = (0, json_1.getOptionalString)(event, 'toolCallId') ?? state.lastToolId;
219
- return {
220
- type: 'tool_result',
221
- toolId,
222
- content: event.result ?? '',
223
- isError: (0, json_1.getBoolean)(event, 'isError') ?? false,
224
- };
225
- }
226
- function parseTurnEnd(event, state) {
227
- const message = (0, json_1.getRecord)(event, 'message');
228
- const events = [];
229
- if (message !== null) {
230
- events.push(...emitAssistantSnapshot(message, state));
231
- }
232
- const usage = message ? (0, json_1.getRecord)(message, 'usage') ?? {} : {};
233
- const stopReason = message ? (0, json_1.getString)(message, 'stopReason') : null;
234
- const errorMessage = message ? (0, json_1.getString)(message, 'errorMessage') : null;
235
- const snapshot = message ? assistantSnapshot(message) : { text: '', thinking: '' };
236
- const success = stopReason !== 'error' && stopReason !== 'aborted' && !errorMessage;
237
- events.push({
238
- type: 'result',
239
- success,
240
- result: success ? snapshot.text || null : null,
241
- error: success ? null : (errorMessage ?? stopReason ?? 'OMP turn failed'),
242
- inputTokens: (0, json_1.getNumber)(usage, 'input') ?? 0,
243
- outputTokens: (0, json_1.getNumber)(usage, 'output') ?? 0,
244
- cacheReadInputTokens: (0, json_1.getNumber)(usage, 'cacheRead') ?? 0,
245
- cacheCreationInputTokens: (0, json_1.getNumber)(usage, 'cacheWrite') ?? 0,
246
- cost: (0, json_1.getRecord)(usage, 'cost') ?? null,
247
- modelUsage: usage,
248
- });
249
- return events;
250
- }
251
- function parseMessageEvent(type, event, state) {
252
- if (type === 'message_start') {
253
- const message = (0, json_1.getRecord)(event, 'message');
254
- if (message !== null && (0, json_1.getString)(message, 'role') === 'assistant') {
255
- state.lastAssistantText = '';
256
- state.lastAssistantThinking = '';
257
- }
258
- return null;
259
- }
260
- if (type === 'message_update') {
261
- const assistantMessageEvent = (0, json_1.getRecord)(event, 'assistantMessageEvent');
262
- if (assistantMessageEvent !== null) {
263
- const assistantEvent = parseAssistantEvent(assistantMessageEvent, state);
264
- if (assistantEvent !== null)
265
- return assistantEvent;
266
- }
267
- const message = (0, json_1.getRecord)(event, 'message');
268
- return message === null ? null : emitAssistantSnapshot(message, state);
269
- }
270
- if (type !== 'message_end')
271
- return undefined;
272
- const message = (0, json_1.getRecord)(event, 'message');
273
- return message === null ? null : emitAssistantSnapshot(message, state);
274
- }
275
- function parseToolEvent(type, event, state) {
276
- if (type === 'tool_execution_start')
277
- return parseToolExecutionStart(event, state);
278
- if (type === 'tool_execution_update')
279
- return parseToolExecutionUpdate(event, state);
280
- if (type === 'tool_execution_end')
281
- return parseToolExecutionEnd(event, state);
282
- return undefined;
232
+ return (0, common_1.createParserState)('omp');
283
233
  }
284
234
  function parseEvent(line, state) {
285
- const parsed = (0, json_1.tryParseJson)(line);
286
- if (!(0, json_1.isRecord)(parsed))
287
- return null;
288
- const type = (0, json_1.getString)(parsed, 'type');
289
- if (type === null || IGNORED_EVENT_TYPES.has(type))
290
- return null;
291
- const messageEvent = parseMessageEvent(type, parsed, state);
292
- if (messageEvent !== undefined)
293
- return messageEvent;
294
- const toolEvent = parseToolEvent(type, parsed, state);
295
- if (toolEvent !== undefined)
296
- return toolEvent;
297
- if (type === 'turn_end')
298
- return parseTurnEnd(parsed, state);
299
- return null;
235
+ return (0, omp_rpc_events_1.parseNormalizedOmpRpcEventLine)(line, state);
300
236
  }
301
237
  function resolveModelSpec(level, overrides) {
302
238
  return (0, common_1.resolveModelSpecWithConfig)({
@@ -310,36 +246,83 @@ function resolveModelSpec(level, overrides) {
310
246
  function validateModelId(modelId) {
311
247
  if (modelId === undefined || modelId === null)
312
248
  return modelId;
313
- if (typeof modelId !== 'string') {
314
- throw new Error(`Invalid model "${(0, json_1.unknownToMessage)(modelId)}" for provider "omp".`);
249
+ if (typeof modelId !== 'string' || !MODEL_ID_PATTERN.test(modelId)) {
250
+ throw new types_1.InvalidProviderModelError(`Invalid model "${(0, json_1.unknownToMessage)(modelId)}" for provider "omp": must match ${MODEL_ID_PATTERN.source}.`);
315
251
  }
316
252
  return modelId;
317
253
  }
254
+ const OMP_RETRYABLE_PATTERNS = [
255
+ /\brate(?:[_ -]?limit| limited)\b/i,
256
+ /\bquota\b/i,
257
+ /\bresource[_ -]?exhausted\b/i,
258
+ /\btemporar(?:y|ily)\b/i,
259
+ /\boverloaded\b/i,
260
+ /\bservice unavailable\b/i,
261
+ ];
262
+ const OMP_PERMANENT_PATTERNS = [
263
+ // Driver stopReason tokens (see omp-rpc-driver.ts) that always indicate a permanent,
264
+ // non-retryable failure: bad binary/protocol/version/limits/selector/config, malformed or
265
+ // over-bound frames, and missing auth/model evidence.
266
+ /\bunsupported-protocol\b/i,
267
+ /\bunsupported-limits\b/i,
268
+ /\bunsupported-provider-cli\b/i,
269
+ /\bunsupported-ui-method\b/i,
270
+ /\bunsupported-capability\b/i,
271
+ /\bunsafe-config\b/i,
272
+ /\bmalformed-response\b/i,
273
+ /\bmalformed-extension-ui-request\b/i,
274
+ /\bmalformed-host-tool-call\b/i,
275
+ /\bmalformed-host-uri-request\b/i,
276
+ /\bextension-error\b/i,
277
+ /\blocal-only-prompt\b/i,
278
+ /\blifetime-request-id-exceeded\b/i,
279
+ /\bpending-request-exceeded\b/i,
280
+ /\bspawn-hook-failed\b/i,
281
+ // Frame decoder codes (omp-rpc-protocol.ts OmpRpcProtocolError.code values) — every one of
282
+ // these means the wire traffic itself is invalid or out-of-bounds, never a transient condition.
283
+ /\bphysical-frame-too-large\b/i,
284
+ /\bmalformed-physical-frame\b/i,
285
+ /\binvalid-chunk-metadata\b/i,
286
+ /\binvalid-chunk-data\b/i,
287
+ /\bchunk-sequence-must-start-at-zero\b/i,
288
+ /\bchunk-sequence-mismatch\b/i,
289
+ /\bchunk-sequence-exceeds-declared-length\b/i,
290
+ /\bchunk-sequence-length-mismatch\b/i,
291
+ /\bmalformed-json-in-reassembled-frame\b/i,
292
+ /\bnon-object-reassembled-frame\b/i,
293
+ /\binvalid-utf8-in-reassembled-frame\b/i,
294
+ /\binflight-reassembly-bytes-exceeded\b/i,
295
+ /\binterleaved-chunk-sequence\b/i,
296
+ /\binterrupted-chunk-sequence\b/i,
297
+ /\bincomplete-physical-frame\b/i,
298
+ /\bincomplete-chunk-sequence\b/i,
299
+ /\boutbound-frame-too-large\b/i,
300
+ /\bpre-negotiation-rpc-chunk\b/i,
301
+ /\b[\w-]+-bound-exceeded\b/i,
302
+ // Auth/model absence and permission/usage errors surfaced verbatim in OMP output.
303
+ /\bno available authenticated\b/i,
304
+ /\bno keyless model\b/i,
305
+ /\bno valid authentication\b/i,
306
+ /\bmissing api key\b/i,
307
+ /\brun\s*\/login\b/i,
308
+ /\bunknown option\b/i,
309
+ /\bfailed to load\b/i,
310
+ /\bcannot find module\b/i,
311
+ /\bno such file or directory\b/i,
312
+ ];
318
313
  function classifyError(error) {
319
- return (0, common_1.classifyBaseProviderError)(error, [
320
- /\brate(?:[_ -]?limit| limited)\b/i,
321
- /\bquota\b/i,
322
- /\bresource[_ -]?exhausted\b/i,
323
- /\btemporar(?:y|ily)\b/i,
324
- /\boverloaded\b/i,
325
- /\bservice unavailable\b/i,
326
- ], [
327
- /\b(cancelled|canceled|aborted|interrupted)\b/i,
328
- /\brun\s*\/login\b/i,
329
- /\bmissing api key\b/i,
330
- /\bno valid authentication\b/i,
331
- /\bunknown option\b/i,
332
- /\bfailed to load\b/i,
333
- /\bcannot find module\b/i,
334
- /\bno such file or directory\b/i,
335
- ]);
314
+ const message = (0, json_1.unknownToMessage)(error);
315
+ if (/\b(cancelled|canceled)\b/i.test(message)) {
316
+ return { retryable: false, kind: 'cancelled' };
317
+ }
318
+ return (0, common_1.classifyBaseProviderError)(error, OMP_RETRYABLE_PATTERNS, OMP_PERMANENT_PATTERNS);
336
319
  }
337
320
  exports.ompAdapter = {
338
321
  id: 'omp',
339
- displayName: 'OMP',
322
+ displayName: 'OMP (Oh My Pi)',
340
323
  binary: 'omp',
341
- adapterVersion: '1',
342
- credentialEnvKeys: [],
324
+ adapterVersion: '2',
325
+ credentialEnvKeys: CREDENTIAL_ENV_KEYS,
343
326
  modelCatalog: MODEL_CATALOG,
344
327
  levelMapping: LEVEL_MAPPING,
345
328
  defaultLevel: 'level2',