smithers-orchestrator 0.22.0 → 0.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.
- package/package.json +38 -27
- package/src/__type-tests__/task-fork-jsx.test.tsx +19 -0
- package/src/create.js +262 -99
- package/src/findSmithersAnchorDir.js +38 -0
- package/src/index.d.ts +31 -5
- package/src/index.js +17 -3
- package/src/jsx-runtime.d.ts +25 -0
- package/src/tools/bash.js +1 -1
- package/src/tools/context.js +10 -29
- package/src/tools/defineTool.js +18 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "smithers-orchestrator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.0",
|
|
4
4
|
"description": "Public Smithers facade for durable coding-agent workflows and Gateway operation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -35,15 +35,20 @@
|
|
|
35
35
|
"import": "./src/control-plane.js",
|
|
36
36
|
"default": "./src/control-plane.js"
|
|
37
37
|
},
|
|
38
|
-
"
|
|
39
|
-
"types": "./src/
|
|
40
|
-
"import": "./src
|
|
41
|
-
"default": "./src
|
|
38
|
+
"./jsx-runtime": {
|
|
39
|
+
"types": "./src/jsx-runtime.d.ts",
|
|
40
|
+
"import": "./src/jsx-runtime.js",
|
|
41
|
+
"default": "./src/jsx-runtime.js"
|
|
42
42
|
},
|
|
43
43
|
"./jsx-dev-runtime": {
|
|
44
|
-
"types": "./src/
|
|
44
|
+
"types": "./src/jsx-runtime.d.ts",
|
|
45
45
|
"import": "./src/jsx-runtime.js",
|
|
46
46
|
"default": "./src/jsx-runtime.js"
|
|
47
|
+
},
|
|
48
|
+
"./*": {
|
|
49
|
+
"types": "./src/index.d.ts",
|
|
50
|
+
"import": "./src/*.js",
|
|
51
|
+
"default": "./src/*.js"
|
|
47
52
|
}
|
|
48
53
|
},
|
|
49
54
|
"files": [
|
|
@@ -61,27 +66,33 @@
|
|
|
61
66
|
"incur": "^0.4.1",
|
|
62
67
|
"react": "^19.2.5",
|
|
63
68
|
"zod": "^4.3.6",
|
|
64
|
-
"@smithers-orchestrator/agents": "0.
|
|
65
|
-
"@smithers-orchestrator/
|
|
66
|
-
"@smithers-orchestrator/
|
|
67
|
-
"@smithers-orchestrator/
|
|
68
|
-
"@smithers-orchestrator/
|
|
69
|
-
"@smithers-orchestrator/engine": "0.
|
|
70
|
-
"@smithers-orchestrator/
|
|
71
|
-
"@smithers-orchestrator/
|
|
72
|
-
"@smithers-orchestrator/gateway-react": "0.
|
|
73
|
-
"@smithers-orchestrator/graph": "0.
|
|
74
|
-
"@smithers-orchestrator/
|
|
75
|
-
"@smithers-orchestrator/
|
|
76
|
-
"@smithers-orchestrator/
|
|
77
|
-
"@smithers-orchestrator/
|
|
78
|
-
"@smithers-orchestrator/
|
|
79
|
-
"@smithers-orchestrator/
|
|
80
|
-
"@smithers-orchestrator/scorers": "0.
|
|
81
|
-
"@smithers-orchestrator/
|
|
82
|
-
"@smithers-orchestrator/
|
|
83
|
-
"@smithers-orchestrator/
|
|
84
|
-
"@smithers-orchestrator/
|
|
69
|
+
"@smithers-orchestrator/agents": "0.24.0",
|
|
70
|
+
"@smithers-orchestrator/components": "0.24.0",
|
|
71
|
+
"@smithers-orchestrator/control-plane": "0.24.0",
|
|
72
|
+
"@smithers-orchestrator/driver": "0.24.0",
|
|
73
|
+
"@smithers-orchestrator/db": "0.24.0",
|
|
74
|
+
"@smithers-orchestrator/engine": "0.24.0",
|
|
75
|
+
"@smithers-orchestrator/errors": "0.24.0",
|
|
76
|
+
"@smithers-orchestrator/gateway-client": "0.24.0",
|
|
77
|
+
"@smithers-orchestrator/gateway-react": "0.24.0",
|
|
78
|
+
"@smithers-orchestrator/graph": "0.24.0",
|
|
79
|
+
"@smithers-orchestrator/memory": "0.24.0",
|
|
80
|
+
"@smithers-orchestrator/observability": "0.24.0",
|
|
81
|
+
"@smithers-orchestrator/openapi": "0.24.0",
|
|
82
|
+
"@smithers-orchestrator/react-reconciler": "0.24.0",
|
|
83
|
+
"@smithers-orchestrator/sandbox": "0.24.0",
|
|
84
|
+
"@smithers-orchestrator/scheduler": "0.24.0",
|
|
85
|
+
"@smithers-orchestrator/scorers": "0.24.0",
|
|
86
|
+
"@smithers-orchestrator/server": "0.24.0",
|
|
87
|
+
"@smithers-orchestrator/time-travel": "0.24.0",
|
|
88
|
+
"@smithers-orchestrator/vcs": "0.24.0",
|
|
89
|
+
"@smithers-orchestrator/tool-context": "0.24.0",
|
|
90
|
+
"@smithers-orchestrator/cli": "0.24.0"
|
|
91
|
+
},
|
|
92
|
+
"optionalDependencies": {
|
|
93
|
+
"@electric-sql/pglite": "0.5.1",
|
|
94
|
+
"@electric-sql/pglite-socket": "0.2.1",
|
|
95
|
+
"pg": "^8.13.1"
|
|
85
96
|
},
|
|
86
97
|
"devDependencies": {
|
|
87
98
|
"@types/bun": "latest",
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { createSmithers } from "../index.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import type { AgentLike } from "@smithers-orchestrator/agents";
|
|
4
|
+
|
|
5
|
+
const agent = {
|
|
6
|
+
generate: async () => ({ ok: true }),
|
|
7
|
+
} satisfies AgentLike;
|
|
8
|
+
|
|
9
|
+
const { Task, outputs } = createSmithers({
|
|
10
|
+
next: z.object({
|
|
11
|
+
ok: z.boolean(),
|
|
12
|
+
}),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const _TaskForkJsx = (
|
|
16
|
+
<Task id="next" output={outputs.next} agent={agent} fork="source">
|
|
17
|
+
Continue from the source task.
|
|
18
|
+
</Task>
|
|
19
|
+
);
|
package/src/create.js
CHANGED
|
@@ -14,8 +14,11 @@ import { Approval as BaseApproval, Workflow as BaseWorkflow, Task as BaseTask, S
|
|
|
14
14
|
import { zodToTable } from "@smithers-orchestrator/db/zodToTable";
|
|
15
15
|
import { zodToCreateTableSQL, syncZodTableSchema } from "@smithers-orchestrator/db/zodToCreateTableSQL";
|
|
16
16
|
import { camelToSnake } from "@smithers-orchestrator/db/utils/camelToSnake";
|
|
17
|
-
import {
|
|
17
|
+
import { SmithersDb } from "@smithers-orchestrator/db/adapter";
|
|
18
|
+
import { POSTGRES } from "@smithers-orchestrator/db/dialect";
|
|
19
|
+
import { resolve, join } from "node:path";
|
|
18
20
|
import { SmithersError } from "@smithers-orchestrator/errors/SmithersError";
|
|
21
|
+
import { findSmithersAnchorDir } from "./findSmithersAnchorDir.js";
|
|
19
22
|
/** @typedef {import("@smithers-orchestrator/components").ApprovalProps<any, any>} ApprovalProps */
|
|
20
23
|
/** @typedef {import("@smithers-orchestrator/components").SandboxProps} SandboxProps */
|
|
21
24
|
/** @typedef {import("@smithers-orchestrator/components").SignalProps<any>} SignalProps */
|
|
@@ -173,43 +176,14 @@ function mergeAlertPolicies(base, override) {
|
|
|
173
176
|
return merged;
|
|
174
177
|
}
|
|
175
178
|
/**
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
* @param {CreateSmithersOptions} [opts]
|
|
181
|
-
* @returns {import("./CreateSmithersApi.ts").CreateSmithersApi<Schemas>}
|
|
182
|
-
*
|
|
183
|
-
* @example
|
|
184
|
-
* ```ts
|
|
185
|
-
* const { Workflow, Task, smithers, outputs } = createSmithers({
|
|
186
|
-
* discover: discoverOutputSchema,
|
|
187
|
-
* research: researchOutputSchema,
|
|
188
|
-
* });
|
|
179
|
+
* Generate the Drizzle table metadata, schema registry, and output refs shared by
|
|
180
|
+
* every backend. The Drizzle tables carry only column/name metadata — the actual
|
|
181
|
+
* storage is created per-dialect by the caller; dialect-aware engine reads consult
|
|
182
|
+
* these objects via getTableColumns/getTableName, never to issue SQLite queries.
|
|
189
183
|
*
|
|
190
|
-
*
|
|
191
|
-
* <Workflow name="my-workflow">
|
|
192
|
-
* <Task id="discover" output={outputs.discover} agent={myAgent}>...</Task>
|
|
193
|
-
* </Workflow>
|
|
194
|
-
* ));
|
|
195
|
-
* ```
|
|
184
|
+
* @param {Record<string, any>} schemas
|
|
196
185
|
*/
|
|
197
|
-
|
|
198
|
-
const dbPath = opts?.dbPath ?? "./smithers.db";
|
|
199
|
-
const absDbPath = resolve(process.cwd(), dbPath);
|
|
200
|
-
if (process.env.SMITHERS_HOT === "1") {
|
|
201
|
-
const sig = computeSchemaSig(schemas, absDbPath);
|
|
202
|
-
const cached = hotCache.get(absDbPath);
|
|
203
|
-
if (cached) {
|
|
204
|
-
if (cached.schemaSig !== sig) {
|
|
205
|
-
throw new SmithersError("SCHEMA_CHANGE_HOT", "[smithers hot] Schema change detected; restart required to apply schema changes.");
|
|
206
|
-
}
|
|
207
|
-
cached.setModuleAlertPolicy(opts?.alertPolicy);
|
|
208
|
-
return cached.api;
|
|
209
|
-
}
|
|
210
|
-
// Will cache after creating the API below
|
|
211
|
-
}
|
|
212
|
-
// 1. Generate Drizzle tables from Zod schemas
|
|
186
|
+
function prepareSmithersTables(schemas) {
|
|
213
187
|
const tables = {};
|
|
214
188
|
const inputTable = schemas.input
|
|
215
189
|
? zodToTable("input", schemas.input, { isInput: true })
|
|
@@ -223,77 +197,39 @@ export function createSmithers(schemas, opts) {
|
|
|
223
197
|
const tableName = camelToSnake(name);
|
|
224
198
|
tables[name] = zodToTable(tableName, zodSchema);
|
|
225
199
|
}
|
|
226
|
-
// 2. Create SQLite db
|
|
227
|
-
const sqlite = new Database(dbPath);
|
|
228
|
-
sqlite.run(`PRAGMA journal_mode = ${opts?.journalMode ?? "WAL"}`);
|
|
229
|
-
// 30s timeout: concurrent worktrees each spawn agent processes that all write
|
|
230
|
-
// to smithers.db simultaneously. 5s is too short and causes SQLITE_IOERR_VNODE
|
|
231
|
-
// on macOS when the VFS can't acquire the WAL shared-memory lock in time.
|
|
232
|
-
sqlite.run("PRAGMA busy_timeout = 30000");
|
|
233
|
-
// NORMAL is safe in WAL mode (no data loss on crash) and reduces fsync
|
|
234
|
-
// stalls that contribute to WAL checkpoint contention across processes.
|
|
235
|
-
sqlite.run("PRAGMA synchronous = NORMAL");
|
|
236
|
-
// Ensure no exclusive lock is held, allowing multiple readers/writers.
|
|
237
|
-
sqlite.run("PRAGMA locking_mode = NORMAL");
|
|
238
|
-
sqlite.run("PRAGMA foreign_keys = ON");
|
|
239
|
-
// Register a process-exit hook to explicitly close the Database.
|
|
240
|
-
// bun:sqlite's GC finalizer calls sqlite3_close() which fatally aborts if
|
|
241
|
-
// Drizzle's cached prepared statements haven't been finalized first.
|
|
242
|
-
// Calling close() ourselves lets sqlite3 finalize everything gracefully.
|
|
243
|
-
let dbClosed = false;
|
|
244
|
-
const closeDb = () => {
|
|
245
|
-
if (dbClosed)
|
|
246
|
-
return;
|
|
247
|
-
dbClosed = true;
|
|
248
|
-
try {
|
|
249
|
-
sqlite.close();
|
|
250
|
-
}
|
|
251
|
-
catch { }
|
|
252
|
-
process.removeListener("exit", closeDb);
|
|
253
|
-
};
|
|
254
|
-
process.once("exit", closeDb);
|
|
255
|
-
// 3. Auto-create tables, and ALTER any existing tables to add columns the
|
|
256
|
-
// current schema introduced (CREATE TABLE IF NOT EXISTS would silently
|
|
257
|
-
// skip the columns and a later upsert would fail with "no column named X").
|
|
258
|
-
if (schemas.input) {
|
|
259
|
-
syncZodTableSchema(sqlite, "input", schemas.input, { isInput: true });
|
|
260
|
-
}
|
|
261
|
-
else {
|
|
262
|
-
sqlite.exec(`CREATE TABLE IF NOT EXISTS "input" (run_id TEXT PRIMARY KEY, payload TEXT)`);
|
|
263
|
-
try {
|
|
264
|
-
const cols = sqlite.query(`PRAGMA table_info("input")`).all();
|
|
265
|
-
const hasPayload = cols.some((col) => col?.name === "payload");
|
|
266
|
-
if (!hasPayload) {
|
|
267
|
-
sqlite.run(`ALTER TABLE "input" ADD COLUMN payload TEXT`);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
catch {
|
|
271
|
-
// ignore - older SQLite or permission issues; input payload remains best-effort
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
for (const [name, zodSchema] of Object.entries(schemas)) {
|
|
275
|
-
if (name === "input")
|
|
276
|
-
continue;
|
|
277
|
-
const tableName = camelToSnake(name);
|
|
278
|
-
syncZodTableSchema(sqlite, tableName, zodSchema);
|
|
279
|
-
}
|
|
280
|
-
// 4. Create Drizzle instance with all tables in the schema
|
|
281
200
|
const drizzleSchema = { input: inputTable };
|
|
282
201
|
for (const [key, table] of Object.entries(tables)) {
|
|
283
202
|
drizzleSchema[key] = table;
|
|
284
203
|
}
|
|
285
|
-
const db = drizzle(sqlite, { schema: drizzleSchema });
|
|
286
|
-
// 5. Build schema registry for engine resolution of string output keys
|
|
287
204
|
const schemaRegistry = new Map();
|
|
288
205
|
for (const [name, zodSchema] of Object.entries(schemas)) {
|
|
289
206
|
if (name === "input")
|
|
290
207
|
continue;
|
|
291
208
|
schemaRegistry.set(name, { table: tables[name], zodSchema });
|
|
292
209
|
}
|
|
293
|
-
// 6. Build output refs and reverse lookup: ZodObject reference → schema key name
|
|
294
210
|
const { outputs, zodToKeyName, ambiguousZodSchemas } = prepareOutputSchemas(schemas);
|
|
295
|
-
|
|
296
|
-
|
|
211
|
+
return { tables, inputTable, drizzleSchema, schemaRegistry, outputs, zodToKeyName, ambiguousZodSchemas };
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Construct the public createSmithers API object around a prepared database
|
|
215
|
+
* handle and shared table metadata. Backend-agnostic: `db` is either a Drizzle
|
|
216
|
+
* bun:sqlite instance or a Postgres descriptor; every engine read/write below it
|
|
217
|
+
* is dialect-aware.
|
|
218
|
+
*
|
|
219
|
+
* @param {{
|
|
220
|
+
* db: unknown;
|
|
221
|
+
* tables: Record<string, unknown>;
|
|
222
|
+
* schemaRegistry: Map<string, unknown>;
|
|
223
|
+
* outputs: Record<string, unknown>;
|
|
224
|
+
* zodToKeyName: Map<unknown, string>;
|
|
225
|
+
* ambiguousZodSchemas: Set<unknown>;
|
|
226
|
+
* opts?: CreateSmithersOptions;
|
|
227
|
+
* inputSchema?: unknown;
|
|
228
|
+
* }} config
|
|
229
|
+
*/
|
|
230
|
+
function buildSmithersApi(config) {
|
|
231
|
+
const { db, tables, schemaRegistry, outputs, zodToKeyName, ambiguousZodSchemas, opts, inputSchema } = config;
|
|
232
|
+
const { SmithersContext: RuntimeSmithersContext, useCtx } = createSmithersContext();
|
|
297
233
|
const ctxRef = { current: null };
|
|
298
234
|
let moduleAlertPolicy = opts?.alertPolicy;
|
|
299
235
|
/**
|
|
@@ -352,9 +288,8 @@ export function createSmithers(schemas, opts) {
|
|
|
352
288
|
});
|
|
353
289
|
}
|
|
354
290
|
/**
|
|
355
|
-
* @param {(ctx: SmithersCtx<
|
|
291
|
+
* @param {(ctx: SmithersCtx<any>) => React.ReactElement} build
|
|
356
292
|
* @param {SmithersWorkflowOptions} [smithersOpts]
|
|
357
|
-
* @returns {SmithersWorkflow<Schemas>}
|
|
358
293
|
*/
|
|
359
294
|
function boundSmithers(build, smithersOpts) {
|
|
360
295
|
const workflowOpts = {
|
|
@@ -372,6 +307,7 @@ export function createSmithers(schemas, opts) {
|
|
|
372
307
|
return React.createElement(RuntimeSmithersContext.Provider, { value: ctxRef.current }, React.createElement(GlobalSmithersContext.Provider, { value: ctxRef.current }, build(ctx)));
|
|
373
308
|
},
|
|
374
309
|
opts: workflowOpts,
|
|
310
|
+
inputSchema,
|
|
375
311
|
schemaRegistry,
|
|
376
312
|
zodToKeyName,
|
|
377
313
|
ambiguousZodSchemas,
|
|
@@ -402,9 +338,122 @@ export function createSmithers(schemas, opts) {
|
|
|
402
338
|
useCtx,
|
|
403
339
|
smithers: boundSmithers,
|
|
404
340
|
db,
|
|
405
|
-
tables
|
|
341
|
+
tables,
|
|
406
342
|
outputs,
|
|
407
343
|
};
|
|
344
|
+
return { api, setModuleAlertPolicy };
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Schema-driven API — users define only Zod schemas, the framework owns the entire storage layer.
|
|
348
|
+
*
|
|
349
|
+
* @template {Record<string, import("zod").ZodObject<any>>} Schemas
|
|
350
|
+
* @param {Schemas} schemas
|
|
351
|
+
* @param {CreateSmithersOptions} [opts]
|
|
352
|
+
* @returns {import("./CreateSmithersApi.ts").CreateSmithersApi<Schemas>}
|
|
353
|
+
*
|
|
354
|
+
* @example
|
|
355
|
+
* ```ts
|
|
356
|
+
* const { Workflow, Task, smithers, outputs } = createSmithers({
|
|
357
|
+
* discover: discoverOutputSchema,
|
|
358
|
+
* research: researchOutputSchema,
|
|
359
|
+
* });
|
|
360
|
+
*
|
|
361
|
+
* export default smithers((ctx) => (
|
|
362
|
+
* <Workflow name="my-workflow">
|
|
363
|
+
* <Task id="discover" output={outputs.discover} agent={myAgent}>...</Task>
|
|
364
|
+
* </Workflow>
|
|
365
|
+
* ));
|
|
366
|
+
* ```
|
|
367
|
+
*/
|
|
368
|
+
export function createSmithers(schemas, opts) {
|
|
369
|
+
// Resolve the DB path from the nearest .smithers/ anchor so that running a
|
|
370
|
+
// workflow from a subdirectory always creates/uses the project-root DB, not
|
|
371
|
+
// a new one at CWD. An explicit opts.dbPath overrides this entirely.
|
|
372
|
+
const anchorDir = findSmithersAnchorDir(process.cwd());
|
|
373
|
+
const defaultDbPath = anchorDir ? join(anchorDir, "smithers.db") : "./smithers.db";
|
|
374
|
+
const dbPath = opts?.dbPath ?? defaultDbPath;
|
|
375
|
+
const absDbPath = resolve(process.cwd(), dbPath);
|
|
376
|
+
if (process.env.SMITHERS_HOT === "1") {
|
|
377
|
+
const sig = computeSchemaSig(schemas, absDbPath);
|
|
378
|
+
const cached = hotCache.get(absDbPath);
|
|
379
|
+
if (cached) {
|
|
380
|
+
if (cached.schemaSig !== sig) {
|
|
381
|
+
throw new SmithersError("SCHEMA_CHANGE_HOT", "[smithers hot] Schema change detected; restart required to apply schema changes.");
|
|
382
|
+
}
|
|
383
|
+
cached.setModuleAlertPolicy(opts?.alertPolicy);
|
|
384
|
+
return cached.api;
|
|
385
|
+
}
|
|
386
|
+
// Will cache after creating the API below
|
|
387
|
+
}
|
|
388
|
+
// 1. Generate Drizzle tables + schema metadata from Zod schemas.
|
|
389
|
+
const { tables, drizzleSchema, schemaRegistry, outputs, zodToKeyName, ambiguousZodSchemas } = prepareSmithersTables(schemas);
|
|
390
|
+
// 2. Create SQLite db
|
|
391
|
+
const sqlite = new Database(dbPath);
|
|
392
|
+
sqlite.run(`PRAGMA journal_mode = ${opts?.journalMode ?? "WAL"}`);
|
|
393
|
+
// 30s timeout: concurrent worktrees each spawn agent processes that all write
|
|
394
|
+
// to smithers.db simultaneously. 5s is too short and causes SQLITE_IOERR_VNODE
|
|
395
|
+
// on macOS when the VFS can't acquire the WAL shared-memory lock in time.
|
|
396
|
+
sqlite.run("PRAGMA busy_timeout = 30000");
|
|
397
|
+
// NORMAL is safe in WAL mode (no data loss on crash) and reduces fsync
|
|
398
|
+
// stalls that contribute to WAL checkpoint contention across processes.
|
|
399
|
+
sqlite.run("PRAGMA synchronous = NORMAL");
|
|
400
|
+
// Ensure no exclusive lock is held, allowing multiple readers/writers.
|
|
401
|
+
sqlite.run("PRAGMA locking_mode = NORMAL");
|
|
402
|
+
sqlite.run("PRAGMA foreign_keys = ON");
|
|
403
|
+
// Register a process-exit hook to explicitly close the Database.
|
|
404
|
+
// bun:sqlite's GC finalizer calls sqlite3_close() which fatally aborts if
|
|
405
|
+
// Drizzle's cached prepared statements haven't been finalized first.
|
|
406
|
+
// Calling close() ourselves lets sqlite3 finalize everything gracefully.
|
|
407
|
+
let dbClosed = false;
|
|
408
|
+
const closeDb = () => {
|
|
409
|
+
if (dbClosed)
|
|
410
|
+
return;
|
|
411
|
+
dbClosed = true;
|
|
412
|
+
try {
|
|
413
|
+
sqlite.close();
|
|
414
|
+
}
|
|
415
|
+
catch { }
|
|
416
|
+
process.removeListener("exit", closeDb);
|
|
417
|
+
};
|
|
418
|
+
process.once("exit", closeDb);
|
|
419
|
+
// 3. Auto-create tables, and ALTER any existing tables to add columns the
|
|
420
|
+
// current schema introduced (CREATE TABLE IF NOT EXISTS would silently
|
|
421
|
+
// skip the columns and a later upsert would fail with "no column named X").
|
|
422
|
+
if (schemas.input) {
|
|
423
|
+
syncZodTableSchema(sqlite, "input", schemas.input, { isInput: true });
|
|
424
|
+
}
|
|
425
|
+
else {
|
|
426
|
+
sqlite.exec(`CREATE TABLE IF NOT EXISTS "input" (run_id TEXT PRIMARY KEY, payload TEXT)`);
|
|
427
|
+
try {
|
|
428
|
+
const cols = sqlite.query(`PRAGMA table_info("input")`).all();
|
|
429
|
+
const hasPayload = cols.some((col) => col?.name === "payload");
|
|
430
|
+
if (!hasPayload) {
|
|
431
|
+
sqlite.run(`ALTER TABLE "input" ADD COLUMN payload TEXT`);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
catch {
|
|
435
|
+
// ignore - older SQLite or permission issues; input payload remains best-effort
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
for (const [name, zodSchema] of Object.entries(schemas)) {
|
|
439
|
+
if (name === "input")
|
|
440
|
+
continue;
|
|
441
|
+
const tableName = camelToSnake(name);
|
|
442
|
+
syncZodTableSchema(sqlite, tableName, zodSchema);
|
|
443
|
+
}
|
|
444
|
+
// 4. Create Drizzle instance with all tables in the schema
|
|
445
|
+
const db = drizzle(sqlite, { schema: drizzleSchema });
|
|
446
|
+
// 5. Build the public API around the prepared db + table metadata.
|
|
447
|
+
const { api, setModuleAlertPolicy } = buildSmithersApi({
|
|
448
|
+
db,
|
|
449
|
+
tables,
|
|
450
|
+
schemaRegistry,
|
|
451
|
+
outputs,
|
|
452
|
+
zodToKeyName,
|
|
453
|
+
ambiguousZodSchemas,
|
|
454
|
+
opts,
|
|
455
|
+
inputSchema: schemas.input,
|
|
456
|
+
});
|
|
408
457
|
if (process.env.SMITHERS_HOT === "1") {
|
|
409
458
|
const sig = computeSchemaSig(schemas, absDbPath);
|
|
410
459
|
hotCache.set(absDbPath, {
|
|
@@ -415,3 +464,117 @@ export function createSmithers(schemas, opts) {
|
|
|
415
464
|
}
|
|
416
465
|
return api;
|
|
417
466
|
}
|
|
467
|
+
/**
|
|
468
|
+
* PostgreSQL/PGlite-backed equivalent of {@link createSmithers}. Asynchronous
|
|
469
|
+
* because connecting and provisioning schema over the wire is async (unlike the
|
|
470
|
+
* synchronous bun:sqlite path). Boots a node-postgres connection (`provider:
|
|
471
|
+
* "postgres"`) or an embedded PGlite over a local socket (`provider: "pglite"`),
|
|
472
|
+
* provisions the durable engine schema + the per-Zod-schema output tables with
|
|
473
|
+
* Postgres-typed DDL, and returns the same createSmithers API surface plus a
|
|
474
|
+
* `close()` teardown for the connection.
|
|
475
|
+
*
|
|
476
|
+
* @template {Record<string, import("zod").ZodObject<any>>} Schemas
|
|
477
|
+
* @param {Schemas} schemas
|
|
478
|
+
* @param {CreateSmithersOptions & ({ provider: "postgres"; connectionString?: string; connection?: object } | { provider: "pglite"; dataDir?: string })} opts
|
|
479
|
+
* @returns {Promise<import("./CreateSmithersApi.ts").CreateSmithersApi<Schemas> & { close: () => Promise<void> }>}
|
|
480
|
+
*/
|
|
481
|
+
export async function createSmithersPostgres(schemas, opts) {
|
|
482
|
+
const provider = opts?.provider ?? "postgres";
|
|
483
|
+
// 1. Generate Drizzle tables + schema metadata from Zod schemas (shared).
|
|
484
|
+
const { tables, drizzleSchema, schemaRegistry, outputs, zodToKeyName, ambiguousZodSchemas } = prepareSmithersTables(schemas);
|
|
485
|
+
// 2. Boot the Postgres/PGlite connection.
|
|
486
|
+
const pgModule = await import("pg");
|
|
487
|
+
const pg = pgModule.default ?? pgModule;
|
|
488
|
+
// BIGINT (ms timestamps, counters) → JS number, matching SQLite's behavior.
|
|
489
|
+
pg.types.setTypeParser(20, (value) => (value === null ? null : Number(value)));
|
|
490
|
+
/** @type {Array<() => Promise<void>>} */
|
|
491
|
+
const teardown = [];
|
|
492
|
+
let connectionString = opts?.connectionString;
|
|
493
|
+
if (provider === "pglite") {
|
|
494
|
+
const { PGlite } = await import("@electric-sql/pglite");
|
|
495
|
+
const { PGLiteSocketServer } = await import("@electric-sql/pglite-socket");
|
|
496
|
+
const pglite = await PGlite.create(opts?.dataDir || undefined);
|
|
497
|
+
const port = await findFreePgPort();
|
|
498
|
+
const server = new PGLiteSocketServer({ db: pglite, host: "127.0.0.1", port, maxConnections: 5 });
|
|
499
|
+
await server.start();
|
|
500
|
+
teardown.push(async () => {
|
|
501
|
+
await server.stop().catch(() => {});
|
|
502
|
+
await pglite.close().catch(() => {});
|
|
503
|
+
});
|
|
504
|
+
connectionString = `postgres://postgres@127.0.0.1:${port}/postgres`;
|
|
505
|
+
}
|
|
506
|
+
const client = new pg.Client(connectionString ? { connectionString } : opts?.connection);
|
|
507
|
+
/** @type {{ api: import("./CreateSmithersApi.ts").CreateSmithersApi<Schemas> }} */
|
|
508
|
+
let built;
|
|
509
|
+
try {
|
|
510
|
+
await client.connect();
|
|
511
|
+
teardown.push(async () => {
|
|
512
|
+
await client.end().catch(() => {});
|
|
513
|
+
});
|
|
514
|
+
// 3. Postgres descriptor consumed by the engine + adapter. The Drizzle table
|
|
515
|
+
// objects (snake_case columns identical to the DDL below) are attached only
|
|
516
|
+
// for column/name metadata; the engine's reads/writes against this descriptor
|
|
517
|
+
// are dialect-aware and go through the @effect/sql adapter or raw $n queries.
|
|
518
|
+
const descriptor = { dialect: "postgres", connection: client, schema: drizzleSchema };
|
|
519
|
+
const adapter = new SmithersDb(descriptor);
|
|
520
|
+
// 4. Durable engine schema (idempotent), then the input + output tables with
|
|
521
|
+
// Postgres-typed DDL derived from the Zod schemas.
|
|
522
|
+
await adapter.internalStorage.ensureSchema();
|
|
523
|
+
if (schemas.input) {
|
|
524
|
+
await client.query({ text: zodToCreateTableSQL("input", schemas.input, { isInput: true, dialect: POSTGRES }) });
|
|
525
|
+
}
|
|
526
|
+
else {
|
|
527
|
+
await client.query({ text: `CREATE TABLE IF NOT EXISTS "input" (run_id TEXT PRIMARY KEY, payload TEXT)` });
|
|
528
|
+
}
|
|
529
|
+
for (const [name, zodSchema] of Object.entries(schemas)) {
|
|
530
|
+
if (name === "input")
|
|
531
|
+
continue;
|
|
532
|
+
const tableName = camelToSnake(name);
|
|
533
|
+
await client.query({ text: zodToCreateTableSQL(tableName, zodSchema, { dialect: POSTGRES }) });
|
|
534
|
+
}
|
|
535
|
+
// 5. Build the public API around the descriptor + table metadata.
|
|
536
|
+
built = buildSmithersApi({
|
|
537
|
+
db: descriptor,
|
|
538
|
+
tables,
|
|
539
|
+
schemaRegistry,
|
|
540
|
+
outputs,
|
|
541
|
+
zodToKeyName,
|
|
542
|
+
ambiguousZodSchemas,
|
|
543
|
+
opts,
|
|
544
|
+
inputSchema: schemas.input,
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
catch (e) {
|
|
548
|
+
// Drain any teardown registered so far (socket server, pg client) so a
|
|
549
|
+
// failure after boot does not leak the port / connection.
|
|
550
|
+
for (const fn of teardown.reverse()) {
|
|
551
|
+
await fn().catch(() => {});
|
|
552
|
+
}
|
|
553
|
+
throw e;
|
|
554
|
+
}
|
|
555
|
+
const { api } = built;
|
|
556
|
+
return {
|
|
557
|
+
...api,
|
|
558
|
+
close: async () => {
|
|
559
|
+
for (const fn of teardown.reverse()) {
|
|
560
|
+
await fn();
|
|
561
|
+
}
|
|
562
|
+
},
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* @returns {Promise<number>}
|
|
567
|
+
*/
|
|
568
|
+
async function findFreePgPort() {
|
|
569
|
+
const net = await import("node:net");
|
|
570
|
+
return new Promise((resolveFn, reject) => {
|
|
571
|
+
const srv = net.createServer();
|
|
572
|
+
srv.unref();
|
|
573
|
+
srv.on("error", reject);
|
|
574
|
+
srv.listen(0, "127.0.0.1", () => {
|
|
575
|
+
const address = srv.address();
|
|
576
|
+
const port = typeof address === "object" && address ? address.port : 0;
|
|
577
|
+
srv.close(() => resolveFn(port));
|
|
578
|
+
});
|
|
579
|
+
});
|
|
580
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { resolve, dirname, join } from "node:path";
|
|
2
|
+
import { existsSync, statSync } from "node:fs";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Walk upward from `from` and return the nearest directory that contains a
|
|
6
|
+
* `.smithers/` subdirectory, or `undefined` if none is found before the
|
|
7
|
+
* filesystem root.
|
|
8
|
+
*
|
|
9
|
+
* Directories at or above $HOME are excluded: a `~/.smithers` global pack
|
|
10
|
+
* must not be treated as a project anchor, so the DB would incorrectly land
|
|
11
|
+
* in the user's home directory.
|
|
12
|
+
*
|
|
13
|
+
* @param {string} from
|
|
14
|
+
* @returns {string | undefined}
|
|
15
|
+
*/
|
|
16
|
+
export function findSmithersAnchorDir(from) {
|
|
17
|
+
let dir = resolve(from);
|
|
18
|
+
const fsRoot = resolve("/");
|
|
19
|
+
const home = process.env.HOME ? resolve(process.env.HOME) : undefined;
|
|
20
|
+
while (true) {
|
|
21
|
+
// Stop at or above HOME — anchors must be proper project directories
|
|
22
|
+
// strictly below the user's home directory.
|
|
23
|
+
// Use startsWith rather than length comparison so that symlinks and
|
|
24
|
+
// unusual mount points (e.g. /home2) don't produce false positives.
|
|
25
|
+
if (home && (dir === home || !dir.startsWith(home + "/"))) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
// Guard: never scan the filesystem root itself.
|
|
29
|
+
if (dir === fsRoot) {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
const candidate = join(dir, ".smithers");
|
|
33
|
+
if (existsSync(candidate) && statSync(candidate).isDirectory()) {
|
|
34
|
+
return dir;
|
|
35
|
+
}
|
|
36
|
+
dir = dirname(dir);
|
|
37
|
+
}
|
|
38
|
+
}
|
package/src/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import * as ai from 'ai';
|
|
|
2
2
|
import { Tool } from 'ai';
|
|
3
3
|
import * as _smithers_graph_XmlNode from '@smithers-orchestrator/graph/XmlNode';
|
|
4
4
|
import * as _smithers_time_travel_timetravel from '@smithers-orchestrator/time-travel/timetravel';
|
|
5
|
+
export { timeTravel } from '@smithers-orchestrator/time-travel/timetravel';
|
|
5
6
|
import * as _smithers_graph_TaskDescriptor from '@smithers-orchestrator/graph/TaskDescriptor';
|
|
6
7
|
import * as _smithers_components_SmithersWorkflow from '@smithers-orchestrator/components/SmithersWorkflow';
|
|
7
8
|
import { SmithersWorkflow as SmithersWorkflow$1 } from '@smithers-orchestrator/components/SmithersWorkflow';
|
|
@@ -24,6 +25,7 @@ import * as _smithers_driver_RunStatus from '@smithers-orchestrator/driver/RunSt
|
|
|
24
25
|
import * as _smithers_driver_RunResult from '@smithers-orchestrator/driver/RunResult';
|
|
25
26
|
import * as _smithers_driver_RunOptions from '@smithers-orchestrator/driver/RunOptions';
|
|
26
27
|
import * as _smithers_time_travel_revert from '@smithers-orchestrator/time-travel/revert';
|
|
28
|
+
export { revertToAttempt } from '@smithers-orchestrator/time-travel/revert';
|
|
27
29
|
import * as _smithers_observability from '@smithers-orchestrator/observability';
|
|
28
30
|
export { SmithersObservability, activeNodes, activeRuns, approvalsDenied, approvalsGranted, approvalsRequested, attemptDuration, cacheHits, cacheMisses, createSmithersObservabilityLayer, createSmithersOtelLayer, createSmithersRuntimeLayer, dbQueryDuration, dbRetries, dbTransactionDuration, dbTransactionRetries, dbTransactionRollbacks, externalWaitAsyncPending, hotReloadDuration, hotReloadFailures, hotReloads, httpRequestDuration, httpRequests, nodeDuration, nodesFailed, nodesFinished, nodesStarted, prometheusContentType, renderPrometheusMetrics, resolveSmithersObservabilityOptions, runsTotal, sandboxActive, sandboxBundleSizeBytes, sandboxCompletedTotal, sandboxCreatedTotal, sandboxDurationMs, sandboxPatchCount, sandboxTransportDurationMs, schedulerQueueDepth, smithersMetrics, timerDelayDuration, timersCancelled, timersCreated, timersFired, timersPending, toolCallsTotal, toolDuration, trackSmithersEvent, vcsDuration } from '@smithers-orchestrator/observability';
|
|
29
31
|
import * as _smithers_driver_OutputKey from '@smithers-orchestrator/driver/OutputKey';
|
|
@@ -56,7 +58,7 @@ import { WorkflowProps } from '@smithers-orchestrator/components/components/Work
|
|
|
56
58
|
import * as _smithers_server_gateway from '@smithers-orchestrator/server/gateway';
|
|
57
59
|
export { Gateway } from '@smithers-orchestrator/server/gateway';
|
|
58
60
|
import * as _smithers_agents from '@smithers-orchestrator/agents';
|
|
59
|
-
export { AmpAgent, AnthropicAgent, AntigravityAgent, ClaudeCodeAgent, CodexAgent, ForgeAgent, GeminiAgent, HermesAgent, KimiAgent, OpenAIAgent, OpenCodeAgent, PiAgent } from '@smithers-orchestrator/agents';
|
|
61
|
+
export { AmpAgent, AnthropicAgent, AntigravityAgent, ClaudeCodeAgent, CodexAgent, ForgeAgent, GeminiAgent, HermesAgent, KimiAgent, OpenAIAgent, OpenCodeAgent, PiAgent, VibeAgent } from '@smithers-orchestrator/agents';
|
|
60
62
|
import * as _smithers_scorers from '@smithers-orchestrator/scorers';
|
|
61
63
|
export { aggregateScores, createScorer, faithfulnessScorer, latencyScorer, llmJudge, relevancyScorer, runScorersAsync, runScorersBatch, schemaAdherenceScorer, smithersScorers, toxicityScorer } from '@smithers-orchestrator/scorers';
|
|
62
64
|
import * as _smithers_agents_capability_registry from '@smithers-orchestrator/agents/capability-registry';
|
|
@@ -70,6 +72,9 @@ export { isSmithersError } from '@smithers-orchestrator/errors/isSmithersError';
|
|
|
70
72
|
export { knownSmithersErrorCodes } from '@smithers-orchestrator/errors/knownSmithersErrorCodes';
|
|
71
73
|
export { signalRun } from '@smithers-orchestrator/engine/signals';
|
|
72
74
|
export { usePatched } from '@smithers-orchestrator/engine/effect/versioning';
|
|
75
|
+
import { SmithersDb } from '@smithers-orchestrator/db/adapter';
|
|
76
|
+
export { SmithersDb } from '@smithers-orchestrator/db/adapter';
|
|
77
|
+
export { loadOutputs, loadOutputsEffect } from '@smithers-orchestrator/db';
|
|
73
78
|
export { ensureSmithersTables } from '@smithers-orchestrator/db/ensure';
|
|
74
79
|
export { markdownComponents } from '@smithers-orchestrator/components/markdownComponents';
|
|
75
80
|
export { renderMdx } from '@smithers-orchestrator/components/renderMdx';
|
|
@@ -78,8 +83,8 @@ export { syncZodTableSchema, zodSchemaColumns, zodToCreateTableSQL } from '@smit
|
|
|
78
83
|
export { camelToSnake } from '@smithers-orchestrator/db/utils/camelToSnake';
|
|
79
84
|
export { unwrapZodType } from '@smithers-orchestrator/db/unwrapZodType';
|
|
80
85
|
export { zodSchemaToJsonExample } from '@smithers-orchestrator/components/zod-to-example';
|
|
81
|
-
export { BuilderApi, BuiltSmithersWorkflow, Smithers, StepOptions, fragment, renderFrame, runWorkflow, workflow } from '@smithers-orchestrator/engine';
|
|
82
|
-
|
|
86
|
+
export { BuilderApi, BuiltSmithersWorkflow, Smithers, StepOptions, approveNode, denyNode, fragment, getRun, listRuns, renderFrame, runWorkflow, workflow } from '@smithers-orchestrator/engine';
|
|
87
|
+
export { resolveWorktreePath } from '@smithers-orchestrator/graph';
|
|
83
88
|
|
|
84
89
|
type SerializedCtx$1 = {
|
|
85
90
|
runId: string;
|
|
@@ -173,7 +178,20 @@ type CreateSmithersOptions$1 = {
|
|
|
173
178
|
* ```
|
|
174
179
|
*/
|
|
175
180
|
declare function createSmithers<Schemas extends Record<string, zod.ZodObject<any>>>(schemas: Schemas, opts?: CreateSmithersOptions): CreateSmithersApi$1<Schemas>;
|
|
176
|
-
type
|
|
181
|
+
type CreateSmithersPostgresOptions = CreateSmithersOptions & ({
|
|
182
|
+
provider?: "postgres";
|
|
183
|
+
connectionString?: string;
|
|
184
|
+
connection?: object;
|
|
185
|
+
} | {
|
|
186
|
+
provider: "pglite";
|
|
187
|
+
dataDir?: string;
|
|
188
|
+
});
|
|
189
|
+
/**
|
|
190
|
+
* PostgreSQL/PGlite-backed equivalent of createSmithers.
|
|
191
|
+
*/
|
|
192
|
+
declare function createSmithersPostgres<Schemas extends Record<string, zod.ZodObject<any>>>(schemas: Schemas, opts?: CreateSmithersPostgresOptions): Promise<CreateSmithersApi$1<Schemas> & {
|
|
193
|
+
close: () => Promise<void>;
|
|
194
|
+
}>;
|
|
177
195
|
|
|
178
196
|
/**
|
|
179
197
|
* Create a SmithersWorkflow from an external build function.
|
|
@@ -301,13 +319,20 @@ type ConnectRequest = _smithers_server_gateway.ConnectRequest;
|
|
|
301
319
|
type ContinueAsNewProps = _smithers_components.ContinueAsNewProps;
|
|
302
320
|
type CreateScorerConfig = _smithers_scorers.CreateScorerConfig;
|
|
303
321
|
type CreateSmithersApi<Schema> = CreateSmithersApi$1<Schema>;
|
|
322
|
+
type CreateSmithersOptions = CreateSmithersOptions$1;
|
|
304
323
|
type DepsSpec = _smithers_components.DepsSpec;
|
|
305
324
|
type EventFrame = _smithers_server_gateway.EventFrame;
|
|
306
325
|
type ExternalSmithersConfig<S> = ExternalSmithersConfig$2<S>;
|
|
307
326
|
type GatewayAuthConfig = _smithers_server_gateway.GatewayAuthConfig;
|
|
308
327
|
type GatewayDefaults = _smithers_server_gateway.GatewayDefaults;
|
|
328
|
+
type GatewayOperatorUiConfig = _smithers_server_gateway.GatewayOperatorUiConfig;
|
|
309
329
|
type GatewayOptions = _smithers_server_gateway.GatewayOptions;
|
|
330
|
+
type GatewayRegisterOptions = _smithers_server_gateway.GatewayRegisterOptions;
|
|
310
331
|
type GatewayTokenGrant = _smithers_server_gateway.GatewayTokenGrant;
|
|
332
|
+
type GatewayUiConfig = _smithers_server_gateway.GatewayUiConfig;
|
|
333
|
+
type GatewayWebhookConfig = _smithers_server_gateway.GatewayWebhookConfig;
|
|
334
|
+
type GatewayWebhookRunConfig = _smithers_server_gateway.GatewayWebhookRunConfig;
|
|
335
|
+
type GatewayWebhookSignalConfig = _smithers_server_gateway.GatewayWebhookSignalConfig;
|
|
311
336
|
type GraphSnapshot = _smithers_graph_GraphSnapshot.GraphSnapshot;
|
|
312
337
|
type HelloResponse = _smithers_server_gateway.HelloResponse;
|
|
313
338
|
type HostContainer = _smithers_react_reconciler_dom_renderer.HostContainer;
|
|
@@ -333,6 +358,7 @@ type MessageHistoryConfig = _smithers_memory.MessageHistoryConfig;
|
|
|
333
358
|
type OpenAIAgentOptions<CALL_OPTIONS = never, TOOLS = ai.ToolSet> = _smithers_agents.OpenAIAgentOptions<CALL_OPTIONS, TOOLS>;
|
|
334
359
|
type HermesAgentOptions<CALL_OPTIONS = never, TOOLS = ai.ToolSet> = _smithers_agents.HermesAgentOptions<CALL_OPTIONS, TOOLS>;
|
|
335
360
|
type OpenCodeAgentOptions = _smithers_agents.OpenCodeAgentOptions;
|
|
361
|
+
type VibeAgentOptions = _smithers_agents.VibeAgentOptions;
|
|
336
362
|
type OpenApiAuth = _smithers_openapi.OpenApiAuth;
|
|
337
363
|
type OpenApiSpec = _smithers_openapi.OpenApiSpec;
|
|
338
364
|
type OpenApiToolsOptions = _smithers_openapi.OpenApiToolsOptions;
|
|
@@ -408,4 +434,4 @@ type XmlElement = _smithers_graph_XmlNode.XmlElement;
|
|
|
408
434
|
type XmlNode = _smithers_graph_XmlNode.XmlNode;
|
|
409
435
|
type XmlText = _smithers_graph_XmlNode.XmlText;
|
|
410
436
|
|
|
411
|
-
export { type AgentCapabilityRegistry, type AgentLike, type AgentToolDescriptor, type AggregateOptions, type AggregateScore, type AnthropicAgentOptions, type ApprovalAutoApprove, type ApprovalDecision, type ApprovalMode, type ApprovalOption, type ApprovalProps, type ApprovalRanking, type ApprovalRequest, type ApprovalSelection, type ColumnDef, type ConnectRequest, type ContinueAsNewProps, type CreateScorerConfig, type CreateSmithersApi, type DepsSpec, type EventFrame, type ExternalSmithersConfig, type GatewayAuthConfig, type GatewayDefaults, type GatewayOptions, type GatewayTokenGrant, type GraphSnapshot, type HelloResponse, type HermesAgentOptions, type HostContainer, type HostNodeJson, type InferDeps, type InferOutputEntry, type InferRow, type JjRevertResult, type KanbanProps, type KnownSmithersErrorCode, type LlmJudgeConfig, type MemoryFact, type MemoryLayerConfig, type MemoryMessage, type MemoryNamespace, type MemoryNamespaceKind, type MemoryProcessor, type MemoryProcessorConfig, type MemoryServiceApi, type MemoryStore, type MemoryThread, type MessageHistoryConfig, type OpenAIAgentOptions, type OpenApiAuth, type OpenApiSpec, type OpenApiToolsOptions, type OpenCodeAgentOptions, type OutputAccessor, type OutputKey, type OutputTarget, type PiAgentOptions, type PiExtensionUiRequest, type PiExtensionUiResponse, type PollerProps, type RequestFrame, type ResolvedSmithersObservabilityOptions, type ResponseFrame, type RevertOptions, type RevertResult, type RunJjOptions, type RunJjResult, type RunOptions, type RunResult, type RunStatus, type SagaProps, type SagaStepDef, type SagaStepProps, type SamplingConfig, type SandboxProps, type SandboxRuntime, type SandboxVolumeMount, type SandboxWorkspaceSpec, type SchemaRegistryEntry, type ScoreResult, type ScoreRow, type Scorer, type ScorerBinding, type ScorerContext, type ScorerFn, type ScorerInput, type ScorersMap, type SemanticRecallConfig, type SerializedCtx, type ServeOptions, type ServerOptions, type SignalProps, type SmithersAlertLabels, type SmithersAlertPolicy, type SmithersAlertPolicyDefaults, type SmithersAlertPolicyRule, type SmithersAlertReaction, type SmithersAlertReactionKind, type SmithersAlertReactionRef, type SmithersAlertSeverity, type SmithersCtx, type SmithersError, type SmithersErrorCode, type SmithersEvent, type SmithersLogFormat, type SmithersObservabilityOptions, type SmithersObservabilityService, type SmithersWorkflow, type SmithersWorkflowOptions, type TaskDescriptor, type TaskMemoryConfig, type TaskProps, type TimeTravelOptions, type TimeTravelResult, type TimerProps, type TryCatchFinallyProps, type WaitForEventProps, type WorkingMemoryConfig, type WorkspaceAddOptions, type WorkspaceInfo, type WorkspaceResult, type XmlElement, type XmlNode, type XmlText, bash, createExternalSmithers, createSmithers, defineTool, edit, getDefinedToolMetadata, grep, mdxPlugin, read, tools, write };
|
|
437
|
+
export { type AgentCapabilityRegistry, type AgentLike, type AgentToolDescriptor, type AggregateOptions, type AggregateScore, type AnthropicAgentOptions, type ApprovalAutoApprove, type ApprovalDecision, type ApprovalMode, type ApprovalOption, type ApprovalProps, type ApprovalRanking, type ApprovalRequest, type ApprovalSelection, type ColumnDef, type ConnectRequest, type ContinueAsNewProps, type CreateScorerConfig, type CreateSmithersApi, type CreateSmithersOptions, type DepsSpec, type EventFrame, type ExternalSmithersConfig, type GatewayAuthConfig, type GatewayDefaults, type GatewayOperatorUiConfig, type GatewayOptions, type GatewayRegisterOptions, type GatewayTokenGrant, type GatewayUiConfig, type GatewayWebhookConfig, type GatewayWebhookRunConfig, type GatewayWebhookSignalConfig, type GraphSnapshot, type HelloResponse, type HermesAgentOptions, type HostContainer, type HostNodeJson, type InferDeps, type InferOutputEntry, type InferRow, type JjRevertResult, type KanbanProps, type KnownSmithersErrorCode, type LlmJudgeConfig, type MemoryFact, type MemoryLayerConfig, type MemoryMessage, type MemoryNamespace, type MemoryNamespaceKind, type MemoryProcessor, type MemoryProcessorConfig, type MemoryServiceApi, type MemoryStore, type MemoryThread, type MessageHistoryConfig, type OpenAIAgentOptions, type OpenApiAuth, type OpenApiSpec, type OpenApiToolsOptions, type OpenCodeAgentOptions, type OutputAccessor, type OutputKey, type OutputTarget, type PiAgentOptions, type PiExtensionUiRequest, type PiExtensionUiResponse, type PollerProps, type RequestFrame, type ResolvedSmithersObservabilityOptions, type ResponseFrame, type RevertOptions, type RevertResult, type RunJjOptions, type RunJjResult, type RunOptions, type RunResult, type RunStatus, type SagaProps, type SagaStepDef, type SagaStepProps, type SamplingConfig, type SandboxProps, type SandboxRuntime, type SandboxVolumeMount, type SandboxWorkspaceSpec, type SchemaRegistryEntry, type ScoreResult, type ScoreRow, type Scorer, type ScorerBinding, type ScorerContext, type ScorerFn, type ScorerInput, type ScorersMap, type SemanticRecallConfig, type SerializedCtx, type ServeOptions, type ServerOptions, type SignalProps, type SmithersAlertLabels, type SmithersAlertPolicy, type SmithersAlertPolicyDefaults, type SmithersAlertPolicyRule, type SmithersAlertReaction, type SmithersAlertReactionKind, type SmithersAlertReactionRef, type SmithersAlertSeverity, type SmithersCtx, type SmithersError, type SmithersErrorCode, type SmithersEvent, type SmithersLogFormat, type SmithersObservabilityOptions, type SmithersObservabilityService, type SmithersWorkflow, type SmithersWorkflowOptions, type TaskDescriptor, type TaskMemoryConfig, type TaskProps, type TimeTravelOptions, type TimeTravelResult, type TimerProps, type TryCatchFinallyProps, type VibeAgentOptions, type WaitForEventProps, type WorkingMemoryConfig, type WorkspaceAddOptions, type WorkspaceInfo, type WorkspaceResult, type XmlElement, type XmlNode, type XmlText, bash, createExternalSmithers, createSmithers, createSmithersPostgres, defineTool, edit, getDefinedToolMetadata, grep, mdxPlugin, read, tools, write };
|
package/src/index.js
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
* @template Schema
|
|
26
26
|
* @typedef {import("./CreateSmithersApi.ts").CreateSmithersApi<Schema>} CreateSmithersApi
|
|
27
27
|
*/
|
|
28
|
+
/** @typedef {import("./CreateSmithersOptions.ts").CreateSmithersOptions} CreateSmithersOptions */
|
|
28
29
|
/** @typedef {import("@smithers-orchestrator/components").DepsSpec} DepsSpec */
|
|
29
30
|
/** @typedef {import("@smithers-orchestrator/server/gateway").EventFrame} EventFrame */
|
|
30
31
|
/**
|
|
@@ -33,8 +34,14 @@
|
|
|
33
34
|
*/
|
|
34
35
|
/** @typedef {import("@smithers-orchestrator/server/gateway").GatewayAuthConfig} GatewayAuthConfig */
|
|
35
36
|
/** @typedef {import("@smithers-orchestrator/server/gateway").GatewayDefaults} GatewayDefaults */
|
|
37
|
+
/** @typedef {import("@smithers-orchestrator/server/gateway").GatewayOperatorUiConfig} GatewayOperatorUiConfig */
|
|
36
38
|
/** @typedef {import("@smithers-orchestrator/server/gateway").GatewayOptions} GatewayOptions */
|
|
39
|
+
/** @typedef {import("@smithers-orchestrator/server/gateway").GatewayRegisterOptions} GatewayRegisterOptions */
|
|
37
40
|
/** @typedef {import("@smithers-orchestrator/server/gateway").GatewayTokenGrant} GatewayTokenGrant */
|
|
41
|
+
/** @typedef {import("@smithers-orchestrator/server/gateway").GatewayUiConfig} GatewayUiConfig */
|
|
42
|
+
/** @typedef {import("@smithers-orchestrator/server/gateway").GatewayWebhookConfig} GatewayWebhookConfig */
|
|
43
|
+
/** @typedef {import("@smithers-orchestrator/server/gateway").GatewayWebhookRunConfig} GatewayWebhookRunConfig */
|
|
44
|
+
/** @typedef {import("@smithers-orchestrator/server/gateway").GatewayWebhookSignalConfig} GatewayWebhookSignalConfig */
|
|
38
45
|
/** @typedef {import("@smithers-orchestrator/graph/GraphSnapshot").GraphSnapshot} GraphSnapshot */
|
|
39
46
|
/** @typedef {import("@smithers-orchestrator/server/gateway").HelloResponse} HelloResponse */
|
|
40
47
|
/** @typedef {import("@smithers-orchestrator/react-reconciler/dom/renderer").HostContainer} HostContainer */
|
|
@@ -86,6 +93,7 @@
|
|
|
86
93
|
/** @typedef {import("@smithers-orchestrator/agents").PiExtensionUiRequest} PiExtensionUiRequest */
|
|
87
94
|
/** @typedef {import("@smithers-orchestrator/agents").PiExtensionUiResponse} PiExtensionUiResponse */
|
|
88
95
|
/** @typedef {import("@smithers-orchestrator/agents").OpenCodeAgentOptions} OpenCodeAgentOptions */
|
|
96
|
+
/** @typedef {import("@smithers-orchestrator/agents").VibeAgentOptions} VibeAgentOptions */
|
|
89
97
|
/** @typedef {import("@smithers-orchestrator/components").PollerProps} PollerProps */
|
|
90
98
|
/** @typedef {import("@smithers-orchestrator/server/gateway").RequestFrame} RequestFrame */
|
|
91
99
|
/** @typedef {import("@smithers-orchestrator/observability").ResolvedSmithersObservabilityOptions} ResolvedSmithersObservabilityOptions */
|
|
@@ -171,18 +179,23 @@ export { knownSmithersErrorCodes } from "@smithers-orchestrator/errors/knownSmit
|
|
|
171
179
|
// Components
|
|
172
180
|
export { Approval, ApprovalGate, Aspects, Branch, CheckSuite, ClassifyAndRoute, ContentPipeline, ContinueAsNew, Debate, DecisionTable, DriftDetector, EscalationChain, GatherAndSynthesize, HumanTask, Kanban, Loop, MergeQueue, Optimizer, Panel, Parallel, Poller, Ralph, ReviewLoop, Runbook, Saga, Sandbox, ScanFixVerify, Sequence, Signal, Subflow, SuperSmithers, Supervisor, Task, Timer, TryCatchFinally, WaitForEvent, Workflow, Worktree, approvalDecisionSchema, approvalRankingSchema, approvalSelectionSchema, continueAsNew, } from "@smithers-orchestrator/components";
|
|
173
181
|
// Agents
|
|
174
|
-
export { AnthropicAgent, OpenAIAgent, HermesAgent, AmpAgent, AntigravityAgent, ClaudeCodeAgent, CodexAgent, GeminiAgent, PiAgent, KimiAgent, ForgeAgent, OpenCodeAgent, } from "@smithers-orchestrator/agents";
|
|
182
|
+
export { AnthropicAgent, OpenAIAgent, HermesAgent, AmpAgent, AntigravityAgent, ClaudeCodeAgent, CodexAgent, GeminiAgent, PiAgent, KimiAgent, ForgeAgent, VibeAgent, OpenCodeAgent, } from "@smithers-orchestrator/agents";
|
|
175
183
|
// VCS
|
|
176
184
|
export { runJj, getJjPointer, revertToJjPointer, isJjRepo, workspaceAdd, workspaceList, workspaceClose, } from "@smithers-orchestrator/vcs/jj";
|
|
177
185
|
// Core API
|
|
178
|
-
export { createSmithers } from "./create.js";
|
|
186
|
+
export { createSmithers, createSmithersPostgres } from "./create.js";
|
|
179
187
|
export {
|
|
188
|
+
approveNode,
|
|
189
|
+
denyNode,
|
|
180
190
|
fragment,
|
|
191
|
+
getRun,
|
|
192
|
+
listRuns,
|
|
181
193
|
renderFrame,
|
|
182
194
|
runWorkflow,
|
|
183
195
|
Smithers,
|
|
184
196
|
workflow,
|
|
185
197
|
} from "@smithers-orchestrator/engine";
|
|
198
|
+
export { resolveWorktreePath } from "@smithers-orchestrator/graph";
|
|
186
199
|
export { signalRun } from "@smithers-orchestrator/engine/signals";
|
|
187
200
|
export { usePatched } from "@smithers-orchestrator/engine/effect/versioning";
|
|
188
201
|
// Tools
|
|
@@ -204,7 +217,8 @@ export { createServeApp } from "@smithers-orchestrator/server/serve";
|
|
|
204
217
|
// Observability
|
|
205
218
|
export { SmithersObservability, createSmithersObservabilityLayer, createSmithersOtelLayer, createSmithersRuntimeLayer, smithersMetrics, trackSmithersEvent, activeNodes, activeRuns, externalWaitAsyncPending, approvalsDenied, approvalsGranted, approvalsRequested, timerDelayDuration, timersCancelled, timersCreated, timersFired, timersPending, attemptDuration, cacheHits, cacheMisses, dbQueryDuration, dbRetries, dbTransactionDuration, dbTransactionRetries, dbTransactionRollbacks, hotReloadDuration, hotReloadFailures, hotReloads, httpRequestDuration, httpRequests, nodeDuration, nodesFailed, nodesFinished, nodesStarted, prometheusContentType, renderPrometheusMetrics, resolveSmithersObservabilityOptions, runsTotal, sandboxActive, sandboxBundleSizeBytes, sandboxCompletedTotal, sandboxCreatedTotal, sandboxDurationMs, sandboxPatchCount, sandboxTransportDurationMs, schedulerQueueDepth, toolCallsTotal, toolDuration, vcsDuration, } from "@smithers-orchestrator/observability";
|
|
206
219
|
// DB
|
|
207
|
-
export { SmithersDb } from "@smithers-orchestrator/db
|
|
220
|
+
export { SmithersDb } from "@smithers-orchestrator/db";
|
|
221
|
+
export { loadOutputs, loadOutputsEffect } from "@smithers-orchestrator/db";
|
|
208
222
|
export { ensureSmithersTables } from "@smithers-orchestrator/db/ensure";
|
|
209
223
|
// Renderer
|
|
210
224
|
export { SmithersRenderer } from "@smithers-orchestrator/react-reconciler/dom/renderer";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ReactElement } from "react";
|
|
2
|
+
|
|
3
|
+
/** Element key accepted by the JSX runtime factories. */
|
|
4
|
+
export type JsxRuntimeKey = string | number | undefined;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Smithers JSX runtime factories — the target of
|
|
8
|
+
* `jsxImportSource: "smithers-orchestrator"` and what `<Workflow/>`, `<Task/>`,
|
|
9
|
+
* etc. compile to. They are deliberately typed wide (`type`/`props` as
|
|
10
|
+
* `unknown`): components validate their own props, and keeping these signatures
|
|
11
|
+
* loose avoids expanding Smithers' deep workflow types during type-checking,
|
|
12
|
+
* which is otherwise expensive. Callers that build trees programmatically can
|
|
13
|
+
* use these directly, e.g. `jsx(Task, { id, output, agent, children }, key)`.
|
|
14
|
+
*/
|
|
15
|
+
export function jsx(type: unknown, props: unknown, key?: JsxRuntimeKey): ReactElement;
|
|
16
|
+
export function jsxs(type: unknown, props: unknown, key?: JsxRuntimeKey): ReactElement;
|
|
17
|
+
export function jsxDEV(
|
|
18
|
+
type: unknown,
|
|
19
|
+
props: unknown,
|
|
20
|
+
key?: JsxRuntimeKey,
|
|
21
|
+
isStaticChildren?: boolean,
|
|
22
|
+
source?: unknown,
|
|
23
|
+
self?: unknown,
|
|
24
|
+
): ReactElement;
|
|
25
|
+
export const Fragment: unknown;
|
package/src/tools/bash.js
CHANGED
|
@@ -175,7 +175,7 @@ export async function bashTool(cmd, args = [], opts = undefined) {
|
|
|
175
175
|
|
|
176
176
|
export const bash = defineTool({
|
|
177
177
|
name: "bash",
|
|
178
|
-
description: "
|
|
178
|
+
description: "Run an executable with arguments",
|
|
179
179
|
schema: z.object({
|
|
180
180
|
cmd: z.string(),
|
|
181
181
|
args: z.array(z.string()).optional(),
|
package/src/tools/context.js
CHANGED
|
@@ -1,29 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function getToolIdempotencyKey(ctx = getToolContext()) {
|
|
14
|
-
if (!ctx) {
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
if (typeof ctx.idempotencyKey === "string" && ctx.idempotencyKey.length > 0) {
|
|
18
|
-
return ctx.idempotencyKey;
|
|
19
|
-
}
|
|
20
|
-
if (!ctx.runId || !ctx.nodeId) {
|
|
21
|
-
return null;
|
|
22
|
-
}
|
|
23
|
-
return `smithers:${ctx.runId}:${ctx.nodeId}:${ctx.iteration ?? 0}`;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function nextToolSeq(ctx) {
|
|
27
|
-
ctx.seq = (ctx.seq ?? 0) + 1;
|
|
28
|
-
return ctx.seq;
|
|
29
|
-
}
|
|
1
|
+
// The tool-execution context now lives in its own low-level package so both the
|
|
2
|
+
// engine and smithers can depend on it without a cycle (the engine needs
|
|
3
|
+
// runWithToolContext to give in-process agent tools their run context). This file
|
|
4
|
+
// stays as a re-export so existing relative importers keep working.
|
|
5
|
+
export {
|
|
6
|
+
runWithToolContext,
|
|
7
|
+
getToolContext,
|
|
8
|
+
getToolIdempotencyKey,
|
|
9
|
+
nextToolSeq,
|
|
10
|
+
} from "@smithers-orchestrator/tool-context";
|
package/src/tools/defineTool.js
CHANGED
|
@@ -26,6 +26,8 @@ function defaultToolContext() {
|
|
|
26
26
|
maxOutputBytes: 200_000,
|
|
27
27
|
timeoutMs: 60_000,
|
|
28
28
|
seq: 0,
|
|
29
|
+
// No-op unless the engine populated a real durability handle (flag on).
|
|
30
|
+
durabilitySnapshot: async () => ({ skipped: true }),
|
|
29
31
|
};
|
|
30
32
|
}
|
|
31
33
|
|
|
@@ -48,14 +50,28 @@ export function defineTool(options) {
|
|
|
48
50
|
inputSchema: zodSchema(options.schema),
|
|
49
51
|
execute: async (args) => {
|
|
50
52
|
const toolContext = getToolContext();
|
|
53
|
+
// Merge the ambient context OVER the defaults, so a partial context from the
|
|
54
|
+
// engine (run/node/cwd + durabilitySnapshot) overrides what it sets and keeps
|
|
55
|
+
// sane defaults for the rest.
|
|
51
56
|
const definedContext = {
|
|
52
|
-
...
|
|
57
|
+
...defaultToolContext(),
|
|
58
|
+
...(toolContext ?? {}),
|
|
53
59
|
idempotencyKey: getToolIdempotencyKey(toolContext),
|
|
54
60
|
toolName: options.name,
|
|
55
61
|
sideEffect,
|
|
56
62
|
idempotent,
|
|
57
63
|
};
|
|
58
|
-
|
|
64
|
+
const result = await options.execute(args, definedContext);
|
|
65
|
+
// Strict Tier 1 snapshot at this tool boundary, before the agent proceeds.
|
|
66
|
+
// No-op by default; never delays past one jj snapshot and never fails the tool.
|
|
67
|
+
if (sideEffect && typeof definedContext.durabilitySnapshot === "function") {
|
|
68
|
+
try {
|
|
69
|
+
await definedContext.durabilitySnapshot(options.name, definedContext.toolUseId);
|
|
70
|
+
} catch {
|
|
71
|
+
/* snapshot failures never fail the tool */
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return result;
|
|
59
75
|
},
|
|
60
76
|
});
|
|
61
77
|
|