@fungi.computer/shiitake 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +454 -2
- package/dist/agar-extension.d.ts +9 -0
- package/dist/agar-extension.js +38 -0
- package/dist/agent-control.d.ts +77 -0
- package/dist/agent-control.js +434 -0
- package/dist/client-entry.d.ts +211 -0
- package/dist/client-entry.js +101 -0
- package/dist/client-wire.d.ts +199 -0
- package/dist/client-wire.js +271 -0
- package/dist/client.d.ts +439 -0
- package/dist/client.js +4 -0
- package/dist/cloudflare.d.ts +220 -0
- package/dist/cloudflare.js +531 -0
- package/dist/effect.d.ts +42 -0
- package/dist/effect.js +20 -0
- package/dist/errors.d.ts +50 -0
- package/dist/errors.js +81 -0
- package/dist/extension-client.d.ts +38 -0
- package/dist/extension-client.js +56 -0
- package/dist/extension-contract.d.ts +73 -0
- package/dist/extension-contract.js +11 -0
- package/dist/extensions.d.ts +589 -0
- package/dist/extensions.js +263 -0
- package/dist/fleet.d.ts +313 -0
- package/dist/fleet.js +540 -0
- package/dist/hosted.d.ts +133 -0
- package/dist/hosted.js +265 -0
- package/dist/http-routes.d.ts +772 -0
- package/dist/http-routes.js +242 -0
- package/dist/http.d.ts +1 -0
- package/dist/http.js +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.js +13 -0
- package/dist/internal/accepted-run-executor.d.ts +23 -0
- package/dist/internal/accepted-run-executor.js +129 -0
- package/dist/internal/admission-door.d.ts +75 -0
- package/dist/internal/admission-door.js +105 -0
- package/dist/internal/agent-close.d.ts +4 -0
- package/dist/internal/agent-close.js +42 -0
- package/dist/internal/browser-sessions.d.ts +31 -0
- package/dist/internal/browser-sessions.js +173 -0
- package/dist/internal/client-boundary.d.ts +262 -0
- package/dist/internal/client-boundary.js +202 -0
- package/dist/internal/compaction/compaction.d.ts +54 -0
- package/dist/internal/compaction/compaction.js +291 -0
- package/dist/internal/compaction/session-compaction.d.ts +69 -0
- package/dist/internal/compaction/session-compaction.js +330 -0
- package/dist/internal/compaction/settings.d.ts +11 -0
- package/dist/internal/compaction/settings.js +40 -0
- package/dist/internal/compaction/utils.d.ts +45 -0
- package/dist/internal/compaction/utils.js +319 -0
- package/dist/internal/contracts.d.ts +235 -0
- package/dist/internal/contracts.js +1 -0
- package/dist/internal/coordinator.d.ts +18 -0
- package/dist/internal/coordinator.js +362 -0
- package/dist/internal/document-codec.d.ts +11 -0
- package/dist/internal/document-codec.js +39 -0
- package/dist/internal/effect-client.d.ts +13 -0
- package/dist/internal/effect-client.js +102 -0
- package/dist/internal/effect-contracts.d.ts +236 -0
- package/dist/internal/effect-contracts.js +2 -0
- package/dist/internal/extension-command-registry.d.ts +11 -0
- package/dist/internal/extension-command-registry.js +29 -0
- package/dist/internal/extension-command-tools.d.ts +17 -0
- package/dist/internal/extension-command-tools.js +50 -0
- package/dist/internal/extension-context.d.ts +25 -0
- package/dist/internal/extension-context.js +35 -0
- package/dist/internal/extension-definitions.d.ts +5 -0
- package/dist/internal/extension-definitions.js +6 -0
- package/dist/internal/extension-hook.d.ts +25 -0
- package/dist/internal/extension-hook.js +46 -0
- package/dist/internal/extension-roster.d.ts +23 -0
- package/dist/internal/extension-roster.js +228 -0
- package/dist/internal/extension-runtime.d.ts +63 -0
- package/dist/internal/extension-runtime.js +1004 -0
- package/dist/internal/failure.d.ts +2 -0
- package/dist/internal/failure.js +9 -0
- package/dist/internal/host-meta.d.ts +41 -0
- package/dist/internal/host-meta.js +39 -0
- package/dist/internal/json-value.d.ts +4 -0
- package/dist/internal/json-value.js +3 -0
- package/dist/internal/model-acquisition.d.ts +21 -0
- package/dist/internal/model-acquisition.js +98 -0
- package/dist/internal/model-preference.d.ts +21 -0
- package/dist/internal/model-preference.js +20 -0
- package/dist/internal/observation-kernel.d.ts +28 -0
- package/dist/internal/observation-kernel.js +169 -0
- package/dist/internal/promise-facade.d.ts +18 -0
- package/dist/internal/promise-facade.js +172 -0
- package/dist/internal/run-scope.d.ts +27 -0
- package/dist/internal/run-scope.js +214 -0
- package/dist/internal/runtime-coordinator.d.ts +34 -0
- package/dist/internal/runtime-coordinator.js +233 -0
- package/dist/internal/runtime-core.d.ts +19 -0
- package/dist/internal/runtime-core.js +39 -0
- package/dist/internal/runtime-reconciliation.d.ts +18 -0
- package/dist/internal/runtime-reconciliation.js +162 -0
- package/dist/internal/session-context.d.ts +11 -0
- package/dist/internal/session-context.js +67 -0
- package/dist/internal/session-status.d.ts +10 -0
- package/dist/internal/session-status.js +52 -0
- package/dist/internal/woodstock/agent-reply.d.ts +25 -0
- package/dist/internal/woodstock/agent-reply.js +67 -0
- package/dist/internal/woodstock/client-projection.d.ts +29 -0
- package/dist/internal/woodstock/client-projection.js +512 -0
- package/dist/internal/woodstock/compaction-activity.d.ts +17 -0
- package/dist/internal/woodstock/compaction-activity.js +32 -0
- package/dist/internal/woodstock/cursor.d.ts +9 -0
- package/dist/internal/woodstock/cursor.js +44 -0
- package/dist/internal/woodstock/extension-store.d.ts +72 -0
- package/dist/internal/woodstock/extension-store.js +262 -0
- package/dist/internal/woodstock/fleet-store.d.ts +36 -0
- package/dist/internal/woodstock/fleet-store.js +100 -0
- package/dist/internal/woodstock/identities.d.ts +6 -0
- package/dist/internal/woodstock/identities.js +11 -0
- package/dist/internal/woodstock/index.d.ts +170 -0
- package/dist/internal/woodstock/index.js +546 -0
- package/dist/internal/woodstock/progress.d.ts +32 -0
- package/dist/internal/woodstock/progress.js +89 -0
- package/dist/internal/woodstock/run-recovery.d.ts +8 -0
- package/dist/internal/woodstock/run-recovery.js +95 -0
- package/dist/internal/woodstock/session-attention.d.ts +16 -0
- package/dist/internal/woodstock/session-attention.js +88 -0
- package/dist/internal/woodstock/session-documents.d.ts +18 -0
- package/dist/internal/woodstock/session-documents.js +51 -0
- package/dist/internal/woodstock/session-entry.d.ts +478 -0
- package/dist/internal/woodstock/session-entry.js +484 -0
- package/dist/internal/woodstock/session-grants.d.ts +24 -0
- package/dist/internal/woodstock/session-grants.js +84 -0
- package/dist/internal/woodstock/session-inbox.d.ts +56 -0
- package/dist/internal/woodstock/session-inbox.js +307 -0
- package/dist/internal/woodstock/session-store.d.ts +432 -0
- package/dist/internal/woodstock/session-store.js +2006 -0
- package/dist/internal/woodstock/storage-admission.d.ts +14 -0
- package/dist/internal/woodstock/storage-admission.js +44 -0
- package/dist/model-preference.d.ts +20 -0
- package/dist/model-preference.js +30 -0
- package/dist/node.d.ts +64 -0
- package/dist/node.js +256 -0
- package/dist/remote-client.d.ts +11 -0
- package/dist/remote-client.js +298 -0
- package/dist/session-attention.d.ts +35 -0
- package/dist/session-attention.js +22 -0
- package/dist/session-documents.d.ts +28 -0
- package/dist/session-documents.js +1 -0
- package/dist/testing.d.ts +54 -0
- package/dist/testing.js +215 -0
- package/docs/api/README.md +26 -0
- package/docs/api/agar-extension.md +40 -0
- package/docs/api/agent-control.md +151 -0
- package/docs/api/client-entry.md +344 -0
- package/docs/api/client.md +1112 -0
- package/docs/api/cloudflare.md +500 -0
- package/docs/api/effect.md +884 -0
- package/docs/api/extensions.md +2003 -0
- package/docs/api/fleet.md +734 -0
- package/docs/api/hosted.md +382 -0
- package/docs/api/http.md +111 -0
- package/docs/api/index.md +1116 -0
- package/docs/api/model-preference.md +151 -0
- package/docs/api/node.md +142 -0
- package/docs/api/testing.md +250 -0
- package/package.json +130 -3
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
export { AttentionItemSchema, } from "./session-attention.js";
|
|
2
|
+
import * as Brand from "effect/Brand";
|
|
3
|
+
import * as Context from "effect/Context";
|
|
4
|
+
import * as Data from "effect/Data";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as Option from "effect/Option";
|
|
7
|
+
import * as Result from "effect/Result";
|
|
8
|
+
import * as Schema from "effect/Schema";
|
|
9
|
+
import { ExtensionId, extensionFingerprintSchema, extensionRevisionSchema, } from "./extension-contract.js";
|
|
10
|
+
export { ExtensionId, extensionIdentifier, extensionVersion, } from "./extension-contract.js";
|
|
11
|
+
import { extensionVersion } from "./extension-contract.js";
|
|
12
|
+
import { registerExtensionCommands, } from "./internal/extension-command-registry.js";
|
|
13
|
+
import { commandTools, } from "./internal/extension-command-tools.js";
|
|
14
|
+
import { bindExtensionState, bindExtensionDocuments, } from "./internal/extension-context.js";
|
|
15
|
+
import { definitionReader } from "./internal/extension-definitions.js";
|
|
16
|
+
import { ExtensionHookError, invokeExtensionHook, invokeSyncHandler, invokeTransactionHook, } from "./internal/extension-hook.js";
|
|
17
|
+
export { ExtensionHookError } from "./internal/extension-hook.js";
|
|
18
|
+
import { JsonValueSchema } from "./internal/json-value.js";
|
|
19
|
+
const parseJsonSource = Schema.decodeUnknownSync(Schema.fromJsonString(JsonValueSchema));
|
|
20
|
+
/** Parse a serialized extension value into the finite JSON contract. */
|
|
21
|
+
export function parseExtensionJson(source) {
|
|
22
|
+
return parseJsonSource(source);
|
|
23
|
+
}
|
|
24
|
+
/** Present only inside a core-run read (projection, run tools, hooks). */
|
|
25
|
+
export class ExtensionRead extends Context.Service()("@fungi.computer/shiitake/ExtensionRead") {
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Present only inside a core-run write transaction (hooks, commands,
|
|
29
|
+
* `transact`). Core runs these Effects synchronously inside the owner
|
|
30
|
+
* transaction; an asynchronous boundary is a defect that stops the extension.
|
|
31
|
+
*/
|
|
32
|
+
export class ExtensionTx extends Context.Service()("@fungi.computer/shiitake/ExtensionTx") {
|
|
33
|
+
}
|
|
34
|
+
/** Durable record failure: stored or supplied values broke their schema or bounds. */
|
|
35
|
+
export class ExtensionStateError extends Data.TaggedError("ExtensionStateError") {
|
|
36
|
+
}
|
|
37
|
+
/** The door refused an extension admission. */
|
|
38
|
+
export class AdmissionError extends Data.TaggedError("AdmissionError") {
|
|
39
|
+
}
|
|
40
|
+
/** Typed rejection of one extension command, returned to its caller. */
|
|
41
|
+
export class ExtensionCommandError extends Data.TaggedError("ExtensionCommandError") {
|
|
42
|
+
}
|
|
43
|
+
/** Fail a hook with this (or die) to stop this extension with a visible reason. */
|
|
44
|
+
export class ExtensionStop extends Data.TaggedError("ExtensionStop") {
|
|
45
|
+
}
|
|
46
|
+
/** Typed activation failure; the extension is stopped with this message. */
|
|
47
|
+
export class ExtensionActivationError extends Data.TaggedError("ExtensionActivationError") {
|
|
48
|
+
}
|
|
49
|
+
/** Marks a `defineCollection` result, across copies of this package. */
|
|
50
|
+
const collectionBrand = Symbol.for("@fungi.computer/shiitake/collection");
|
|
51
|
+
const stateDeclarationKeys = new Set([
|
|
52
|
+
"version",
|
|
53
|
+
"collections",
|
|
54
|
+
"migrations",
|
|
55
|
+
]);
|
|
56
|
+
/** The full form names `collections` and nothing outside the declaration keys. */
|
|
57
|
+
function isStateDeclaration(value) {
|
|
58
|
+
const keys = Object.keys(value);
|
|
59
|
+
return (keys.includes("collections") &&
|
|
60
|
+
keys.every((key) => stateDeclarationKeys.has(key)));
|
|
61
|
+
}
|
|
62
|
+
/** Configure typed metadata, then register callbacks against its actual values. */
|
|
63
|
+
export class ExtensionBuilderV0 {
|
|
64
|
+
metadata;
|
|
65
|
+
constructor(metadata) {
|
|
66
|
+
this.metadata = metadata;
|
|
67
|
+
}
|
|
68
|
+
/** Begin with concrete empty metadata and no requested capability. */
|
|
69
|
+
static fromIdentity(identity) {
|
|
70
|
+
return new ExtensionBuilderV0({
|
|
71
|
+
...identity,
|
|
72
|
+
config: {},
|
|
73
|
+
state: { version: 1, collections: {}, migrations: {} },
|
|
74
|
+
documents: {},
|
|
75
|
+
declaresState: false,
|
|
76
|
+
declaresDocuments: false,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
/** Hash this explicit JSON configuration with the extension revision. */
|
|
80
|
+
config(value) {
|
|
81
|
+
return new ExtensionBuilderV0({ ...this.metadata, config: value });
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Request state and bind handles to each collection's declared schema.
|
|
85
|
+
* Pass the collections alone (state version 1, no migrations) or the full
|
|
86
|
+
* versioned declaration.
|
|
87
|
+
*/
|
|
88
|
+
state(value) {
|
|
89
|
+
const declared = isStateDeclaration(value) ? value : { collections: value };
|
|
90
|
+
if (isStateDeclaration(value)
|
|
91
|
+
? !Object.values(value.collections).every((spec) => collectionBrand in spec)
|
|
92
|
+
: Object.keys(value).some((name) => stateDeclarationKeys.has(name)))
|
|
93
|
+
throw new Error("A collection named collections, version or migrations needs the full state declaration");
|
|
94
|
+
return new ExtensionBuilderV0({
|
|
95
|
+
...this.metadata,
|
|
96
|
+
state: {
|
|
97
|
+
version: declared.version ?? 1,
|
|
98
|
+
collections: declared.collections,
|
|
99
|
+
migrations: declared.migrations ?? {},
|
|
100
|
+
},
|
|
101
|
+
declaresState: true,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
/** Request bounded Session documents under the state grant. */
|
|
105
|
+
documents(value) {
|
|
106
|
+
return new ExtensionBuilderV0({
|
|
107
|
+
...this.metadata,
|
|
108
|
+
documents: value,
|
|
109
|
+
declaresDocuments: true,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
define(definition) {
|
|
113
|
+
return compileExtension(this.metadata, definition);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const decodeExtensionId = Schema.decodeUnknownSync(ExtensionId);
|
|
117
|
+
const decodeExtensionVersion = Schema.decodeUnknownSync(extensionVersion);
|
|
118
|
+
const isBareExtensionId = Schema.is(Schema.String);
|
|
119
|
+
/**
|
|
120
|
+
* Begin with honest empty defaults; optional contributions are declared
|
|
121
|
+
* explicitly. The version defaults to `0.0.0` and any SemVer, including a
|
|
122
|
+
* pre-release, is valid. It is part of the extension's revision, which already
|
|
123
|
+
* covers schemas, config and requested capabilities; a different version marks
|
|
124
|
+
* a behaviour change those do not show, such as a fixed hook.
|
|
125
|
+
*/
|
|
126
|
+
export function defineExtension(identity) {
|
|
127
|
+
const declared = isBareExtensionId(identity) ? { id: identity } : identity;
|
|
128
|
+
return ExtensionBuilderV0.fromIdentity({
|
|
129
|
+
id: decodeExtensionId(declared.id),
|
|
130
|
+
version: decodeExtensionVersion(declared.version ?? "0.0.0"),
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
function compileExtension(metadata, definition) {
|
|
134
|
+
if (definition.projection?.catalog !== undefined &&
|
|
135
|
+
definition.catalog === undefined)
|
|
136
|
+
throw new Error("A projected catalog requires an advertised catalog");
|
|
137
|
+
const requests = [];
|
|
138
|
+
if (definition.attention === true)
|
|
139
|
+
requests.push("attention");
|
|
140
|
+
if (metadata.declaresState || metadata.declaresDocuments)
|
|
141
|
+
requests.push("state");
|
|
142
|
+
if (definition.hooks?.onSettled !== undefined)
|
|
143
|
+
requests.push("settled", "send");
|
|
144
|
+
if (definition.commands !== undefined)
|
|
145
|
+
requests.push("commands", "send");
|
|
146
|
+
if (definition.hooks?.onTimer !== undefined || definition.timers === true)
|
|
147
|
+
requests.push("timers", "send");
|
|
148
|
+
if (definition.projection !== undefined)
|
|
149
|
+
requests.push("projection");
|
|
150
|
+
if (definition.tools !== undefined)
|
|
151
|
+
requests.push("run_tools");
|
|
152
|
+
if (definition.files !== undefined)
|
|
153
|
+
requests.push("files");
|
|
154
|
+
if (definition.prompt !== undefined)
|
|
155
|
+
requests.push("prompt");
|
|
156
|
+
if (definition.compaction !== undefined)
|
|
157
|
+
requests.push("compaction_handoff");
|
|
158
|
+
const manifest = {
|
|
159
|
+
protocol: "shiitake.extension/v0",
|
|
160
|
+
id: metadata.id,
|
|
161
|
+
version: metadata.version,
|
|
162
|
+
requests: [...new Set(requests)],
|
|
163
|
+
};
|
|
164
|
+
const contract = {
|
|
165
|
+
id: metadata.id,
|
|
166
|
+
commands: definition.commands?.specs ?? {},
|
|
167
|
+
projection: definition.projection === undefined
|
|
168
|
+
? null
|
|
169
|
+
: { schema: definition.projection.schema },
|
|
170
|
+
};
|
|
171
|
+
const { hooks, commands, projection, prompt, tools, files, compaction } = definition;
|
|
172
|
+
const onSettled = hooks?.onSettled;
|
|
173
|
+
const onTimer = hooks?.onTimer;
|
|
174
|
+
const engine = {
|
|
175
|
+
manifest,
|
|
176
|
+
contract,
|
|
177
|
+
config: metadata.config,
|
|
178
|
+
state: metadata.state,
|
|
179
|
+
activate: (port) => {
|
|
180
|
+
const context = Object.freeze({
|
|
181
|
+
...port.context,
|
|
182
|
+
config: metadata.config,
|
|
183
|
+
state: bindExtensionState(metadata.state.collections, port),
|
|
184
|
+
documents: bindExtensionDocuments(metadata.documents, port),
|
|
185
|
+
});
|
|
186
|
+
return Effect.gen(function* () {
|
|
187
|
+
if (hooks?.start !== undefined)
|
|
188
|
+
yield* invokeExtensionHook(() => hooks.start?.(context));
|
|
189
|
+
const registered = commands === undefined
|
|
190
|
+
? new Map()
|
|
191
|
+
: registerExtensionCommands(commands.specs, commands.handlers(context));
|
|
192
|
+
const result = {
|
|
193
|
+
commands: registered,
|
|
194
|
+
};
|
|
195
|
+
if (onSettled !== undefined)
|
|
196
|
+
Object.assign(result, {
|
|
197
|
+
onSettled: (page) => invokeTransactionHook(() => onSettled(context, page)),
|
|
198
|
+
});
|
|
199
|
+
if (onTimer !== undefined)
|
|
200
|
+
Object.assign(result, {
|
|
201
|
+
onTimer: (timer) => invokeTransactionHook(() => onTimer(context, timer)),
|
|
202
|
+
});
|
|
203
|
+
if (tools !== undefined)
|
|
204
|
+
Object.assign(result, {
|
|
205
|
+
moduleForRun: (run) => invokeExtensionHook(() => tools(context, run, commandTools(commands?.specs, () => registered, context.transact, run, context.grants.includes("commands")))).pipe(Effect.map((value) => Option.isOption(value) ? value : Option.fromNullishOr(value))),
|
|
206
|
+
});
|
|
207
|
+
if (files !== undefined)
|
|
208
|
+
Object.assign(result, {
|
|
209
|
+
filesForRun: (run) => invokeExtensionHook(() => files(context, run)).pipe(Effect.map((value) => Option.isOption(value) ? value : Option.fromNullishOr(value))),
|
|
210
|
+
});
|
|
211
|
+
if (prompt !== undefined)
|
|
212
|
+
Object.assign(result, {
|
|
213
|
+
prompt: (run) => prompt(context, run),
|
|
214
|
+
});
|
|
215
|
+
if (projection !== undefined)
|
|
216
|
+
Object.assign(result, {
|
|
217
|
+
project: (sessionId) => {
|
|
218
|
+
const value = invokeSyncHandler(() => projection.read(context, sessionId), undefined);
|
|
219
|
+
return Option.isOption(value)
|
|
220
|
+
? value
|
|
221
|
+
: Option.fromUndefinedOr(value);
|
|
222
|
+
},
|
|
223
|
+
});
|
|
224
|
+
const projectCatalog = projection?.catalog;
|
|
225
|
+
if (projection !== undefined && projectCatalog !== undefined)
|
|
226
|
+
Object.assign(result, {
|
|
227
|
+
projectCatalog: (value) => projectCatalog(Schema.decodeUnknownSync(projection.schema)(value)),
|
|
228
|
+
});
|
|
229
|
+
if (compaction !== undefined) {
|
|
230
|
+
const contribution = compaction(context);
|
|
231
|
+
Object.assign(result, {
|
|
232
|
+
compactionHandoff: {
|
|
233
|
+
consume: (view) => invokeExtensionHook(() => contribution.consume(view)),
|
|
234
|
+
},
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
return result;
|
|
238
|
+
});
|
|
239
|
+
},
|
|
240
|
+
};
|
|
241
|
+
if (metadata.declaresDocuments)
|
|
242
|
+
Object.assign(engine, { documents: metadata.documents });
|
|
243
|
+
if (definition.catalog !== undefined)
|
|
244
|
+
Object.assign(engine, { catalog: definition.catalog });
|
|
245
|
+
const brand = Brand.nominal();
|
|
246
|
+
const rostered = Object.assign(brand({ manifest, [definitionReader]: () => engine }), { contract });
|
|
247
|
+
Object.defineProperty(rostered, definitionReader, { enumerable: false });
|
|
248
|
+
return Object.freeze(rostered);
|
|
249
|
+
}
|
|
250
|
+
/** Declare one collection with its key inferred from the row schema. */
|
|
251
|
+
export function defineCollection(schema, keys) {
|
|
252
|
+
const spec = {
|
|
253
|
+
schema,
|
|
254
|
+
...keys,
|
|
255
|
+
bind: (port, name) => ({
|
|
256
|
+
read: port.collection(name, spec),
|
|
257
|
+
update: port.updateCollection(name, spec),
|
|
258
|
+
}),
|
|
259
|
+
indexFromEncoded: (value) => Result.map(Schema.decodeUnknownResult(schema)(value), (decoded) => spec.index?.(decoded) ?? null),
|
|
260
|
+
};
|
|
261
|
+
Object.defineProperty(spec, collectionBrand, { value: true });
|
|
262
|
+
return Object.freeze(spec);
|
|
263
|
+
}
|
package/dist/fleet.d.ts
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import { type VerifiedAgentReply } from "./internal/woodstock/index.js";
|
|
2
|
+
import type { CommandSettlement } from "./internal/contracts.js";
|
|
3
|
+
import { type Pending } from "@fungi.computer/agar";
|
|
4
|
+
import type { BirdDogMail } from "@fungi.computer/bird-dog";
|
|
5
|
+
import * as Schema from "effect/Schema";
|
|
6
|
+
import { type Accepted, type ShiitakeAgent } from "./client.js";
|
|
7
|
+
import type { Json } from "./extensions.js";
|
|
8
|
+
import type { WatchdogSqliteOwner } from "@fungi.computer/watchdog";
|
|
9
|
+
import { type CairnId } from "@fungi.computer/cairn/id";
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
import { type FungiAuthor } from "@fungi.computer/agar/agents";
|
|
12
|
+
/** Operations explicitly admitted by the host. */
|
|
13
|
+
export declare const agentActionSchema: z.ZodEnum<{
|
|
14
|
+
send: "send";
|
|
15
|
+
read: "read";
|
|
16
|
+
create: "create";
|
|
17
|
+
manage: "manage";
|
|
18
|
+
delegate: "delegate";
|
|
19
|
+
}>;
|
|
20
|
+
/** One host-admitted fleet operation. */
|
|
21
|
+
export type AgentAction = z.infer<typeof agentActionSchema>;
|
|
22
|
+
/** Attribution supplied by the admitting host, without Team semantics. */
|
|
23
|
+
export declare const agentProvenanceSchema: z.ZodObject<{
|
|
24
|
+
actor: z.ZodString;
|
|
25
|
+
workflowRunId: z.ZodOptional<z.ZodString>;
|
|
26
|
+
toolCallInputDigest: z.ZodOptional<z.ZodString>;
|
|
27
|
+
session: z.ZodOptional<z.ZodObject<{
|
|
28
|
+
agentId: z.ZodString;
|
|
29
|
+
sessionId: z.ZodString;
|
|
30
|
+
}, z.core.$strict>>;
|
|
31
|
+
}, z.core.$strict>;
|
|
32
|
+
/** Fleet authority is supplied, never looked up in host policy. */
|
|
33
|
+
export declare const agentGrantSchema: z.ZodObject<{
|
|
34
|
+
agents: z.ZodUnion<readonly [z.ZodLiteral<"all">, z.ZodArray<z.ZodString>]>;
|
|
35
|
+
actions: z.ZodArray<z.ZodEnum<{
|
|
36
|
+
send: "send";
|
|
37
|
+
read: "read";
|
|
38
|
+
create: "create";
|
|
39
|
+
manage: "manage";
|
|
40
|
+
delegate: "delegate";
|
|
41
|
+
}>>;
|
|
42
|
+
expiresAt: z.ZodNumber;
|
|
43
|
+
provenance: z.ZodObject<{
|
|
44
|
+
actor: z.ZodString;
|
|
45
|
+
workflowRunId: z.ZodOptional<z.ZodString>;
|
|
46
|
+
toolCallInputDigest: z.ZodOptional<z.ZodString>;
|
|
47
|
+
session: z.ZodOptional<z.ZodObject<{
|
|
48
|
+
agentId: z.ZodString;
|
|
49
|
+
sessionId: z.ZodString;
|
|
50
|
+
}, z.core.$strict>>;
|
|
51
|
+
}, z.core.$strict>;
|
|
52
|
+
meta: z.ZodOptional<z.ZodJSONSchema>;
|
|
53
|
+
maxDepth: z.ZodOptional<z.ZodNumber>;
|
|
54
|
+
}, z.core.$strict>;
|
|
55
|
+
/** A trusted host's bounded, addressed authority for fleet operations. */
|
|
56
|
+
export type AgentGrant = z.infer<typeof agentGrantSchema>;
|
|
57
|
+
/** A committed directory transition, returned in the host's transaction. */
|
|
58
|
+
export type AgentLifecycleFact = Readonly<{
|
|
59
|
+
kind: "created" | "deleted";
|
|
60
|
+
agentId: string;
|
|
61
|
+
provenance: AgentGrant["provenance"];
|
|
62
|
+
}>;
|
|
63
|
+
/** Refusal of supplied authority; no host policy lookup is performed. */
|
|
64
|
+
export declare class AgentGrantError extends Error {
|
|
65
|
+
readonly reason: "agent" | "action" | "expired" | "delegation_loop" | "delegation_depth";
|
|
66
|
+
constructor(reason: "agent" | "action" | "expired" | "delegation_loop" | "delegation_depth");
|
|
67
|
+
}
|
|
68
|
+
/** Check every operation against its explicit authority. */
|
|
69
|
+
export declare function assertAgentGrant(grant: AgentGrant, action: AgentAction, agentId?: string): void;
|
|
70
|
+
/** Stable Agent identities, retained across host compositions. */
|
|
71
|
+
export declare const agentIds: Readonly<{
|
|
72
|
+
readonly agent: import("@fungi.computer/cairn/id").IdCodec<"agent", "agent", 1>;
|
|
73
|
+
}>;
|
|
74
|
+
/** An ordinary Agent directory identity. */
|
|
75
|
+
export type AgentId = CairnId<"agent", "agent">;
|
|
76
|
+
/** Stable replay input; configuration is an opaque host creation choice. */
|
|
77
|
+
export declare const agentCreationSchema: z.ZodObject<{
|
|
78
|
+
name: z.ZodString;
|
|
79
|
+
requestId: z.ZodString;
|
|
80
|
+
configuration: z.ZodString;
|
|
81
|
+
}, z.core.$strict>;
|
|
82
|
+
/** One idempotent directory reservation. */
|
|
83
|
+
export type AgentCreation = z.infer<typeof agentCreationSchema>;
|
|
84
|
+
/** Owner-only rename input: an Agent's new display name. */
|
|
85
|
+
export declare const agentRenameSchema: z.ZodObject<{
|
|
86
|
+
name: z.ZodString;
|
|
87
|
+
}, z.core.$strict>;
|
|
88
|
+
/** Input to {@link createAgentDirectory}'s `rename`. */
|
|
89
|
+
export type AgentRename = z.infer<typeof agentRenameSchema>;
|
|
90
|
+
/** One durable Agent directory record. */
|
|
91
|
+
export type DirectoryAgent = Readonly<{
|
|
92
|
+
agentId: AgentId;
|
|
93
|
+
name: string;
|
|
94
|
+
createdAt: number;
|
|
95
|
+
updatedAt: number;
|
|
96
|
+
}>;
|
|
97
|
+
/** Directory input, replay or storage refusal. */
|
|
98
|
+
export declare class DirectoryError extends Error {
|
|
99
|
+
readonly status: 400 | 403 | 404 | 409 | 503;
|
|
100
|
+
readonly code: "invalid_input" | "not_found" | "name_taken" | "request_conflict" | "computer_team_conflict" | "partial_init";
|
|
101
|
+
constructor(status: 400 | 403 | 404 | 409 | 503, code: "invalid_input" | "not_found" | "name_taken" | "request_conflict" | "computer_team_conflict" | "partial_init");
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Agent identities, replay receipts and erasure roster. Mutations belong inside
|
|
105
|
+
* the caller's storage transaction, so lifecycle facts and host projections
|
|
106
|
+
* commit together. Physical table names retain the existing Hub store layout.
|
|
107
|
+
*/
|
|
108
|
+
export declare function createAgentDirectory(sql: WatchdogSqliteOwner["sql"]): {
|
|
109
|
+
/** Resolve a matching creation receipt before host admission of a new reservation. */
|
|
110
|
+
readCreation: (grant: AgentGrant, raw: AgentCreation) => DirectoryAgent | null;
|
|
111
|
+
/** Reserve an Agent once and return its committed lifecycle fact. */
|
|
112
|
+
create: (grant: AgentGrant, raw: AgentCreation) => {
|
|
113
|
+
agent: Readonly<{
|
|
114
|
+
agentId: AgentId;
|
|
115
|
+
name: string;
|
|
116
|
+
createdAt: number;
|
|
117
|
+
updatedAt: number;
|
|
118
|
+
}>;
|
|
119
|
+
fact: null;
|
|
120
|
+
} | {
|
|
121
|
+
agent: Readonly<{
|
|
122
|
+
agentId: AgentId;
|
|
123
|
+
name: string;
|
|
124
|
+
createdAt: number;
|
|
125
|
+
updatedAt: number;
|
|
126
|
+
}>;
|
|
127
|
+
fact: {
|
|
128
|
+
kind: "created";
|
|
129
|
+
agentId: CairnId<"agent", "agent", 1>;
|
|
130
|
+
provenance: {
|
|
131
|
+
actor: string;
|
|
132
|
+
workflowRunId?: string | undefined;
|
|
133
|
+
toolCallInputDigest?: string | undefined;
|
|
134
|
+
session?: {
|
|
135
|
+
agentId: string;
|
|
136
|
+
sessionId: string;
|
|
137
|
+
} | undefined;
|
|
138
|
+
};
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
/** Read one admitted Agent identity. */
|
|
142
|
+
read: (grant: AgentGrant, agentId: AgentId) => DirectoryAgent | null;
|
|
143
|
+
/** List only identities covered by the supplied grant. */
|
|
144
|
+
list: (grant: AgentGrant) => readonly DirectoryAgent[];
|
|
145
|
+
/** Remove an identity while retaining its erasure address. */
|
|
146
|
+
remove: (grant: AgentGrant, agentId: AgentId) => AgentLifecycleFact | null;
|
|
147
|
+
/** Rename an existing Agent; refuses a name already held by another one. */
|
|
148
|
+
rename: (grant: AgentGrant, agentId: AgentId, raw: AgentRename) => DirectoryAgent;
|
|
149
|
+
/** Read the host actor recorded at creation. */
|
|
150
|
+
readCreator: (grant: AgentGrant, agentId: string) => string | null;
|
|
151
|
+
/** Enumerate retained addresses for host erasure. */
|
|
152
|
+
listErasureIds: () => readonly string[];
|
|
153
|
+
/** Whether the retained erasure roster covers this store. */
|
|
154
|
+
erasureRosterComplete: () => boolean;
|
|
155
|
+
};
|
|
156
|
+
/** Replay identity and work, with the parent supplied exclusively by the grant. */
|
|
157
|
+
export declare const agentDelegationTaskSchema: z.ZodObject<{
|
|
158
|
+
requestId: z.ZodString;
|
|
159
|
+
agentId: z.ZodString;
|
|
160
|
+
sessionId: z.ZodOptional<z.ZodString>;
|
|
161
|
+
text: z.ZodString;
|
|
162
|
+
}, z.core.$strict>;
|
|
163
|
+
/** A caller reuses this task unchanged while polling Pending. */
|
|
164
|
+
export type AgentDelegationTask = z.infer<typeof agentDelegationTaskSchema>;
|
|
165
|
+
/** Exact host facts encoded over internal transports, without transcript content. */
|
|
166
|
+
export declare const commandSettlementSchema: Schema.Codec<CommandSettlement>;
|
|
167
|
+
/** Exact settled Session facts, including Pi usage and tool-call records. */
|
|
168
|
+
export type AgentDelegationOutcome = Readonly<{
|
|
169
|
+
kind: "settled";
|
|
170
|
+
agentId: string;
|
|
171
|
+
sessionId: string;
|
|
172
|
+
}> & CommandSettlement;
|
|
173
|
+
/** Ordinary runtime and mail transports; these ports do not decide host policy. */
|
|
174
|
+
export type FleetDelegationOptions = Readonly<{
|
|
175
|
+
storage: WatchdogSqliteOwner;
|
|
176
|
+
/** Admit the frozen addressed mail through the destination owner. */
|
|
177
|
+
deliver: (mail: BirdDogMail) => Promise<Accepted>;
|
|
178
|
+
/** Read exact work facts at the target owner, independent of transcript selection. */
|
|
179
|
+
readSettlement: (agentId: string, sessionId: string, commandId: string) => Promise<CommandSettlement | undefined>;
|
|
180
|
+
/** Acquire a Session client only when creating the delegated conversation. */
|
|
181
|
+
open: (agentId: string) => Promise<Readonly<{
|
|
182
|
+
agent: ShiitakeAgent;
|
|
183
|
+
/** Release the borrowed transport without stopping its run. */
|
|
184
|
+
release: () => Promise<void>;
|
|
185
|
+
}>>;
|
|
186
|
+
}>;
|
|
187
|
+
/**
|
|
188
|
+
* The delegation meta the host attaches to an authenticated reply: the
|
|
189
|
+
* caller's own path plus the verified reply, whose `agentId` is the reply's
|
|
190
|
+
* author.
|
|
191
|
+
*/
|
|
192
|
+
export type AuthenticatedDelegationReply = Readonly<{
|
|
193
|
+
ancestors: readonly string[];
|
|
194
|
+
maxDepth: number;
|
|
195
|
+
reply: VerifiedAgentReply;
|
|
196
|
+
}>;
|
|
197
|
+
/** The host metadata a delegated send carries, as JSON. */
|
|
198
|
+
export type DelegationSendMeta = {
|
|
199
|
+
author: FungiAuthor;
|
|
200
|
+
delegation?: {
|
|
201
|
+
ancestors: string[];
|
|
202
|
+
maxDepth: number;
|
|
203
|
+
};
|
|
204
|
+
};
|
|
205
|
+
/** The host metadata on one authenticated reply line, as JSON. */
|
|
206
|
+
export type DelegationReplyMeta = Readonly<{
|
|
207
|
+
author: FungiAuthor;
|
|
208
|
+
delegation: Readonly<{
|
|
209
|
+
ancestors: readonly string[];
|
|
210
|
+
maxDepth: number;
|
|
211
|
+
reply: VerifiedAgentReply;
|
|
212
|
+
}>;
|
|
213
|
+
}>;
|
|
214
|
+
/**
|
|
215
|
+
* Provenance for one delegated send from the invoking Agent's Session. The
|
|
216
|
+
* model program's digest is frozen with the replay input, so a retried tool
|
|
217
|
+
* call that changed its code conflicts instead of replaying.
|
|
218
|
+
*/
|
|
219
|
+
export declare function delegationProvenance(session: Readonly<{
|
|
220
|
+
agentId: string;
|
|
221
|
+
sessionId: string;
|
|
222
|
+
}>, toolCallCode?: string): Promise<AgentGrant["provenance"]>;
|
|
223
|
+
/**
|
|
224
|
+
* The host metadata one delegated send carries: the sending Agent as author
|
|
225
|
+
* and only the path inherited from the invoking line. A reply's verified facts
|
|
226
|
+
* stay on that reply's own line and never travel onward.
|
|
227
|
+
*/
|
|
228
|
+
export declare function delegationSendMeta(sender: FungiAuthor, invocationMeta?: Json): DelegationSendMeta;
|
|
229
|
+
/**
|
|
230
|
+
* The host metadata for one authenticated reply line: the replying Agent is
|
|
231
|
+
* its author, and the verified reply rides beside the caller's own path.
|
|
232
|
+
*/
|
|
233
|
+
export declare function delegationReplyMeta(delegation: AuthenticatedDelegationReply, replierName: string): DelegationReplyMeta;
|
|
234
|
+
/** One Agent a Session sent work to: its latest addressed conversation. */
|
|
235
|
+
export type FleetRecipient = Readonly<{
|
|
236
|
+
agentId: string;
|
|
237
|
+
sessionId: string;
|
|
238
|
+
sentAt: number;
|
|
239
|
+
}>;
|
|
240
|
+
/** A bounded page of recipients and how many more exist past it. */
|
|
241
|
+
export type FleetRecipients = Readonly<{
|
|
242
|
+
recipients: readonly FleetRecipient[];
|
|
243
|
+
more: number;
|
|
244
|
+
}>;
|
|
245
|
+
/**
|
|
246
|
+
* Hosted BirdDog submission and Pending observation. The durable row freezes
|
|
247
|
+
* correspondence before transport; an ambiguous delivery reuses that exact mail.
|
|
248
|
+
* Shiitake owns work deduplication, execution and settlement; Post owns replies.
|
|
249
|
+
*/
|
|
250
|
+
export declare function createFleetDelegation(options: FleetDelegationOptions): {
|
|
251
|
+
/** Authenticate a reply against its frozen mail and restore the caller's path. */
|
|
252
|
+
authenticateReply: (mail: BirdDogMail) => AuthenticatedDelegationReply | undefined;
|
|
253
|
+
/** One grouped read of the Agents a parent Session sent work to. */
|
|
254
|
+
recipients: (parent: Readonly<{
|
|
255
|
+
agentId: string;
|
|
256
|
+
sessionId: string;
|
|
257
|
+
}>, limit: number) => FleetRecipients;
|
|
258
|
+
/** Submit once and return the existing Shiitake admission receipt. */
|
|
259
|
+
start: (grant: AgentGrant, raw: AgentDelegationTask) => Promise<Accepted>;
|
|
260
|
+
/** Submit or poll the exact turn, yielding Agar Pending until settled. */
|
|
261
|
+
delegate: (grant: AgentGrant, task: AgentDelegationTask) => Promise<Pending | AgentDelegationOutcome>;
|
|
262
|
+
};
|
|
263
|
+
/** Acquire ordinary Session access; an in-process host applies meta with withMeta. */
|
|
264
|
+
export type FleetAgentAccess = (agentId: string, meta?: Json) => Promise<Readonly<{
|
|
265
|
+
agent: ShiitakeAgent;
|
|
266
|
+
/** Release the borrowed transport without stopping its run. */
|
|
267
|
+
release: () => Promise<void>;
|
|
268
|
+
}>>;
|
|
269
|
+
/** One idempotent prompt, using the Session owner's existing delivery grammar. */
|
|
270
|
+
export type FleetMessage = Readonly<{
|
|
271
|
+
requestId: string;
|
|
272
|
+
text: string;
|
|
273
|
+
delivery?: "steer" | "followUp";
|
|
274
|
+
}>;
|
|
275
|
+
/**
|
|
276
|
+
* Addressed Session operations over the existing Shiitake client. Each operation
|
|
277
|
+
* checks a fresh supplied grant and releases its transport without stopping work.
|
|
278
|
+
*/
|
|
279
|
+
export declare function createFleetSessions(open: FleetAgentAccess): {
|
|
280
|
+
/** Enumerate existing Sessions through the owner's bounded cursor. */
|
|
281
|
+
list: (grant: AgentGrant, agentId: string, after?: string) => Promise<Readonly<{
|
|
282
|
+
sessions: readonly import("./client.js").SessionSummaryRow[];
|
|
283
|
+
next: string | undefined;
|
|
284
|
+
}>>;
|
|
285
|
+
/** Open the exact saved conversation without creating work. */
|
|
286
|
+
read: (grant: AgentGrant, agentId: string, sessionId: string) => Promise<Readonly<{
|
|
287
|
+
sessionId: string;
|
|
288
|
+
cursor: string | null;
|
|
289
|
+
hasMore: boolean;
|
|
290
|
+
oldestCursor?: string | null;
|
|
291
|
+
messages: readonly import("./client.js").SessionMessage[];
|
|
292
|
+
terminals: readonly import("./client.js").SessionTerminal[];
|
|
293
|
+
compactions?: readonly import("./client.js").SessionCompactionMarker[];
|
|
294
|
+
compactionNotices?: readonly import("./client.js").SessionCompactionNotice[];
|
|
295
|
+
sandboxFailures?: readonly import("@fungi.computer/mycelium").SandboxFailureEvent[];
|
|
296
|
+
pending: import("./client.js").SessionPendingPrompts;
|
|
297
|
+
activity: import("./client.js").SessionActivity;
|
|
298
|
+
progress: import("./client.js").SessionProgress | null;
|
|
299
|
+
extensions: import("./client.js").SessionExtensionSlots;
|
|
300
|
+
attention: readonly import("./session-attention.js").SessionAttention[];
|
|
301
|
+
context?: import("./client.js").SessionContext;
|
|
302
|
+
}>>;
|
|
303
|
+
/** Create a Session once under the caller's replay identity. */
|
|
304
|
+
create: (grant: AgentGrant, agentId: string, requestId: string) => Promise<string>;
|
|
305
|
+
/** Remove a Session through its runtime owner. */
|
|
306
|
+
remove: (grant: AgentGrant, agentId: string, sessionId: string) => Promise<boolean>;
|
|
307
|
+
/** Send once; an omitted Session is created under the same replay identity. */
|
|
308
|
+
send: (grant: AgentGrant, agentId: string, sessionId: string | undefined, message: FleetMessage) => Promise<{
|
|
309
|
+
sessionId: string;
|
|
310
|
+
status: "accepted";
|
|
311
|
+
commandId: string;
|
|
312
|
+
}>;
|
|
313
|
+
};
|