wicked-core-ts 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.
Files changed (3) hide show
  1. package/index.d.ts +159 -0
  2. package/index.js +316 -0
  3. package/package.json +53 -0
package/index.d.ts ADDED
@@ -0,0 +1,159 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ /* auto-generated by NAPI-RS */
5
+
6
+ /**
7
+ * Options for [`Core::launch_run`]. `clisJson` is a JSON array of `AgenticCli` seats (the council
8
+ * roster); `Core.registryRoster()` returns the production roster ready to pass here.
9
+ */
10
+ export interface LaunchOptions {
11
+ /** The free-text problem to decompose into ordered work units. */
12
+ problem: string
13
+ /** A stable session/run id (empty → the caller must supply one; Core requires an explicit id here). */
14
+ sessionId: string
15
+ /** JSON array of `AgenticCli` seats — the council roster for this run. */
16
+ clisJson: string
17
+ /** `shared` (default) | `isolated` — the collection-scope mode. */
18
+ entityMode?: string
19
+ /** Human-confirm gate policy: `none` (default) | `all` | `before:<ord>`. */
20
+ humanConfirm?: string
21
+ /** The id of a registered repo to run within (creates an isolated worktree). Omit for a repo-less run. */
22
+ repoRef?: string
23
+ }
24
+ /**
25
+ * A handle to a wicked-core runtime. Construct with [`Core::spawn`] (production engine: real
26
+ * council + wrapped-CLI subprocesses) or [`Core::spawn_stub`] (deterministic offline engine).
27
+ */
28
+ export declare class Core {
29
+ /**
30
+ * Spawn the store actor over the estate db at `path` with the PRODUCTION engine (real council
31
+ * dispatcher + real wrapped-CLI step runner — runs actual agentic CLIs). The actor lives until
32
+ * every handle is dropped.
33
+ */
34
+ static spawn(path: string): Core
35
+ /**
36
+ * Spawn the store actor with the STUB engine — a deterministic council dispatcher +
37
+ * `StubStepRunner`, no subprocesses. For tests / offline runs that must not touch a real LLM.
38
+ */
39
+ static spawnStub(path: string): Core
40
+ /**
41
+ * The production council roster (built-ins ∪ the user's `~/.config/wicked-council/clis.toml`),
42
+ * as a JSON array of `AgenticCli` — pass straight into `launchRun`'s `clisJson`.
43
+ */
44
+ static registryRoster(): string
45
+ /**
46
+ * Subscribe to the live [`CoreEvent`] stream. `callback` follows the Node error-first
47
+ * convention — `(err, eventJson)` — and is invoked once per event with the event serialized as
48
+ * a JSON string (`{ type, ...fields }`); parse it in JS. Events arrive in emission order. Call
49
+ * this BEFORE `launchRun` to catch the whole sequence, and HOLD the returned [`Subscription`]:
50
+ * `close()` / `unsubscribe()` stops delivery and tears the pump thread + callback down.
51
+ *
52
+ * NOTE (ordering): async methods resolve their Promise off a libuv worker thread, while events
53
+ * are delivered from a separate pump thread — so an event emitted by a call MAY be observed by
54
+ * this callback slightly AFTER that call's Promise resolves. Await the event you need (as the
55
+ * smoke does) rather than assuming it precedes the method's resolution.
56
+ */
57
+ subscribe(callback: (err: Error | null, eventJson: string) => void): Subscription
58
+ /** Liveness probe — emits a `Heartbeat` to subscribers and resolves once the actor acks (`"ok"`). */
59
+ ping(): Promise<string>
60
+ /**
61
+ * Launch an interactive, resumable run: plans + distributes, then executes each unit off-thread
62
+ * (or pauses at a human-confirm gate). Resolves to the run id. Progress arrives as `CoreEvent`s
63
+ * — `subscribe()` first. Rejects with a busy error if a run with that id is already in flight.
64
+ */
65
+ launchRun(opts: LaunchOptions): Promise<string>
66
+ /**
67
+ * Resume an interactive run from its persisted cursor (after a pause, crash, or fresh process).
68
+ * Resolves to the resulting status token.
69
+ */
70
+ resumeRun(runId: string): Promise<string>
71
+ /**
72
+ * Resolve a human-confirm gate on a PAUSED run. `approve=true` proceeds (optionally applying
73
+ * `amend` to the next unit's instruction); `approve=false` rejects → cancels the run. Resolves
74
+ * to the resulting status token. Rejects if the run is not paused at a gate.
75
+ */
76
+ confirmGate(runId: string, approve: boolean, amend?: string | undefined | null): Promise<string>
77
+ /**
78
+ * Cancel a run — mark it terminally `Cancelled` and stop advancing it. Resolves to the status
79
+ * token. Safe whether the run is executing or paused.
80
+ */
81
+ cancelRun(runId: string): Promise<string>
82
+ /** The agent session ids currently on the store, as a JSON array of strings. */
83
+ sessions(): Promise<string>
84
+ /**
85
+ * Every session + its ordered units, as a JSON array of `{ session, units }` objects (the read
86
+ * a UI builds its project list from).
87
+ */
88
+ sessionsDetail(): Promise<string>
89
+ /** A unit's captured work output (transcript), as a JSON value — a string, or `null` if none. */
90
+ workOutput(unitId: string): Promise<string>
91
+ /**
92
+ * Register a git repository the orchestrator can run within. Validates it is a git repo with
93
+ * ≥1 commit; resolves to the persisted `RepoEntry` as a JSON object.
94
+ */
95
+ registerRepo(name: string, rootPath: string): Promise<string>
96
+ /** List every registered repository, as a JSON array of `RepoEntry` objects. */
97
+ listRepos(): Promise<string>
98
+ /**
99
+ * Open a PTY terminal session running `cmd` (or the login shell if omitted) in `cwd`, sized
100
+ * `cols`x`rows`. `governed=false` is a loud, opt-in UNGOVERNED operator shell that bypasses the
101
+ * gate-hook (DES §7); pass `true` for the governed default. Resolves the new terminal id. Output
102
+ * arrives as `terminalOutput` events, so `subscribe()` FIRST to catch `terminalOpened` + bytes.
103
+ */
104
+ openTerminal(cwd: string, cmd: Array<string> | undefined | null, cols: number, rows: number, governed: boolean): Promise<string>
105
+ /**
106
+ * Write raw input bytes (keystrokes) to a terminal. The `bytes` Buffer is copied to an owned
107
+ * `Vec<u8>` on the Node thread (a cheap memcpy — keystroke payloads are tiny) so the blocking
108
+ * write can run off-thread without moving a JS-owned Buffer across threads. Resolves `"ok"`;
109
+ * rejects if the terminal id is unknown or the write fails.
110
+ */
111
+ writeTerminal(id: string, bytes: Buffer): Promise<string>
112
+ /**
113
+ * Resize a terminal's PTY to `cols`x`rows`. Resolves `"ok"`; rejects if the terminal id is
114
+ * unknown or the resize fails.
115
+ */
116
+ resizeTerminal(id: string, cols: number, rows: number): Promise<string>
117
+ /**
118
+ * Close a terminal: the actor kills the child, joins the reader thread, and drops the registry +
119
+ * I/O entries (no orphaned process/thread). Resolves `"ok"` once teardown completes; a
120
+ * `terminalExited` event is emitted. Rejects on an unknown id.
121
+ */
122
+ closeTerminal(id: string): Promise<string>
123
+ }
124
+ /**
125
+ * A live event subscription returned by [`Core::subscribe`]. Owns the FIFO pump thread + its
126
+ * [`ThreadsafeFunction`]. `close()` / `unsubscribe()` tears both down deterministically (set the
127
+ * stop flag → join the pump, which drops the event `Receiver` so the actor prunes its sender →
128
+ * abort the tsfn). Idempotent; dropping the JS handle without an explicit close also stops the pump.
129
+ */
130
+ export declare class Subscription {
131
+ /**
132
+ * Stop delivering events and release the pump thread + `ThreadsafeFunction`. Idempotent and
133
+ * safe on a normal shutdown path; after it returns the pump is joined and the tsfn aborted, so
134
+ * the callback will not fire again. This is the teardown that makes re-subscribe leak-free and
135
+ * lets a plain `main()` return promptly.
136
+ */
137
+ close(): void
138
+ /** Alias for [`Subscription::close`]. */
139
+ unsubscribe(): void
140
+ }
141
+
142
+ // ─── hand-authored (not napi-generated): see scripts/finalize-dts.mjs ───
143
+ /**
144
+ * A CoreEvent, delivered as a JSON string to the {@link Core.subscribe} callback. Discriminated on
145
+ * `type`. Fields vary by variant (see wicked-core `CoreEvent`): e.g.
146
+ * `sessionStarted` `{session, problem}`, `unitPlanned` `{session, ord, description}`,
147
+ * `unitDistributed` `{session, ord, cli}`, `awaitingHuman` `{session, ord, prompt}`,
148
+ * `gateDecided` `{session, ord, allow}`, `unitDone`/`unitExecuting`/`resumed` `{session, ord}`,
149
+ * `sessionCompleted` `{session}`, `sessionFailed` `{session, ord}`, `error` `{session, message}`.
150
+ * PTY terminal sessions emit `terminalOpened` `{id, cwd}`, `terminalOutput` `{id, seq, bytesB64}`
151
+ * (raw output base64-encoded in `bytesB64`), and `terminalExited` `{id, status}`.
152
+ */
153
+ export interface CoreEventJson {
154
+ type: string
155
+ session?: string
156
+ ord?: number
157
+ [k: string]: unknown
158
+ }
159
+ // ─── end hand-authored ───
package/index.js ADDED
@@ -0,0 +1,316 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+ /* prettier-ignore */
4
+
5
+ /* auto-generated by NAPI-RS */
6
+
7
+ const { existsSync, readFileSync } = require('fs')
8
+ const { join } = require('path')
9
+
10
+ const { platform, arch } = process
11
+
12
+ let nativeBinding = null
13
+ let localFileExisted = false
14
+ let loadError = null
15
+
16
+ function isMusl() {
17
+ // For Node 10
18
+ if (!process.report || typeof process.report.getReport !== 'function') {
19
+ try {
20
+ const lddPath = require('child_process').execSync('which ldd').toString().trim()
21
+ return readFileSync(lddPath, 'utf8').includes('musl')
22
+ } catch (e) {
23
+ return true
24
+ }
25
+ } else {
26
+ const { glibcVersionRuntime } = process.report.getReport().header
27
+ return !glibcVersionRuntime
28
+ }
29
+ }
30
+
31
+ switch (platform) {
32
+ case 'android':
33
+ switch (arch) {
34
+ case 'arm64':
35
+ localFileExisted = existsSync(join(__dirname, 'wicked-core-ts.android-arm64.node'))
36
+ try {
37
+ if (localFileExisted) {
38
+ nativeBinding = require('./wicked-core-ts.android-arm64.node')
39
+ } else {
40
+ nativeBinding = require('wicked-core-ts-android-arm64')
41
+ }
42
+ } catch (e) {
43
+ loadError = e
44
+ }
45
+ break
46
+ case 'arm':
47
+ localFileExisted = existsSync(join(__dirname, 'wicked-core-ts.android-arm-eabi.node'))
48
+ try {
49
+ if (localFileExisted) {
50
+ nativeBinding = require('./wicked-core-ts.android-arm-eabi.node')
51
+ } else {
52
+ nativeBinding = require('wicked-core-ts-android-arm-eabi')
53
+ }
54
+ } catch (e) {
55
+ loadError = e
56
+ }
57
+ break
58
+ default:
59
+ throw new Error(`Unsupported architecture on Android ${arch}`)
60
+ }
61
+ break
62
+ case 'win32':
63
+ switch (arch) {
64
+ case 'x64':
65
+ localFileExisted = existsSync(
66
+ join(__dirname, 'wicked-core-ts.win32-x64-msvc.node')
67
+ )
68
+ try {
69
+ if (localFileExisted) {
70
+ nativeBinding = require('./wicked-core-ts.win32-x64-msvc.node')
71
+ } else {
72
+ nativeBinding = require('wicked-core-ts-win32-x64-msvc')
73
+ }
74
+ } catch (e) {
75
+ loadError = e
76
+ }
77
+ break
78
+ case 'ia32':
79
+ localFileExisted = existsSync(
80
+ join(__dirname, 'wicked-core-ts.win32-ia32-msvc.node')
81
+ )
82
+ try {
83
+ if (localFileExisted) {
84
+ nativeBinding = require('./wicked-core-ts.win32-ia32-msvc.node')
85
+ } else {
86
+ nativeBinding = require('wicked-core-ts-win32-ia32-msvc')
87
+ }
88
+ } catch (e) {
89
+ loadError = e
90
+ }
91
+ break
92
+ case 'arm64':
93
+ localFileExisted = existsSync(
94
+ join(__dirname, 'wicked-core-ts.win32-arm64-msvc.node')
95
+ )
96
+ try {
97
+ if (localFileExisted) {
98
+ nativeBinding = require('./wicked-core-ts.win32-arm64-msvc.node')
99
+ } else {
100
+ nativeBinding = require('wicked-core-ts-win32-arm64-msvc')
101
+ }
102
+ } catch (e) {
103
+ loadError = e
104
+ }
105
+ break
106
+ default:
107
+ throw new Error(`Unsupported architecture on Windows: ${arch}`)
108
+ }
109
+ break
110
+ case 'darwin':
111
+ localFileExisted = existsSync(join(__dirname, 'wicked-core-ts.darwin-universal.node'))
112
+ try {
113
+ if (localFileExisted) {
114
+ nativeBinding = require('./wicked-core-ts.darwin-universal.node')
115
+ } else {
116
+ nativeBinding = require('wicked-core-ts-darwin-universal')
117
+ }
118
+ break
119
+ } catch {}
120
+ switch (arch) {
121
+ case 'x64':
122
+ localFileExisted = existsSync(join(__dirname, 'wicked-core-ts.darwin-x64.node'))
123
+ try {
124
+ if (localFileExisted) {
125
+ nativeBinding = require('./wicked-core-ts.darwin-x64.node')
126
+ } else {
127
+ nativeBinding = require('wicked-core-ts-darwin-x64')
128
+ }
129
+ } catch (e) {
130
+ loadError = e
131
+ }
132
+ break
133
+ case 'arm64':
134
+ localFileExisted = existsSync(
135
+ join(__dirname, 'wicked-core-ts.darwin-arm64.node')
136
+ )
137
+ try {
138
+ if (localFileExisted) {
139
+ nativeBinding = require('./wicked-core-ts.darwin-arm64.node')
140
+ } else {
141
+ nativeBinding = require('wicked-core-ts-darwin-arm64')
142
+ }
143
+ } catch (e) {
144
+ loadError = e
145
+ }
146
+ break
147
+ default:
148
+ throw new Error(`Unsupported architecture on macOS: ${arch}`)
149
+ }
150
+ break
151
+ case 'freebsd':
152
+ if (arch !== 'x64') {
153
+ throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)
154
+ }
155
+ localFileExisted = existsSync(join(__dirname, 'wicked-core-ts.freebsd-x64.node'))
156
+ try {
157
+ if (localFileExisted) {
158
+ nativeBinding = require('./wicked-core-ts.freebsd-x64.node')
159
+ } else {
160
+ nativeBinding = require('wicked-core-ts-freebsd-x64')
161
+ }
162
+ } catch (e) {
163
+ loadError = e
164
+ }
165
+ break
166
+ case 'linux':
167
+ switch (arch) {
168
+ case 'x64':
169
+ if (isMusl()) {
170
+ localFileExisted = existsSync(
171
+ join(__dirname, 'wicked-core-ts.linux-x64-musl.node')
172
+ )
173
+ try {
174
+ if (localFileExisted) {
175
+ nativeBinding = require('./wicked-core-ts.linux-x64-musl.node')
176
+ } else {
177
+ nativeBinding = require('wicked-core-ts-linux-x64-musl')
178
+ }
179
+ } catch (e) {
180
+ loadError = e
181
+ }
182
+ } else {
183
+ localFileExisted = existsSync(
184
+ join(__dirname, 'wicked-core-ts.linux-x64-gnu.node')
185
+ )
186
+ try {
187
+ if (localFileExisted) {
188
+ nativeBinding = require('./wicked-core-ts.linux-x64-gnu.node')
189
+ } else {
190
+ nativeBinding = require('wicked-core-ts-linux-x64-gnu')
191
+ }
192
+ } catch (e) {
193
+ loadError = e
194
+ }
195
+ }
196
+ break
197
+ case 'arm64':
198
+ if (isMusl()) {
199
+ localFileExisted = existsSync(
200
+ join(__dirname, 'wicked-core-ts.linux-arm64-musl.node')
201
+ )
202
+ try {
203
+ if (localFileExisted) {
204
+ nativeBinding = require('./wicked-core-ts.linux-arm64-musl.node')
205
+ } else {
206
+ nativeBinding = require('wicked-core-ts-linux-arm64-musl')
207
+ }
208
+ } catch (e) {
209
+ loadError = e
210
+ }
211
+ } else {
212
+ localFileExisted = existsSync(
213
+ join(__dirname, 'wicked-core-ts.linux-arm64-gnu.node')
214
+ )
215
+ try {
216
+ if (localFileExisted) {
217
+ nativeBinding = require('./wicked-core-ts.linux-arm64-gnu.node')
218
+ } else {
219
+ nativeBinding = require('wicked-core-ts-linux-arm64-gnu')
220
+ }
221
+ } catch (e) {
222
+ loadError = e
223
+ }
224
+ }
225
+ break
226
+ case 'arm':
227
+ if (isMusl()) {
228
+ localFileExisted = existsSync(
229
+ join(__dirname, 'wicked-core-ts.linux-arm-musleabihf.node')
230
+ )
231
+ try {
232
+ if (localFileExisted) {
233
+ nativeBinding = require('./wicked-core-ts.linux-arm-musleabihf.node')
234
+ } else {
235
+ nativeBinding = require('wicked-core-ts-linux-arm-musleabihf')
236
+ }
237
+ } catch (e) {
238
+ loadError = e
239
+ }
240
+ } else {
241
+ localFileExisted = existsSync(
242
+ join(__dirname, 'wicked-core-ts.linux-arm-gnueabihf.node')
243
+ )
244
+ try {
245
+ if (localFileExisted) {
246
+ nativeBinding = require('./wicked-core-ts.linux-arm-gnueabihf.node')
247
+ } else {
248
+ nativeBinding = require('wicked-core-ts-linux-arm-gnueabihf')
249
+ }
250
+ } catch (e) {
251
+ loadError = e
252
+ }
253
+ }
254
+ break
255
+ case 'riscv64':
256
+ if (isMusl()) {
257
+ localFileExisted = existsSync(
258
+ join(__dirname, 'wicked-core-ts.linux-riscv64-musl.node')
259
+ )
260
+ try {
261
+ if (localFileExisted) {
262
+ nativeBinding = require('./wicked-core-ts.linux-riscv64-musl.node')
263
+ } else {
264
+ nativeBinding = require('wicked-core-ts-linux-riscv64-musl')
265
+ }
266
+ } catch (e) {
267
+ loadError = e
268
+ }
269
+ } else {
270
+ localFileExisted = existsSync(
271
+ join(__dirname, 'wicked-core-ts.linux-riscv64-gnu.node')
272
+ )
273
+ try {
274
+ if (localFileExisted) {
275
+ nativeBinding = require('./wicked-core-ts.linux-riscv64-gnu.node')
276
+ } else {
277
+ nativeBinding = require('wicked-core-ts-linux-riscv64-gnu')
278
+ }
279
+ } catch (e) {
280
+ loadError = e
281
+ }
282
+ }
283
+ break
284
+ case 's390x':
285
+ localFileExisted = existsSync(
286
+ join(__dirname, 'wicked-core-ts.linux-s390x-gnu.node')
287
+ )
288
+ try {
289
+ if (localFileExisted) {
290
+ nativeBinding = require('./wicked-core-ts.linux-s390x-gnu.node')
291
+ } else {
292
+ nativeBinding = require('wicked-core-ts-linux-s390x-gnu')
293
+ }
294
+ } catch (e) {
295
+ loadError = e
296
+ }
297
+ break
298
+ default:
299
+ throw new Error(`Unsupported architecture on Linux: ${arch}`)
300
+ }
301
+ break
302
+ default:
303
+ throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
304
+ }
305
+
306
+ if (!nativeBinding) {
307
+ if (loadError) {
308
+ throw loadError
309
+ }
310
+ throw new Error(`Failed to load native binding`)
311
+ }
312
+
313
+ const { Core, Subscription } = nativeBinding
314
+
315
+ module.exports.Core = Core
316
+ module.exports.Subscription = Subscription
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "wicked-core-ts",
3
+ "version": "0.1.0",
4
+ "description": "Node/TypeScript bindings (napi-rs) for wicked-core: drive the in-process orchestration engine from JS/TS.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/mikeparcewski/wicked-core.git"
9
+ },
10
+ "main": "index.js",
11
+ "types": "index.d.ts",
12
+ "files": [
13
+ "index.js",
14
+ "index.d.ts"
15
+ ],
16
+ "napi": {
17
+ "name": "wicked-core-ts",
18
+ "package": {
19
+ "name": "wicked-core-ts"
20
+ },
21
+ "triples": {
22
+ "defaults": false,
23
+ "additional": [
24
+ "x86_64-apple-darwin",
25
+ "aarch64-apple-darwin",
26
+ "x86_64-unknown-linux-gnu",
27
+ "aarch64-unknown-linux-gnu",
28
+ "x86_64-pc-windows-msvc"
29
+ ]
30
+ }
31
+ },
32
+ "engines": {
33
+ "node": ">= 20"
34
+ },
35
+ "scripts": {
36
+ "build": "napi build --platform --release && node scripts/finalize-dts.mjs",
37
+ "build:debug": "napi build --platform && node scripts/finalize-dts.mjs",
38
+ "smoke": "node smoke.mjs",
39
+ "smoke:lifecycle": "node smoke-lifecycle.mjs",
40
+ "smoke:terminal": "node smoke-terminal.mjs",
41
+ "smoke:all": "node smoke.mjs && node smoke-lifecycle.mjs && node smoke-terminal.mjs"
42
+ },
43
+ "optionalDependencies": {
44
+ "wicked-core-ts-darwin-arm64": "0.1.0",
45
+ "wicked-core-ts-darwin-x64": "0.1.0",
46
+ "wicked-core-ts-linux-arm64-gnu": "0.1.0",
47
+ "wicked-core-ts-linux-x64-gnu": "0.1.0",
48
+ "wicked-core-ts-win32-x64-msvc": "0.1.0"
49
+ },
50
+ "devDependencies": {
51
+ "@napi-rs/cli": "^2.18.4"
52
+ }
53
+ }