@fungi.computer/shiitake-extensions 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.
@@ -0,0 +1,16 @@
1
+ import type { ShiitakeAgent } from "@fungi.computer/shiitake";
2
+ import type * as z from "zod";
3
+ import { agentScheduleListInputSchema, type AgentScheduleRow, type AgentSchedulePage, type AgentScheduleTarget, type AgentScheduleControlReceipt } from "../schedules.js";
4
+ /**
5
+ * Read one already-admitted Agent, without scanning Sessions or draining pages.
6
+ * The caller owns Agent, home and resource authorization and the owner's lifetime.
7
+ */
8
+ export declare function readAgentSchedulePage(agentId: string, owner: Pick<ShiitakeAgent, "extensions">, input?: z.input<typeof agentScheduleListInputSchema>): Promise<AgentSchedulePage>;
9
+ /**
10
+ * Explicit content-returning control for callers admitted to both read and manage.
11
+ * In particular, private Local retains its native-row reply. The supplied owner
12
+ * must already be admitted for target.agentId; this helper grants no authority.
13
+ */
14
+ export declare function controlAgentScheduleWithContent(owner: Pick<ShiitakeAgent, "extensions">, input: AgentScheduleTarget, action: "pause" | "resume" | "delete"): Promise<AgentScheduleRow>;
15
+ /** Control an already-admitted owner; manage-only callers receive no read content. */
16
+ export declare function controlAgentSchedule(owner: Pick<ShiitakeAgent, "extensions">, target: AgentScheduleTarget, action: "pause" | "resume" | "delete"): Promise<AgentScheduleControlReceipt>;
@@ -0,0 +1,81 @@
1
+ import { bindAgentExtension } from "@fungi.computer/shiitake/client";
2
+ import { almanacContract } from "../almanac/contract.js";
3
+ import { loopContract } from "../loop/contract.js";
4
+ import { agentScheduleListInputSchema, agentScheduleTargetSchema, } from "../schedules.js";
5
+ /**
6
+ * Read one already-admitted Agent, without scanning Sessions or draining pages.
7
+ * The caller owns Agent, home and resource authorization and the owner's lifetime.
8
+ */
9
+ export async function readAgentSchedulePage(agentId, owner, input = {}) {
10
+ const { after, limit } = agentScheduleListInputSchema.parse(input);
11
+ if (after !== undefined && after.agentId !== agentId)
12
+ throw new Error("Schedule continuation belongs to another Agent");
13
+ const items = [];
14
+ if (after?.kind !== "loop") {
15
+ const nativeInput = after?.after === undefined ? { limit } : { limit, after: after.after };
16
+ const rows = await bindAgentExtension(owner, almanacContract).call("list", nativeInput);
17
+ for (const schedule of rows)
18
+ items.push({ agentId, kind: "almanac", schedule });
19
+ const last = rows.at(-1);
20
+ if (items.length === limit && last !== undefined)
21
+ return {
22
+ items,
23
+ next: { agentId, kind: "almanac", after: last.id },
24
+ };
25
+ }
26
+ const remaining = limit - items.length;
27
+ const cursor = after?.kind === "loop" ? after.after : undefined;
28
+ const nativeInput = cursor === undefined
29
+ ? { limit: remaining }
30
+ : { limit: remaining, after: cursor };
31
+ const rows = await bindAgentExtension(owner, loopContract).call("list", nativeInput);
32
+ for (const schedule of rows)
33
+ items.push({ agentId, kind: "loop", schedule });
34
+ const last = rows.at(-1);
35
+ return {
36
+ items,
37
+ next: items.length === limit && last !== undefined
38
+ ? { agentId, kind: "loop", after: last.sessionId }
39
+ : null,
40
+ };
41
+ }
42
+ /**
43
+ * Explicit content-returning control for callers admitted to both read and manage.
44
+ * In particular, private Local retains its native-row reply. The supplied owner
45
+ * must already be admitted for target.agentId; this helper grants no authority.
46
+ */
47
+ export async function controlAgentScheduleWithContent(owner, input, action) {
48
+ const target = agentScheduleTargetSchema.parse(input);
49
+ if (target.kind === "almanac") {
50
+ const schedule = await bindAgentExtension(owner, almanacContract).call(action === "delete" ? "cancel" : action, { scheduleId: target.scheduleId });
51
+ return { agentId: target.agentId, kind: "almanac", schedule };
52
+ }
53
+ const loop = await bindAgentExtension(owner, loopContract).call(action === "pause"
54
+ ? "pauseLoop"
55
+ : action === "resume"
56
+ ? "resumeLoop"
57
+ : "stopLoop", { sessionId: target.sessionId, loopId: target.loopId });
58
+ return {
59
+ agentId: target.agentId,
60
+ kind: "loop",
61
+ schedule: { ...loop, sessionId: target.sessionId },
62
+ };
63
+ }
64
+ /** Control an already-admitted owner; manage-only callers receive no read content. */
65
+ export async function controlAgentSchedule(owner, target, action) {
66
+ const row = await controlAgentScheduleWithContent(owner, target, action);
67
+ return row.kind === "almanac"
68
+ ? {
69
+ agentId: row.agentId,
70
+ kind: "almanac",
71
+ scheduleId: row.schedule.id,
72
+ state: row.schedule.state,
73
+ }
74
+ : {
75
+ agentId: row.agentId,
76
+ kind: "loop",
77
+ sessionId: row.schedule.sessionId,
78
+ loopId: row.schedule.loopId,
79
+ state: row.schedule.state,
80
+ };
81
+ }
@@ -1,6 +1,5 @@
1
- import type { ShiitakeAgent } from "@fungi.computer/shiitake";
2
1
  import * as Schema from "effect/Schema";
3
- import { z } from "zod";
2
+ import * as z from "zod";
4
3
  /** Exclusive native key within one Agent's Almanac-then-Loop traversal. */
5
4
  export declare const agentScheduleCursorSchema: z.ZodObject<{
6
5
  agentId: z.ZodString;
@@ -163,16 +162,3 @@ export declare const agentScheduleControlReceiptSchema: Schema.Union<readonly [S
163
162
  }>]>;
164
163
  /** Content-free acknowledgement of the native owner's completed transition. */
165
164
  export type AgentScheduleControlReceipt = typeof agentScheduleControlReceiptSchema.Type;
166
- /**
167
- * Read one already-admitted Agent, without scanning Sessions or draining pages.
168
- * The caller owns Agent, home and resource authorization and the owner's lifetime.
169
- */
170
- export declare function readAgentSchedulePage(agentId: string, owner: Pick<ShiitakeAgent, "extensions">, input?: z.input<typeof agentScheduleListInputSchema>): Promise<AgentSchedulePage>;
171
- /**
172
- * Explicit content-returning control for callers admitted to both read and manage.
173
- * In particular, private Local retains its native-row reply. The supplied owner
174
- * must already be admitted for target.agentId; this helper grants no authority.
175
- */
176
- export declare function controlAgentScheduleWithContent(owner: Pick<ShiitakeAgent, "extensions">, input: AgentScheduleTarget, action: "pause" | "delete"): Promise<AgentScheduleRow>;
177
- /** Control an already-admitted owner; manage-only callers receive no read content. */
178
- export declare function controlAgentSchedule(owner: Pick<ShiitakeAgent, "extensions">, target: AgentScheduleTarget, action: "pause" | "delete"): Promise<AgentScheduleControlReceipt>;
package/dist/schedules.js CHANGED
@@ -1,8 +1,8 @@
1
- import { bindAgentExtension } from "@fungi.computer/shiitake/client";
2
1
  import * as Schema from "effect/Schema";
3
- import { z } from "zod";
4
- import { almanacContract, Schedule } from "./almanac/contract.js";
5
- import { Loop, loopContract } from "./loop/contract.js";
2
+ import * as z from "zod";
3
+ import { Schedule, ScheduleListInput } from "./almanac/schema.js";
4
+ import { Loop, LoopListInput } from "./loop/schema.js";
5
+ import { SessionId as LoopSessionId } from "./internal/schedule-fields.js";
6
6
  const identity = z.string().min(1).max(256);
7
7
  /** Exclusive native key within one Agent's Almanac-then-Loop traversal. */
8
8
  export const agentScheduleCursorSchema = z
@@ -14,9 +14,7 @@ export const agentScheduleCursorSchema = z
14
14
  /** Exclusive Almanac schedule ID or Loop Session ID; absent starts the kind. */
15
15
  after: identity.optional(),
16
16
  })
17
- .refine(({ kind, after }) => Schema.is(kind === "almanac"
18
- ? almanacContract.commands.list.input
19
- : loopContract.commands.list.input)(after === undefined ? {} : { after }), { message: "Invalid schedule continuation key" });
17
+ .refine(({ kind, after }) => Schema.is(kind === "almanac" ? ScheduleListInput : LoopListInput)(after === undefined ? {} : { after }), { message: "Invalid schedule continuation key" });
20
18
  /** One bounded read; a full native page conservatively carries continuation. */
21
19
  export const agentScheduleListInputSchema = z.strictObject({
22
20
  /** Native continuation from the previous page of this Agent's schedules. */
@@ -43,7 +41,7 @@ export const agentScheduleRowSchema = Schema.Union([
43
41
  schedule: Schema.Struct({
44
42
  ...Loop.fields,
45
43
  /** Session containing this exact Loop. */
46
- sessionId: loopContract.commands.pauseLoop.input.fields.sessionId,
44
+ sessionId: LoopSessionId,
47
45
  }),
48
46
  }),
49
47
  ]);
@@ -63,7 +61,7 @@ export const agentScheduleTargetSchema = z.discriminatedUnion("kind", [
63
61
  /** Agent whose owner the caller must admit before controlling this target. */
64
62
  agentId: identity,
65
63
  /** Session containing the listed Loop. */
66
- sessionId: identity.refine(Schema.is(loopContract.commands.pauseLoop.input.fields.sessionId)),
64
+ sessionId: identity.refine(Schema.is(LoopSessionId)),
67
65
  /** Exact listed Loop identity; a replacement must not be controlled instead. */
68
66
  loopId: identity.refine(Schema.is(Loop.fields.loopId)),
69
67
  }),
@@ -100,83 +98,10 @@ export const agentScheduleControlReceiptSchema = Schema.Union([
100
98
  /** Identifies the controlled native Loop. */
101
99
  kind: Schema.Literal("loop"),
102
100
  /** Session containing the controlled Loop. */
103
- sessionId: loopContract.commands.pauseLoop.input.fields.sessionId,
101
+ sessionId: LoopSessionId,
104
102
  /** Exact Loop identity checked by the native transition. */
105
103
  loopId: Loop.fields.loopId,
106
104
  /** Native lifecycle state returned after the transition. */
107
105
  state: Loop.fields.state,
108
106
  }),
109
107
  ]);
110
- /**
111
- * Read one already-admitted Agent, without scanning Sessions or draining pages.
112
- * The caller owns Agent, home and resource authorization and the owner's lifetime.
113
- */
114
- export async function readAgentSchedulePage(agentId, owner, input = {}) {
115
- const { after, limit } = agentScheduleListInputSchema.parse(input);
116
- if (after !== undefined && after.agentId !== agentId)
117
- throw new Error("Schedule continuation belongs to another Agent");
118
- const items = [];
119
- if (after?.kind !== "loop") {
120
- const nativeInput = after?.after === undefined ? { limit } : { limit, after: after.after };
121
- const rows = await bindAgentExtension(owner, almanacContract).call("list", nativeInput);
122
- for (const schedule of rows)
123
- items.push({ agentId, kind: "almanac", schedule });
124
- const last = rows.at(-1);
125
- if (items.length === limit && last !== undefined)
126
- return {
127
- items,
128
- next: { agentId, kind: "almanac", after: last.id },
129
- };
130
- }
131
- const remaining = limit - items.length;
132
- const cursor = after?.kind === "loop" ? after.after : undefined;
133
- const nativeInput = cursor === undefined
134
- ? { limit: remaining }
135
- : { limit: remaining, after: cursor };
136
- const rows = await bindAgentExtension(owner, loopContract).call("list", nativeInput);
137
- for (const schedule of rows)
138
- items.push({ agentId, kind: "loop", schedule });
139
- const last = rows.at(-1);
140
- return {
141
- items,
142
- next: items.length === limit && last !== undefined
143
- ? { agentId, kind: "loop", after: last.sessionId }
144
- : null,
145
- };
146
- }
147
- /**
148
- * Explicit content-returning control for callers admitted to both read and manage.
149
- * In particular, private Local retains its native-row reply. The supplied owner
150
- * must already be admitted for target.agentId; this helper grants no authority.
151
- */
152
- export async function controlAgentScheduleWithContent(owner, input, action) {
153
- const target = agentScheduleTargetSchema.parse(input);
154
- if (target.kind === "almanac") {
155
- const schedule = await bindAgentExtension(owner, almanacContract).call(action === "pause" ? "pause" : "cancel", { scheduleId: target.scheduleId });
156
- return { agentId: target.agentId, kind: "almanac", schedule };
157
- }
158
- const loop = await bindAgentExtension(owner, loopContract).call(action === "pause" ? "pauseLoop" : "stopLoop", { sessionId: target.sessionId, loopId: target.loopId });
159
- return {
160
- agentId: target.agentId,
161
- kind: "loop",
162
- schedule: { ...loop, sessionId: target.sessionId },
163
- };
164
- }
165
- /** Control an already-admitted owner; manage-only callers receive no read content. */
166
- export async function controlAgentSchedule(owner, target, action) {
167
- const row = await controlAgentScheduleWithContent(owner, target, action);
168
- return row.kind === "almanac"
169
- ? {
170
- agentId: row.agentId,
171
- kind: "almanac",
172
- scheduleId: row.schedule.id,
173
- state: row.schedule.state,
174
- }
175
- : {
176
- agentId: row.agentId,
177
- kind: "loop",
178
- sessionId: row.schedule.sessionId,
179
- loopId: row.schedule.loopId,
180
- state: row.schedule.state,
181
- };
182
- }
@@ -29,6 +29,7 @@
29
29
  | [roster](roster.md) | - |
30
30
  | [roster/conversation-agents](roster/conversation-agents.md) | - |
31
31
  | [schedules](schedules.md) | - |
32
+ | [schedules/client](schedules/client.md) | - |
32
33
  | [skills/host](skills/host.md) | - |
33
34
  | [skills/source](skills/source.md) | - |
34
35
  | [subagents/client](subagents/client.md) | - |
@@ -20,6 +20,52 @@ One durable schedule.
20
20
 
21
21
  ## Variables
22
22
 
23
+ ### almanacContract
24
+
25
+ ```ts
26
+ const almanacContract: object;
27
+ ```
28
+
29
+ Almanac's contract: agent-scope schedule CRUD, no Session projection.
30
+
31
+ #### Type Declaration
32
+
33
+ | Name | Type | Default value | Description |
34
+ | --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | ------------------------------------------------------------ |
35
+ | <a id="property-id"></a> `id` | `string` & `Brand`\<`"ExtensionId"`\> | - | Stable extension identity. |
36
+ | <a id="property-commands"></a> `commands` | `object` | - | Agent-scoped schedule operations. |
37
+ | `commands.createOneShot` | `object` | - | Create a schedule with one due occurrence. |
38
+ | `commands.createOneShot.scope` | `"agent"` | `"agent"` | The Agent owns the schedule collection. |
39
+ | `commands.createOneShot.input` | `Struct`\<\{ `requestId`: `String`; `sessionId`: `String`; `prompt`: `String`; `dueAt`: `Int`; \}\> | - | Decode the caller's one-shot schedule request. |
40
+ | `commands.createOneShot.output` | `Struct`\<\{ `id`: `String`; `sessionId`: `String`; `prompt`: `String`; `cron`: `NullOr`\<`Struct`\<\{ `expression`: `String`; `timeZone`: `String`; \}\>\>; `nextDueAt`: `Int`; `state`: `Literals`\<readonly \[`"active"`, `"paused"`, `"cancelled"`, `"finished"`\]\>; `lastCommandId`: `NullOr`\<`String`\>; `lastError`: `NullOr`\<`String`\>; `attempt`: `Int`; \}\> | `Schedule` | Return the created durable schedule. |
41
+ | `commands.createRecurring` | `object` | - | Create a recurring cron schedule. |
42
+ | `commands.createRecurring.scope` | `"agent"` | `"agent"` | The Agent owns the schedule collection. |
43
+ | `commands.createRecurring.input` | `Struct`\<\{ `requestId`: `String`; `sessionId`: `String`; `prompt`: `String`; `expression`: `String`; `timeZone`: `String`; \}\> | - | Decode the caller's recurring schedule request. |
44
+ | `commands.createRecurring.output` | `Struct`\<\{ `id`: `String`; `sessionId`: `String`; `prompt`: `String`; `cron`: `NullOr`\<`Struct`\<\{ `expression`: `String`; `timeZone`: `String`; \}\>\>; `nextDueAt`: `Int`; `state`: `Literals`\<readonly \[`"active"`, `"paused"`, `"cancelled"`, `"finished"`\]\>; `lastCommandId`: `NullOr`\<`String`\>; `lastError`: `NullOr`\<`String`\>; `attempt`: `Int`; \}\> | `Schedule` | Return the created durable schedule. |
45
+ | `commands.read` | `object` | - | Read one schedule, or null when absent. |
46
+ | `commands.read.scope` | `"agent"` | `"agent"` | Read from the Agent's schedule collection. |
47
+ | `commands.read.input` | `Struct`\<\{ `scheduleId`: `String`; \}\> | `ScheduleRef` | Identify the schedule to read. |
48
+ | `commands.read.output` | `NullOr`\<`Struct`\<\{ `id`: `String`; `sessionId`: `String`; `prompt`: `String`; `cron`: `NullOr`\<`Struct`\<\{ `expression`: `String`; `timeZone`: `String`; \}\>\>; `nextDueAt`: `Int`; `state`: `Literals`\<readonly \[`"active"`, `"paused"`, `"cancelled"`, `"finished"`\]\>; `lastCommandId`: `NullOr`\<`String`\>; `lastError`: `NullOr`\<`String`\>; `attempt`: `Int`; \}\>\> | - | Decode the schedule or its absence. |
49
+ | `commands.list` | `object` | - | Read a bounded page of schedules after an optional identity. |
50
+ | `commands.list.scope` | `"agent"` | `"agent"` | Read from the Agent's schedule collection. |
51
+ | `commands.list.input` | `Struct`\<\{ `after`: `optionalKey`\<`String`\>; `limit`: `optionalKey`\<`Int`\>; \}\> | `ScheduleListInput` | Decode pagination arguments. |
52
+ | `commands.list.output` | `$Array`\<`Struct`\<\{ `id`: `String`; `sessionId`: `String`; `prompt`: `String`; `cron`: `NullOr`\<`Struct`\<\{ `expression`: `String`; `timeZone`: `String`; \}\>\>; `nextDueAt`: `Int`; `state`: `Literals`\<readonly \[`"active"`, `"paused"`, `"cancelled"`, `"finished"`\]\>; `lastCommandId`: `NullOr`\<`String`\>; `lastError`: `NullOr`\<`String`\>; `attempt`: `Int`; \}\>\> | - | Decode the returned schedule rows. |
53
+ | `commands.pause` | `object` | - | Suspend future occurrences of a schedule. |
54
+ | `commands.pause.scope` | `"agent"` | `"agent"` | The Agent owns the schedule. |
55
+ | `commands.pause.input` | `Struct`\<\{ `scheduleId`: `String`; \}\> | `ScheduleRef` | Identify the schedule to pause. |
56
+ | `commands.pause.output` | `Struct`\<\{ `id`: `String`; `sessionId`: `String`; `prompt`: `String`; `cron`: `NullOr`\<`Struct`\<\{ `expression`: `String`; `timeZone`: `String`; \}\>\>; `nextDueAt`: `Int`; `state`: `Literals`\<readonly \[`"active"`, `"paused"`, `"cancelled"`, `"finished"`\]\>; `lastCommandId`: `NullOr`\<`String`\>; `lastError`: `NullOr`\<`String`\>; `attempt`: `Int`; \}\> | `Schedule` | Return its updated state. |
57
+ | `commands.resume` | `object` | - | Restore a paused schedule to active scheduling. |
58
+ | `commands.resume.scope` | `"agent"` | `"agent"` | The Agent owns the schedule. |
59
+ | `commands.resume.input` | `Struct`\<\{ `scheduleId`: `String`; \}\> | `ScheduleRef` | Identify the schedule to resume. |
60
+ | `commands.resume.output` | `Struct`\<\{ `id`: `String`; `sessionId`: `String`; `prompt`: `String`; `cron`: `NullOr`\<`Struct`\<\{ `expression`: `String`; `timeZone`: `String`; \}\>\>; `nextDueAt`: `Int`; `state`: `Literals`\<readonly \[`"active"`, `"paused"`, `"cancelled"`, `"finished"`\]\>; `lastCommandId`: `NullOr`\<`String`\>; `lastError`: `NullOr`\<`String`\>; `attempt`: `Int`; \}\> | `Schedule` | Return its updated state. |
61
+ | `commands.cancel` | `object` | - | Cancel future occurrences of a schedule. |
62
+ | `commands.cancel.scope` | `"agent"` | `"agent"` | The Agent owns the schedule. |
63
+ | `commands.cancel.input` | `Struct`\<\{ `scheduleId`: `String`; \}\> | `ScheduleRef` | Identify the schedule to cancel. |
64
+ | `commands.cancel.output` | `Struct`\<\{ `id`: `String`; `sessionId`: `String`; `prompt`: `String`; `cron`: `NullOr`\<`Struct`\<\{ `expression`: `String`; `timeZone`: `String`; \}\>\>; `nextDueAt`: `Int`; `state`: `Literals`\<readonly \[`"active"`, `"paused"`, `"cancelled"`, `"finished"`\]\>; `lastCommandId`: `NullOr`\<`String`\>; `lastError`: `NullOr`\<`String`\>; `attempt`: `Int`; \}\> | `Schedule` | Return its updated state. |
65
+ | <a id="property-projection"></a> `projection` | `null` | `null` | Almanac has no Session projection. |
66
+
67
+ ---
68
+
23
69
  ### Schedule
24
70
 
25
71
  ```ts
@@ -42,49 +88,3 @@ const Schedule: Struct<{
42
88
  ```
43
89
 
44
90
  One durable schedule as every caller sees it.
45
-
46
- ---
47
-
48
- ### almanacContract
49
-
50
- ```ts
51
- const almanacContract: object;
52
- ```
53
-
54
- Almanac's contract: agent-scope schedule CRUD, no Session projection.
55
-
56
- #### Type Declaration
57
-
58
- | Name | Type | Default value | Description |
59
- | --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | ------------------------------------------------------------ |
60
- | <a id="property-id"></a> `id` | `string` & `Brand`\<`"ExtensionId"`\> | - | Stable extension identity. |
61
- | <a id="property-commands"></a> `commands` | `object` | - | Agent-scoped schedule operations. |
62
- | `commands.createOneShot` | `object` | - | Create a schedule with one due occurrence. |
63
- | `commands.createOneShot.scope` | `"agent"` | `"agent"` | The Agent owns the schedule collection. |
64
- | `commands.createOneShot.input` | `Struct`\<\{ `requestId`: `String`; `sessionId`: `String`; `prompt`: `String`; `dueAt`: `Int`; \}\> | - | Decode the caller's one-shot schedule request. |
65
- | `commands.createOneShot.output` | `Struct`\<\{ `id`: `String`; `sessionId`: `String`; `prompt`: `String`; `cron`: `NullOr`\<`Struct`\<\{ `expression`: `String`; `timeZone`: `String`; \}\>\>; `nextDueAt`: `Int`; `state`: `Literals`\<readonly \[`"active"`, `"paused"`, `"cancelled"`, `"finished"`\]\>; `lastCommandId`: `NullOr`\<`String`\>; `lastError`: `NullOr`\<`String`\>; `attempt`: `Int`; \}\> | `Schedule` | Return the created durable schedule. |
66
- | `commands.createRecurring` | `object` | - | Create a recurring cron schedule. |
67
- | `commands.createRecurring.scope` | `"agent"` | `"agent"` | The Agent owns the schedule collection. |
68
- | `commands.createRecurring.input` | `Struct`\<\{ `requestId`: `String`; `sessionId`: `String`; `prompt`: `String`; `expression`: `String`; `timeZone`: `String`; \}\> | - | Decode the caller's recurring schedule request. |
69
- | `commands.createRecurring.output` | `Struct`\<\{ `id`: `String`; `sessionId`: `String`; `prompt`: `String`; `cron`: `NullOr`\<`Struct`\<\{ `expression`: `String`; `timeZone`: `String`; \}\>\>; `nextDueAt`: `Int`; `state`: `Literals`\<readonly \[`"active"`, `"paused"`, `"cancelled"`, `"finished"`\]\>; `lastCommandId`: `NullOr`\<`String`\>; `lastError`: `NullOr`\<`String`\>; `attempt`: `Int`; \}\> | `Schedule` | Return the created durable schedule. |
70
- | `commands.read` | `object` | - | Read one schedule, or null when absent. |
71
- | `commands.read.scope` | `"agent"` | `"agent"` | Read from the Agent's schedule collection. |
72
- | `commands.read.input` | `Struct`\<\{ `scheduleId`: `String`; \}\> | `ScheduleRef` | Identify the schedule to read. |
73
- | `commands.read.output` | `NullOr`\<`Struct`\<\{ `id`: `String`; `sessionId`: `String`; `prompt`: `String`; `cron`: `NullOr`\<`Struct`\<\{ `expression`: `String`; `timeZone`: `String`; \}\>\>; `nextDueAt`: `Int`; `state`: `Literals`\<readonly \[`"active"`, `"paused"`, `"cancelled"`, `"finished"`\]\>; `lastCommandId`: `NullOr`\<`String`\>; `lastError`: `NullOr`\<`String`\>; `attempt`: `Int`; \}\>\> | - | Decode the schedule or its absence. |
74
- | `commands.list` | `object` | - | Read a bounded page of schedules after an optional identity. |
75
- | `commands.list.scope` | `"agent"` | `"agent"` | Read from the Agent's schedule collection. |
76
- | `commands.list.input` | `Struct`\<\{ `after`: `optionalKey`\<`String`\>; `limit`: `optionalKey`\<`Int`\>; \}\> | - | Decode pagination arguments. |
77
- | `commands.list.output` | `$Array`\<`Struct`\<\{ `id`: `String`; `sessionId`: `String`; `prompt`: `String`; `cron`: `NullOr`\<`Struct`\<\{ `expression`: `String`; `timeZone`: `String`; \}\>\>; `nextDueAt`: `Int`; `state`: `Literals`\<readonly \[`"active"`, `"paused"`, `"cancelled"`, `"finished"`\]\>; `lastCommandId`: `NullOr`\<`String`\>; `lastError`: `NullOr`\<`String`\>; `attempt`: `Int`; \}\>\> | - | Decode the returned schedule rows. |
78
- | `commands.pause` | `object` | - | Suspend future occurrences of a schedule. |
79
- | `commands.pause.scope` | `"agent"` | `"agent"` | The Agent owns the schedule. |
80
- | `commands.pause.input` | `Struct`\<\{ `scheduleId`: `String`; \}\> | `ScheduleRef` | Identify the schedule to pause. |
81
- | `commands.pause.output` | `Struct`\<\{ `id`: `String`; `sessionId`: `String`; `prompt`: `String`; `cron`: `NullOr`\<`Struct`\<\{ `expression`: `String`; `timeZone`: `String`; \}\>\>; `nextDueAt`: `Int`; `state`: `Literals`\<readonly \[`"active"`, `"paused"`, `"cancelled"`, `"finished"`\]\>; `lastCommandId`: `NullOr`\<`String`\>; `lastError`: `NullOr`\<`String`\>; `attempt`: `Int`; \}\> | `Schedule` | Return its updated state. |
82
- | `commands.resume` | `object` | - | Restore a paused schedule to active scheduling. |
83
- | `commands.resume.scope` | `"agent"` | `"agent"` | The Agent owns the schedule. |
84
- | `commands.resume.input` | `Struct`\<\{ `scheduleId`: `String`; \}\> | `ScheduleRef` | Identify the schedule to resume. |
85
- | `commands.resume.output` | `Struct`\<\{ `id`: `String`; `sessionId`: `String`; `prompt`: `String`; `cron`: `NullOr`\<`Struct`\<\{ `expression`: `String`; `timeZone`: `String`; \}\>\>; `nextDueAt`: `Int`; `state`: `Literals`\<readonly \[`"active"`, `"paused"`, `"cancelled"`, `"finished"`\]\>; `lastCommandId`: `NullOr`\<`String`\>; `lastError`: `NullOr`\<`String`\>; `attempt`: `Int`; \}\> | `Schedule` | Return its updated state. |
86
- | `commands.cancel` | `object` | - | Cancel future occurrences of a schedule. |
87
- | `commands.cancel.scope` | `"agent"` | `"agent"` | The Agent owns the schedule. |
88
- | `commands.cancel.input` | `Struct`\<\{ `scheduleId`: `String`; \}\> | `ScheduleRef` | Identify the schedule to cancel. |
89
- | `commands.cancel.output` | `Struct`\<\{ `id`: `String`; `sessionId`: `String`; `prompt`: `String`; `cron`: `NullOr`\<`Struct`\<\{ `expression`: `String`; `timeZone`: `String`; \}\>\>; `nextDueAt`: `Int`; `state`: `Literals`\<readonly \[`"active"`, `"paused"`, `"cancelled"`, `"finished"`\]\>; `lastCommandId`: `NullOr`\<`String`\>; `lastError`: `NullOr`\<`String`\>; `attempt`: `Int`; \}\> | `Schedule` | Return its updated state. |
90
- | <a id="property-projection"></a> `projection` | `null` | `null` | Almanac has no Session projection. |
@@ -20,49 +20,6 @@ One Session's loop.
20
20
 
21
21
  ## Variables
22
22
 
23
- ### LoopCron
24
-
25
- ```ts
26
- const LoopCron: Struct<{
27
- expression: String;
28
- timeZone: String;
29
- }>;
30
- ```
31
-
32
- A named cron cadence evaluated in one IANA time zone.
33
-
34
- ---
35
-
36
- ### Loop
37
-
38
- ```ts
39
- const Loop: Struct<{
40
- loopId: String;
41
- origin: Literals<readonly ["human", "model"]>;
42
- expiresAt: NullOr<Int>;
43
- prompt: String;
44
- mode: Literals<readonly ["self_paced", "fixed_interval"]>;
45
- cron: NullOr<
46
- Struct<{
47
- expression: String;
48
- timeZone: String;
49
- }>
50
- >;
51
- state: Literals<
52
- readonly ["active", "paused", "finished", "failed", "cancelled"]
53
- >;
54
- commandId: String;
55
- reason: NullOr<String>;
56
- nextDueAt: NullOr<Int>;
57
- lastError: NullOr<String>;
58
- consecutiveFailures: Int;
59
- }>;
60
- ```
61
-
62
- One Session's loop as every client sees it.
63
-
64
- ---
65
-
66
23
  ### LoopCommandInput
67
24
 
68
25
  ```ts
@@ -138,12 +95,16 @@ Session-owned current-Loop controls and Agent-scoped identified-Loop controls.
138
95
  | <a id="property-commands"></a> `commands` | `object` | - | Loop operations admitted by their Agent or Session owner. |
139
96
  | `commands.list` | `object` | - | Read an Agent's bounded Loop page, including each destination Session. |
140
97
  | `commands.list.scope` | `"agent"` | `"agent"` | The Agent owns the collection of its Sessions' Loops. |
141
- | `commands.list.input` | `Struct`\<\{ `after`: `optionalKey`\<`String`\>; `limit`: `optionalKey`\<`Int`\>; \}\> | - | Page strictly after a Session identity, in identity order. |
142
- | `commands.list.output` | `$Array`\<`Struct`\<\{ `loopId`: `String`; `origin`: `Literals`\<readonly \[`"human"`, `"model"`\]\>; `expiresAt`: `NullOr`\<`Int`\>; `prompt`: `String`; `mode`: `Literals`\<readonly \[`"self_paced"`, `"fixed_interval"`\]\>; `cron`: `NullOr`\<`Struct`\<\{ `expression`: `String`; `timeZone`: `String`; \}\>\>; `state`: `Literals`\<readonly \[`"active"`, `"paused"`, `"finished"`, `"failed"`, `"cancelled"`\]\>; `commandId`: `String`; `reason`: `NullOr`\<`String`\>; `nextDueAt`: `NullOr`\<`Int`\>; `lastError`: `NullOr`\<`String`\>; `consecutiveFailures`: `Int`; `sessionId`: `String`; \}\>\> | - | Public Loop values with Session targets, never private scheduling state. |
98
+ | `commands.list.input` | `Struct`\<\{ `after`: `optionalKey`\<`String`\>; `limit`: `optionalKey`\<`Int`\>; \}\> | `LoopListInput` | Page strictly after a Session identity, in identity order. |
99
+ | `commands.list.output` | `$Array`\<`Struct`\<\{ `sessionId`: `String`; `loopId`: `String`; `origin`: `Literals`\<readonly \[`"human"`, `"model"`\]\>; `expiresAt`: `NullOr`\<`Int`\>; `prompt`: `String`; `mode`: `Literals`\<readonly \[`"self_paced"`, `"fixed_interval"`\]\>; `cron`: `NullOr`\<`Struct`\<\{ `expression`: `String`; `timeZone`: `String`; \}\>\>; `state`: `Literals`\<readonly \[`"active"`, `"paused"`, `"finished"`, `"failed"`, `"cancelled"`\]\>; `commandId`: `String`; `reason`: `NullOr`\<`String`\>; `nextDueAt`: `NullOr`\<`Int`\>; `lastError`: `NullOr`\<`String`\>; `consecutiveFailures`: `Int`; \}\>\> | - | Public Loop values with Session targets, never private scheduling state. |
143
100
  | `commands.pauseLoop` | `object` | - | Pause an identified Loop; refuse a stale target after replacement. |
144
101
  | `commands.pauseLoop.scope` | `"agent"` | `"agent"` | The Agent owns the identified Loop and its Session. |
145
102
  | `commands.pauseLoop.input` | `Struct`\<\{ `sessionId`: `String`; `loopId`: `String`; \}\> | `LoopTarget` | The listed Session and Loop identities must both still match. |
146
103
  | `commands.pauseLoop.output` | `Struct`\<\{ `loopId`: `String`; `origin`: `Literals`\<readonly \[`"human"`, `"model"`\]\>; `expiresAt`: `NullOr`\<`Int`\>; `prompt`: `String`; `mode`: `Literals`\<readonly \[`"self_paced"`, `"fixed_interval"`\]\>; `cron`: `NullOr`\<`Struct`\<\{ `expression`: `String`; `timeZone`: `String`; \}\>\>; `state`: `Literals`\<readonly \[`"active"`, `"paused"`, `"finished"`, `"failed"`, `"cancelled"`\]\>; `commandId`: `String`; `reason`: `NullOr`\<`String`\>; `nextDueAt`: `NullOr`\<`Int`\>; `lastError`: `NullOr`\<`String`\>; `consecutiveFailures`: `Int`; \}\> | `Loop` | Return the paused Loop without cancelling accepted work. |
104
+ | `commands.resumeLoop` | `object` | - | Resume an identified Loop; refuse a stale target after replacement. |
105
+ | `commands.resumeLoop.scope` | `"agent"` | `"agent"` | The Agent owns the identified Loop and its Session. |
106
+ | `commands.resumeLoop.input` | `Struct`\<\{ `sessionId`: `String`; `loopId`: `String`; \}\> | `LoopTarget` | The listed Session and Loop identities must both still match. |
107
+ | `commands.resumeLoop.output` | `Struct`\<\{ `loopId`: `String`; `origin`: `Literals`\<readonly \[`"human"`, `"model"`\]\>; `expiresAt`: `NullOr`\<`Int`\>; `prompt`: `String`; `mode`: `Literals`\<readonly \[`"self_paced"`, `"fixed_interval"`\]\>; `cron`: `NullOr`\<`Struct`\<\{ `expression`: `String`; `timeZone`: `String`; \}\>\>; `state`: `Literals`\<readonly \[`"active"`, `"paused"`, `"finished"`, `"failed"`, `"cancelled"`\]\>; `commandId`: `String`; `reason`: `NullOr`\<`String`\>; `nextDueAt`: `NullOr`\<`Int`\>; `lastError`: `NullOr`\<`String`\>; `consecutiveFailures`: `Int`; \}\> | `Loop` | Return the resumed Loop without changing accepted work. |
147
108
  | `commands.stopLoop` | `object` | - | Cancel an identified Loop's future occurrences, retaining accepted work. |
148
109
  | `commands.stopLoop.scope` | `"agent"` | `"agent"` | The Agent owns the identified Loop and its Session. |
149
110
  | `commands.stopLoop.input` | `Struct`\<\{ `sessionId`: `String`; `loopId`: `String`; \}\> | `LoopTarget` | The listed Session and Loop identities must both still match. |
@@ -158,7 +119,7 @@ Session-owned current-Loop controls and Agent-scoped identified-Loop controls.
158
119
  | `commands.startSelfPaced.output` | `Struct`\<\{ `loop`: `Struct`\<\{ `loopId`: `String`; `origin`: `Literals`\<readonly \[`"human"`, `"model"`\]\>; `expiresAt`: `NullOr`\<`Int`\>; `prompt`: `String`; `mode`: `Literals`\<readonly \[`"self_paced"`, `"fixed_interval"`\]\>; `cron`: `NullOr`\<`Struct`\<\{ `expression`: `String`; `timeZone`: `String`; \}\>\>; `state`: `Literals`\<readonly \[`"active"`, `"paused"`, `"finished"`, `"failed"`, `"cancelled"`\]\>; `commandId`: `String`; `reason`: `NullOr`\<`String`\>; `nextDueAt`: `NullOr`\<`Int`\>; `lastError`: `NullOr`\<`String`\>; `consecutiveFailures`: `Int`; \}\>; `accepted`: `Struct`\<\{ `status`: `Literal`\<`"accepted"`\>; `commandId`: `String`; \}\>; \}\> | `StartResult` | Return the loop and admission receipt. |
159
120
  | `commands.startFixedInterval` | `object` | - | Start a loop with a fixed cron cadence. |
160
121
  | `commands.startFixedInterval.scope` | `"session"` | `"session"` | The Session owns this loop. |
161
- | `commands.startFixedInterval.input` | `Struct`\<\{ `expression`: `String`; `timeZone`: `String`; `prompt`: `String`; `requestId`: `String`; \}\> | - | Decode the prompt, cadence and command identity. |
122
+ | `commands.startFixedInterval.input` | `Struct`\<\{ `prompt`: `String`; `requestId`: `String`; `expression`: `String`; `timeZone`: `String`; \}\> | - | Decode the prompt, cadence and command identity. |
162
123
  | `commands.startFixedInterval.output` | `Struct`\<\{ `loop`: `Struct`\<\{ `loopId`: `String`; `origin`: `Literals`\<readonly \[`"human"`, `"model"`\]\>; `expiresAt`: `NullOr`\<`Int`\>; `prompt`: `String`; `mode`: `Literals`\<readonly \[`"self_paced"`, `"fixed_interval"`\]\>; `cron`: `NullOr`\<`Struct`\<\{ `expression`: `String`; `timeZone`: `String`; \}\>\>; `state`: `Literals`\<readonly \[`"active"`, `"paused"`, `"finished"`, `"failed"`, `"cancelled"`\]\>; `commandId`: `String`; `reason`: `NullOr`\<`String`\>; `nextDueAt`: `NullOr`\<`Int`\>; `lastError`: `NullOr`\<`String`\>; `consecutiveFailures`: `Int`; \}\>; `accepted`: `Struct`\<\{ `status`: `Literal`\<`"accepted"`\>; `commandId`: `String`; \}\>; \}\> | `StartResult` | Return the loop and admission receipt. |
163
124
  | `commands.pause` | `object` | - | Suspend the current loop. |
164
125
  | `commands.pause.scope` | `"session"` | `"session"` | The Session owns this loop. |
@@ -174,3 +135,46 @@ Session-owned current-Loop controls and Agent-scoped identified-Loop controls.
174
135
  | `commands.stop.output` | `Struct`\<\{ `loopId`: `String`; `origin`: `Literals`\<readonly \[`"human"`, `"model"`\]\>; `expiresAt`: `NullOr`\<`Int`\>; `prompt`: `String`; `mode`: `Literals`\<readonly \[`"self_paced"`, `"fixed_interval"`\]\>; `cron`: `NullOr`\<`Struct`\<\{ `expression`: `String`; `timeZone`: `String`; \}\>\>; `state`: `Literals`\<readonly \[`"active"`, `"paused"`, `"finished"`, `"failed"`, `"cancelled"`\]\>; `commandId`: `String`; `reason`: `NullOr`\<`String`\>; `nextDueAt`: `NullOr`\<`Int`\>; `lastError`: `NullOr`\<`String`\>; `consecutiveFailures`: `Int`; \}\> | `Loop` | Return the stopped loop. |
175
136
  | <a id="property-projection"></a> `projection` | `object` | - | Current loop visible to Session clients. |
176
137
  | `projection.schema` | `Struct`\<\{ `loop`: `Struct`\<\{ `loopId`: `String`; `origin`: `Literals`\<readonly \[`"human"`, `"model"`\]\>; `expiresAt`: `NullOr`\<`Int`\>; `prompt`: `String`; `mode`: `Literals`\<readonly \[`"self_paced"`, `"fixed_interval"`\]\>; `cron`: `NullOr`\<`Struct`\<\{ `expression`: `String`; `timeZone`: `String`; \}\>\>; `state`: `Literals`\<readonly \[`"active"`, `"paused"`, `"finished"`, `"failed"`, `"cancelled"`\]\>; `commandId`: `String`; `reason`: `NullOr`\<`String`\>; `nextDueAt`: `NullOr`\<`Int`\>; `lastError`: `NullOr`\<`String`\>; `consecutiveFailures`: `Int`; \}\>; \}\> | `LoopProjection` | Decoder for projected loop state. |
138
+
139
+ ---
140
+
141
+ ### LoopCron
142
+
143
+ ```ts
144
+ const LoopCron: Struct<{
145
+ expression: String;
146
+ timeZone: String;
147
+ }>;
148
+ ```
149
+
150
+ A named cron cadence evaluated in one IANA time zone.
151
+
152
+ ---
153
+
154
+ ### Loop
155
+
156
+ ```ts
157
+ const Loop: Struct<{
158
+ loopId: String;
159
+ origin: Literals<readonly ["human", "model"]>;
160
+ expiresAt: NullOr<Int>;
161
+ prompt: String;
162
+ mode: Literals<readonly ["self_paced", "fixed_interval"]>;
163
+ cron: NullOr<
164
+ Struct<{
165
+ expression: String;
166
+ timeZone: String;
167
+ }>
168
+ >;
169
+ state: Literals<
170
+ readonly ["active", "paused", "finished", "failed", "cancelled"]
171
+ >;
172
+ commandId: String;
173
+ reason: NullOr<String>;
174
+ nextDueAt: NullOr<Int>;
175
+ lastError: NullOr<String>;
176
+ consecutiveFailures: Int;
177
+ }>;
178
+ ```
179
+
180
+ One Session's loop as every client sees it.
@@ -49,6 +49,28 @@ owners.
49
49
 
50
50
  ---
51
51
 
52
+ ### adoptDelegatedGoal()
53
+
54
+ ```ts
55
+ function adoptDelegatedGoal(session, input): Promise<void>;
56
+ ```
57
+
58
+ Adopt the first accepted turn once, even when the sender was offline at
59
+ delivery.
60
+
61
+ #### Parameters
62
+
63
+ | Parameter | Type |
64
+ | --------- | -------------------------------------------------------------------------------------------------------- |
65
+ | `session` | `Pick`\<`ShiitakeSession`, `"extension"`\> |
66
+ | `input` | `Readonly`\<\{ `text`: `string`; `goal`: `string` \| `false` \| `undefined`; `commandId`: `string`; \}\> |
67
+
68
+ #### Returns
69
+
70
+ `Promise`\<`void`\>
71
+
72
+ ---
73
+
52
74
  ### createConversationAgents()
53
75
 
54
76
  ```ts