@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.
@@ -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
- /** Present only when this host authorizes ordinary Agent creation. */
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) => Promise<AgentControlAgent>;
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;
@@ -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).catch((cause) => admitModelRefusal("create", cause))),
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 !== "followUp")
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 { type Api, type Model, type Usage } from "@earendil-works/pi-ai";
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
- * Pi v0.84.4 semantic compaction, adapted only at Woodstock's entry boundary.
3
- * The retained preparation/result vocabulary is intentionally visible here;
4
- * Shiitake supplies native Message values and its selected model stream.
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>;
@@ -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.1",
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.1",
80
- "@fungi.computer/mule": "0.0.1",
81
- "@fungi.computer/mycelium": "0.0.1",
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.1"
88
+ "@fungi.computer/agar": "0.1.0"
89
89
  },
90
90
  "devDependencies": {
91
91
  "@cloudflare/workers-types": "5.20260828.1",