@bastani/atomic 0.9.44-alpha.7 → 0.9.45-alpha.1
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/CHANGELOG.md +58 -0
- package/dist/builtin/intercom/CHANGELOG.md +18 -0
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/CHANGELOG.md +7 -0
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +9 -0
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +42 -0
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/durable/journal/internal.d.ts +6 -37
- package/dist/builtin/workflows/src/durable/journal/resolution.d.ts +2 -0
- package/dist/builtin/workflows/src/durable/journal/sql-run-journal.d.ts +5 -4
- package/dist/builtin/workflows/src/durable/journal/types.d.ts +1 -1
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +40393 -40289
- package/dist/builtin/workflows/src/extension/local-worker-entry.mjs +55675 -55570
- package/dist/builtin/workflows/src/index.js +126 -22
- package/dist/builtin/workflows/src/local-worker-entry.mjs +55675 -55570
- package/dist/core/settings-schema.d.ts.map +1 -1
- package/dist/core/settings-schema.js +1 -1
- package/dist/core/settings-schema.js.map +1 -1
- package/dist/core/storage/provider.d.ts +6 -3
- package/dist/core/storage/provider.d.ts.map +1 -1
- package/dist/core/storage/provider.js +7 -5
- package/dist/core/storage/provider.js.map +1 -1
- package/dist/core/storage/run-journal.d.ts +34 -0
- package/dist/core/storage/run-journal.d.ts.map +1 -1
- package/dist/core/storage/run-journal.js.map +1 -1
- package/docs/settings.md +1 -1
- package/docs/storage.md +3 -1
- package/docs/workflows/api-reference.md +8 -1
- package/docs/workflows/operations.md +1 -1
- package/npm-shrinkwrap.json +32 -32
- package/package.json +3 -3
- package/schemas/settings.schema.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-journal.js","sourceRoot":"","sources":["../../../src/core/storage/run-journal.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,eAAe,GAAG;IAC9B,UAAU,EAAE,YAAY;IACxB,WAAW,EAAE,aAAa;IAC1B,aAAa,EAAE,eAAe;IAC9B,kBAAkB,EAAE,oBAAoB;IACxC,WAAW,EAAE,aAAa;IAC1B,cAAc,EAAE,gBAAgB;IAChC,gBAAgB,EAAE,kBAAkB;IACpC,aAAa,EAAE,eAAe;IAC9B,gBAAgB,EAAE,kBAAkB;IACpC,cAAc,EAAE,gBAAgB;IAChC,cAAc,EAAE,gBAAgB;IAChC,eAAe,EAAE,iBAAiB;CACzB,CAAC","sourcesContent":["import type { StorageDescriptor } from \"./database.js\";\n\nexport const RUN_EVENT_TYPES = {\n\trunStarted: \"RunStarted\",\n\trunFinished: \"RunFinished\",\n\tstatusChanged: \"StatusChanged\",\n\tcheckpointRecorded: \"CheckpointRecorded\",\n\tpromptAsked: \"PromptAsked\",\n\tpromptReleased: \"PromptReleased\",\n\tcontrolRequested: \"ControlRequested\",\n\tmessageQueued: \"MessageQueued\",\n\tmessageDelivered: \"MessageDelivered\",\n\tmessageSettled: \"MessageSettled\",\n\ttimerScheduled: \"TimerScheduled\",\n\tsummaryRecorded: \"SummaryRecorded\",\n} as const;\nexport type RunEventType = (typeof RUN_EVENT_TYPES)[keyof typeof RUN_EVENT_TYPES];\n\nexport type JournalSerializableValue =\n\t| string\n\t| number\n\t| boolean\n\t| null\n\t| readonly JournalSerializableValue[]\n\t| { readonly [key: string]: JournalSerializableValue | undefined };\n\nexport interface RunHeader {\n\treadonly runId: string;\n\treadonly name: string;\n\treadonly cwd: string;\n\treadonly createdAt: number;\n\treadonly status: string;\n\treadonly inputs?: JournalSerializableValue;\n\treadonly storage?: StorageDescriptor;\n}\nexport type RunSummary = RunHeader;\n\ntype EventOf<Type extends string, Payload = JournalSerializableValue> = {\n\treadonly type: Type;\n\treadonly payload: Payload;\n};\nexport type RunEvent =\n\t| EventOf<\"RunStarted\" | \"RunFinished\">\n\t| EventOf<\"StatusChanged\", { readonly status: string; readonly [key: string]: JournalSerializableValue }>\n\t| EventOf<\n\t\t\t\"CheckpointRecorded\",\n\t\t\t{\n\t\t\t\treadonly kind: \"tool\" | \"ui\" | \"stage\" | \"task\" | \"boundary\";\n\t\t\t\treadonly [key: string]: JournalSerializableValue;\n\t\t\t}\n\t >\n\t| EventOf<\n\t\t\t| \"PromptAsked\"\n\t\t\t| \"PromptReleased\"\n\t\t\t| \"ControlRequested\"\n\t\t\t| \"MessageQueued\"\n\t\t\t| \"MessageDelivered\"\n\t\t\t| \"MessageSettled\"\n\t\t\t| \"TimerScheduled\"\n\t\t\t| \"SummaryRecorded\"\n\t >;\nexport interface Lease {\n\treadonly runId: string;\n\treadonly holderId: string;\n\treadonly epoch: number;\n}\nexport type LeaseState = Lease & { readonly renewedAt: number; readonly ageMs: number };\nexport type LeaseOutcome =\n\t| { readonly status: \"acquired\"; readonly lease: Lease }\n\t| { readonly status: \"held\"; readonly holderId: string | null; readonly epoch: number };\nexport interface JournalEntry {\n\treadonly runId: string;\n\treadonly seq: number;\n\treadonly epoch: number;\n\treadonly key?: string;\n\treadonly event: RunEvent;\n\treadonly at: number;\n}\nexport type AppendOutcome = { readonly status: \"appended\" | \"exists\"; readonly entry: JournalEntry };\nexport interface RunJournal {\n\tcreateRun(header: RunHeader): Promise<\"created\" | \"exists\">;\n\tgetRun(runId: string): Promise<RunSummary | undefined>;\n\tlistRuns(filter?: { cwd?: string }): Promise<readonly RunSummary[]>;\n\tacquire(runId: string, holderId: string): Promise<LeaseOutcome>;\n\ttakeover(runId: string, holderId: string, expectedHolder: string): Promise<LeaseOutcome>;\n\ttakeoverExpired(runId: string, holderId: string, staleAfterMs: number): Promise<LeaseOutcome>;\n\tleaseState(runId: string): Promise<LeaseState | undefined>;\n\trenew(lease: Lease): Promise<void>;\n\trelease(lease: Lease): Promise<void>;\n\tappend(lease: Lease, event: RunEvent, options?: { key?: string; expectSeq?: number }): Promise<AppendOutcome>;\n\tread(runId: string, fromSeq?: number): AsyncIterable<JournalEntry>;\n\treadKey(runId: string, key: string): Promise<JournalEntry | undefined>;\n\tdeleteOwnedRun(lease: Lease, expectSeq?: number): Promise<void>;\n\tdeleteRun(runId: string): Promise<void>;\n\tclose(): Promise<void>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"run-journal.js","sourceRoot":"","sources":["../../../src/core/storage/run-journal.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,eAAe,GAAG;IAC9B,UAAU,EAAE,YAAY;IACxB,WAAW,EAAE,aAAa;IAC1B,aAAa,EAAE,eAAe;IAC9B,kBAAkB,EAAE,oBAAoB;IACxC,WAAW,EAAE,aAAa;IAC1B,cAAc,EAAE,gBAAgB;IAChC,gBAAgB,EAAE,kBAAkB;IACpC,aAAa,EAAE,eAAe;IAC9B,gBAAgB,EAAE,kBAAkB;IACpC,cAAc,EAAE,gBAAgB;IAChC,cAAc,EAAE,gBAAgB;IAChC,eAAe,EAAE,iBAAiB;CACzB,CAAC","sourcesContent":["import type { StorageDescriptor } from \"./database.js\";\n\nexport const RUN_EVENT_TYPES = {\n\trunStarted: \"RunStarted\",\n\trunFinished: \"RunFinished\",\n\tstatusChanged: \"StatusChanged\",\n\tcheckpointRecorded: \"CheckpointRecorded\",\n\tpromptAsked: \"PromptAsked\",\n\tpromptReleased: \"PromptReleased\",\n\tcontrolRequested: \"ControlRequested\",\n\tmessageQueued: \"MessageQueued\",\n\tmessageDelivered: \"MessageDelivered\",\n\tmessageSettled: \"MessageSettled\",\n\ttimerScheduled: \"TimerScheduled\",\n\tsummaryRecorded: \"SummaryRecorded\",\n} as const;\nexport type RunEventType = (typeof RUN_EVENT_TYPES)[keyof typeof RUN_EVENT_TYPES];\n\nexport type JournalSerializableValue =\n\t| string\n\t| number\n\t| boolean\n\t| null\n\t| readonly JournalSerializableValue[]\n\t| { readonly [key: string]: JournalSerializableValue | undefined };\n\nexport interface RunHeader {\n\treadonly runId: string;\n\treadonly name: string;\n\treadonly cwd: string;\n\treadonly createdAt: number;\n\treadonly status: string;\n\treadonly inputs?: JournalSerializableValue;\n\treadonly storage?: StorageDescriptor;\n}\nexport type RunSummary = RunHeader;\n\ntype EventOf<Type extends string, Payload = JournalSerializableValue> = {\n\treadonly type: Type;\n\treadonly payload: Payload;\n};\nexport type RunEvent =\n\t| EventOf<\"RunStarted\" | \"RunFinished\">\n\t| EventOf<\"StatusChanged\", { readonly status: string; readonly [key: string]: JournalSerializableValue }>\n\t| EventOf<\n\t\t\t\"CheckpointRecorded\",\n\t\t\t{\n\t\t\t\treadonly kind: \"tool\" | \"ui\" | \"stage\" | \"task\" | \"boundary\";\n\t\t\t\treadonly [key: string]: JournalSerializableValue;\n\t\t\t}\n\t >\n\t| EventOf<\n\t\t\t| \"PromptAsked\"\n\t\t\t| \"PromptReleased\"\n\t\t\t| \"ControlRequested\"\n\t\t\t| \"MessageQueued\"\n\t\t\t| \"MessageDelivered\"\n\t\t\t| \"MessageSettled\"\n\t\t\t| \"TimerScheduled\"\n\t\t\t| \"SummaryRecorded\"\n\t >;\nexport interface Lease {\n\treadonly runId: string;\n\treadonly holderId: string;\n\treadonly epoch: number;\n}\nexport type LeaseState = Lease & { readonly renewedAt: number; readonly ageMs: number };\nexport type LeaseOutcome =\n\t| { readonly status: \"acquired\"; readonly lease: Lease }\n\t| { readonly status: \"held\"; readonly holderId: string | null; readonly epoch: number };\nexport interface JournalEntry {\n\treadonly runId: string;\n\treadonly seq: number;\n\treadonly epoch: number;\n\treadonly key?: string;\n\treadonly event: RunEvent;\n\treadonly at: number;\n}\nexport type AppendOutcome = { readonly status: \"appended\" | \"exists\"; readonly entry: JournalEntry };\n/** A run's latest event. A run whose history was deleted and recorded again ends with a different event. */\nexport interface RunVersion {\n\treadonly seq: number;\n\treadonly at: number;\n}\n/**\n * A run's latest snapshot event (one carrying the run's handle) and the checkpoints recorded after it: enough to\n * list the run in a catalog without reading its history.\n */\nexport interface RunSnapshotTail {\n\t/** The run's latest event of any type. */\n\treadonly version: RunVersion;\n\treadonly snapshot: JournalEntry;\n\treadonly laterCheckpoints: number;\n\t/** `completedAt` of the last of `laterCheckpoints`. */\n\treadonly lastCheckpointAt?: number;\n}\n/** One append of a batch. `context` runs a function in the async context the append was issued from. */\nexport interface RunJournalBatchAppend {\n\treadonly event: RunEvent;\n\treadonly key?: string;\n\treadonly context: <R>(action: () => R) => R;\n}\nexport interface RunJournal {\n\tcreateRun(header: RunHeader): Promise<\"created\" | \"exists\">;\n\tgetRun(runId: string): Promise<RunSummary | undefined>;\n\tlistRuns(filter?: { cwd?: string }): Promise<readonly RunSummary[]>;\n\tacquire(runId: string, holderId: string): Promise<LeaseOutcome>;\n\ttakeover(runId: string, holderId: string, expectedHolder: string): Promise<LeaseOutcome>;\n\ttakeoverExpired(runId: string, holderId: string, staleAfterMs: number): Promise<LeaseOutcome>;\n\tleaseState(runId: string): Promise<LeaseState | undefined>;\n\trenew(lease: Lease): Promise<void>;\n\trelease(lease: Lease): Promise<void>;\n\tappend(lease: Lease, event: RunEvent, options?: { key?: string; expectSeq?: number }): Promise<AppendOutcome>;\n\tread(runId: string, fromSeq?: number): AsyncIterable<JournalEntry>;\n\treadKey(runId: string, key: string): Promise<JournalEntry | undefined>;\n\tdeleteOwnedRun(lease: Lease, expectSeq?: number): Promise<void>;\n\tdeleteRun(runId: string): Promise<void>;\n\tclose(): Promise<void>;\n\t/**\n\t * Optional change tracking, used only when `changeToken`, `runVersions` and `snapshotTail` are all present. The\n\t * token moves whenever any connection, in this process or another, commits a change to the journal's store.\n\t */\n\tchangeToken?(): Promise<string>;\n\t/** Every listed run with its latest event; a run with no events has version `{ seq: 0, at: 0 }`. */\n\trunVersions?(): Promise<ReadonlyMap<string, RunVersion>>;\n\t/** Undefined for a run with no snapshot event. */\n\tsnapshotTail?(runId: string): Promise<RunSnapshotTail | undefined>;\n\t/** Optional batched appends to one run in one transaction; each append is settled on its own, in order. */\n\tappendMany?(\n\t\tlease: Lease,\n\t\tappends: readonly RunJournalBatchAppend[],\n\t): Promise<readonly PromiseSettledResult<AppendOutcome>[]>;\n}\n"]}
|
package/docs/settings.md
CHANGED
|
@@ -602,7 +602,7 @@ Local worker pools are disabled unless `workflows.localWorkers` is set. With the
|
|
|
602
602
|
|
|
603
603
|
`count` is a positive integer. Paths in the settings object resolve against the invocation working directory. Worker settings and entry-module digests are saved with the root; resume refuses changed settings or definitions. The entry-module digest does not include imported dependencies.
|
|
604
604
|
|
|
605
|
-
`startupTimeoutMs` is how long, in milliseconds, each worker process may take to become ready.
|
|
605
|
+
`startupTimeoutMs` is how long, in milliseconds, each worker process may take to become ready. When it is unset, the deadline is 30000 ms, scaled up when the pool has more workers than the machine has CPU cores or the machine is already busy: it is 30000 ms times (worker count + 1-minute load average) ÷ CPU cores, at least 30000 ms and at most 600000 ms. Raise it if runs fail with `Local worker startup timed out … workers were too slow to start`. The pool runs children once any worker is ready and fails only when no worker starts. This value is not saved with the root, so changing it does not block a resume. Each worker's standard error is written to `worker-logs/<root run ID>/<worker ID>.log` in the workflow journal's directory, and worker failure messages name that file. See [Worker startup and failures](/workflows/operations#worker-startup-and-failures).
|
|
606
606
|
|
|
607
607
|
`leaseMs` is how long, in milliseconds, a worker that is still running but has stopped responding keeps its child before the child is replayed on another worker. It defaults to `30000` and must be at least `2000`. A worker that exits is replaced immediately, and a worker that is still responding keeps its child even when the pool is briefly too busy to process its heartbeats. Like `startupTimeoutMs`, this value is not saved with the root.
|
|
608
608
|
|
package/docs/storage.md
CHANGED
|
@@ -251,11 +251,13 @@ Select it with `sessions.storage: { "adapter": "./storage/libsql-adapter.ts" }`,
|
|
|
251
251
|
|
|
252
252
|
Adapter modules import `@bastani/atomic/storage` and `@bastani/atomic` from the running Atomic, in the npm package and the standalone binary alike, exactly as extensions do. They need no installed or linked copy of Atomic, and Atomic recognizes the storage errors they throw. List `@bastani/atomic` in an adapter package's `peerDependencies`, not its `dependencies`.
|
|
253
253
|
|
|
254
|
+
When Atomic loads an adapter to open a workflow journal, the adapter can also import `@bastani/atomic/workflows` and gets the running Atomic's workflows module. An `openRunJournal` hook can build on `SqlRunJournal`, and errors such as `StaleLeaseError` pass Atomic's `instanceof` checks. Adapters loaded only for sessions or Intercom do not get this module.
|
|
255
|
+
|
|
254
256
|
`options` is an object of SQLite scalar values or booleans. In JSON settings use strings, numbers, booleans, or null. `secrets` maps option names to `{ env }` or `{ file }`, and resolved values override same-named options. A `{ file }` secret is read as written, except that one trailing line ending (`\n` or `\r\n`) is removed, so a token saved with `turso db tokens create <db> > token` works as is. Other whitespace is kept. Keep credentials out of `options` and database descriptors. `context` contains `agentDir`, `domain: "sessions" | "journal" | "intercom"`, and an optional `signal`. Intercom brokers open the top-level `storage` selection with `domain: "intercom"` through `openDatabase`.
|
|
255
257
|
|
|
256
258
|
A SQLite adapter implements `openDatabase(options, context): Promise<SqliteDatabase>`. Atomic applies its domain schema and optional table prefix. A full adapter can instead implement `openSessionStore(options, context, storage)` or `openRunJournal(options, context, storage)`; the domain hook takes priority over `openDatabase`. The typed third argument is `{ readonly prefix?: string }`. Domain adapters must honor this prefix to isolate selected stores. A missing domain/database hook raises `StorageConfigError` with reason `"adapter-domain-unsupported"`. Load failures and invalid module contracts raise `StorageAdapterLoadError`; driver opening failures raise `StorageUnavailableError`. None selects memory as a fallback.
|
|
257
259
|
|
|
258
|
-
The exported `StorageProvider` can open either domain explicitly. Construct it with `{ memory: (descriptor) => new MemoryRunJournal(descriptor), sql: SqlRunJournal.open }` from `@bastani/atomic/workflows`, then call `openSessionStore(selection, context)` or `openRunJournal(selection, context)`. For sessions alone, `new StorageProvider()` needs no journal factories. `StorageSelection` uses `kind: "memory"`, `"jsonl"` with `dir` for sessions only, `"sqlite"` with `path`, `"database"` with a caller-owned facade, or `"adapter"` with `module`, optional options/secrets/prefix.
|
|
260
|
+
The exported `StorageProvider` can open either domain explicitly. Construct it with `{ memory: (descriptor) => new MemoryRunJournal(descriptor), sql: SqlRunJournal.open }` from `@bastani/atomic/workflows`, then call `openSessionStore(selection, context)` or `openRunJournal(selection, context)`. Add `hostModules: { "@bastani/atomic/workflows": workflows }` to give journal adapters your copy of the workflows module; `loadStorageAdapter(module, context, hostModules)` accepts the same map. For sessions alone, `new StorageProvider()` needs no journal factories. `StorageSelection` uses `kind: "memory"`, `"jsonl"` with `dir` for sessions only, `"sqlite"` with `path`, `"database"` with a caller-owned facade, or `"adapter"` with `module`, optional options/secrets/prefix.
|
|
259
261
|
|
|
260
262
|
One provider shares a database for matching owned SQLite or adapter selections. Close every returned store; the last store closes the owned database. Closing a store is idempotent. A caller-owned `database` is never closed by the provider. A full domain adapter owns its returned store's lifecycle. Invalid configuration stops selection, and a configured persistent store that cannot open never becomes an in-memory store.
|
|
261
263
|
|
|
@@ -1247,7 +1247,7 @@ Only first-level child workflow subtrees are placed on workers. Nested children
|
|
|
1247
1247
|
|
|
1248
1248
|
#### Local worker options
|
|
1249
1249
|
|
|
1250
|
-
`RunOpts.localWorkers` enables a local process pool for this root. `count` must be a positive integer. `definitions` lists `{ path, exportName }` entries. The definitions are loaded in each worker from the local filesystem. The optional `startupTimeoutMs` is how long, in milliseconds, each worker process may take to become ready; it must be a positive integer no greater than `2147483647
|
|
1250
|
+
`RunOpts.localWorkers` enables a local process pool for this root. `count` must be a positive integer. `definitions` lists `{ path, exportName }` entries. The definitions are loaded in each worker from the local filesystem. The optional `startupTimeoutMs` is how long, in milliseconds, each worker process may take to become ready; it must be a positive integer no greater than `2147483647`. When it is unset, the deadline is 30000 ms scaled by (worker count + 1-minute load average) ÷ CPU cores, at least 30000 ms and at most 600000 ms. The optional `leaseMs` is how long, in milliseconds, a worker that is still running but has stopped responding keeps its child before the child is replayed on another worker; it must be an integer from `2000` to `2147483647` and defaults to `30000`. `RunOpts.admission` accepts `limits` for one root, `userLimits` across runs, a `userDatabase` canonical local SQLite path, and optional host thresholds `maxLoadPerCpu` and `minFreeMemoryBytes`.
|
|
1251
1251
|
|
|
1252
1252
|
The option is off by default. Without it, Atomic creates no pool tables, worker processes, or polling loops. CLI users can set the same options under `workflows.localWorkers` and `workflows.admission` in settings. Settings paths resolve against the invocation working directory; SDK paths resolve against `cwd` (or the current directory). Effective settings and definition entry-module digests are persisted with the root and checked on resume. Changing them fails compatibility checks instead of silently changing placement. `startupTimeoutMs` and `leaseMs` are the exceptions: they are not persisted, and each start or resume uses the values it is given.
|
|
1253
1253
|
|
|
@@ -1520,6 +1520,13 @@ interface RunJournal {
|
|
|
1520
1520
|
|
|
1521
1521
|
Custom journals need only the async contract; no synchronous journal methods are required. Use `registerRunJournalConformance(runner, name, open, observeRead)` to check a fresh journal per case. Supply a read observer that reports actual page sizes and entries loaded or copied, with `restore()` and `reset()` methods, so the suite can verify lazy reads without consuming the whole history.
|
|
1522
1522
|
|
|
1523
|
+
A custom journal can also implement two optional speed-ups that `SqlRunJournal` already provides. Atomic uses them whenever they are present on the journal object, including journals returned by a storage adapter's `openRunJournal`:
|
|
1524
|
+
|
|
1525
|
+
- `changeToken()`, `runVersions()` and `snapshotTail(runId)`, implemented together, let `/workflow status` and resume skip runs that have not changed and summarize the others from their latest snapshot instead of reading every event. `changeToken()` must return a different string after any commit to the store, from any connection. `runVersions()` returns each listed run's latest `{ seq, at }`, or `{ seq: 0, at: 0 }` for a run with no events. `snapshotTail(runId)` returns the run's latest event that is not `CheckpointRecorded`, `MessageSettled` or `MessageDelivered`, the latest version, the number of checkpoints after that event and the last one's `completedAt`, or `undefined` when there is no such event.
|
|
1526
|
+
- `appendMany(lease, appends)` writes a burst of delivery receipts and settlements to one run in one transaction. Check the lease once for the batch and reject the whole call with `StaleLeaseError` if it is stale. Otherwise settle each append on its own, in order, with the same results `append` would give; one append's failure must not undo the others.
|
|
1527
|
+
|
|
1528
|
+
The types `RunVersion`, `RunSnapshotTail` and `RunJournalBatchAppend` are exported from `@bastani/atomic/storage`. When these members are present, `registerRunJournalConformance` also checks them.
|
|
1529
|
+
|
|
1523
1530
|
Precedence is `RunOpts.journal` (`createAgentSession({ journal })` for a session's `workflow` tool), `--storage` or `--storage-file`, `ATOMIC_WORKFLOWS_JOURNAL` or non-empty `ATOMIC_WORKFLOW_JOURNAL_PATH`, `ATOMIC_STORAGE`, `workflows.journal`, shared top-level `storage`, then the default `~/.atomic/workflows/journal.sqlite`. Nearer settings selections replace whole objects, never merge options or secrets. Relative settings paths resolve against Atomic home. Invalid selected values raise `StorageConfigError`; storage failures reject the call without selecting memory. Keep the same journal and working directory when resuming stored runs.
|
|
1524
1531
|
|
|
1525
1532
|
```ts
|
|
@@ -885,7 +885,7 @@ The root's existing `/workflow status`, `/workflow stages`, steering, pause, qui
|
|
|
885
885
|
|
|
886
886
|
### Worker startup and failures
|
|
887
887
|
|
|
888
|
-
Each worker process must report that it is ready within `localWorkers.startupTimeoutMs` milliseconds, 30000
|
|
888
|
+
Each worker process must report that it is ready within `localWorkers.startupTimeoutMs` milliseconds. By default the deadline is 30000 ms, scaled up when the pool has more workers than the machine has CPU cores or the machine is already busy: it is 30000 ms times (worker count + 1-minute load average) ÷ CPU cores, at least 30000 ms and at most 600000 ms. When a pool starts, it runs children as soon as one worker is ready. A worker that exits or times out during that startup is left out of the pool, and the run fails only when no worker starts. A replacement worker that cannot start fails the run. `startupTimeoutMs` is not saved with the root, so you can change it before resuming. If a run fails with `Local worker startup timed out after … ms: workers were too slow to start`, the machine could not start the workers in time; set `workflows.localWorkers.startupTimeoutMs` (or `localWorkers.startupTimeoutMs` in the SDK) to a higher value, or use fewer workers.
|
|
889
889
|
|
|
890
890
|
A worker that exits is detected immediately, and its child is replayed from its last committed checkpoint on a replacement worker. A worker that is still running keeps its child as long as it keeps responding, even when the pool is briefly too busy to process its heartbeats. Only a running worker that has not responded for `localWorkers.leaseMs` milliseconds (30000 by default) is stopped and its child replayed. When a root is resumed after its process crashed, children that were held by the crashed process's workers are replayed on the new workers right away.
|
|
891
891
|
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/atomic",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.45-alpha.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bastani/atomic",
|
|
9
|
-
"version": "0.9.
|
|
9
|
+
"version": "0.9.45-alpha.1",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@bastani/atomic-natives": "0.9.
|
|
13
|
-
"@bastani/pi-ai": "0.9.
|
|
12
|
+
"@bastani/atomic-natives": "0.9.45-alpha.1",
|
|
13
|
+
"@bastani/pi-ai": "0.9.45-alpha.1",
|
|
14
14
|
"@earendil-works/pi-agent-core": "1.4.0",
|
|
15
15
|
"@earendil-works/pi-codemode": "1.4.0",
|
|
16
16
|
"@earendil-works/pi-tui": "1.4.0",
|
|
@@ -427,18 +427,18 @@
|
|
|
427
427
|
}
|
|
428
428
|
},
|
|
429
429
|
"node_modules/@bastani/atomic-natives": {
|
|
430
|
-
"version": "0.9.
|
|
431
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives/-/atomic-natives-0.9.
|
|
430
|
+
"version": "0.9.45-alpha.1",
|
|
431
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives/-/atomic-natives-0.9.45-alpha.1.tgz",
|
|
432
432
|
"license": "MIT",
|
|
433
433
|
"optionalDependencies": {
|
|
434
|
-
"@bastani/atomic-natives-darwin-arm64": "0.9.
|
|
435
|
-
"@bastani/atomic-natives-darwin-x64": "0.9.
|
|
436
|
-
"@bastani/atomic-natives-linux-arm64-gnu": "0.9.
|
|
437
|
-
"@bastani/atomic-natives-linux-arm64-musl": "0.9.
|
|
438
|
-
"@bastani/atomic-natives-linux-x64-gnu": "0.9.
|
|
439
|
-
"@bastani/atomic-natives-linux-x64-musl": "0.9.
|
|
440
|
-
"@bastani/atomic-natives-win32-arm64-msvc": "0.9.
|
|
441
|
-
"@bastani/atomic-natives-win32-x64-msvc": "0.9.
|
|
434
|
+
"@bastani/atomic-natives-darwin-arm64": "0.9.45-alpha.1",
|
|
435
|
+
"@bastani/atomic-natives-darwin-x64": "0.9.45-alpha.1",
|
|
436
|
+
"@bastani/atomic-natives-linux-arm64-gnu": "0.9.45-alpha.1",
|
|
437
|
+
"@bastani/atomic-natives-linux-arm64-musl": "0.9.45-alpha.1",
|
|
438
|
+
"@bastani/atomic-natives-linux-x64-gnu": "0.9.45-alpha.1",
|
|
439
|
+
"@bastani/atomic-natives-linux-x64-musl": "0.9.45-alpha.1",
|
|
440
|
+
"@bastani/atomic-natives-win32-arm64-msvc": "0.9.45-alpha.1",
|
|
441
|
+
"@bastani/atomic-natives-win32-x64-msvc": "0.9.45-alpha.1"
|
|
442
442
|
},
|
|
443
443
|
"engines": {
|
|
444
444
|
"bun": ">=1.4.2",
|
|
@@ -446,8 +446,8 @@
|
|
|
446
446
|
}
|
|
447
447
|
},
|
|
448
448
|
"node_modules/@bastani/atomic-natives-darwin-arm64": {
|
|
449
|
-
"version": "0.9.
|
|
450
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-arm64/-/atomic-natives-darwin-arm64-0.9.
|
|
449
|
+
"version": "0.9.45-alpha.1",
|
|
450
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-arm64/-/atomic-natives-darwin-arm64-0.9.45-alpha.1.tgz",
|
|
451
451
|
"license": "MIT",
|
|
452
452
|
"os": [
|
|
453
453
|
"darwin"
|
|
@@ -458,8 +458,8 @@
|
|
|
458
458
|
"optional": true
|
|
459
459
|
},
|
|
460
460
|
"node_modules/@bastani/atomic-natives-darwin-x64": {
|
|
461
|
-
"version": "0.9.
|
|
462
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-x64/-/atomic-natives-darwin-x64-0.9.
|
|
461
|
+
"version": "0.9.45-alpha.1",
|
|
462
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-darwin-x64/-/atomic-natives-darwin-x64-0.9.45-alpha.1.tgz",
|
|
463
463
|
"license": "MIT",
|
|
464
464
|
"os": [
|
|
465
465
|
"darwin"
|
|
@@ -470,8 +470,8 @@
|
|
|
470
470
|
"optional": true
|
|
471
471
|
},
|
|
472
472
|
"node_modules/@bastani/atomic-natives-linux-arm64-gnu": {
|
|
473
|
-
"version": "0.9.
|
|
474
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-gnu/-/atomic-natives-linux-arm64-gnu-0.9.
|
|
473
|
+
"version": "0.9.45-alpha.1",
|
|
474
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-gnu/-/atomic-natives-linux-arm64-gnu-0.9.45-alpha.1.tgz",
|
|
475
475
|
"license": "MIT",
|
|
476
476
|
"os": [
|
|
477
477
|
"linux"
|
|
@@ -485,8 +485,8 @@
|
|
|
485
485
|
"optional": true
|
|
486
486
|
},
|
|
487
487
|
"node_modules/@bastani/atomic-natives-linux-arm64-musl": {
|
|
488
|
-
"version": "0.9.
|
|
489
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-musl/-/atomic-natives-linux-arm64-musl-0.9.
|
|
488
|
+
"version": "0.9.45-alpha.1",
|
|
489
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-arm64-musl/-/atomic-natives-linux-arm64-musl-0.9.45-alpha.1.tgz",
|
|
490
490
|
"license": "MIT",
|
|
491
491
|
"os": [
|
|
492
492
|
"linux"
|
|
@@ -500,8 +500,8 @@
|
|
|
500
500
|
"optional": true
|
|
501
501
|
},
|
|
502
502
|
"node_modules/@bastani/atomic-natives-linux-x64-gnu": {
|
|
503
|
-
"version": "0.9.
|
|
504
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-gnu/-/atomic-natives-linux-x64-gnu-0.9.
|
|
503
|
+
"version": "0.9.45-alpha.1",
|
|
504
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-gnu/-/atomic-natives-linux-x64-gnu-0.9.45-alpha.1.tgz",
|
|
505
505
|
"license": "MIT",
|
|
506
506
|
"os": [
|
|
507
507
|
"linux"
|
|
@@ -515,8 +515,8 @@
|
|
|
515
515
|
"optional": true
|
|
516
516
|
},
|
|
517
517
|
"node_modules/@bastani/atomic-natives-linux-x64-musl": {
|
|
518
|
-
"version": "0.9.
|
|
519
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-musl/-/atomic-natives-linux-x64-musl-0.9.
|
|
518
|
+
"version": "0.9.45-alpha.1",
|
|
519
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-linux-x64-musl/-/atomic-natives-linux-x64-musl-0.9.45-alpha.1.tgz",
|
|
520
520
|
"license": "MIT",
|
|
521
521
|
"os": [
|
|
522
522
|
"linux"
|
|
@@ -530,8 +530,8 @@
|
|
|
530
530
|
"optional": true
|
|
531
531
|
},
|
|
532
532
|
"node_modules/@bastani/atomic-natives-win32-arm64-msvc": {
|
|
533
|
-
"version": "0.9.
|
|
534
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-arm64-msvc/-/atomic-natives-win32-arm64-msvc-0.9.
|
|
533
|
+
"version": "0.9.45-alpha.1",
|
|
534
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-arm64-msvc/-/atomic-natives-win32-arm64-msvc-0.9.45-alpha.1.tgz",
|
|
535
535
|
"license": "MIT",
|
|
536
536
|
"os": [
|
|
537
537
|
"win32"
|
|
@@ -542,8 +542,8 @@
|
|
|
542
542
|
"optional": true
|
|
543
543
|
},
|
|
544
544
|
"node_modules/@bastani/atomic-natives-win32-x64-msvc": {
|
|
545
|
-
"version": "0.9.
|
|
546
|
-
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-x64-msvc/-/atomic-natives-win32-x64-msvc-0.9.
|
|
545
|
+
"version": "0.9.45-alpha.1",
|
|
546
|
+
"resolved": "https://registry.npmjs.org/@bastani/atomic-natives-win32-x64-msvc/-/atomic-natives-win32-x64-msvc-0.9.45-alpha.1.tgz",
|
|
547
547
|
"license": "MIT",
|
|
548
548
|
"os": [
|
|
549
549
|
"win32"
|
|
@@ -554,8 +554,8 @@
|
|
|
554
554
|
"optional": true
|
|
555
555
|
},
|
|
556
556
|
"node_modules/@bastani/pi-ai": {
|
|
557
|
-
"version": "0.9.
|
|
558
|
-
"resolved": "https://registry.npmjs.org/@bastani/pi-ai/-/pi-ai-0.9.
|
|
557
|
+
"version": "0.9.45-alpha.1",
|
|
558
|
+
"resolved": "https://registry.npmjs.org/@bastani/pi-ai/-/pi-ai-0.9.45-alpha.1.tgz",
|
|
559
559
|
"license": "MIT",
|
|
560
560
|
"dependencies": {
|
|
561
561
|
"@anthropic-ai/sdk": "0.129.0",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/atomic",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.45-alpha.1",
|
|
4
4
|
"description": "Atomic coding agent CLI with read, bash, edit, write tools and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"atomicConfig": {
|
|
@@ -89,8 +89,8 @@
|
|
|
89
89
|
"prepublishOnly": "bun run clean && bun run build && bun run shrinkwrap"
|
|
90
90
|
},
|
|
91
91
|
"dependencies": {
|
|
92
|
-
"@bastani/atomic-natives": "0.9.
|
|
93
|
-
"@bastani/pi-ai": "0.9.
|
|
92
|
+
"@bastani/atomic-natives": "0.9.45-alpha.1",
|
|
93
|
+
"@bastani/pi-ai": "0.9.45-alpha.1",
|
|
94
94
|
"@earendil-works/pi-agent-core": "1.4.0",
|
|
95
95
|
"@earendil-works/pi-codemode": "1.4.0",
|
|
96
96
|
"@earendil-works/pi-tui": "1.4.0",
|
|
@@ -564,7 +564,7 @@
|
|
|
564
564
|
"type": "integer",
|
|
565
565
|
"minimum": 1,
|
|
566
566
|
"maximum": 2147483647,
|
|
567
|
-
"description": "Milliseconds each worker process may take to become ready. Default: 30000."
|
|
567
|
+
"description": "Milliseconds each worker process may take to become ready. Default: 30000, scaled up when workers plus load exceed CPU cores (at most 600000)."
|
|
568
568
|
},
|
|
569
569
|
"leaseMs": {
|
|
570
570
|
"type": "integer",
|