@noir-ai/daemon 1.0.0-beta.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/LICENSE +21 -0
- package/README.md +21 -0
- package/dist/index.d.ts +324 -0
- package/dist/index.js +759 -0
- package/dist/index.js.map +1 -0
- package/package.json +64 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 agaaaptr
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# @noir-ai/daemon
|
|
2
|
+
|
|
3
|
+
The runtime authority: owns the store write handle, resolves the embedder once, and exposes the single Noir MCP server (stdio + Streamable HTTP). Store-touching CLI commands are MCP clients to this daemon; a read-only filesystem fallback covers the daemon-down case.
|
|
4
|
+
|
|
5
|
+
Part of the **[Noir](https://github.com/agaaaptr/noir#readme)** toolkit — the discipline, context, and memory layer for any agentic CLI.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @noir-ai/daemon
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
> Most users install the CLI instead, which manages the daemon lifecycle (`noir daemon start|stop|status`):
|
|
14
|
+
>
|
|
15
|
+
> ```bash
|
|
16
|
+
> npm install -g @noir-ai/cli
|
|
17
|
+
> ```
|
|
18
|
+
|
|
19
|
+
## License
|
|
20
|
+
|
|
21
|
+
MIT © agaaaptr
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import { EmbedderConfig, ContextEngine, EmbedFn } from '@noir-ai/context';
|
|
2
|
+
export { ContextStatus } from '@noir-ai/context';
|
|
3
|
+
import { ProjectId, ProjectInfo } from '@noir-ai/core';
|
|
4
|
+
import { Store } from '@noir-ai/store';
|
|
5
|
+
import { MemoryConfig, MemoryEngine } from '@noir-ai/memory';
|
|
6
|
+
import { ResolvedModelConfig } from '@noir-ai/model';
|
|
7
|
+
import { McpServer } from '@modelcontextprotocol/server';
|
|
8
|
+
import { WorkflowEngine, Phase, WorkflowState, Mode, GateResult } from '@noir-ai/workflow';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Build the daemon's {@link ContextEngine} from its already-open store handle
|
|
12
|
+
* + the project `root` + `projectId` + a resolved {@link EmbedderConfig}.
|
|
13
|
+
*
|
|
14
|
+
* One engine per serve lifecycle — constructed once alongside the store (see
|
|
15
|
+
* {@link openStoreForDaemon}) and the workflow engine (see
|
|
16
|
+
* {@link buildWorkflowEngine}), and reused across every HTTP request, exactly
|
|
17
|
+
* as those handles are. The engine resolves its embedder once (a lazy local
|
|
18
|
+
* model loads at most once per lifecycle) and then owns the indexer (the only
|
|
19
|
+
* context writer) + the retriever (the only context reader) over the SAME
|
|
20
|
+
* injected handle — it never opens a second connection, so the daemon's
|
|
21
|
+
* single-writer discipline is preserved (blueprint D6: in-process, no sidecar,
|
|
22
|
+
* canonical `ProjectId`).
|
|
23
|
+
*
|
|
24
|
+
* Degraded story (mirrors the store + the engine's own contract): pass the
|
|
25
|
+
* store's `storeDegraded` flag so the engine's persistent `degraded` field is
|
|
26
|
+
* honest — `context_status` then reports `degraded:true` for a read-only
|
|
27
|
+
* (daemon-down) handle, and `context_index` short-circuits with a clear error
|
|
28
|
+
* envelope instead of letting the first write throw mid-run. A `kind:'none'`
|
|
29
|
+
* embedder on a WRITABLE store is NOT blocking here: docs still index without
|
|
30
|
+
* vectors (the indexer's tested degraded path), so only the read-only case is
|
|
31
|
+
* fenced off at the tool boundary.
|
|
32
|
+
*/
|
|
33
|
+
declare function buildContextEngine(store: Store, root: string, projectId: ProjectId, embedderCfg: EmbedderConfig, storeDegraded?: boolean): ContextEngine;
|
|
34
|
+
|
|
35
|
+
interface EnsureResult {
|
|
36
|
+
port: number;
|
|
37
|
+
url: string;
|
|
38
|
+
started: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Stops the daemon THIS call started. When `started` is true this closes the
|
|
41
|
+
* in-process http server, clears `daemon.json`, and clears the idle timer.
|
|
42
|
+
* When `started` is false (a healthy daemon was reused) this is a no-op: the
|
|
43
|
+
* reused daemon is owned by whichever process started it (in tests that pid is
|
|
44
|
+
* `process.pid`, so killing it would be fatal) and must not be torn down by a
|
|
45
|
+
* mere consumer.
|
|
46
|
+
*/
|
|
47
|
+
stop: () => Promise<void>;
|
|
48
|
+
}
|
|
49
|
+
declare function ensureDaemonRunning(opts: {
|
|
50
|
+
project: ProjectInfo;
|
|
51
|
+
idleTimeoutSec: number;
|
|
52
|
+
}): Promise<EnsureResult>;
|
|
53
|
+
|
|
54
|
+
interface StartHttpOptions {
|
|
55
|
+
project: ProjectInfo;
|
|
56
|
+
port?: number;
|
|
57
|
+
idleTimeoutSec: number;
|
|
58
|
+
}
|
|
59
|
+
interface RunningDaemon {
|
|
60
|
+
port: number;
|
|
61
|
+
pid: number;
|
|
62
|
+
startedAt: number;
|
|
63
|
+
stop: () => Promise<void>;
|
|
64
|
+
}
|
|
65
|
+
declare function startHttpServer(opts: StartHttpOptions): Promise<RunningDaemon>;
|
|
66
|
+
|
|
67
|
+
interface DaemonRecord {
|
|
68
|
+
pid: number;
|
|
69
|
+
port: number;
|
|
70
|
+
startedAt: number;
|
|
71
|
+
}
|
|
72
|
+
declare function noirHome(): string;
|
|
73
|
+
declare function daemonJsonPath(): string;
|
|
74
|
+
declare function readDaemonRecord(): DaemonRecord | null;
|
|
75
|
+
declare function writeDaemonRecord(rec: DaemonRecord): void;
|
|
76
|
+
declare function clearDaemonRecord(): void;
|
|
77
|
+
declare function pidAlive(pid: number): boolean;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Derive the consolidation provider + model id from a resolved MODEL config —
|
|
81
|
+
* the MODEL-DERIVED FALLBACK used ONLY when the user enabled consolidation
|
|
82
|
+
* under `memory:` but did NOT name a provider there (see
|
|
83
|
+
* {@link resolveConsolidationCapability}). Blueprint D5/D6 — provider-EXPLICIT,
|
|
84
|
+
* never env-inferred.
|
|
85
|
+
*
|
|
86
|
+
* The provider is resolved ONLY from an explicit opt-in: the `consolidate` tier
|
|
87
|
+
* key, falling back to `defaultProvider`. Env-var presence is NEVER consulted
|
|
88
|
+
* (DS-6) — `ANTHROPIC_API_KEY` being set for another tool does NOT activate
|
|
89
|
+
* consolidation here. A provider is "consolidation-capable" only when that key
|
|
90
|
+
* resolves to a configured provider block that itself declares a `model` id;
|
|
91
|
+
* otherwise this returns `null`.
|
|
92
|
+
*
|
|
93
|
+
* NOTE: this function ALONE is NOT the consolidation gate — it ignores the
|
|
94
|
+
* user's `memory.consolidation.enabled` master switch. The AND of that switch
|
|
95
|
+
* with this derivation (and with the memory-block provider) lives in
|
|
96
|
+
* {@link resolveConsolidationCapability}, which is what the daemon wiring +
|
|
97
|
+
* {@link buildMemoryEngine} actually consult to decide tool registration.
|
|
98
|
+
*/
|
|
99
|
+
declare function resolveMemoryConsolidation(modelCfg: ResolvedModelConfig | undefined): {
|
|
100
|
+
provider: string;
|
|
101
|
+
model: string;
|
|
102
|
+
} | null;
|
|
103
|
+
/**
|
|
104
|
+
* The consolidation capability gate — the SINGLE source of truth both
|
|
105
|
+
* {@link buildMemoryEngine} and the daemon wiring (stdio/http) consult to decide
|
|
106
|
+
* (a) whether the `memory_consolidate` MCP tool registers and (b) whether the
|
|
107
|
+
* engine's `consolidate` can run. Returns the usable `{provider, model}` when
|
|
108
|
+
* consolidation is ON, or `null` when it must be fully off.
|
|
109
|
+
*
|
|
110
|
+
* The gate is the AND of ALL three (blueprint D6 / §9 — NEVER a silent paid
|
|
111
|
+
* call, the Agent-Memory anti-pattern):
|
|
112
|
+
* (a) `resolvedMemory.consolidation.enabled === true` — the user's EXPLICIT
|
|
113
|
+
* master switch under `memory:`. This is the LOAD-BEARING gate: a config
|
|
114
|
+
* with no `memory:` block (or `enabled:false`) resolves to `null`
|
|
115
|
+
* REGARDLESS of `model.defaultProvider`, so a `model:` block set for
|
|
116
|
+
* summarize/title/draft does NOT silently enable a paid consolidation call.
|
|
117
|
+
* (b) a usable provider+model — prefer the one named under `memory:` (with its
|
|
118
|
+
* own `model` id); fall back to the MODEL-derived derivation
|
|
119
|
+
* ({@link resolveMemoryConsolidation}) ONLY when the user enabled
|
|
120
|
+
* consolidation but did NOT name a provider under `memory:`.
|
|
121
|
+
* (c) the resolved pair has both a `provider` and a `model` id.
|
|
122
|
+
*
|
|
123
|
+
* `resolvedMemory` is the output of `resolveMemoryConfig(config.memory)` — the
|
|
124
|
+
* pure core→memory bridge (no env inference, no cycle). Pure projection — reads
|
|
125
|
+
* NO env, holds NO secrets, never throws. Whether the provider is actually
|
|
126
|
+
* CALLABLE at runtime (key present, network up) is decided inside `complete()`
|
|
127
|
+
* (S8) — here we only decide config-time capability.
|
|
128
|
+
*/
|
|
129
|
+
declare function resolveConsolidationCapability(resolvedMemory: MemoryConfig | undefined, modelCfg: ResolvedModelConfig | undefined): {
|
|
130
|
+
provider: string;
|
|
131
|
+
model: string;
|
|
132
|
+
} | null;
|
|
133
|
+
/**
|
|
134
|
+
* Build the daemon's {@link MemoryEngine} from its already-open store handle +
|
|
135
|
+
* the project `root` + `projectId` + the SAME `EmbedFn` the daemon resolved once
|
|
136
|
+
* for S6 (the daemon owns one embedder; memory takes `{store, embed, ...}`, no
|
|
137
|
+
* embedder duplication — plan §Architecture).
|
|
138
|
+
*
|
|
139
|
+
* One engine per serve lifecycle — constructed once alongside the store (see
|
|
140
|
+
* {@link openStoreForDaemon}), the workflow engine (see
|
|
141
|
+
* {@link buildWorkflowEngine}), and the context engine (see
|
|
142
|
+
* {@link buildContextEngine}), and reused across every HTTP request, exactly as
|
|
143
|
+
* those handles are. The engine — like the context indexer — is the ONLY thing
|
|
144
|
+
* that writes `source:'memory'` rows through the injected handle; it never opens
|
|
145
|
+
* a second connection, so the daemon's single-writer discipline is preserved
|
|
146
|
+
* (blueprint D6: in-process, no sidecar, canonical `ProjectId`).
|
|
147
|
+
*
|
|
148
|
+
* Consolidation is OPT-IN + provider-explicit (DS-6 / §9 — NEVER a silent paid
|
|
149
|
+
* call). The capability gate is {@link resolveConsolidationCapability} — the AND
|
|
150
|
+
* of the user's `memory.consolidation.enabled` master switch (the load-bearing
|
|
151
|
+
* gate), a usable provider+model (preferring the `memory:` block, falling back
|
|
152
|
+
* to the model-derived derivation when enabled but no provider named under
|
|
153
|
+
* `memory:`), and `modelCfg` being present to bind S8's `complete`. When the
|
|
154
|
+
* gate resolves a `{provider, model}`:
|
|
155
|
+
* - S8's {@link complete} is bound as the engine's model injection, AND
|
|
156
|
+
* - the runtime gate `config.consolidation` is set so `consolidate` can run.
|
|
157
|
+
* When the gate is `null` — most importantly when `enabled === false`, regardless
|
|
158
|
+
* of `model.defaultProvider` — NO model is wired and `engine.consolidate`
|
|
159
|
+
* self-refuses (`'no-provider'`) WITHOUT calling the model. The daemon registers
|
|
160
|
+
* the `memory_consolidate` MCP tool only in the capable case.
|
|
161
|
+
*
|
|
162
|
+
* `resolvedMemory` is the output of `resolveMemoryConfig(config.memory)` — the
|
|
163
|
+
* pure core→memory bridge. Passing it here means the engine's `config` reflects
|
|
164
|
+
* the user's `memory:` consent exactly (never a hardcoded `enabled:true`).
|
|
165
|
+
*
|
|
166
|
+
* Degraded story (mirrors the store + the context engine): pass the store's
|
|
167
|
+
* `storeDegraded` flag so the engine's persistent `degraded` field is honest —
|
|
168
|
+
* `memory_save` / `memory_forget` then refuse with a clear envelope (the engine
|
|
169
|
+
* throws upfront on a read-only handle) while reads (`memory_recall` /
|
|
170
|
+
* `memory_search` / `memory_sessions`) keep working off the same handle.
|
|
171
|
+
*/
|
|
172
|
+
declare function buildMemoryEngine(store: Store, root: string, projectId: ProjectId, embed: EmbedFn, modelCfg?: ResolvedModelConfig, storeDegraded?: boolean, resolvedMemory?: MemoryConfig): MemoryEngine;
|
|
173
|
+
|
|
174
|
+
type Transport = 'stdio' | 'streamable-http';
|
|
175
|
+
interface HostStatus {
|
|
176
|
+
noir: string;
|
|
177
|
+
project: {
|
|
178
|
+
id: string;
|
|
179
|
+
name: string;
|
|
180
|
+
};
|
|
181
|
+
host: string;
|
|
182
|
+
transport: Transport;
|
|
183
|
+
daemon: boolean;
|
|
184
|
+
pid?: number;
|
|
185
|
+
uptimeSec?: number;
|
|
186
|
+
}
|
|
187
|
+
interface StatusContext {
|
|
188
|
+
transport: Transport;
|
|
189
|
+
daemon: boolean;
|
|
190
|
+
pid?: number;
|
|
191
|
+
startedAt?: number;
|
|
192
|
+
}
|
|
193
|
+
declare function buildStatus(project: ProjectInfo, ctx: StatusContext): HostStatus;
|
|
194
|
+
|
|
195
|
+
interface ServerContext {
|
|
196
|
+
project: ProjectInfo;
|
|
197
|
+
transport: Transport;
|
|
198
|
+
daemon: boolean;
|
|
199
|
+
pid?: number;
|
|
200
|
+
startedAt?: number;
|
|
201
|
+
/**
|
|
202
|
+
* Optional store handle. When present, the `store_status` tool is
|
|
203
|
+
* registered. The daemon is the single writer; stdio/HTTP serve paths open
|
|
204
|
+
* the store once per serve lifecycle and reuse the same handle.
|
|
205
|
+
*/
|
|
206
|
+
store?: Store;
|
|
207
|
+
/** Filesystem path to the store DB (reported by `store_status`). */
|
|
208
|
+
dbPath?: string;
|
|
209
|
+
/** True when the store was opened read-only (writable open failed). */
|
|
210
|
+
storeDegraded?: boolean;
|
|
211
|
+
/**
|
|
212
|
+
* Optional workflow engine. When present, the `workflow_status` and
|
|
213
|
+
* `checkpoint` tools are registered. Built once per serve lifecycle from the
|
|
214
|
+
* same store handle (see {@link buildWorkflowEngine}) and reused across HTTP
|
|
215
|
+
* requests, mirroring the store.
|
|
216
|
+
*/
|
|
217
|
+
engine?: WorkflowEngine;
|
|
218
|
+
/**
|
|
219
|
+
* Optional context engine. When present, the `context_search`,
|
|
220
|
+
* `context_index`, and `context_status` tools are registered. Built once per
|
|
221
|
+
* serve lifecycle from the same store handle (see `buildContextEngine` in
|
|
222
|
+
* `./context-seam.js`) and reused across HTTP requests, mirroring the store
|
|
223
|
+
* + engine. The engine — through its indexer — is the only thing that writes
|
|
224
|
+
* context rows, so the daemon's single-writer discipline is preserved.
|
|
225
|
+
*/
|
|
226
|
+
context?: ContextEngine;
|
|
227
|
+
/**
|
|
228
|
+
* Optional memory engine. When present, the `memory_save`, `memory_recall`,
|
|
229
|
+
* `memory_search`, `memory_sessions`, and `memory_forget` tools are
|
|
230
|
+
* registered. Built once per serve lifecycle from the same store handle + the
|
|
231
|
+
* SAME `EmbedFn` already resolved for S6 (see `buildMemoryEngine` in
|
|
232
|
+
* `./memory-seam.js`) and reused across HTTP requests, mirroring the store +
|
|
233
|
+
* engine + context. The engine is the only thing that writes `source:memory`
|
|
234
|
+
* rows through the injected handle, so the daemon's single-writer discipline
|
|
235
|
+
* is preserved (blueprint D6: in-process, no sidecar, canonical `ProjectId`).
|
|
236
|
+
*/
|
|
237
|
+
memory?: MemoryEngine;
|
|
238
|
+
/**
|
|
239
|
+
* Whether the {@link memory} engine is consolidation-capable — i.e. the user
|
|
240
|
+
* opted in (`memory.consolidation.enabled === true`) AND a usable provider+model
|
|
241
|
+
* resolved (see `resolveConsolidationCapability` in `./memory-seam.js`, the AND
|
|
242
|
+
* of the master switch + the provider derivation). Only when this is true is the
|
|
243
|
+
* `memory_consolidate` tool registered: consolidation is OPT-IN +
|
|
244
|
+
* provider-explicit (blueprint D5/D6/DS-6 / §9), NEVER a silent paid call — a
|
|
245
|
+
* `model:` block set for summarize/title/draft does NOT flip this when the user
|
|
246
|
+
* left `memory.consolidation.enabled` false. The engine's `consolidate`
|
|
247
|
+
* self-refuses (`no-provider`/`model-unavailable`) when this flag is false, so
|
|
248
|
+
* the flag + the engine agree by construction.
|
|
249
|
+
*/
|
|
250
|
+
memoryConsolidation?: boolean;
|
|
251
|
+
}
|
|
252
|
+
/** JSON returned by the `store_status` tool. */
|
|
253
|
+
interface StoreStatus {
|
|
254
|
+
ok: boolean;
|
|
255
|
+
projectId: string;
|
|
256
|
+
docCount: number;
|
|
257
|
+
vecCount: number;
|
|
258
|
+
dbPath: string | null;
|
|
259
|
+
degraded: boolean;
|
|
260
|
+
}
|
|
261
|
+
/** JSON returned by the `workflow_status` / `checkpoint` tools. */
|
|
262
|
+
interface WorkflowStatus {
|
|
263
|
+
ok: boolean;
|
|
264
|
+
taskId: string;
|
|
265
|
+
phase: Phase;
|
|
266
|
+
state: WorkflowState;
|
|
267
|
+
/** Next gate-phase ahead of the current phase (null past verify, or blocked). */
|
|
268
|
+
nextGate: Phase | null;
|
|
269
|
+
mode: Mode;
|
|
270
|
+
/** In-process view of the observable gate audit (Noir §9.1). */
|
|
271
|
+
history: GateResult[];
|
|
272
|
+
updatedAt: number;
|
|
273
|
+
/** Mirrors `store_status`: true when the store is a read-only fallback. */
|
|
274
|
+
degraded: boolean;
|
|
275
|
+
}
|
|
276
|
+
declare function createNoirServer(ctx: ServerContext): McpServer;
|
|
277
|
+
|
|
278
|
+
declare function startStdioServer(ctx: ServerContext): Promise<void>;
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* A store handle opened by the daemon for its own lifecycle.
|
|
282
|
+
*
|
|
283
|
+
* - `store` — the single writer/reader handle (the daemon is the only writer).
|
|
284
|
+
* - `dbPath` — absolute path to `<root>/.noir/store/<projectId>.db`; reported by
|
|
285
|
+
* `store_status`.
|
|
286
|
+
* - `degraded` — `true` when the writable open failed and we fell back to a
|
|
287
|
+
* read-only handle. In degraded mode writes throw
|
|
288
|
+
* `"store is read-only (daemon down)"`, but reads (FTS, kNN, counts) keep
|
|
289
|
+
* working, so the MCP surface still reports accurate state.
|
|
290
|
+
*/
|
|
291
|
+
interface DaemonStore {
|
|
292
|
+
store: Store;
|
|
293
|
+
dbPath: string;
|
|
294
|
+
degraded: boolean;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Open the project's store for the daemon — the single writer.
|
|
298
|
+
*
|
|
299
|
+
* Tries a read-write open first (creating the DB + migrating schema if
|
|
300
|
+
* needed). On any failure (DB locked by another writer, permissions, transient
|
|
301
|
+
* FS error) it falls back to a read-only open so the daemon still has an
|
|
302
|
+
* accurate read handle — the FS-fallback / degraded story. The caller threads
|
|
303
|
+
* `degraded` into `ServerContext` so `store_status` can surface it.
|
|
304
|
+
*/
|
|
305
|
+
declare function openStoreForDaemon(projectId: ProjectId, root: string): Promise<DaemonStore>;
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Build the daemon's {@link WorkflowEngine} from its already-open store handle
|
|
309
|
+
* + the project `root` + `projectId`.
|
|
310
|
+
*
|
|
311
|
+
* One engine per serve lifecycle — constructed once alongside the store (see
|
|
312
|
+
* {@link openStoreForDaemon}) and reused across every HTTP request, exactly as
|
|
313
|
+
* the store handle is. The engine is a thin orchestrator over the store KV, so
|
|
314
|
+
* it inherits the daemon's single-writer discipline for free.
|
|
315
|
+
*
|
|
316
|
+
* Degraded story: the engine itself is mode-agnostic; when the underlying store
|
|
317
|
+
* was opened read-only (`storeDegraded === true`), `workflow_status` still works
|
|
318
|
+
* (a pure KV read via {@link Store.getState}) while `checkpoint { action:'save' }`
|
|
319
|
+
* throws `"store is read-only (daemon down)"` — the tool handler catches that and
|
|
320
|
+
* surfaces a clear JSON error instead of crashing the daemon.
|
|
321
|
+
*/
|
|
322
|
+
declare function buildWorkflowEngine(store: Store, root: string, projectId: ProjectId): WorkflowEngine;
|
|
323
|
+
|
|
324
|
+
export { type DaemonRecord, type DaemonStore, type EnsureResult, type HostStatus, type RunningDaemon, type ServerContext, type StartHttpOptions, type StatusContext, type StoreStatus, type Transport, type WorkflowStatus, buildContextEngine, buildMemoryEngine, buildStatus, buildWorkflowEngine, clearDaemonRecord, createNoirServer, daemonJsonPath, ensureDaemonRunning, noirHome, openStoreForDaemon, pidAlive, readDaemonRecord, resolveConsolidationCapability, resolveMemoryConsolidation, startHttpServer, startStdioServer, writeDaemonRecord };
|