@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.
@@ -0,0 +1,19 @@
1
+ /**
2
+ * JackProvider — plugin contract for an AI provider integration.
3
+ *
4
+ * A provider package (in-tree `providers/claude/`, future external
5
+ * `jack-codex`, `jack-gemini`, …) registers a single `JackProvider` object
6
+ * that wires up everything the host needs to drive that AI:
7
+ *
8
+ * - one or more {@link BackendDescriptor}s (the wire-protocol implementations)
9
+ * - a {@link CapabilityMatrix} so the UI knows what features to show
10
+ * - a {@link ToolDescriptor} catalog so the renderer can map provider-native
11
+ * tool names to canonical Jack shapes
12
+ * - a {@link JackProvider.detect} probe so the gate UI can warn when the
13
+ * host lacks a usable installation
14
+ *
15
+ * This file is the boundary between Jack core and a provider package — keep
16
+ * it free of provider-specific imports.
17
+ */
18
+ export {};
19
+ //# 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,55 @@
1
+ /**
2
+ * ProcessSpawner — abstraction over "how we get a running provider CLI
3
+ * with stdin/stdout pipes attached". Consumed by every backend so they
4
+ * don't need to know whether the process runs locally or inside a Docker
5
+ * container.
6
+ *
7
+ * Design goals:
8
+ * - The shape matches the Anthropic SDK's `SpawnedProcess` / `SpawnOptions`
9
+ * exactly, so a single spawner can be fed to that SDK without
10
+ * translation. Other providers happily reuse the same shape.
11
+ * - The only Docker-aware code lives in the host's `docker/sandbox.ts`
12
+ * which exposes a `createDockerSpawner()` that returns a ProcessSpawner.
13
+ * - The host decides which spawner to use based on `session.sandboxed`
14
+ * and hands it to the provider via `AgentQueryOptions.spawner`.
15
+ */
16
+ import type { Readable, Writable } from 'node:stream';
17
+ /**
18
+ * Minimal process handle that both `ChildProcess` (node) and the Anthropic
19
+ * SDK's `SpawnedProcess` satisfy. Deliberately identical to the SDK
20
+ * interface so that values of this type can be handed back to the SDK
21
+ * verbatim.
22
+ */
23
+ export interface ProcessHandle {
24
+ stdin: Writable;
25
+ stdout: Readable;
26
+ readonly killed: boolean;
27
+ readonly exitCode: number | null;
28
+ kill(signal?: NodeJS.Signals): boolean;
29
+ on(event: 'exit', listener: (code: number | null, signal: NodeJS.Signals | null) => void): void;
30
+ on(event: 'error', listener: (error: Error) => void): void;
31
+ once(event: 'exit', listener: (code: number | null, signal: NodeJS.Signals | null) => void): void;
32
+ once(event: 'error', listener: (error: Error) => void): void;
33
+ off(event: 'exit', listener: (code: number | null, signal: NodeJS.Signals | null) => void): void;
34
+ off(event: 'error', listener: (error: Error) => void): void;
35
+ }
36
+ /**
37
+ * Arguments handed to a spawner. Matches the Anthropic SDK `SpawnOptions`
38
+ * shape so the same function can be plugged into `spawnClaudeCodeProcess`.
39
+ */
40
+ export interface SpawnArgs {
41
+ command: string;
42
+ args: string[];
43
+ cwd?: string;
44
+ env: {
45
+ [k: string]: string | undefined;
46
+ };
47
+ signal: AbortSignal;
48
+ }
49
+ export type ProcessSpawner = (args: SpawnArgs) => ProcessHandle;
50
+ /**
51
+ * Default local spawner — plain `child_process.spawn`. The returned
52
+ * ChildProcess satisfies ProcessHandle because we pipe all three streams.
53
+ */
54
+ export declare const localSpawner: ProcessSpawner;
55
+ //# sourceMappingURL=spawner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawner.d.ts","sourceRoot":"","sources":["../src/spawner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAErD;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,QAAQ,CAAA;IACf,MAAM,EAAE,QAAQ,CAAA;IAChB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,GAAG,OAAO,CAAA;IACtC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI,CAAA;IAC/F,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAA;IAC1D,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI,CAAA;IACjG,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAA;IAC5D,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI,CAAA;IAChG,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAA;CAC5D;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE;QAAE,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;KAAE,CAAA;IACxC,MAAM,EAAE,WAAW,CAAA;CACpB;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,SAAS,KAAK,aAAa,CAAA;AAE/D;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,cAY1B,CAAA"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * ProcessSpawner — abstraction over "how we get a running provider CLI
3
+ * with stdin/stdout pipes attached". Consumed by every backend so they
4
+ * don't need to know whether the process runs locally or inside a Docker
5
+ * container.
6
+ *
7
+ * Design goals:
8
+ * - The shape matches the Anthropic SDK's `SpawnedProcess` / `SpawnOptions`
9
+ * exactly, so a single spawner can be fed to that SDK without
10
+ * translation. Other providers happily reuse the same shape.
11
+ * - The only Docker-aware code lives in the host's `docker/sandbox.ts`
12
+ * which exposes a `createDockerSpawner()` that returns a ProcessSpawner.
13
+ * - The host decides which spawner to use based on `session.sandboxed`
14
+ * and hands it to the provider via `AgentQueryOptions.spawner`.
15
+ */
16
+ import { spawn } from 'node:child_process';
17
+ /**
18
+ * Default local spawner — plain `child_process.spawn`. The returned
19
+ * ChildProcess satisfies ProcessHandle because we pipe all three streams.
20
+ */
21
+ export const localSpawner = ({ command, args, cwd, env, signal }) => {
22
+ const cp = spawn(command, args, {
23
+ cwd,
24
+ env,
25
+ stdio: ['pipe', 'pipe', 'pipe']
26
+ });
27
+ signal.addEventListener('abort', () => {
28
+ if (!cp.killed) {
29
+ try {
30
+ cp.kill('SIGTERM');
31
+ }
32
+ catch { /* ignore */ }
33
+ }
34
+ });
35
+ return cp;
36
+ };
37
+ //# sourceMappingURL=spawner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawner.js","sourceRoot":"","sources":["../src/spawner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,KAAK,EAAuC,MAAM,oBAAoB,CAAA;AAqC/E;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAmB,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE;IAClF,MAAM,EAAE,GAAmC,KAAK,CAAC,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"}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@ottimis/jack-provider-sdk",
3
+ "version": "0.1.0",
4
+ "description": "Plugin contract for AI provider integrations in Jack — backend interface, capability matrix, spawner primitives, knowledge context. Consumed both by in-tree providers and external packages.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/ottimis/JACK-provider-sdk.git"
9
+ },
10
+ "type": "module",
11
+ "main": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js",
17
+ "require": "./dist/cjs/index.js"
18
+ }
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "src",
23
+ "README.md"
24
+ ],
25
+ "scripts": {
26
+ "build": "pnpm clean && tsc && tsc -p tsconfig.cjs.json && node -e \"require('fs').writeFileSync('dist/cjs/package.json', JSON.stringify({type:'commonjs'}))\"",
27
+ "typecheck": "tsc --noEmit",
28
+ "test": "node --test --import tsx tests/*.test.ts",
29
+ "clean": "rm -rf dist"
30
+ },
31
+ "peerDependencies": {
32
+ "@ottimis/jack-chat-core": ">=0.5.5"
33
+ },
34
+ "devDependencies": {
35
+ "@ottimis/jack-chat-core": "^0.5.5",
36
+ "@types/node": "^22.14.1",
37
+ "tsx": "^4.19.2",
38
+ "typescript": "^5.8.3"
39
+ }
40
+ }
package/src/backend.ts ADDED
@@ -0,0 +1,291 @@
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
+
28
+ import type { ProcessSpawner } from './spawner'
29
+ import type {
30
+ NormalizedMessage,
31
+ NormalizedPermissionRequest,
32
+ NormalizedPermissionResult,
33
+ NormalizedHookEvent
34
+ } from '@ottimis/jack-chat-core'
35
+
36
+ /**
37
+ * Open string union — every provider declares its own backend ids. Today
38
+ * `'sdk'` and `'cli'` are Claude-specific; Gemini ships `'acp'`. The host
39
+ * resolves the active backend by id against the provider's `backends[]`
40
+ * list, so widening to `string` is required for non-Claude providers.
41
+ */
42
+ export type BackendName = string
43
+
44
+ // ─────────────────────────────────────────────────────────────────────────────
45
+ // Neutral option types
46
+ // ─────────────────────────────────────────────────────────────────────────────
47
+
48
+ /** Permission gate behaviour. Strings the host may toggle live. */
49
+ export type AgentPermissionMode =
50
+ | 'default'
51
+ | 'acceptEdits'
52
+ | 'plan'
53
+ | 'bypassPermissions'
54
+
55
+ /** Settings layers the provider should consult at boot. */
56
+ export type AgentSettingSource = 'user' | 'project' | 'local'
57
+
58
+ /**
59
+ * System prompt shape: a plain string (provider replaces its default), or
60
+ * a preset envelope with an optional append (provider extends its default).
61
+ * The preset name is provider-specific; today only `'claude_code'` exists.
62
+ */
63
+ export type AgentSystemPrompt =
64
+ | string
65
+ | { type: 'preset'; preset: string; append?: string }
66
+
67
+ /**
68
+ * MCP server configuration — opaque to the host. The host never inspects
69
+ * the inner shape; each provider validates / consumes its own format.
70
+ */
71
+ export type AgentMcpServerConfig = unknown
72
+
73
+ /** Reasoning-effort knob. Provider-validated; not all providers honor every value. */
74
+ export type AgentEffortLevel = 'low' | 'medium' | 'high' | 'xhigh' | 'max'
75
+
76
+ /**
77
+ * Hook handler — receives a normalized lifecycle event and may return an
78
+ * opaque object the provider interprets (e.g. `{ continue: false }` to
79
+ * abort a tool call). Most handlers just return `undefined`.
80
+ */
81
+ export type AgentHookHandler = (event: NormalizedHookEvent) => Promise<unknown> | unknown
82
+
83
+ export type AgentHookMatcher = {
84
+ /**
85
+ * Glob over tool names. `'*'` matches every tool. Semantics provider-side
86
+ * but every provider understands `'*'`.
87
+ */
88
+ matcher: string
89
+ hooks: AgentHookHandler[]
90
+ timeout?: number
91
+ }
92
+
93
+ export type AgentHooks = {
94
+ preToolUse?: AgentHookMatcher[]
95
+ postToolUse?: AgentHookMatcher[]
96
+ }
97
+
98
+ /**
99
+ * Context window usage snapshot returned by {@link AgentSession.getContextUsage}.
100
+ * Loose-typed because providers expose different breakdowns; the renderer
101
+ * picks `totalTokens` / `maxTokens` / `percentage` and falls back to the
102
+ * raw bag for advanced UI.
103
+ */
104
+ export type AgentContextUsage = {
105
+ total?: number
106
+ totalTokens?: number
107
+ maxTokens?: number
108
+ rawMaxTokens?: number
109
+ percentage?: number
110
+ model?: string
111
+ by_category?: Record<string, number>
112
+ [k: string]: unknown
113
+ }
114
+
115
+ /**
116
+ * Listing entry for `~/.claude/projects/<encoded>/<uuid>.jsonl` (or its
117
+ * equivalent under future providers). Loose-typed: providers may expose
118
+ * extra fields that the scanner just passes through.
119
+ */
120
+ export type AgentSessionInfo = {
121
+ sessionId: string
122
+ cwd?: string
123
+ summary?: string
124
+ customTitle?: string | null
125
+ firstPrompt?: string | null
126
+ lastModified?: number
127
+ createdAt?: number | null
128
+ gitBranch?: string | null
129
+ fileSize?: number
130
+ [k: string]: unknown
131
+ }
132
+
133
+ /**
134
+ * One turn of input the host pushes onto the prompt queue. Plain text today
135
+ * — providers wrap it into their wire-native user-message envelope. When a
136
+ * future host needs to push richer turns (e.g. images), this can grow into
137
+ * a structured union without breaking the queue contract.
138
+ */
139
+ export type AgentUserPrompt = string
140
+
141
+ // ─────────────────────────────────────────────────────────────────────────────
142
+ // Query options & input
143
+ // ─────────────────────────────────────────────────────────────────────────────
144
+
145
+ /**
146
+ * Options the host hands to {@link AgentBackend.query}. All fields are
147
+ * neutral; provider-private extras live behind {@link providerSpawnHints}.
148
+ */
149
+ export type AgentQueryOptions = {
150
+ cwd?: string
151
+ permissionMode?: AgentPermissionMode
152
+ includePartialMessages?: boolean
153
+ settingSources?: AgentSettingSource[]
154
+ agentProgressSummaries?: boolean
155
+ allowedTools?: string[]
156
+ systemPrompt?: AgentSystemPrompt
157
+ /**
158
+ * Extra working directories beyond `cwd` that the agent can Read/Write
159
+ * across. Populated via `JackProvider.applyKnowledgeContext` from the
160
+ * merged KnowledgeContext (workspace tree + AgentDefinition `kind=dir`
161
+ * knowledge sources).
162
+ */
163
+ additionalDirectories?: string[]
164
+ mcpServers?: Record<string, AgentMcpServerConfig>
165
+ resume?: string
166
+ /**
167
+ * Initial model for the spawn. Live switches use
168
+ * {@link AgentSession.setModel}.
169
+ */
170
+ model?: string
171
+ /**
172
+ * Initial effort level for the spawn. Live switches use
173
+ * {@link AgentSession.applyFlagSettings} with `{ effortLevel: ... }`.
174
+ */
175
+ effort?: AgentEffortLevel
176
+ /**
177
+ * Process spawner — decides how the provider's child process is launched.
178
+ * Defaults to running locally. For sandboxed sessions, the host passes a
179
+ * spawner created by `createDockerSpawner()`.
180
+ */
181
+ spawner?: ProcessSpawner
182
+ /** Extra env vars merged into the spawned process environment. */
183
+ env?: { [key: string]: string | undefined }
184
+ /**
185
+ * Provider-private spawn details. Populated by
186
+ * `JackProvider.prepareSpawnOptions` and consumed by the matching backend
187
+ * implementation. The host treats this bag as opaque — never read or
188
+ * mutate the inner fields outside the provider package.
189
+ *
190
+ * Today the Claude provider stores `executable` and
191
+ * `pathToClaudeCodeExecutable` here so the SDK backend can locate the
192
+ * asar-unpacked `cli.js` + the macOS Electron Helper.
193
+ */
194
+ providerSpawnHints?: Record<string, unknown>
195
+ /**
196
+ * Permission gate. Receives a {@link NormalizedPermissionRequest} and
197
+ * resolves to a {@link NormalizedPermissionResult}. Each provider's
198
+ * backend translates between its wire format and these neutral shapes.
199
+ */
200
+ canUseTool?: (req: NormalizedPermissionRequest) => Promise<NormalizedPermissionResult>
201
+ hooks?: AgentHooks
202
+ }
203
+
204
+ export type AgentQueryInput = {
205
+ prompt: AgentUserPrompt | AsyncIterable<AgentUserPrompt>
206
+ options: AgentQueryOptions
207
+ }
208
+
209
+ // ─────────────────────────────────────────────────────────────────────────────
210
+ // Session interface
211
+ // ─────────────────────────────────────────────────────────────────────────────
212
+
213
+ /**
214
+ * Session-like object returned by backend.query(). Mirrors the subset of
215
+ * the provider's runtime control surface that the host actually depends
216
+ * on — intentionally narrow to keep backend implementations small.
217
+ */
218
+ export interface AgentSession extends AsyncIterable<NormalizedMessage> {
219
+ interrupt(): Promise<void>
220
+ close(): void
221
+ getContextUsage(): Promise<AgentContextUsage>
222
+ stopTask(taskId: string): Promise<void>
223
+ /**
224
+ * Switch permission mode live, without respawning the child process.
225
+ * Mirrors the CLI's Shift+Tab cycle (Claude provider).
226
+ */
227
+ setPermissionMode(mode: AgentPermissionMode | undefined): Promise<void>
228
+ /**
229
+ * Switch the model live. Pass `undefined` to clear any override and
230
+ * fall back to the provider default.
231
+ */
232
+ setModel(model?: string): Promise<void>
233
+ /**
234
+ * Merge arbitrary settings into the flag-settings layer at runtime.
235
+ * Used for values the provider exposes only as persisted flags
236
+ * (notably `effortLevel` on Claude).
237
+ */
238
+ applyFlagSettings(settings: Record<string, unknown>): Promise<void>
239
+ /**
240
+ * Read the effective merged settings layer. The response shape is
241
+ * `{ effective, sources }` where `effective` is the deep-merged result.
242
+ * The host uses it to discover the runtime `effortLevel` the provider
243
+ * booted with.
244
+ */
245
+ getSettings(): Promise<AgentSettingsResponse>
246
+ }
247
+
248
+ /**
249
+ * Slimmed-down shape of the `get_settings` response. Providers may surface
250
+ * hundreds of fields; we only look at the bits the host cares about and
251
+ * keep the rest opaque.
252
+ */
253
+ export type AgentSettingsResponse = {
254
+ effective?: { effortLevel?: string; [key: string]: unknown }
255
+ sources?: Record<string, unknown>
256
+ }
257
+
258
+ /** Options for backend.listSessions(). */
259
+ export type AgentListSessionsOptions = {
260
+ dir?: string
261
+ limit?: number
262
+ offset?: number
263
+ }
264
+
265
+ /** Options for backend.forkSession(). */
266
+ export type AgentForkSessionOptions = {
267
+ dir?: string
268
+ upToMessageId?: string
269
+ title?: string
270
+ }
271
+
272
+ export interface AgentBackend {
273
+ readonly name: BackendName
274
+ query(input: AgentQueryInput): AgentSession
275
+
276
+ /**
277
+ * List provider sessions on disk. Each backend reads its provider's
278
+ * native transcript layout (`~/.claude/projects/...`,
279
+ * `~/.codex/sessions/...`, `~/.gemini/tmp/.../chats/...`).
280
+ */
281
+ listSessions(opts?: AgentListSessionsOptions): Promise<AgentSessionInfo[]>
282
+
283
+ /** Persist a custom title for a session. */
284
+ renameSession(sessionId: string, title: string, opts?: { dir?: string }): Promise<void>
285
+
286
+ /** Fork a session into a new one (optionally truncated at a cutoff message). */
287
+ forkSession(
288
+ sessionId: string,
289
+ opts?: AgentForkSessionOptions
290
+ ): Promise<{ sessionId: string }>
291
+ }
package/src/index.ts ADDED
@@ -0,0 +1,34 @@
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
+
24
+ export * from './backend'
25
+ export * from './spawner'
26
+ export * from './provider'
27
+
28
+ /**
29
+ * Re-export of `NormalizedMessage` from chat-core so consumers don't need
30
+ * to depend on it directly when their only entrypoint into the wire shape
31
+ * is via `AgentBackend`. Mirrors the legacy
32
+ * `src/main/agent/backend.ts` re-export.
33
+ */
34
+ export type { NormalizedMessage } from '@ottimis/jack-chat-core'