@ottimis/jack-provider-sdk 0.1.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.
package/README.md ADDED
@@ -0,0 +1,62 @@
1
+ # `@ottimis/jack-provider-sdk`
2
+
3
+ Plugin contract for AI provider integrations in [Jack](https://github.com/ottimis/JACK). Every package that drives an AI coding agent inside Jack — `jack-claude`, `jack-codex`, `jack-gemini`, future `jack-<name>` — depends on this SDK and exports a single `JackProvider` object that satisfies the contract here.
4
+
5
+ ## What's in the box
6
+
7
+ Three layers, all re-exported from the package root:
8
+
9
+ - **`./backend`** — neutral wire-shape contract: `AgentBackend`, `AgentQueryOptions`, `AgentSession`, `AgentPermissionMode`, `AgentEffortLevel`, `AgentHooks`, `BackendName` (open string union — `'sdk'`, `'cli'`, `'acp'`, …), `AgentForkSessionOptions`, `AgentListSessionsOptions`.
10
+ - **`./spawner`** — process-spawning primitives shared by every backend: `ProcessSpawner`, `ProcessHandle`, `SpawnArgs`, `localSpawner`. The host can swap `localSpawner` for a Docker variant (`createDockerSpawner()`) and providers won't notice.
11
+ - **`./provider`** — plugin-level contract: `JackProvider`, `CapabilityMatrix`, `ToolDescriptor`, `ProviderBranding`, `ProviderModelOption`, `ProviderModelDefaults`, `KnowledgeContext`, `KnowledgeMcpResolution`, `SlashCommandSupport`, `SlashCommandDef`, `PrepareSpawnContext`, `InProcessMcpServerSpec`, `PersistedPermissionsApi`, `ProviderDetectResult`, `BackendDescriptor`.
12
+
13
+ `NormalizedMessage` and other wire-shape canonicals are re-exported from `@ottimis/jack-chat-core` so consumers don't need a direct dep on chat-core when their only entrypoint is the wire shape.
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ pnpm add @ottimis/jack-provider-sdk @ottimis/jack-chat-core
19
+ ```
20
+
21
+ `@ottimis/jack-chat-core` is a peer dep — pin a compatible version in your provider package.
22
+
23
+ ## Implementing a `JackProvider`
24
+
25
+ ```ts
26
+ import type { JackProvider } from '@ottimis/jack-provider-sdk'
27
+
28
+ export const myProvider: JackProvider = {
29
+ id: 'my-agent',
30
+ label: 'My Agent',
31
+ branding: { accentColor: '#ff6b6b', iconKey: 'sparkles' },
32
+ detect: async () => ({ installed: true }),
33
+ backends: [{ id: 'sdk', label: 'SDK backend', factory: () => myBackend }],
34
+ defaultBackendId: 'sdk',
35
+ capabilities: { /* honest declaration — see CapabilityMatrix */ },
36
+ modelDefaults: { oneShot: 'my-cheap-model' },
37
+ toolCatalog: [/* ToolDescriptor[] */],
38
+ parseToolName: (raw) => ({ kind: 'native', toolName: raw }),
39
+ applyKnowledgeContext: (ctx, opts) => { /* fold into native opts */ },
40
+ readSessionTranscript: async (opts) => { /* on-disk replay */ }
41
+ }
42
+ ```
43
+
44
+ Full contract documented in the consumer repo: [`docs/provider-package-spec.md`](https://github.com/ottimis/JACK/blob/main/docs/provider-package-spec.md).
45
+
46
+ ## Versioning
47
+
48
+ - **Minor** bumps add optional fields to `JackProvider` / `CapabilityMatrix` / `ToolShape`. Existing providers keep working.
49
+ - **Major** bumps rename or restructure required fields. Provider authors update their pinned range.
50
+
51
+ The host (Jack) declares the minimum SDK version it supports. The plugin loader (Phase 5 follow-up) rejects packages whose declared `peerDependencies.@ottimis/jack-provider-sdk` doesn't satisfy the host's range.
52
+
53
+ ## Build & test
54
+
55
+ ```bash
56
+ pnpm install
57
+ pnpm typecheck
58
+ pnpm test
59
+ pnpm build
60
+ ```
61
+
62
+ `pnpm build` produces dual ESM (`dist/`) + CJS (`dist/cjs/`) output with declaration files. `dist/cjs/package.json` is auto-written with `{ "type": "commonjs" }` so Node resolves the right module format.
@@ -0,0 +1,256 @@
1
+ /**
2
+ * AgentBackend — abstraction that lets the host talk to an AI provider via
3
+ * one of its concrete backends (Claude SDK / Claude CLI / Codex / Gemini ACP / …).
4
+ *
5
+ * Every type on this surface is **provider-neutral**: no SDK/Claude type
6
+ * leaks past this boundary. Each provider package translates between its
7
+ * native wire format and these neutral types inside the backend
8
+ * implementation. The host never imports from a provider's native SDK
9
+ * directly.
10
+ *
11
+ * - The output stream is {@link NormalizedMessage} (parsed by the
12
+ * provider's translator).
13
+ * - The {@link AgentQueryOptions.canUseTool} callback receives a
14
+ * {@link NormalizedPermissionRequest} and resolves to a
15
+ * {@link NormalizedPermissionResult} — the provider does the wire
16
+ * translation on both sides.
17
+ * - The {@link AgentHooks} pipeline is fed {@link NormalizedHookEvent}s.
18
+ * - Provider-private spawn details (e.g. Claude SDK's `executable` +
19
+ * `pathToClaudeCodeExecutable`) ride in the
20
+ * {@link AgentQueryOptions.providerSpawnHints} escape hatch — the host
21
+ * populates them via `JackProvider.prepareSpawnOptions` and never
22
+ * inspects the contents.
23
+ *
24
+ * Selection happens in the host's `backendFactory` → which delegates to
25
+ * the provider registry.
26
+ */
27
+ import type { ProcessSpawner } from './spawner';
28
+ import type { NormalizedMessage, NormalizedPermissionRequest, NormalizedPermissionResult, NormalizedHookEvent } from '@ottimis/jack-chat-core';
29
+ /**
30
+ * Open string union — every provider declares its own backend ids. Today
31
+ * `'sdk'` and `'cli'` are Claude-specific; Gemini ships `'acp'`. The host
32
+ * resolves the active backend by id against the provider's `backends[]`
33
+ * list, so widening to `string` is required for non-Claude providers.
34
+ */
35
+ export type BackendName = string;
36
+ /** Permission gate behaviour. Strings the host may toggle live. */
37
+ export type AgentPermissionMode = 'default' | 'acceptEdits' | 'plan' | 'bypassPermissions';
38
+ /** Settings layers the provider should consult at boot. */
39
+ export type AgentSettingSource = 'user' | 'project' | 'local';
40
+ /**
41
+ * System prompt shape: a plain string (provider replaces its default), or
42
+ * a preset envelope with an optional append (provider extends its default).
43
+ * The preset name is provider-specific; today only `'claude_code'` exists.
44
+ */
45
+ export type AgentSystemPrompt = string | {
46
+ type: 'preset';
47
+ preset: string;
48
+ append?: string;
49
+ };
50
+ /**
51
+ * MCP server configuration — opaque to the host. The host never inspects
52
+ * the inner shape; each provider validates / consumes its own format.
53
+ */
54
+ export type AgentMcpServerConfig = unknown;
55
+ /** Reasoning-effort knob. Provider-validated; not all providers honor every value. */
56
+ export type AgentEffortLevel = 'low' | 'medium' | 'high' | 'xhigh' | 'max';
57
+ /**
58
+ * Hook handler — receives a normalized lifecycle event and may return an
59
+ * opaque object the provider interprets (e.g. `{ continue: false }` to
60
+ * abort a tool call). Most handlers just return `undefined`.
61
+ */
62
+ export type AgentHookHandler = (event: NormalizedHookEvent) => Promise<unknown> | unknown;
63
+ export type AgentHookMatcher = {
64
+ /**
65
+ * Glob over tool names. `'*'` matches every tool. Semantics provider-side
66
+ * but every provider understands `'*'`.
67
+ */
68
+ matcher: string;
69
+ hooks: AgentHookHandler[];
70
+ timeout?: number;
71
+ };
72
+ export type AgentHooks = {
73
+ preToolUse?: AgentHookMatcher[];
74
+ postToolUse?: AgentHookMatcher[];
75
+ };
76
+ /**
77
+ * Context window usage snapshot returned by {@link AgentSession.getContextUsage}.
78
+ * Loose-typed because providers expose different breakdowns; the renderer
79
+ * picks `totalTokens` / `maxTokens` / `percentage` and falls back to the
80
+ * raw bag for advanced UI.
81
+ */
82
+ export type AgentContextUsage = {
83
+ total?: number;
84
+ totalTokens?: number;
85
+ maxTokens?: number;
86
+ rawMaxTokens?: number;
87
+ percentage?: number;
88
+ model?: string;
89
+ by_category?: Record<string, number>;
90
+ [k: string]: unknown;
91
+ };
92
+ /**
93
+ * Listing entry for `~/.claude/projects/<encoded>/<uuid>.jsonl` (or its
94
+ * equivalent under future providers). Loose-typed: providers may expose
95
+ * extra fields that the scanner just passes through.
96
+ */
97
+ export type AgentSessionInfo = {
98
+ sessionId: string;
99
+ cwd?: string;
100
+ summary?: string;
101
+ customTitle?: string | null;
102
+ firstPrompt?: string | null;
103
+ lastModified?: number;
104
+ createdAt?: number | null;
105
+ gitBranch?: string | null;
106
+ fileSize?: number;
107
+ [k: string]: unknown;
108
+ };
109
+ /**
110
+ * One turn of input the host pushes onto the prompt queue. Plain text today
111
+ * — providers wrap it into their wire-native user-message envelope. When a
112
+ * future host needs to push richer turns (e.g. images), this can grow into
113
+ * a structured union without breaking the queue contract.
114
+ */
115
+ export type AgentUserPrompt = string;
116
+ /**
117
+ * Options the host hands to {@link AgentBackend.query}. All fields are
118
+ * neutral; provider-private extras live behind {@link providerSpawnHints}.
119
+ */
120
+ export type AgentQueryOptions = {
121
+ cwd?: string;
122
+ permissionMode?: AgentPermissionMode;
123
+ includePartialMessages?: boolean;
124
+ settingSources?: AgentSettingSource[];
125
+ agentProgressSummaries?: boolean;
126
+ allowedTools?: string[];
127
+ systemPrompt?: AgentSystemPrompt;
128
+ /**
129
+ * Extra working directories beyond `cwd` that the agent can Read/Write
130
+ * across. Populated via `JackProvider.applyKnowledgeContext` from the
131
+ * merged KnowledgeContext (workspace tree + AgentDefinition `kind=dir`
132
+ * knowledge sources).
133
+ */
134
+ additionalDirectories?: string[];
135
+ mcpServers?: Record<string, AgentMcpServerConfig>;
136
+ resume?: string;
137
+ /**
138
+ * Initial model for the spawn. Live switches use
139
+ * {@link AgentSession.setModel}.
140
+ */
141
+ model?: string;
142
+ /**
143
+ * Initial effort level for the spawn. Live switches use
144
+ * {@link AgentSession.applyFlagSettings} with `{ effortLevel: ... }`.
145
+ */
146
+ effort?: AgentEffortLevel;
147
+ /**
148
+ * Process spawner — decides how the provider's child process is launched.
149
+ * Defaults to running locally. For sandboxed sessions, the host passes a
150
+ * spawner created by `createDockerSpawner()`.
151
+ */
152
+ spawner?: ProcessSpawner;
153
+ /** Extra env vars merged into the spawned process environment. */
154
+ env?: {
155
+ [key: string]: string | undefined;
156
+ };
157
+ /**
158
+ * Provider-private spawn details. Populated by
159
+ * `JackProvider.prepareSpawnOptions` and consumed by the matching backend
160
+ * implementation. The host treats this bag as opaque — never read or
161
+ * mutate the inner fields outside the provider package.
162
+ *
163
+ * Today the Claude provider stores `executable` and
164
+ * `pathToClaudeCodeExecutable` here so the SDK backend can locate the
165
+ * asar-unpacked `cli.js` + the macOS Electron Helper.
166
+ */
167
+ providerSpawnHints?: Record<string, unknown>;
168
+ /**
169
+ * Permission gate. Receives a {@link NormalizedPermissionRequest} and
170
+ * resolves to a {@link NormalizedPermissionResult}. Each provider's
171
+ * backend translates between its wire format and these neutral shapes.
172
+ */
173
+ canUseTool?: (req: NormalizedPermissionRequest) => Promise<NormalizedPermissionResult>;
174
+ hooks?: AgentHooks;
175
+ };
176
+ export type AgentQueryInput = {
177
+ prompt: AgentUserPrompt | AsyncIterable<AgentUserPrompt>;
178
+ options: AgentQueryOptions;
179
+ };
180
+ /**
181
+ * Session-like object returned by backend.query(). Mirrors the subset of
182
+ * the provider's runtime control surface that the host actually depends
183
+ * on — intentionally narrow to keep backend implementations small.
184
+ */
185
+ export interface AgentSession extends AsyncIterable<NormalizedMessage> {
186
+ interrupt(): Promise<void>;
187
+ close(): void;
188
+ getContextUsage(): Promise<AgentContextUsage>;
189
+ stopTask(taskId: string): Promise<void>;
190
+ /**
191
+ * Switch permission mode live, without respawning the child process.
192
+ * Mirrors the CLI's Shift+Tab cycle (Claude provider).
193
+ */
194
+ setPermissionMode(mode: AgentPermissionMode | undefined): Promise<void>;
195
+ /**
196
+ * Switch the model live. Pass `undefined` to clear any override and
197
+ * fall back to the provider default.
198
+ */
199
+ setModel(model?: string): Promise<void>;
200
+ /**
201
+ * Merge arbitrary settings into the flag-settings layer at runtime.
202
+ * Used for values the provider exposes only as persisted flags
203
+ * (notably `effortLevel` on Claude).
204
+ */
205
+ applyFlagSettings(settings: Record<string, unknown>): Promise<void>;
206
+ /**
207
+ * Read the effective merged settings layer. The response shape is
208
+ * `{ effective, sources }` where `effective` is the deep-merged result.
209
+ * The host uses it to discover the runtime `effortLevel` the provider
210
+ * booted with.
211
+ */
212
+ getSettings(): Promise<AgentSettingsResponse>;
213
+ }
214
+ /**
215
+ * Slimmed-down shape of the `get_settings` response. Providers may surface
216
+ * hundreds of fields; we only look at the bits the host cares about and
217
+ * keep the rest opaque.
218
+ */
219
+ export type AgentSettingsResponse = {
220
+ effective?: {
221
+ effortLevel?: string;
222
+ [key: string]: unknown;
223
+ };
224
+ sources?: Record<string, unknown>;
225
+ };
226
+ /** Options for backend.listSessions(). */
227
+ export type AgentListSessionsOptions = {
228
+ dir?: string;
229
+ limit?: number;
230
+ offset?: number;
231
+ };
232
+ /** Options for backend.forkSession(). */
233
+ export type AgentForkSessionOptions = {
234
+ dir?: string;
235
+ upToMessageId?: string;
236
+ title?: string;
237
+ };
238
+ export interface AgentBackend {
239
+ readonly name: BackendName;
240
+ query(input: AgentQueryInput): AgentSession;
241
+ /**
242
+ * List provider sessions on disk. Each backend reads its provider's
243
+ * native transcript layout (`~/.claude/projects/...`,
244
+ * `~/.codex/sessions/...`, `~/.gemini/tmp/.../chats/...`).
245
+ */
246
+ listSessions(opts?: AgentListSessionsOptions): Promise<AgentSessionInfo[]>;
247
+ /** Persist a custom title for a session. */
248
+ renameSession(sessionId: string, title: string, opts?: {
249
+ dir?: string;
250
+ }): Promise<void>;
251
+ /** Fork a session into a new one (optionally truncated at a cutoff message). */
252
+ forkSession(sessionId: string, opts?: AgentForkSessionOptions): Promise<{
253
+ sessionId: string;
254
+ }>;
255
+ }
256
+ //# sourceMappingURL=backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * AgentBackend — abstraction that lets the host talk to an AI provider via
3
+ * one of its concrete backends (Claude SDK / Claude CLI / Codex / Gemini ACP / …).
4
+ *
5
+ * Every type on this surface is **provider-neutral**: no SDK/Claude type
6
+ * leaks past this boundary. Each provider package translates between its
7
+ * native wire format and these neutral types inside the backend
8
+ * implementation. The host never imports from a provider's native SDK
9
+ * directly.
10
+ *
11
+ * - The output stream is {@link NormalizedMessage} (parsed by the
12
+ * provider's translator).
13
+ * - The {@link AgentQueryOptions.canUseTool} callback receives a
14
+ * {@link NormalizedPermissionRequest} and resolves to a
15
+ * {@link NormalizedPermissionResult} — the provider does the wire
16
+ * translation on both sides.
17
+ * - The {@link AgentHooks} pipeline is fed {@link NormalizedHookEvent}s.
18
+ * - Provider-private spawn details (e.g. Claude SDK's `executable` +
19
+ * `pathToClaudeCodeExecutable`) ride in the
20
+ * {@link AgentQueryOptions.providerSpawnHints} escape hatch — the host
21
+ * populates them via `JackProvider.prepareSpawnOptions` and never
22
+ * inspects the contents.
23
+ *
24
+ * Selection happens in the host's `backendFactory` → which delegates to
25
+ * the provider registry.
26
+ */
27
+ export {};
28
+ //# sourceMappingURL=backend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend.js","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG"}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ /**
3
+ * AgentBackend — abstraction that lets the host talk to an AI provider via
4
+ * one of its concrete backends (Claude SDK / Claude CLI / Codex / Gemini ACP / …).
5
+ *
6
+ * Every type on this surface is **provider-neutral**: no SDK/Claude type
7
+ * leaks past this boundary. Each provider package translates between its
8
+ * native wire format and these neutral types inside the backend
9
+ * implementation. The host never imports from a provider's native SDK
10
+ * directly.
11
+ *
12
+ * - The output stream is {@link NormalizedMessage} (parsed by the
13
+ * provider's translator).
14
+ * - The {@link AgentQueryOptions.canUseTool} callback receives a
15
+ * {@link NormalizedPermissionRequest} and resolves to a
16
+ * {@link NormalizedPermissionResult} — the provider does the wire
17
+ * translation on both sides.
18
+ * - The {@link AgentHooks} pipeline is fed {@link NormalizedHookEvent}s.
19
+ * - Provider-private spawn details (e.g. Claude SDK's `executable` +
20
+ * `pathToClaudeCodeExecutable`) ride in the
21
+ * {@link AgentQueryOptions.providerSpawnHints} escape hatch — the host
22
+ * populates them via `JackProvider.prepareSpawnOptions` and never
23
+ * inspects the contents.
24
+ *
25
+ * Selection happens in the host's `backendFactory` → which delegates to
26
+ * the provider registry.
27
+ */
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ //# sourceMappingURL=backend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend.js","sourceRoot":"","sources":["../../src/backend.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG"}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ /**
3
+ * `@ottimis/jack-provider-sdk` — public surface for AI provider plugins.
4
+ *
5
+ * In-tree providers (Claude, Codex, Gemini) and any future external
6
+ * package import every neutral type + primitive from here. The host
7
+ * imports from here too so a provider package depends only on this SDK
8
+ * (not on Jack's main process internals) and Jack stays free to evolve
9
+ * its host code without breaking provider authors.
10
+ *
11
+ * Re-exports cover three layers:
12
+ * - `./backend` — neutral wire-shape contract (`AgentBackend`,
13
+ * `AgentQueryOptions`, `AgentSession`, …)
14
+ * - `./spawner` — process-spawning primitives shared by every backend
15
+ * (`ProcessSpawner`, `ProcessHandle`, `localSpawner`, …)
16
+ * - `./provider` — plugin-level contract (`JackProvider`,
17
+ * `CapabilityMatrix`, `ToolDescriptor`, `ProviderBranding`, …)
18
+ *
19
+ * Companion runtime types from `@ottimis/jack-chat-core` (`NormalizedMessage`,
20
+ * `ClientToolHandler`, `ToolShape`, …) are re-exported through `./provider`
21
+ * so consumers don't need to import from chat-core directly when they only
22
+ * need the canonical wire shapes.
23
+ */
24
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
25
+ if (k2 === undefined) k2 = k;
26
+ var desc = Object.getOwnPropertyDescriptor(m, k);
27
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
28
+ desc = { enumerable: true, get: function() { return m[k]; } };
29
+ }
30
+ Object.defineProperty(o, k2, desc);
31
+ }) : (function(o, m, k, k2) {
32
+ if (k2 === undefined) k2 = k;
33
+ o[k2] = m[k];
34
+ }));
35
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
36
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ __exportStar(require("./backend"), exports);
40
+ __exportStar(require("./spawner"), exports);
41
+ __exportStar(require("./provider"), exports);
42
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;;;;;;;;;;;;;;;;AAEH,4CAAyB;AACzB,4CAAyB;AACzB,6CAA0B"}
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ /**
3
+ * JackProvider — plugin contract for an AI provider integration.
4
+ *
5
+ * A provider package (in-tree `providers/claude/`, future external
6
+ * `jack-codex`, `jack-gemini`, …) registers a single `JackProvider` object
7
+ * that wires up everything the host needs to drive that AI:
8
+ *
9
+ * - one or more {@link BackendDescriptor}s (the wire-protocol implementations)
10
+ * - a {@link CapabilityMatrix} so the UI knows what features to show
11
+ * - a {@link ToolDescriptor} catalog so the renderer can map provider-native
12
+ * tool names to canonical Jack shapes
13
+ * - a {@link JackProvider.detect} probe so the gate UI can warn when the
14
+ * host lacks a usable installation
15
+ *
16
+ * This file is the boundary between Jack core and a provider package — keep
17
+ * it free of provider-specific imports.
18
+ */
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/provider.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;GAgBG"}
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ /**
3
+ * ProcessSpawner — abstraction over "how we get a running provider CLI
4
+ * with stdin/stdout pipes attached". Consumed by every backend so they
5
+ * don't need to know whether the process runs locally or inside a Docker
6
+ * container.
7
+ *
8
+ * Design goals:
9
+ * - The shape matches the Anthropic SDK's `SpawnedProcess` / `SpawnOptions`
10
+ * exactly, so a single spawner can be fed to that SDK without
11
+ * translation. Other providers happily reuse the same shape.
12
+ * - The only Docker-aware code lives in the host's `docker/sandbox.ts`
13
+ * which exposes a `createDockerSpawner()` that returns a ProcessSpawner.
14
+ * - The host decides which spawner to use based on `session.sandboxed`
15
+ * and hands it to the provider via `AgentQueryOptions.spawner`.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.localSpawner = void 0;
19
+ const node_child_process_1 = require("node:child_process");
20
+ /**
21
+ * Default local spawner — plain `child_process.spawn`. The returned
22
+ * ChildProcess satisfies ProcessHandle because we pipe all three streams.
23
+ */
24
+ const localSpawner = ({ command, args, cwd, env, signal }) => {
25
+ const cp = (0, node_child_process_1.spawn)(command, args, {
26
+ cwd,
27
+ env,
28
+ stdio: ['pipe', 'pipe', 'pipe']
29
+ });
30
+ signal.addEventListener('abort', () => {
31
+ if (!cp.killed) {
32
+ try {
33
+ cp.kill('SIGTERM');
34
+ }
35
+ catch { /* ignore */ }
36
+ }
37
+ });
38
+ return cp;
39
+ };
40
+ exports.localSpawner = localSpawner;
41
+ //# sourceMappingURL=spawner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawner.js","sourceRoot":"","sources":["../../src/spawner.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;AAEH,2DAA+E;AAqC/E;;;GAGG;AACI,MAAM,YAAY,GAAmB,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE;IAClF,MAAM,EAAE,GAAmC,IAAA,0BAAK,EAAC,OAAO,EAAE,IAAI,EAAE;QAC9D,GAAG;QACH,GAAG;QACH,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;KAChC,CAAC,CAAA;IACF,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;QACpC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC;YACf,IAAI,CAAC;gBAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;QACnD,CAAC;IACH,CAAC,CAAC,CAAA;IACF,OAAO,EAAE,CAAA;AACX,CAAC,CAAA;AAZY,QAAA,YAAY,gBAYxB"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * `@ottimis/jack-provider-sdk` — public surface for AI provider plugins.
3
+ *
4
+ * In-tree providers (Claude, Codex, Gemini) and any future external
5
+ * package import every neutral type + primitive from here. The host
6
+ * imports from here too so a provider package depends only on this SDK
7
+ * (not on Jack's main process internals) and Jack stays free to evolve
8
+ * its host code without breaking provider authors.
9
+ *
10
+ * Re-exports cover three layers:
11
+ * - `./backend` — neutral wire-shape contract (`AgentBackend`,
12
+ * `AgentQueryOptions`, `AgentSession`, …)
13
+ * - `./spawner` — process-spawning primitives shared by every backend
14
+ * (`ProcessSpawner`, `ProcessHandle`, `localSpawner`, …)
15
+ * - `./provider` — plugin-level contract (`JackProvider`,
16
+ * `CapabilityMatrix`, `ToolDescriptor`, `ProviderBranding`, …)
17
+ *
18
+ * Companion runtime types from `@ottimis/jack-chat-core` (`NormalizedMessage`,
19
+ * `ClientToolHandler`, `ToolShape`, …) are re-exported through `./provider`
20
+ * so consumers don't need to import from chat-core directly when they only
21
+ * need the canonical wire shapes.
22
+ */
23
+ export * from './backend';
24
+ export * from './spawner';
25
+ export * from './provider';
26
+ /**
27
+ * Re-export of `NormalizedMessage` from chat-core so consumers don't need
28
+ * to depend on it directly when their only entrypoint into the wire shape
29
+ * is via `AgentBackend`. Mirrors the legacy
30
+ * `src/main/agent/backend.ts` re-export.
31
+ */
32
+ export type { NormalizedMessage } from '@ottimis/jack-chat-core';
33
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA;AACzB,cAAc,YAAY,CAAA;AAE1B;;;;;GAKG;AACH,YAAY,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,26 @@
1
+ /**
2
+ * `@ottimis/jack-provider-sdk` — public surface for AI provider plugins.
3
+ *
4
+ * In-tree providers (Claude, Codex, Gemini) and any future external
5
+ * package import every neutral type + primitive from here. The host
6
+ * imports from here too so a provider package depends only on this SDK
7
+ * (not on Jack's main process internals) and Jack stays free to evolve
8
+ * its host code without breaking provider authors.
9
+ *
10
+ * Re-exports cover three layers:
11
+ * - `./backend` — neutral wire-shape contract (`AgentBackend`,
12
+ * `AgentQueryOptions`, `AgentSession`, …)
13
+ * - `./spawner` — process-spawning primitives shared by every backend
14
+ * (`ProcessSpawner`, `ProcessHandle`, `localSpawner`, …)
15
+ * - `./provider` — plugin-level contract (`JackProvider`,
16
+ * `CapabilityMatrix`, `ToolDescriptor`, `ProviderBranding`, …)
17
+ *
18
+ * Companion runtime types from `@ottimis/jack-chat-core` (`NormalizedMessage`,
19
+ * `ClientToolHandler`, `ToolShape`, …) are re-exported through `./provider`
20
+ * so consumers don't need to import from chat-core directly when they only
21
+ * need the canonical wire shapes.
22
+ */
23
+ export * from './backend';
24
+ export * from './spawner';
25
+ export * from './provider';
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA;AACzB,cAAc,YAAY,CAAA"}