@fungi.computer/shiitake 0.0.1 → 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/dist/agent-control.d.ts +7 -2
- package/dist/agent-control.js +6 -3
- package/dist/fleet.d.ts +16 -0
- package/dist/fleet.js +25 -0
- package/dist/internal/admission-door.js +1 -1
- package/dist/internal/compaction/compaction.d.ts +1 -1
- package/dist/internal/compaction/compaction.js +5 -6
- package/dist/internal/compaction/session-compaction.js +1 -1
- package/dist/internal/coordinator.js +1 -1
- package/dist/internal/woodstock/fleet-store.d.ts +4 -0
- package/dist/internal/woodstock/fleet-store.js +7 -0
- package/docs/api/agent-control.md +1 -1
- package/docs/api/effect.md +0 -20
- package/docs/api/fleet.md +28 -0
- package/package.json +5 -5
package/dist/agent-control.d.ts
CHANGED
|
@@ -36,11 +36,16 @@ export type AgentControlDirectory = Readonly<{
|
|
|
36
36
|
list: (signal: AbortSignal) => Promise<readonly AgentControlAgent[]>;
|
|
37
37
|
/** Follow-up delegation with durable replies to the invoking Session. */
|
|
38
38
|
send?: (input: AgentDelegationInput, sourceSessionId: string, signal: AbortSignal, invocation?: AgentDelegationInvocation) => Promise<Accepted>;
|
|
39
|
-
/**
|
|
39
|
+
/**
|
|
40
|
+
* Present only when this host authorizes ordinary Agent creation. `invoker`
|
|
41
|
+
* names the Session whose run asked, so a host can record provenance.
|
|
42
|
+
*/
|
|
40
43
|
create?: (input: Readonly<{
|
|
41
44
|
requestId: string;
|
|
42
45
|
model?: ModelPreference;
|
|
43
|
-
}>, signal: AbortSignal
|
|
46
|
+
}>, signal: AbortSignal, invoker?: Readonly<{
|
|
47
|
+
sessionId: string;
|
|
48
|
+
}>) => Promise<AgentControlAgent>;
|
|
44
49
|
/** Present only when the host authorizes changing an Agent's future default. */
|
|
45
50
|
setModel?: (input: Readonly<{
|
|
46
51
|
agentId: string;
|
package/dist/agent-control.js
CHANGED
|
@@ -235,7 +235,7 @@ function admitModelRefusal(operation, cause) {
|
|
|
235
235
|
/** Compose one authorized Agent-control projection for a single run lease. */
|
|
236
236
|
export function createAgentControlSource(directory) {
|
|
237
237
|
const create = directory.create;
|
|
238
|
-
const createOperation = create === undefined
|
|
238
|
+
const createOperation = (session) => create === undefined
|
|
239
239
|
? undefined
|
|
240
240
|
: Mycelium.operation({
|
|
241
241
|
replay: "unsafe",
|
|
@@ -244,9 +244,10 @@ export function createAgentControlSource(directory) {
|
|
|
244
244
|
output: agentOutput,
|
|
245
245
|
execute: async ({ requestId, model }, context) => agentOutput.parse(await create(model === undefined
|
|
246
246
|
? { requestId }
|
|
247
|
-
: { requestId, model: parseModelAddress(model) }, context.signal
|
|
247
|
+
: { requestId, model: parseModelAddress(model) }, context.signal, session === undefined
|
|
248
|
+
? undefined
|
|
249
|
+
: { sessionId: session.sessionId }).catch((cause) => admitModelRefusal("create", cause))),
|
|
248
250
|
});
|
|
249
|
-
const createOperations = createOperation === undefined ? {} : { create: createOperation };
|
|
250
251
|
const setModel = directory.setModel;
|
|
251
252
|
const modelOperations = setModel === undefined
|
|
252
253
|
? {}
|
|
@@ -287,6 +288,8 @@ export function createAgentControlSource(directory) {
|
|
|
287
288
|
acquire: ({ signal, session }) => {
|
|
288
289
|
signal.throwIfAborted();
|
|
289
290
|
const sends = new WeakMap();
|
|
291
|
+
const created = createOperation(session);
|
|
292
|
+
const createOperations = created === undefined ? {} : { create: created };
|
|
290
293
|
return Promise.resolve({
|
|
291
294
|
snapshot: {
|
|
292
295
|
version: "shiitake-agent-control-v6",
|
package/dist/fleet.d.ts
CHANGED
|
@@ -231,6 +231,17 @@ export declare function delegationSendMeta(sender: FungiAuthor, invocationMeta?:
|
|
|
231
231
|
* its author, and the verified reply rides beside the caller's own path.
|
|
232
232
|
*/
|
|
233
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
|
+
}>;
|
|
234
245
|
/**
|
|
235
246
|
* Hosted BirdDog submission and Pending observation. The durable row freezes
|
|
236
247
|
* correspondence before transport; an ambiguous delivery reuses that exact mail.
|
|
@@ -239,6 +250,11 @@ export declare function delegationReplyMeta(delegation: AuthenticatedDelegationR
|
|
|
239
250
|
export declare function createFleetDelegation(options: FleetDelegationOptions): {
|
|
240
251
|
/** Authenticate a reply against its frozen mail and restore the caller's path. */
|
|
241
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;
|
|
242
258
|
/** Submit once and return the existing Shiitake admission receipt. */
|
|
243
259
|
start: (grant: AgentGrant, raw: AgentDelegationTask) => Promise<Accepted>;
|
|
244
260
|
/** Submit or poll the exact turn, yielding Agar Pending until settled. */
|
package/dist/fleet.js
CHANGED
|
@@ -324,6 +324,12 @@ const delegationRowSchema = z.strictObject({
|
|
|
324
324
|
receipt: z.string().nullable(),
|
|
325
325
|
});
|
|
326
326
|
const decodeMail = Schema.decodeUnknownSync(Schema.fromJsonString(BirdDogMailSchema));
|
|
327
|
+
const recipientRowSchema = z.strictObject({
|
|
328
|
+
agent_id: identity,
|
|
329
|
+
session_id: identity,
|
|
330
|
+
sent_at: z.number().int().nonnegative(),
|
|
331
|
+
total: z.number().int().nonnegative(),
|
|
332
|
+
});
|
|
327
333
|
/**
|
|
328
334
|
* Hosted BirdDog submission and Pending observation. The durable row freezes
|
|
329
335
|
* correspondence before transport; an ambiguous delivery reuses that exact mail.
|
|
@@ -464,9 +470,28 @@ export function createFleetDelegation(options) {
|
|
|
464
470
|
reply,
|
|
465
471
|
};
|
|
466
472
|
}
|
|
473
|
+
/**
|
|
474
|
+
* The distinct Agents one parent Session sent work to, newest send first,
|
|
475
|
+
* with how many more exist past `limit`. Read-only over the frozen mail.
|
|
476
|
+
*/
|
|
477
|
+
function recipients(parent, limit) {
|
|
478
|
+
const rows = store
|
|
479
|
+
.recipients(parent.agentId, parent.sessionId, limit)
|
|
480
|
+
.map((row) => recipientRowSchema.parse(row));
|
|
481
|
+
return {
|
|
482
|
+
recipients: rows.map((row) => ({
|
|
483
|
+
agentId: row.agent_id,
|
|
484
|
+
sessionId: row.session_id,
|
|
485
|
+
sentAt: row.sent_at,
|
|
486
|
+
})),
|
|
487
|
+
more: Math.max(0, (rows[0]?.total ?? 0) - rows.length),
|
|
488
|
+
};
|
|
489
|
+
}
|
|
467
490
|
return {
|
|
468
491
|
/** Authenticate a reply against its frozen mail and restore the caller's path. */
|
|
469
492
|
authenticateReply,
|
|
493
|
+
/** One grouped read of the Agents a parent Session sent work to. */
|
|
494
|
+
recipients,
|
|
470
495
|
/** Submit once and return the existing Shiitake admission receipt. */
|
|
471
496
|
start,
|
|
472
497
|
/** Submit or poll the exact turn, yielding Agar Pending until settled. */
|
|
@@ -20,7 +20,7 @@ function decodeReply(request) {
|
|
|
20
20
|
mail.from.agentId !== reply.agentId ||
|
|
21
21
|
mail.from.sessionId !== reply.sessionId ||
|
|
22
22
|
request.command.type !== "prompt" ||
|
|
23
|
-
request.command.delivery !== "
|
|
23
|
+
request.command.delivery !== "steer")
|
|
24
24
|
throw new ShiitakeError("contract", "invalid", "Verified Agent reply does not match its mail");
|
|
25
25
|
return reply;
|
|
26
26
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* The retained preparation/result vocabulary is intentionally visible here;
|
|
4
4
|
* Shiitake supplies native Message values and its selected model stream.
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
6
|
+
import type { Api, Model, Usage } from "@earendil-works/pi-ai";
|
|
7
7
|
import type { MuleStreamFunction } from "@fungi.computer/mule/effect";
|
|
8
8
|
import * as Effect from "effect/Effect";
|
|
9
9
|
import type { BorrowedCompactionViewV0 } from "../../extensions.js";
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import { contentText, normalizeContext, retryAssistantCall, uuidv7, } from "@earendil-works/pi-ai";
|
|
1
|
+
// Leaf helpers, not Pi's root entry, which also evaluates its validators.
|
|
2
|
+
import { retryAssistantCall } from "@earendil-works/pi-ai/utils/retry";
|
|
3
|
+
import { contentText } from "@earendil-works/pi-ai/utils/text";
|
|
4
|
+
import { normalizeContext } from "@earendil-works/pi-ai/utils/transcript";
|
|
5
|
+
import { uuidv7 } from "@earendil-works/pi-ai/utils/uuid";
|
|
7
6
|
import * as Effect from "effect/Effect";
|
|
8
7
|
import { ShiitakeError } from "../../errors.js";
|
|
9
8
|
import { computeFileLists, createFileOps, extractFileOpsFromMessage, formatFileOperations, serializeConversation, SUMMARIZATION_PROMPT, SUMMARIZATION_SYSTEM_PROMPT, TURN_PREFIX_SUMMARIZATION_PROMPT, UPDATE_SUMMARIZATION_PROMPT, compactionSummaryMessage, estimateContextTokens, estimateTokens, summaryFailure, } from "./utils.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isContextOverflow, } from "@fungi.computer/mule/effect";
|
|
2
|
-
import { isRecoverableLength } from "@earendil-works/pi-ai";
|
|
2
|
+
import { isRecoverableLength } from "@earendil-works/pi-ai/utils/overflow";
|
|
3
3
|
import * as Effect from "effect/Effect";
|
|
4
4
|
import { ShiitakeError } from "../../errors.js";
|
|
5
5
|
import { borrowedView, compact, prepareCompaction, } from "./compaction.js";
|
|
@@ -355,7 +355,7 @@ export function openCoordinator(options, runtime) {
|
|
|
355
355
|
export function acceptAddressedMail(runtime, mail, meta, reply) {
|
|
356
356
|
return admitUserWork(runtime, mail.to.sessionId, {
|
|
357
357
|
requestId: mail.key,
|
|
358
|
-
delivery: "followUp",
|
|
358
|
+
delivery: reply === undefined ? "followUp" : "steer",
|
|
359
359
|
type: "prompt",
|
|
360
360
|
text: mail.content,
|
|
361
361
|
}, meta, mail, reply);
|
|
@@ -27,6 +27,10 @@ export declare function createFleetDelegationStore(storage: WatchdogSqliteOwner)
|
|
|
27
27
|
read: (requestId: string) => {
|
|
28
28
|
readonly [x: string]: string | number | ArrayBuffer | null;
|
|
29
29
|
} | undefined;
|
|
30
|
+
/** Distinct addressed Agents of one parent Session, newest send first. */
|
|
31
|
+
recipients: (parentAgentId: string, parentSessionId: string, limit: number) => readonly {
|
|
32
|
+
readonly [x: string]: string | number | ArrayBuffer | null;
|
|
33
|
+
}[];
|
|
30
34
|
reserve(requestId: string, input: string, mail: string): void;
|
|
31
35
|
recordReceipt(requestId: string, receipt: string): void;
|
|
32
36
|
};
|
|
@@ -70,15 +70,22 @@ export function createFleetDirectoryStore(sql) {
|
|
|
70
70
|
return row?.complete === 1;
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
|
+
const fromAgent = "json_extract(mail, '$.from.agentId')";
|
|
74
|
+
const fromSession = "json_extract(mail, '$.from.sessionId')";
|
|
73
75
|
/** Durable correspondence is frozen before delivery; retries reuse the same row. */
|
|
74
76
|
export function createFleetDelegationStore(storage) {
|
|
75
77
|
storage.sql.exec(`CREATE TABLE IF NOT EXISTS shiitake_fleet_delegations (
|
|
76
78
|
request_id TEXT PRIMARY KEY, input TEXT NOT NULL, mail TEXT NOT NULL, receipt TEXT
|
|
77
79
|
) STRICT`);
|
|
80
|
+
storage.sql.exec(`CREATE INDEX IF NOT EXISTS idx_shiitake_fleet_delegations_parent ON shiitake_fleet_delegations(${fromAgent}, ${fromSession})`);
|
|
78
81
|
return {
|
|
79
82
|
read: (requestId) => storage.sql
|
|
80
83
|
.exec("SELECT input, mail, receipt FROM shiitake_fleet_delegations WHERE request_id = ?", requestId)
|
|
81
84
|
.toArray()[0],
|
|
85
|
+
/** Distinct addressed Agents of one parent Session, newest send first. */
|
|
86
|
+
recipients: (parentAgentId, parentSessionId, limit) => storage.sql
|
|
87
|
+
.exec(`SELECT json_extract(mail, '$.to.agentId') AS agent_id, json_extract(mail, '$.to.sessionId') AS session_id, MAX(json_extract(mail, '$.createdAt')) AS sent_at, COUNT(*) OVER () AS total FROM shiitake_fleet_delegations WHERE ${fromAgent} = ? AND ${fromSession} = ? GROUP BY agent_id ORDER BY sent_at DESC, agent_id LIMIT ?`, parentAgentId, parentSessionId, limit)
|
|
88
|
+
.toArray(),
|
|
82
89
|
reserve(requestId, input, mail) {
|
|
83
90
|
storage.transactionSync(() => {
|
|
84
91
|
storage.sql.exec("INSERT OR IGNORE INTO shiitake_fleet_delegations(request_id, input, mail) VALUES (?, ?, ?)", requestId, input, mail);
|
|
@@ -72,7 +72,7 @@ Host-only identity and admitted command metadata for one delegated send.
|
|
|
72
72
|
type AgentControlDirectory = Readonly<{
|
|
73
73
|
list: (signal) => Promise<readonly AgentControlAgent[]>;
|
|
74
74
|
send?: (input, sourceSessionId, signal, invocation?) => Promise<Accepted>;
|
|
75
|
-
create?: (input, signal) => Promise<AgentControlAgent>;
|
|
75
|
+
create?: (input, signal, invoker?) => Promise<AgentControlAgent>;
|
|
76
76
|
setModel?: (input, signal) => Promise<void>;
|
|
77
77
|
models?: (signal) => Promise<readonly AgentControlModel[]>;
|
|
78
78
|
checkModel?: (input, signal) => Promise<void>;
|
package/docs/api/effect.md
CHANGED
|
@@ -535,26 +535,6 @@ for it. An unreadable Session is its own `unavailable` row.
|
|
|
535
535
|
[`StoredSessionSummaryRow`](#storedsessionsummaryrow)[]; `next`: `string` \|
|
|
536
536
|
`undefined`; \}\>, [`ShiitakeError`](index.md#shiitakeerror), `never`\>
|
|
537
537
|
|
|
538
|
-
---
|
|
539
|
-
|
|
540
|
-
### inspectWoodstockStoreProtocol()
|
|
541
|
-
|
|
542
|
-
```ts
|
|
543
|
-
function inspectWoodstockStoreProtocol(owner): "fresh" | "v0" | "unmarked";
|
|
544
|
-
```
|
|
545
|
-
|
|
546
|
-
Inspect one unopened store before the file-backed host takes custody.
|
|
547
|
-
|
|
548
|
-
#### Parameters
|
|
549
|
-
|
|
550
|
-
| Parameter | Type |
|
|
551
|
-
| --------- | ------------------------------------- |
|
|
552
|
-
| `owner` | [`SqliteOwner`](index.md#sqliteowner) |
|
|
553
|
-
|
|
554
|
-
#### Returns
|
|
555
|
-
|
|
556
|
-
`"fresh"` \| `"v0"` \| `"unmarked"`
|
|
557
|
-
|
|
558
538
|
## References
|
|
559
539
|
|
|
560
540
|
### AbortCommand
|
package/docs/api/fleet.md
CHANGED
|
@@ -303,6 +303,33 @@ The host metadata on one authenticated reply line, as JSON.
|
|
|
303
303
|
|
|
304
304
|
---
|
|
305
305
|
|
|
306
|
+
### FleetRecipient
|
|
307
|
+
|
|
308
|
+
```ts
|
|
309
|
+
type FleetRecipient = Readonly<{
|
|
310
|
+
agentId: string;
|
|
311
|
+
sessionId: string;
|
|
312
|
+
sentAt: number;
|
|
313
|
+
}>;
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
One Agent a Session sent work to: its latest addressed conversation.
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
### FleetRecipients
|
|
321
|
+
|
|
322
|
+
```ts
|
|
323
|
+
type FleetRecipients = Readonly<{
|
|
324
|
+
recipients: readonly FleetRecipient[];
|
|
325
|
+
more: number;
|
|
326
|
+
}>;
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
A bounded page of recipients and how many more exist past it.
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
306
333
|
### FleetAgentAccess
|
|
307
334
|
|
|
308
335
|
```ts
|
|
@@ -675,6 +702,7 @@ Shiitake owns work deduplication, execution and settlement; Post owns replies.
|
|
|
675
702
|
| Name | Type | Description |
|
|
676
703
|
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
677
704
|
| `authenticateReply()` | (`mail`) => \| `Readonly`\<\{ `ancestors`: readonly `string`[]; `maxDepth`: `number`; `reply`: \{ `commandId`: `string`; `outcome`: `"completed"` \| `"failed"` \| `"cancelled"` \| `"interrupted"` \| `"outcome_unknown"`; `diagnostic?`: `string`; `agentId`: `string`; `sessionId`: `string`; \}; \}\> \| `undefined` | Authenticate a reply against its frozen mail and restore the caller's path. Authenticate one arriving reply against the frozen mail this owner sent. It must be BirdDog's single reply key for that mail, mirror its sender and recipient exactly, carry BirdDog's settlement facts and, once the send's receipt is recorded, name that receipt's `commandId`. The result restores the caller's own delegation path and the verified reply; it never reads the reply's text or any settlement metadata. |
|
|
705
|
+
| `recipients()` | (`parent`, `limit`) => [`FleetRecipients`](#fleetrecipients) | One grouped read of the Agents a parent Session sent work to. The distinct Agents one parent Session sent work to, newest send first, with how many more exist past `limit`. Read-only over the frozen mail. |
|
|
678
706
|
| `start()` | (`grant`, `raw`) => `Promise`\<`Readonly`\<\{ `status`: `"accepted"`; `commandId`: `string`; \}\>\> | Submit once and return the existing Shiitake admission receipt. |
|
|
679
707
|
| `delegate()` | (`grant`, `task`) => `Promise`\< \| `Readonly`\<\{ `kind`: `"pending"`; `retryAfterMs`: `number`; \}\> \| [`AgentDelegationOutcome`](#agentdelegationoutcome)\> | Submit or poll the exact turn, yielding Agar Pending until settled. |
|
|
680
708
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fungi.computer/shiitake",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"author": "Levi <levi@technomancy.dev>",
|
|
5
5
|
"description": "Effect-native durable Session acceptance and bounded run orchestration",
|
|
6
6
|
"type": "module",
|
|
@@ -76,16 +76,16 @@
|
|
|
76
76
|
"dependencies": {
|
|
77
77
|
"@fungi.computer/bird-dog": "0.0.1",
|
|
78
78
|
"@fungi.computer/cairn": "0.0.1",
|
|
79
|
-
"@fungi.computer/knapsack": "0.0.
|
|
80
|
-
"@fungi.computer/mule": "0.0.
|
|
81
|
-
"@fungi.computer/mycelium": "0.0.
|
|
79
|
+
"@fungi.computer/knapsack": "0.0.2",
|
|
80
|
+
"@fungi.computer/mule": "0.0.2",
|
|
81
|
+
"@fungi.computer/mycelium": "0.0.2",
|
|
82
82
|
"@fungi.computer/watchdog": "0.0.1",
|
|
83
83
|
"effect": "4.0.2",
|
|
84
84
|
"hono": "4.13.5",
|
|
85
85
|
"zod": "4.4.3",
|
|
86
86
|
"@earendil-works/pi-ai": "0.99.2",
|
|
87
87
|
"@fungi.computer/gills": "0.0.1",
|
|
88
|
-
"@fungi.computer/agar": "0.0
|
|
88
|
+
"@fungi.computer/agar": "0.1.0"
|
|
89
89
|
},
|
|
90
90
|
"devDependencies": {
|
|
91
91
|
"@cloudflare/workers-types": "5.20260828.1",
|