@fungi.computer/shiitake 0.5.0 → 0.6.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.
Files changed (65) hide show
  1. package/dist/agent-control.d.ts +93 -1
  2. package/dist/agent-control.js +108 -6
  3. package/dist/client-entry.d.ts +20 -0
  4. package/dist/client-entry.js +5 -0
  5. package/dist/client-visitor.d.ts +31 -0
  6. package/dist/client-visitor.js +226 -0
  7. package/dist/client-wire.d.ts +5 -0
  8. package/dist/client-wire.js +6 -0
  9. package/dist/client.d.ts +4 -3
  10. package/dist/client.js +1 -0
  11. package/dist/delegation.d.ts +74 -53
  12. package/dist/delegation.js +4 -15
  13. package/dist/effect.d.ts +25 -0
  14. package/dist/effect.js +14 -1
  15. package/dist/extensions.d.ts +21 -2
  16. package/dist/extensions.js +1 -1
  17. package/dist/fleet.d.ts +15 -0
  18. package/dist/fleet.js +32 -6
  19. package/dist/hosted.js +3 -0
  20. package/dist/http-routes.d.ts +11 -0
  21. package/dist/internal/accepted-run-executor.js +2 -1
  22. package/dist/internal/admission-door.d.ts +5 -0
  23. package/dist/internal/admission-door.js +27 -1
  24. package/dist/internal/contracts.d.ts +14 -1
  25. package/dist/internal/coordinator.js +8 -2
  26. package/dist/internal/effect-client.js +1 -1
  27. package/dist/internal/effect-contracts.d.ts +4 -2
  28. package/dist/internal/extension-command-registry.d.ts +2 -1
  29. package/dist/internal/extension-command-registry.js +3 -1
  30. package/dist/internal/extension-runtime.d.ts +3 -1
  31. package/dist/internal/extension-runtime.js +13 -5
  32. package/dist/internal/model-acquisition.js +2 -0
  33. package/dist/internal/observation-kernel.d.ts +2 -0
  34. package/dist/internal/observation-kernel.js +17 -6
  35. package/dist/internal/run-scope.d.ts +14 -0
  36. package/dist/internal/run-scope.js +32 -9
  37. package/dist/internal/runtime-coordinator.js +8 -1
  38. package/dist/internal/runtime-reconciliation.js +119 -24
  39. package/dist/internal/woodstock/agent-reply.d.ts +5 -0
  40. package/dist/internal/woodstock/agent-reply.js +3 -0
  41. package/dist/internal/woodstock/client-projection.js +9 -1
  42. package/dist/internal/woodstock/index.d.ts +4 -0
  43. package/dist/internal/woodstock/index.js +7 -0
  44. package/dist/internal/woodstock/session-delegator.d.ts +12 -0
  45. package/dist/internal/woodstock/session-delegator.js +44 -0
  46. package/dist/internal/woodstock/session-entry.d.ts +12 -2
  47. package/dist/internal/woodstock/session-store.d.ts +2 -0
  48. package/dist/internal/woodstock/session-store.js +20 -0
  49. package/dist/internal/woodstock/work-senders.d.ts +32 -0
  50. package/dist/internal/woodstock/work-senders.js +70 -0
  51. package/dist/remote-client.js +7 -2
  52. package/dist/server-visitor-stream.d.ts +13 -0
  53. package/dist/server-visitor-stream.js +115 -0
  54. package/dist/session-attention.d.ts +30 -0
  55. package/dist/session-attention.js +14 -0
  56. package/docs/api/agent-control.md +209 -13
  57. package/docs/api/client-entry.md +3 -0
  58. package/docs/api/client.md +136 -1
  59. package/docs/api/cloudflare.md +7 -1
  60. package/docs/api/delegation.md +234 -61
  61. package/docs/api/effect.md +16 -6
  62. package/docs/api/extensions.md +65 -4
  63. package/docs/api/fleet.md +69 -16
  64. package/docs/api/index.md +6 -4
  65. package/package.json +10 -6
package/dist/client.d.ts CHANGED
@@ -5,12 +5,13 @@ export { type SessionAttention } from "./session-attention.js";
5
5
  import type { SandboxFailureEvent } from "@fungi.computer/mycelium";
6
6
  import type { ModelPreference } from "./internal/model-preference.js";
7
7
  import type { Message } from "@fungi.computer/mule/effect";
8
- import type { ExtensionSlotV0, ExtensionStatusV0, Json } from "./extensions.js";
8
+ import type { ExtensionCommandCallerV0, ExtensionSlotV0, ExtensionStatusV0, Json } from "./extensions.js";
9
9
  import type { AbortCommand, BranchCommand, CompactCommand, OperatorCommand, TitleCommand, CancelCommand, ForkCommand, PromptCommand, PromptDelivery, SessionCommand } from "./internal/client-boundary.js";
10
10
  export { createShiitakeClient, type ShiitakeClientOptions, } from "./remote-client.js";
11
11
  export { bindAgentExtension, bindSessionExtension, type BoundAgentExtensionV0, type BoundCallV0, type BoundSessionExtensionV0, type ExtensionViewV0, type ScopedCommandsV0, } from "./extension-client.js";
12
12
  export { AcceptedSchema, DelegationReceiptSchema, HeldSchema, parseAccepted, parseDelegationReceipt, parseCancelResult, parseLatestPendingPrompt, parseWithdrawResult, parseForkedSession, parseSessionFrame, parseSessionSnapshot, parseSessionSummaryPage, parseShiitakeError, } from "./client-wire.js";
13
13
  export type { AbortCommand, BranchCommand, CompactCommand, CancelCommand, ForkCommand, OperatorCommand, PromptCommand, PromptDelivery, SessionCommand, TitleCommand, } from "./internal/client-boundary.js";
14
+ export { participantSnapshot, visitorPendingPrompt, visitorSnapshot, visitorView, type ParticipantPolicy, type VisitorPendingPrompt, type VisitorView, } from "./client-visitor.js";
14
15
  /** Semantic acknowledgement returned after one durable acceptance commit. */
15
16
  export type Accepted = Readonly<{
16
17
  /** Indicates that the owner transaction committed. */
@@ -185,8 +186,8 @@ export type SessionActivity = Readonly<{
185
186
  export type SessionExtensionSlots = Readonly<Record<string, ExtensionSlotV0>>;
186
187
  /** Generic Session-scope extension commands. */
187
188
  export type SessionExtensionControls = Readonly<{
188
- /** Call one Session-scope command with its encoded input; resolves the encoded output. */
189
- call: (command: string, input: Json) => Promise<Json>;
189
+ /** Call one Session-scope command with its encoded input and optional host caller. */
190
+ call: (command: string, input: Json, caller?: ExtensionCommandCallerV0) => Promise<Json>;
190
191
  }>;
191
192
  /** Generic Agent-scope extension controls. */
192
193
  export type AgentExtensionControls = Readonly<{
package/dist/client.js CHANGED
@@ -2,3 +2,4 @@ export {} from "./session-attention.js";
2
2
  export { createShiitakeClient, } from "./remote-client.js";
3
3
  export { bindAgentExtension, bindSessionExtension, } from "./extension-client.js";
4
4
  export { AcceptedSchema, DelegationReceiptSchema, HeldSchema, parseAccepted, parseDelegationReceipt, parseCancelResult, parseLatestPendingPrompt, parseWithdrawResult, parseForkedSession, parseSessionFrame, parseSessionSnapshot, parseSessionSummaryPage, parseShiitakeError, } from "./client-wire.js";
5
+ export { participantSnapshot, visitorPendingPrompt, visitorSnapshot, visitorView, } from "./client-visitor.js";
@@ -34,7 +34,7 @@ export declare class AgentDelegation {
34
34
  private scope;
35
35
  /** Recipient-local disclosure through the public host, never another Agent's RPC. */
36
36
  settlement(sender: DelegationIdentity, sessionId: string, commandId: string, host: Pick<ShiitakeHost, "readSettlement">): Promise<CommandSettlement | undefined>;
37
- /** Delegate work to an in-scope Agent: steer its Session, or start fleet correspondence. */
37
+ /** Delegate work to an in-scope Agent through fleet correspondence; a steer rides the mail. */
38
38
  send(input: AgentDelegationInput, sourceSessionId: string, signal: AbortSignal, invocation?: AgentDelegationInvocation): Promise<DelegationReceipt>;
39
39
  /** Resolve this sender's exact request, then let the recipient guard pending work. */
40
40
  recall(input: AgentRecallInput, sourceSessionId: string, signal: AbortSignal): Promise<CancelResult>;
@@ -63,15 +63,9 @@ export type AgentReplySettlement = (mail: BirdDogMail) => Promise<CommandSettlem
63
63
  export declare function agentMailRoute(namespace: PostRoute<never, never>["namespace"], replySettlement: AgentReplySettlement): PostRoute<import("@fungi.computer/seam/machine-link-protocol").AgentMailAddress, {
64
64
  readonly key: string;
65
65
  readonly content: string;
66
- readonly createdAt: number;
67
- readonly from: {
68
- readonly kind: "agent";
69
- readonly agentId: string;
70
- readonly sessionId: string;
71
- };
72
66
  readonly to: {
73
- readonly kind: "agent";
74
67
  readonly agentId: string;
68
+ readonly kind: "agent";
75
69
  readonly sessionId?: string;
76
70
  };
77
71
  readonly replyTo: readonly {
@@ -79,11 +73,22 @@ export declare function agentMailRoute(namespace: PostRoute<never, never>["names
79
73
  readonly agentId: string;
80
74
  readonly sessionId: string;
81
75
  }[];
76
+ readonly createdAt: number;
77
+ readonly from: {
78
+ readonly kind: "agent";
79
+ readonly agentId: string;
80
+ readonly sessionId: string;
81
+ };
82
82
  readonly meta?: Schema.Json;
83
83
  readonly reply?: {
84
84
  readonly commandId: string;
85
85
  readonly outcome: "completed" | "failed" | "cancelled" | "interrupted" | "outcome_unknown";
86
86
  readonly diagnostic?: string;
87
+ readonly waitingOnYou?: readonly {
88
+ readonly itemId: string;
89
+ readonly kind: string;
90
+ readonly summary: string;
91
+ }[];
87
92
  } | {
88
93
  readonly outcome: "accepted";
89
94
  readonly commandId: string;
@@ -98,14 +103,9 @@ export declare function agentMailRoute(namespace: PostRoute<never, never>["names
98
103
  readonly reason: "recipient_offline";
99
104
  };
100
105
  readonly content: string;
101
- readonly createdAt: number;
102
- readonly from: {
103
- readonly kind: "system";
104
- readonly systemId: "hub";
105
- };
106
106
  readonly to: {
107
- readonly kind: "agent";
108
107
  readonly agentId: string;
108
+ readonly kind: "agent";
109
109
  readonly sessionId?: string;
110
110
  };
111
111
  readonly replyTo: readonly {
@@ -113,19 +113,18 @@ export declare function agentMailRoute(namespace: PostRoute<never, never>["names
113
113
  readonly agentId: string;
114
114
  readonly sessionId: string;
115
115
  }[];
116
+ readonly createdAt: number;
117
+ readonly from: {
118
+ readonly kind: "system";
119
+ readonly systemId: "hub";
120
+ };
116
121
  readonly meta?: Schema.Json;
117
122
  }, {
118
123
  readonly key: string;
119
124
  readonly content: string;
120
- readonly createdAt: number;
121
- readonly from: {
122
- readonly kind: "agent";
123
- readonly agentId: string;
124
- readonly sessionId: string;
125
- };
126
125
  readonly to: {
127
- readonly kind: "agent";
128
126
  readonly agentId: string;
127
+ readonly kind: "agent";
129
128
  readonly sessionId?: string;
130
129
  };
131
130
  readonly replyTo: readonly {
@@ -133,11 +132,22 @@ export declare function agentMailRoute(namespace: PostRoute<never, never>["names
133
132
  readonly agentId: string;
134
133
  readonly sessionId: string;
135
134
  }[];
135
+ readonly createdAt: number;
136
+ readonly from: {
137
+ readonly kind: "agent";
138
+ readonly agentId: string;
139
+ readonly sessionId: string;
140
+ };
136
141
  readonly meta?: Schema.Json;
137
142
  readonly reply?: {
138
143
  readonly commandId: string;
139
144
  readonly outcome: "completed" | "failed" | "cancelled" | "interrupted" | "outcome_unknown";
140
145
  readonly diagnostic?: string;
146
+ readonly waitingOnYou?: readonly {
147
+ readonly itemId: string;
148
+ readonly kind: string;
149
+ readonly summary: string;
150
+ }[];
141
151
  } | {
142
152
  readonly outcome: "accepted";
143
153
  readonly commandId: string;
@@ -152,14 +162,9 @@ export declare function agentMailRoute(namespace: PostRoute<never, never>["names
152
162
  readonly reason: "recipient_offline";
153
163
  };
154
164
  readonly content: string;
155
- readonly createdAt: number;
156
- readonly from: {
157
- readonly kind: "system";
158
- readonly systemId: "hub";
159
- };
160
165
  readonly to: {
161
- readonly kind: "agent";
162
166
  readonly agentId: string;
167
+ readonly kind: "agent";
163
168
  readonly sessionId?: string;
164
169
  };
165
170
  readonly replyTo: readonly {
@@ -167,19 +172,18 @@ export declare function agentMailRoute(namespace: PostRoute<never, never>["names
167
172
  readonly agentId: string;
168
173
  readonly sessionId: string;
169
174
  }[];
175
+ readonly createdAt: number;
176
+ readonly from: {
177
+ readonly kind: "system";
178
+ readonly systemId: "hub";
179
+ };
170
180
  readonly meta?: Schema.Json;
171
181
  }, import("@fungi.computer/seam/machine-link-protocol").AgentMailAddress, {
172
182
  readonly key: string;
173
183
  readonly content: string;
174
- readonly createdAt: number;
175
- readonly from: {
176
- readonly kind: "agent";
177
- readonly agentId: string;
178
- readonly sessionId: string;
179
- };
180
184
  readonly to: {
181
- readonly kind: "agent";
182
185
  readonly agentId: string;
186
+ readonly kind: "agent";
183
187
  readonly sessionId?: string;
184
188
  };
185
189
  readonly replyTo: readonly {
@@ -187,11 +191,22 @@ export declare function agentMailRoute(namespace: PostRoute<never, never>["names
187
191
  readonly agentId: string;
188
192
  readonly sessionId: string;
189
193
  }[];
194
+ readonly createdAt: number;
195
+ readonly from: {
196
+ readonly kind: "agent";
197
+ readonly agentId: string;
198
+ readonly sessionId: string;
199
+ };
190
200
  readonly meta?: Schema.Json;
191
201
  readonly reply?: {
192
202
  readonly commandId: string;
193
203
  readonly outcome: "completed" | "failed" | "cancelled" | "interrupted" | "outcome_unknown";
194
204
  readonly diagnostic?: string;
205
+ readonly waitingOnYou?: readonly {
206
+ readonly itemId: string;
207
+ readonly kind: string;
208
+ readonly summary: string;
209
+ }[];
195
210
  } | {
196
211
  readonly outcome: "accepted";
197
212
  readonly commandId: string;
@@ -206,14 +221,9 @@ export declare function agentMailRoute(namespace: PostRoute<never, never>["names
206
221
  readonly reason: "recipient_offline";
207
222
  };
208
223
  readonly content: string;
209
- readonly createdAt: number;
210
- readonly from: {
211
- readonly kind: "system";
212
- readonly systemId: "hub";
213
- };
214
224
  readonly to: {
215
- readonly kind: "agent";
216
225
  readonly agentId: string;
226
+ readonly kind: "agent";
217
227
  readonly sessionId?: string;
218
228
  };
219
229
  readonly replyTo: readonly {
@@ -221,19 +231,18 @@ export declare function agentMailRoute(namespace: PostRoute<never, never>["names
221
231
  readonly agentId: string;
222
232
  readonly sessionId: string;
223
233
  }[];
234
+ readonly createdAt: number;
235
+ readonly from: {
236
+ readonly kind: "system";
237
+ readonly systemId: "hub";
238
+ };
224
239
  readonly meta?: Schema.Json;
225
240
  }, {
226
241
  readonly key: string;
227
242
  readonly content: string;
228
- readonly createdAt: number;
229
- readonly from: {
230
- readonly kind: "agent";
231
- readonly agentId: string;
232
- readonly sessionId: string;
233
- };
234
243
  readonly to: {
235
- readonly kind: "agent";
236
244
  readonly agentId: string;
245
+ readonly kind: "agent";
237
246
  readonly sessionId?: string;
238
247
  };
239
248
  readonly replyTo: readonly {
@@ -241,11 +250,22 @@ export declare function agentMailRoute(namespace: PostRoute<never, never>["names
241
250
  readonly agentId: string;
242
251
  readonly sessionId: string;
243
252
  }[];
253
+ readonly createdAt: number;
254
+ readonly from: {
255
+ readonly kind: "agent";
256
+ readonly agentId: string;
257
+ readonly sessionId: string;
258
+ };
244
259
  readonly meta?: Schema.Json;
245
260
  readonly reply?: {
246
261
  readonly commandId: string;
247
262
  readonly outcome: "completed" | "failed" | "cancelled" | "interrupted" | "outcome_unknown";
248
263
  readonly diagnostic?: string;
264
+ readonly waitingOnYou?: readonly {
265
+ readonly itemId: string;
266
+ readonly kind: string;
267
+ readonly summary: string;
268
+ }[];
249
269
  } | {
250
270
  readonly outcome: "accepted";
251
271
  readonly commandId: string;
@@ -260,14 +280,9 @@ export declare function agentMailRoute(namespace: PostRoute<never, never>["names
260
280
  readonly reason: "recipient_offline";
261
281
  };
262
282
  readonly content: string;
263
- readonly createdAt: number;
264
- readonly from: {
265
- readonly kind: "system";
266
- readonly systemId: "hub";
267
- };
268
283
  readonly to: {
269
- readonly kind: "agent";
270
284
  readonly agentId: string;
285
+ readonly kind: "agent";
271
286
  readonly sessionId?: string;
272
287
  };
273
288
  readonly replyTo: readonly {
@@ -275,6 +290,11 @@ export declare function agentMailRoute(namespace: PostRoute<never, never>["names
275
290
  readonly agentId: string;
276
291
  readonly sessionId: string;
277
292
  }[];
293
+ readonly createdAt: number;
294
+ readonly from: {
295
+ readonly kind: "system";
296
+ readonly systemId: "hub";
297
+ };
278
298
  readonly meta?: Schema.Json;
279
299
  }> & Omit<Readonly<{
280
300
  addressKind: string;
@@ -317,6 +337,7 @@ export declare class AgentMail {
317
337
  stageAcceptedNotice(mail: BirdDogMail, scopeId: string): void;
318
338
  /** BirdDog's mail room: disclosed settlement replies fan out over Post. */
319
339
  mailRoom(): BirdDogEffect & {
340
+ /** Stage acceptance through this Post owner within the caller's transaction. */
320
341
  stageAcceptedNotice: (mail: BirdDogMail, scopeId: string) => void;
321
342
  };
322
343
  }
@@ -3,7 +3,7 @@
3
3
  * addressed Agent mail over Carrier Post, and the Agent grammar a host hands
4
4
  * to Oyster's machine link as ports. Oyster core never imports this engine.
5
5
  */
6
- import { commandSettlementSchema, createAgentDirectory, createFleetCorrespondence, agentDelegationRequestKey, delegationProvenance, delegationReplyMeta, delegationSendMeta, } from "./fleet.js";
6
+ import { commandSettlementSchema, createAgentDirectory, createFleetCorrespondence, agentDelegationRequestKey, delegationProvenance, delegationReplyMeta, delegationSendMeta, settlementReadableBy, } from "./fleet.js";
7
7
  import * as Schema from "effect/Schema";
8
8
  import { agentMailAddressSchema } from "@fungi.computer/seam/machine-link-protocol";
9
9
  import { BirdDogMailSchema, BirdDogError, settlementReplies, } from "@fungi.computer/bird-dog/effect";
@@ -44,11 +44,11 @@ export class AgentDelegation {
44
44
  !scope.agents.some(({ agentId }) => agentId === sender.agentId))
45
45
  throw new AgentDisclosureRefused();
46
46
  const facts = await host.readSettlement(sessionId, commandId);
47
- if (facts !== undefined && facts.acceptedSender !== sender.agentId)
47
+ if (facts !== undefined && !settlementReadableBy(facts, sender.agentId))
48
48
  throw new AgentDisclosureRefused();
49
49
  return facts;
50
50
  }
51
- /** Delegate work to an in-scope Agent: steer its Session, or start fleet correspondence. */
51
+ /** Delegate work to an in-scope Agent through fleet correspondence; a steer rides the mail. */
52
52
  async send(input, sourceSessionId, signal, invocation) {
53
53
  if (invocation === undefined)
54
54
  throw new Error("Delegation requires a tool invocation");
@@ -66,18 +66,6 @@ export class AgentDelegation {
66
66
  requestId: input.requestId,
67
67
  });
68
68
  signal.throwIfAborted();
69
- if (input.delivery === "steer") {
70
- const opened = await this.deps.directory().open(input.agentId, signal);
71
- try {
72
- return await opened.agent.session(input.sessionId).send(input.text, {
73
- requestId,
74
- delivery: "steer",
75
- });
76
- }
77
- finally {
78
- await opened.release();
79
- }
80
- }
81
69
  const provenance = await delegationProvenance({
82
70
  agentId: scope.agentId,
83
71
  sessionId: sourceSessionId,
@@ -93,6 +81,7 @@ export class AgentDelegation {
93
81
  }, {
94
82
  agentId: input.agentId,
95
83
  sessionId: input.sessionId,
84
+ delivery: input.delivery,
96
85
  text: input.text,
97
86
  requestId,
98
87
  });
package/dist/effect.d.ts CHANGED
@@ -38,5 +38,30 @@ export declare function readSessionSummaries(owner: SqliteOwner, after?: string)
38
38
  sessions: readonly import("./internal/woodstock/session-store.js").StoredSessionSummaryRow[];
39
39
  next: string | undefined;
40
40
  }>, ShiitakeError, never>;
41
+ /**
42
+ * One page of saved conversations with their stored run state (needs_you,
43
+ * running, errored, done), in tier then newest-activity order, read from the
44
+ * store alone: no Agent runtime starts. The state is as the runtime last wrote
45
+ * it, so it can lag work a stopped runtime left behind.
46
+ */
47
+ export declare function readStoredSessionStates(owner: SqliteOwner, after?: string): Effect.Effect<Readonly<{
48
+ sessions: readonly import("./client.js").SessionSummaryRow[];
49
+ next: string | undefined;
50
+ }>, ShiitakeError, never>;
51
+ /** One saved conversation's open attention items, read from the store alone. */
52
+ export declare function readStoredAttention(owner: SqliteOwner, sessionId: string): Effect.Effect<readonly {
53
+ readonly id: string;
54
+ readonly kind: string;
55
+ readonly summary: string;
56
+ readonly since: number;
57
+ readonly extensionId: string;
58
+ readonly expiresAt?: number | undefined;
59
+ readonly inbox?: false | undefined;
60
+ readonly waitingOn?: {
61
+ readonly agentId: string;
62
+ readonly sessionId: string;
63
+ readonly name: string;
64
+ } | undefined;
65
+ }[], ShiitakeError, never>;
41
66
  export { sqliteRowSchema } from "./internal/contracts.js";
42
67
  export type { CommandSettlement } from "./internal/contracts.js";
package/dist/effect.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as Effect from "effect/Effect";
2
- import { readSessionFactPage } from "./internal/woodstock/index.js";
2
+ import { readSessionFactPage, readSessionInbox, readStoredSessionAttention, } from "./internal/woodstock/index.js";
3
3
  export { ShiitakeError } from "./errors.js";
4
4
  /** Construct the canonical Effect-native Shiitake scaffold. */
5
5
  export function make(options) {
@@ -17,4 +17,17 @@ export function openHost(options, mailRoom) {
17
17
  export function readSessionSummaries(owner, after) {
18
18
  return readSessionFactPage(owner, after);
19
19
  }
20
+ /**
21
+ * One page of saved conversations with their stored run state (needs_you,
22
+ * running, errored, done), in tier then newest-activity order, read from the
23
+ * store alone: no Agent runtime starts. The state is as the runtime last wrote
24
+ * it, so it can lag work a stopped runtime left behind.
25
+ */
26
+ export function readStoredSessionStates(owner, after) {
27
+ return readSessionInbox(owner, after);
28
+ }
29
+ /** One saved conversation's open attention items, read from the store alone. */
30
+ export function readStoredAttention(owner, sessionId) {
31
+ return readStoredSessionAttention(owner, sessionId);
32
+ }
20
33
  export { sqliteRowSchema } from "./internal/contracts.js";
@@ -1,6 +1,6 @@
1
1
  import type { FileTool } from "@fungi.computer/knapsack";
2
- import type { AttentionItem } from "./session-attention.js";
3
- export { AttentionItemSchema, type AttentionItem, type SessionAttention, } from "./session-attention.js";
2
+ import type { AttentionItem, AttentionRecipient } from "./session-attention.js";
3
+ export { AttentionItemSchema, AttentionRecipientSchema, type AttentionItem, type AttentionRecipient, type SessionAttention, } from "./session-attention.js";
4
4
  import type { Message, Usage } from "@fungi.computer/mule/effect";
5
5
  import type { ModuleRegistration } from "@fungi.computer/mycelium";
6
6
  import * as Brand from "effect/Brand";
@@ -261,6 +261,8 @@ export type SendInputV0 = Readonly<{
261
261
  when: "now" | "idle";
262
262
  /** Stored with the admission and returned on `SettledRunV0.origin`. */
263
263
  correlation?: string;
264
+ /** This work continues earlier work of the Session and keeps its sender. */
265
+ continuesWorkId?: string;
264
266
  }>;
265
267
  /** Door outcome for one extension admission. */
266
268
  export type SendResultV0 = Readonly<{
@@ -290,17 +292,26 @@ export type CommandSessionIdsV0 = {
290
292
  agent: null;
291
293
  session: string;
292
294
  };
295
+ /** Host-authenticated caller context; never decoded from command JSON or HTTP. */
296
+ export type ExtensionCommandCallerV0 = Readonly<{
297
+ agentId: string;
298
+ sessionId: string;
299
+ }>;
293
300
  /** Handlers for every declared command, run in one core transaction. */
294
301
  export type CommandHandlersV0<C extends CommandsV0> = {
295
302
  readonly [K in keyof C]: (call: Readonly<{
296
303
  sessionId: CommandSessionIdsV0[C[K]["scope"]];
297
304
  input: C[K]["input"]["Type"];
305
+ /** Present only when the owning in-process host authenticates a caller. */
306
+ caller?: ExtensionCommandCallerV0;
298
307
  }>) => C[K]["output"]["Type"] | Effect.Effect<C[K]["output"]["Type"], ExtensionCommandError | ExtensionStateError | AdmissionError, ExtensionTx | ExtensionRead>;
299
308
  };
300
309
  /** Transaction-scoped, extension-owned attention on an existing Session. */
301
310
  export type AttentionV0 = Readonly<{
302
311
  /** Upsert this extension’s item and publish the committed Session change. */
303
312
  set: (sessionId: string, item: AttentionItem) => Effect.Effect<void, ExtensionStateError, ExtensionTx>;
313
+ /** Whether any extension holds an inbox item asking a person to act (a question or approval). */
314
+ awaitsPerson: (sessionId: string) => Effect.Effect<boolean, ExtensionStateError, ExtensionRead>;
304
315
  /** Clear this extension’s item; other owners cannot be changed. */
305
316
  clear: (sessionId: string, id: string) => Effect.Effect<void, ExtensionStateError, ExtensionTx>;
306
317
  }>;
@@ -322,10 +333,18 @@ export type ExtensionContextV0<S extends CollectionsV0, Config extends Json, D e
322
333
  sessionPosition: (sessionId: string) => Effect.Effect<number, ExtensionStateError, ExtensionRead>;
323
334
  /** Observe accepted steering without consuming Mule's next control delivery. Requires run_tools. */
324
335
  hasPendingSteer: (run: Pick<RunIdentityV0, "sessionId" | "workId">) => Effect.Effect<boolean, ExtensionStateError, ExtensionRead>;
336
+ /**
337
+ * The Agent Session that sent this run, or null when a person (or the host)
338
+ * did. Attention an extension raises for the run waits on it first.
339
+ * Requires run_tools.
340
+ */
341
+ workSender: (run: Pick<RunIdentityV0, "sessionId" | "workId">) => Effect.Effect<AttentionRecipient | null, ExtensionStateError, ExtensionRead>;
325
342
  /** Whether this run durably recorded a successful tool outcome. Requires run_tools. */
326
343
  hasSuccessfulToolResult: (run: Pick<RunIdentityV0, "sessionId" | "workId">, toolCallId: string) => Effect.Effect<boolean, ExtensionStateError, ExtensionRead>;
327
344
  /** Publish a Session observation after this transaction commits. */
328
345
  observe: (sessionId: string) => Effect.Effect<void, never, ExtensionTx>;
346
+ /** Process-local live-view demand, excluding exact-command settlement waiters. */
347
+ isObserved: (sessionId: string) => boolean;
329
348
  /**
330
349
  * Run one write transaction from outside a hook (for example a Mycelium
331
350
  * tool execute). Core commits, publishes, and requests a wake when it
@@ -1,4 +1,4 @@
1
- export { AttentionItemSchema, } from "./session-attention.js";
1
+ export { AttentionItemSchema, AttentionRecipientSchema, } from "./session-attention.js";
2
2
  import * as Brand from "effect/Brand";
3
3
  import * as Context from "effect/Context";
4
4
  import * as Data from "effect/Data";
package/dist/fleet.d.ts CHANGED
@@ -180,11 +180,22 @@ export declare function createAgentDirectory(sql: WatchdogSqliteOwner["sql"]): {
180
180
  /** Whether the retained erasure roster covers this store. */
181
181
  erasureRosterComplete: () => boolean;
182
182
  };
183
+ /**
184
+ * Whether an Agent may read one command's settlement: the Agent whose mail the
185
+ * command answered, or the Session's delegator of record for work no Agent's
186
+ * mail admitted (goal, loop and person turns, the work its reports carry).
187
+ * Another Agent's correspondence stays with that Agent.
188
+ */
189
+ export declare function settlementReadableBy(facts: Pick<CommandSettlement, "acceptedSender" | "delegator">, agentId: string): boolean;
183
190
  /** Replay identity and work, with the parent supplied exclusively by the grant. */
184
191
  export declare const agentDelegationTaskSchema: z.ZodLazy<z.ZodObject<{
185
192
  requestId: z.ZodString;
186
193
  agentId: z.ZodString;
187
194
  sessionId: z.ZodOptional<z.ZodString>;
195
+ delivery: z.ZodOptional<z.ZodEnum<{
196
+ followUp: "followUp";
197
+ steer: "steer";
198
+ }>>;
188
199
  text: z.ZodString;
189
200
  }, z.core.$strict>>;
190
201
  /** A caller reuses this task unchanged while polling Pending. */
@@ -280,7 +291,9 @@ export declare function createFleetCorrespondence(options: Omit<FleetDelegationO
280
291
  start: (grant: AgentGrant, raw: AgentDelegationTask) => Promise<DelegationReceipt>;
281
292
  /** Match a reply to frozen mail and restore the caller's delegation path. */
282
293
  authenticateReply: (mail: BirdDogMail) => AuthenticatedDelegationReply | undefined;
294
+ /** Bind exhausted local delivery to its frozen sender correspondence. */
283
295
  recordLocalUndeliverable: (original: BirdDogMail, reply: BirdDogMail) => boolean;
296
+ /** Prevent replay after a system undeliverable reply is admitted. */
284
297
  recordUndeliverableReply: (mailKey: string) => boolean;
285
298
  /** Read an existing acceptance receipt without reserving or delivering mail. */
286
299
  receipt: (requestId: string) => Accepted | undefined;
@@ -295,7 +308,9 @@ export declare function createFleetDelegation(options: FleetDelegationOptions):
295
308
  start: (grant: AgentGrant, raw: AgentDelegationTask) => Promise<DelegationReceipt>;
296
309
  /** Match a reply to frozen mail and restore the caller's delegation path. */
297
310
  authenticateReply: (mail: BirdDogMail) => AuthenticatedDelegationReply | undefined;
311
+ /** Bind exhausted local delivery to its frozen sender correspondence. */
298
312
  recordLocalUndeliverable: (original: BirdDogMail, reply: BirdDogMail) => boolean;
313
+ /** Prevent replay after a system undeliverable reply is admitted. */
299
314
  recordUndeliverableReply: (mailKey: string) => boolean;
300
315
  /** Read an existing acceptance receipt without reserving or delivering mail. */
301
316
  receipt: (requestId: string) => Accepted | undefined;
package/dist/fleet.js CHANGED
@@ -269,11 +269,23 @@ export function createAgentDirectory(sql) {
269
269
  erasureRosterComplete: store.erasureRosterComplete,
270
270
  };
271
271
  }
272
+ /**
273
+ * Whether an Agent may read one command's settlement: the Agent whose mail the
274
+ * command answered, or the Session's delegator of record for work no Agent's
275
+ * mail admitted (goal, loop and person turns, the work its reports carry).
276
+ * Another Agent's correspondence stays with that Agent.
277
+ */
278
+ export function settlementReadableBy(facts, agentId) {
279
+ return (facts.acceptedSender === agentId ||
280
+ (facts.acceptedSender === null && facts.delegator === agentId));
281
+ }
272
282
  /** Replay identity and work, with the parent supplied exclusively by the grant. */
273
283
  export const agentDelegationTaskSchema = z.lazy(() => z.strictObject({
274
284
  requestId: identity,
275
285
  agentId: identity,
276
286
  sessionId: identity.optional(),
287
+ /** A live steer into the recipient's running turn; queued follow-up when omitted. */
288
+ delivery: z.enum(["followUp", "steer"]).optional(),
277
289
  text: z
278
290
  .string()
279
291
  .min(1)
@@ -395,7 +407,8 @@ export function createFleetCorrespondence(options) {
395
407
  throw new AgentGrantError("delegation_loop");
396
408
  if (ancestors.length >= maxDepth)
397
409
  throw new AgentGrantError("delegation_depth");
398
- const delegation = { ancestors: [...ancestors, parent.agentId], maxDepth };
410
+ const path = { ancestors: [...ancestors, parent.agentId], maxDepth };
411
+ const delegation = task.delivery === "steer" ? { ...path, steer: true } : path;
399
412
  const outgoingMeta = {
400
413
  ...(objectMeta.success
401
414
  ? objectMeta.data
@@ -471,13 +484,23 @@ export function createFleetCorrespondence(options) {
471
484
  */
472
485
  function authenticateReply(mail) {
473
486
  // This owner sends to one correspondent, so BirdDog's reply index is zero.
474
- const suffix = ":reply:0";
487
+ // A report names the idle Session's delegator mail and the settled command.
475
488
  if (mail.replyTo.length !== 0 ||
476
489
  mail.reply === undefined ||
477
- mail.reply.outcome === "accepted" ||
478
- !mail.key.endsWith(suffix))
490
+ mail.reply.outcome === "accepted")
491
+ return undefined;
492
+ const reportAt = mail.key.lastIndexOf(":report:");
493
+ // A report's key names the command it settles.
494
+ const isReport = reportAt >= 0 &&
495
+ "commandId" in mail.reply &&
496
+ mail.key.slice(reportAt) === `:report:${mail.reply.commandId}:0`;
497
+ const mailKey = isReport
498
+ ? mail.key.slice(0, reportAt)
499
+ : mail.key.endsWith(":reply:0")
500
+ ? mail.key.slice(0, -":reply:0".length)
501
+ : undefined;
502
+ if (mailKey === undefined)
479
503
  return undefined;
480
- const mailKey = mail.key.slice(0, -suffix.length);
481
504
  const row = read(mailKey);
482
505
  if (row === undefined || row.state === "undeliverable")
483
506
  return undefined;
@@ -508,7 +531,8 @@ export function createFleetCorrespondence(options) {
508
531
  mail.reply.reason === "recipient_offline" &&
509
532
  !systemUndeliverable)
510
533
  return undefined;
511
- if (mail.reply.outcome !== "undeliverable" &&
534
+ if (!isReport &&
535
+ mail.reply.outcome !== "undeliverable" &&
512
536
  row.state === "accepted" &&
513
537
  row.receipt !== null) {
514
538
  const sentResult = parseAccepted(row.receipt);
@@ -627,7 +651,9 @@ export function createFleetCorrespondence(options) {
627
651
  start,
628
652
  /** Match a reply to frozen mail and restore the caller's delegation path. */
629
653
  authenticateReply,
654
+ /** Bind exhausted local delivery to its frozen sender correspondence. */
630
655
  recordLocalUndeliverable,
656
+ /** Prevent replay after a system undeliverable reply is admitted. */
631
657
  recordUndeliverableReply,
632
658
  /** Read an existing acceptance receipt without reserving or delivering mail. */
633
659
  receipt,
package/dist/hosted.js CHANGED
@@ -166,12 +166,15 @@ function hostedPort(manifest, revision, grants) {
166
166
  }),
167
167
  attention: Object.freeze({
168
168
  set: () => Effect.fail(unavailable("Attention")),
169
+ awaitsPerson: () => Effect.fail(unavailable("Attention")),
169
170
  clear: () => Effect.fail(unavailable("Attention")),
170
171
  }),
171
172
  hasPendingSteer: () => Effect.fail(unavailable("Steering")),
173
+ workSender: () => Effect.fail(unavailable("Run sender")),
172
174
  sessionPosition: () => Effect.fail(unavailable("Session timeline")),
173
175
  hasSuccessfulToolResult: () => Effect.fail(unavailable("A tool result")),
174
176
  observe: () => Effect.die(unavailable("Observation")),
177
+ isObserved: () => false,
175
178
  transact: () => Effect.fail(new ShiitakeError("extensions", "rejected", "A hosted extension has no Agent transaction")),
176
179
  }),
177
180
  });
@@ -502,6 +502,7 @@ export declare function createShiitakeHttpRoutes(resolveSession: ShiitakeSession
502
502
  };
503
503
  output: {
504
504
  readonly acceptedSender: string | null;
505
+ readonly delegator: string | null;
505
506
  readonly terminal: {
506
507
  readonly commandId: string;
507
508
  readonly outcome: "completed" | "cancelled" | "failed" | "interrupted";
@@ -531,6 +532,11 @@ export declare function createShiitakeHttpRoutes(resolveSession: ShiitakeSession
531
532
  };
532
533
  }[];
533
534
  readonly toolCalls: number;
535
+ readonly waitingOnYou: readonly {
536
+ readonly itemId: string;
537
+ readonly kind: string;
538
+ readonly summary: string;
539
+ }[];
534
540
  } | null;
535
541
  outputFormat: "json";
536
542
  status: 200;
@@ -873,6 +879,11 @@ export declare function createShiitakeHttpRoutes(resolveSession: ShiitakeSession
873
879
  readonly extensionId: string;
874
880
  readonly expiresAt?: number | undefined;
875
881
  readonly inbox?: false | undefined;
882
+ readonly waitingOn?: {
883
+ readonly agentId: string;
884
+ readonly sessionId: string;
885
+ readonly name: string;
886
+ } | undefined;
876
887
  }[];
877
888
  readonly context?: {
878
889
  readonly tokens: number;