@fungi.computer/shiitake-extensions 0.0.2 → 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.
Files changed (66) hide show
  1. package/README.md +43 -13
  2. package/dist/almanac/contract.d.ts +94 -0
  3. package/dist/almanac/contract.js +71 -5
  4. package/dist/goal/client.d.ts +5 -2
  5. package/dist/goal/client.js +66 -72
  6. package/dist/goal/contract.d.ts +181 -64
  7. package/dist/goal/contract.js +102 -12
  8. package/dist/goal/host.js +188 -113
  9. package/dist/home/contract.d.ts +18 -0
  10. package/dist/home/contract.js +24 -3
  11. package/dist/home/host.d.ts +3 -0
  12. package/dist/home/host.js +1 -2
  13. package/dist/home/routing.js +13 -24
  14. package/dist/internal/history.d.ts +16 -0
  15. package/dist/internal/history.js +8 -0
  16. package/dist/loop/client.d.ts +1 -1
  17. package/dist/loop/client.js +28 -34
  18. package/dist/loop/contract.d.ts +113 -84
  19. package/dist/loop/contract.js +77 -9
  20. package/dist/loop/host.d.ts +1 -0
  21. package/dist/loop/host.js +17 -30
  22. package/dist/plan/client.d.ts +1 -1
  23. package/dist/plan/contract.d.ts +33 -0
  24. package/dist/plan/contract.js +28 -3
  25. package/dist/plan/host.js +12 -7
  26. package/dist/question/client.d.ts +1 -1
  27. package/dist/question/contract.d.ts +158 -0
  28. package/dist/question/contract.js +92 -7
  29. package/dist/question/host.js +34 -20
  30. package/dist/roster/conversation-agents.d.ts +31 -0
  31. package/dist/roster/conversation-agents.js +114 -0
  32. package/dist/roster.js +1 -0
  33. package/dist/skills/host.d.ts +1 -0
  34. package/dist/skills/host.js +22 -17
  35. package/dist/skills/source.d.ts +34 -0
  36. package/dist/subagents/client.d.ts +1 -1
  37. package/dist/subagents/client.js +43 -12
  38. package/dist/subagents/contract.d.ts +46 -8
  39. package/dist/subagents/contract.js +38 -8
  40. package/dist/subagents/host.d.ts +20 -8
  41. package/dist/subagents/host.js +58 -12
  42. package/docs/api/README.md +35 -0
  43. package/docs/api/almanac/contract.md +90 -0
  44. package/docs/api/almanac/host.md +19 -0
  45. package/docs/api/goal/client.md +26 -0
  46. package/docs/api/goal/contract.md +247 -0
  47. package/docs/api/goal/host.md +29 -0
  48. package/docs/api/home/contract.md +58 -0
  49. package/docs/api/home/host.md +55 -0
  50. package/docs/api/loop/client.md +25 -0
  51. package/docs/api/loop/contract.md +159 -0
  52. package/docs/api/loop/host.md +30 -0
  53. package/docs/api/plan/client.md +26 -0
  54. package/docs/api/plan/contract.md +163 -0
  55. package/docs/api/plan/host.md +19 -0
  56. package/docs/api/question/client.md +25 -0
  57. package/docs/api/question/contract.md +377 -0
  58. package/docs/api/question/host.md +19 -0
  59. package/docs/api/roster/conversation-agents.md +80 -0
  60. package/docs/api/roster.md +40 -0
  61. package/docs/api/skills/host.md +39 -0
  62. package/docs/api/skills/source.md +104 -0
  63. package/docs/api/subagents/client.md +26 -0
  64. package/docs/api/subagents/contract.md +131 -0
  65. package/docs/api/subagents/host.md +115 -0
  66. package/package.json +14 -8
@@ -1,10 +1,11 @@
1
- import { ExtensionId } from "@fungi.computer/shiitake/extensions";
1
+ import { ExtensionId, } from "@fungi.computer/shiitake/extensions";
2
2
  import * as Schema from "effect/Schema";
3
+ import { CatalogStep } from "../internal/catalog.js";
3
4
  const identity = Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(256));
4
5
  /** The most Agents one conversation's footer lists; the rest are counted. */
5
6
  export const maximumSubagents = 16;
6
7
  /**
7
- * What the human sees for one sub-agent. `waiting` is any open attention on
8
+ * What the human sees for one ordinary created Agent. `waiting` is any open attention on
8
9
  * its conversation (a question or a tool approval); `unavailable` means its
9
10
  * status could not be read, and is never shown as idle.
10
11
  */
@@ -15,24 +16,53 @@ export const SubagentState = Schema.Literals([
15
16
  "failed",
16
17
  "unavailable",
17
18
  ]);
18
- /** One Agent this conversation sent work to or created. */
19
+ /** A footer row for an ordinary Agent created by this Agent, never merely sent work. */
19
20
  export const Subagent = Schema.Struct({
21
+ /** Identity of the created Agent. */
20
22
  agentId: identity,
23
+ /** Display name of the created Agent. */
21
24
  name: identity,
22
- /** The conversation this one last addressed; null when never messaged. */
25
+ /** Its latest conversation; null when it has none. */
23
26
  sessionId: Schema.NullOr(identity),
27
+ /** Observed conversation state, including unreadable status. */
24
28
  state: SubagentState,
25
29
  /** The child's own summary of what waits on the human, when waiting. */
26
30
  attention: Schema.optionalKey(Schema.String.check(Schema.isMaxLength(200))),
27
31
  });
28
- /** This conversation's sub-agents, newest first, and how many are not listed. */
32
+ /**
33
+ * This Agent's created Agents and how many are not listed.
34
+ * `expanded` is whether the footer lists each one; a person toggles it with
35
+ * `/agents`, and a collapsed footer keeps one summary row.
36
+ */
29
37
  export const SubagentsProjection = Schema.Struct({
38
+ /** Created Agents currently listed in the footer. */
30
39
  agents: Schema.Array(Subagent).check(Schema.isMaxLength(maximumSubagents)),
40
+ /** Additional created Agents not included in the visible rows. */
31
41
  more: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),
42
+ /** Whether individual rows are expanded instead of summarized. */
43
+ expanded: Schema.Boolean,
32
44
  });
33
- /** A read-only view: no commands, one projection slot. */
45
+ /** The human `/agents` command: a bare call expands or collapses the footer rows. */
46
+ const commands = {
47
+ /** Toggle the created-Agent footer between expanded and summarized views. */
48
+ agents: {
49
+ /** The Session owns its footer view. */
50
+ scope: "session",
51
+ /** No additional arguments are required. */
52
+ input: Schema.Struct({}),
53
+ /** Return the server-owned human control step. */
54
+ output: CatalogStep,
55
+ },
56
+ };
57
+ /** Created-Agent footer control and its visible projection. */
34
58
  export const subagentsContract = {
59
+ /** Stable extension identity. */
35
60
  id: ExtensionId.make("botanical-session-subagents"),
36
- commands: {},
37
- projection: { schema: SubagentsProjection },
61
+ /** Human footer controls. */
62
+ commands,
63
+ /** Footer rows and expansion state. */
64
+ projection: {
65
+ /** Decoder for the projected footer. */
66
+ schema: SubagentsProjection,
67
+ },
38
68
  };
@@ -1,30 +1,40 @@
1
1
  import type { ShiitakeAgent, ShiitakeSession } from "@fungi.computer/shiitake";
2
2
  import { type ExtensionGrantV0, type RosteredExtensionV0 } from "@fungi.computer/shiitake/extensions";
3
- /** One Agent the host recorded this Session sending work to or creating. */
3
+ /** A footer row for an ordinary Agent created by the current Agent. */
4
4
  export type SubagentRecord = Readonly<{
5
+ /** Identity of the ordinary created Agent. */
5
6
  agentId: string;
7
+ /** Display name supplied by the host. */
6
8
  name: string;
7
- /** The conversation it last addressed; null when it was only created. */
9
+ /** A host-selected conversation; null asks the view to read its latest one. */
8
10
  sessionId: string | null;
9
11
  }>;
10
12
  /** The two owner reads a status needs from one child Agent. */
11
13
  export type SubagentAgent = Readonly<{
14
+ /** Read the child's owner-ordered conversation summaries. */
12
15
  listSessions: ShiitakeAgent["listSessions"];
16
+ /** Open the read-only view of a selected child conversation. */
13
17
  session: (sessionId: string) => Pick<ShiitakeSession, "read">;
14
18
  }>;
15
19
  /**
16
- * The host's read-only facts. `read` returns this Session's sub-agents,
17
- * newest first and at most `limit`, with a count of the rest; `open` is the
20
+ * The host's read-only facts. `read` returns ordinary created Agents,
21
+ * at most `limit`, with a count of the rest; `open` is the
18
22
  * host's existing per-operation Agent access (an `AgentControlDirectory`'s
19
23
  * `open` fits), and releasing it never stops the Agent's work.
20
24
  */
21
25
  export type SubagentSource = Readonly<{
26
+ /** Read a bounded list of this conversation's created Agents. */
22
27
  read: (sessionId: string, limit: number) => Promise<Readonly<{
28
+ /** Created Agents included in this page. */
23
29
  agents: readonly SubagentRecord[];
30
+ /** Additional created Agents not included in this page. */
24
31
  more: number;
25
32
  }>>;
33
+ /** Acquire existing owner access for one child Agent. */
26
34
  open: (agentId: string, signal: AbortSignal) => Promise<Readonly<{
35
+ /** Read-only Agent access held by this acquisition. */
27
36
  agent: SubagentAgent;
37
+ /** Release this acquisition without stopping the Agent's work. */
28
38
  release: () => Promise<void>;
29
39
  }>>;
30
40
  }>;
@@ -37,12 +47,14 @@ export type SubagentTiming = Readonly<{
37
47
  /** Polling stops once no watcher has read the Session this long. */
38
48
  interestMs: number;
39
49
  }>;
50
+ /** Host admission for the read-only created-Agent footer and human toggle. */
40
51
  export declare const subagentsGrant: ExtensionGrantV0;
41
52
  /**
42
- * The read-only sub-agent view: the Agents this conversation sent work to or
43
- * created, one row each, with their live status. It owns no relationship,
44
- * no durable state and no command; the collaboration App remains the only
45
- * relationship owner.
53
+ * The read-only footer: ordinary Agents created by this Agent, one row each,
54
+ * with their live status. It owns neither relationships nor durable state;
55
+ * the Agent directory owns immutable creation attribution.
56
+ * Its one command, `/agents`, only expands or collapses
57
+ * the footer rows.
46
58
  */
47
59
  export declare function subagentsExtension(options: Readonly<{
48
60
  source: SubagentSource;
@@ -1,6 +1,7 @@
1
1
  import { defineExtension, } from "@fungi.computer/shiitake/extensions";
2
2
  import * as Effect from "effect/Effect";
3
3
  import * as Option from "effect/Option";
4
+ import { catalog, done } from "../internal/catalog.js";
4
5
  import { maximumSubagents, subagentsContract, } from "./contract.js";
5
6
  const defaultTiming = Object.freeze({
6
7
  refreshMs: 1_000,
@@ -11,9 +12,10 @@ const defaultTiming = Object.freeze({
11
12
  const cachedSessions = 64;
12
13
  /** Owner pages scanned for one child's row: 400 conversations. */
13
14
  const statusPages = 2;
15
+ /** Host admission for the read-only created-Agent footer and human toggle. */
14
16
  export const subagentsGrant = {
15
17
  id: subagentsContract.id,
16
- capabilities: ["projection"],
18
+ capabilities: ["projection", "commands"],
17
19
  };
18
20
  const settledState = {
19
21
  running: "working",
@@ -46,20 +48,23 @@ async function status(source, record, signal) {
46
48
  try {
47
49
  const opened = await source.open(record.agentId, signal);
48
50
  try {
49
- if (record.sessionId === null)
51
+ const row = record.sessionId === null
52
+ ? (await opened.agent.listSessions()).sessions[0]
53
+ : await findSession(opened.agent, record.sessionId);
54
+ if (row === undefined && record.sessionId === null)
50
55
  return { ...base, state: "idle" };
51
- const row = await findSession(opened.agent, record.sessionId);
52
56
  if (row === undefined || row.state === "unavailable")
53
57
  return { ...base, state: "unavailable" };
58
+ const selected = { ...base, sessionId: row.sessionId };
54
59
  if (row.state !== "needs_you")
55
- return { ...base, state: settledState[row.state] };
60
+ return { ...selected, state: settledState[row.state] };
56
61
  const snapshot = await opened.agent
57
- .session(record.sessionId)
62
+ .session(row.sessionId)
58
63
  .read({ limit: 1 });
59
64
  const attention = snapshot.attention[0]?.summary;
60
65
  return attention === undefined
61
- ? { ...base, state: "waiting" }
62
- : { ...base, state: "waiting", attention };
66
+ ? { ...selected, state: "waiting" }
67
+ : { ...selected, state: "waiting", attention };
63
68
  }
64
69
  finally {
65
70
  await opened.release();
@@ -117,12 +122,21 @@ function createRoster(source, timing, publish) {
117
122
  }, timing.pollMs);
118
123
  }
119
124
  return {
125
+ /** Flip whether the footer lists the rows; undefined while there is nothing to list. */
126
+ toggle(sessionId) {
127
+ const entry = entries.get(sessionId);
128
+ if (entry?.value === undefined || entry.value.agents.length === 0)
129
+ return undefined;
130
+ entry.expanded = !entry.expanded;
131
+ return entry.expanded;
132
+ },
120
133
  read(sessionId) {
121
134
  const now = Date.now();
122
135
  let entry = entries.get(sessionId);
123
136
  if (entry === undefined) {
124
137
  entry = {
125
138
  value: undefined,
139
+ expanded: false,
126
140
  refreshedAt: Number.NEGATIVE_INFINITY,
127
141
  readAt: now,
128
142
  refreshing: false,
@@ -138,7 +152,9 @@ function createRoster(source, timing, publish) {
138
152
  entry.readAt = now;
139
153
  if (!entry.refreshing && now - entry.refreshedAt >= timing.refreshMs)
140
154
  void refresh(sessionId, entry);
141
- return entry.value;
155
+ return entry.value === undefined
156
+ ? undefined
157
+ : { ...entry.value, expanded: entry.expanded };
142
158
  },
143
159
  close() {
144
160
  lifetime.abort();
@@ -148,10 +164,11 @@ function createRoster(source, timing, publish) {
148
164
  };
149
165
  }
150
166
  /**
151
- * The read-only sub-agent view: the Agents this conversation sent work to or
152
- * created, one row each, with their live status. It owns no relationship,
153
- * no durable state and no command; the collaboration App remains the only
154
- * relationship owner.
167
+ * The read-only footer: ordinary Agents created by this Agent, one row each,
168
+ * with their live status. It owns neither relationships nor durable state;
169
+ * the Agent directory owns immutable creation attribution.
170
+ * Its one command, `/agents`, only expands or collapses
171
+ * the footer rows.
155
172
  */
156
173
  export function subagentsExtension(options) {
157
174
  const rosters = new WeakMap();
@@ -168,9 +185,38 @@ export function subagentsExtension(options) {
168
185
  rosters.delete(ctx);
169
186
  })).pipe(Effect.asVoid),
170
187
  },
188
+ catalog: catalog([
189
+ {
190
+ id: "agents",
191
+ title: "Agents",
192
+ category: "Conversation",
193
+ description: "Show or hide this conversation's sub-agents",
194
+ projections: {
195
+ help: { order: 6 },
196
+ palette: { order: 6 },
197
+ slash: { aliases: ["agents"], order: 6 },
198
+ },
199
+ },
200
+ ]),
171
201
  projection: {
172
202
  schema: subagentsContract.projection.schema,
173
203
  read: (ctx, sessionId) => Option.fromUndefinedOr(rosters.get(ctx)?.read(sessionId)),
174
204
  },
205
+ commands: {
206
+ specs: subagentsContract.commands,
207
+ handlers: (ctx) => ({
208
+ agents: ({ sessionId }) => Effect.gen(function* () {
209
+ const expanded = rosters.get(ctx)?.toggle(sessionId);
210
+ if (expanded === undefined)
211
+ return done({
212
+ type: "info",
213
+ message: "This conversation has no sub-agents.",
214
+ });
215
+ yield* ctx.observe(sessionId);
216
+ // The changed rows already show the result; don't echo the toggle.
217
+ return { type: "done" };
218
+ }),
219
+ }),
220
+ },
175
221
  });
176
222
  }
@@ -0,0 +1,35 @@
1
+ <!-- Generated by Botanical API docs (TypeDoc + typedoc-plugin-markdown). Do not edit. -->
2
+
3
+ **@fungi.computer/shiitake-extensions**
4
+
5
+ ---
6
+
7
+ # @fungi.computer/shiitake-extensions
8
+
9
+ ## Modules
10
+
11
+ | Module | Description |
12
+ | ----------------------------------------------------------- | ----------- |
13
+ | [almanac/contract](almanac/contract.md) | - |
14
+ | [almanac/host](almanac/host.md) | - |
15
+ | [goal/client](goal/client.md) | - |
16
+ | [goal/contract](goal/contract.md) | - |
17
+ | [goal/host](goal/host.md) | - |
18
+ | [home/contract](home/contract.md) | - |
19
+ | [home/host](home/host.md) | - |
20
+ | [loop/client](loop/client.md) | - |
21
+ | [loop/contract](loop/contract.md) | - |
22
+ | [loop/host](loop/host.md) | - |
23
+ | [plan/client](plan/client.md) | - |
24
+ | [plan/contract](plan/contract.md) | - |
25
+ | [plan/host](plan/host.md) | - |
26
+ | [question/client](question/client.md) | - |
27
+ | [question/contract](question/contract.md) | - |
28
+ | [question/host](question/host.md) | - |
29
+ | [roster](roster.md) | - |
30
+ | [roster/conversation-agents](roster/conversation-agents.md) | - |
31
+ | [skills/host](skills/host.md) | - |
32
+ | [skills/source](skills/source.md) | - |
33
+ | [subagents/client](subagents/client.md) | - |
34
+ | [subagents/contract](subagents/contract.md) | - |
35
+ | [subagents/host](subagents/host.md) | - |
@@ -0,0 +1,90 @@
1
+ <!-- Generated by Botanical API docs (TypeDoc + typedoc-plugin-markdown). Do not edit. -->
2
+
3
+ [**@fungi.computer/shiitake-extensions**](../README.md)
4
+
5
+ ---
6
+
7
+ [@fungi.computer/shiitake-extensions](../README.md) / almanac/contract
8
+
9
+ # almanac/contract
10
+
11
+ ## Type Aliases
12
+
13
+ ### Schedule
14
+
15
+ ```ts
16
+ type Schedule = Schema.Schema.Type<typeof Schedule>;
17
+ ```
18
+
19
+ One durable schedule.
20
+
21
+ ## Variables
22
+
23
+ ### Schedule
24
+
25
+ ```ts
26
+ const Schedule: Struct<{
27
+ id: String;
28
+ sessionId: String;
29
+ prompt: String;
30
+ cron: NullOr<
31
+ Struct<{
32
+ expression: String;
33
+ timeZone: String;
34
+ }>
35
+ >;
36
+ nextDueAt: Int;
37
+ state: Literals<readonly ["active", "paused", "cancelled", "finished"]>;
38
+ lastCommandId: NullOr<String>;
39
+ lastError: NullOr<String>;
40
+ attempt: Int;
41
+ }>;
42
+ ```
43
+
44
+ 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. |
@@ -0,0 +1,19 @@
1
+ <!-- Generated by Botanical API docs (TypeDoc + typedoc-plugin-markdown). Do not edit. -->
2
+
3
+ [**@fungi.computer/shiitake-extensions**](../README.md)
4
+
5
+ ---
6
+
7
+ [@fungi.computer/shiitake-extensions](../README.md) / almanac/host
8
+
9
+ # almanac/host
10
+
11
+ ## Variables
12
+
13
+ ### almanacExtension
14
+
15
+ ```ts
16
+ const almanacExtension: RosteredExtensionV0;
17
+ ```
18
+
19
+ Botanical's Almanac on Shiitake timers and the one admission door.
@@ -0,0 +1,26 @@
1
+ <!-- Generated by Botanical API docs (TypeDoc + typedoc-plugin-markdown). Do not edit. -->
2
+
3
+ [**@fungi.computer/shiitake-extensions**](../README.md)
4
+
5
+ ---
6
+
7
+ [@fungi.computer/shiitake-extensions](../README.md) / goal/client
8
+
9
+ # goal/client
10
+
11
+ ## Variables
12
+
13
+ ### default
14
+
15
+ ```ts
16
+ default: Readonly<{
17
+ protocol: "shiitake.client/v1";
18
+ id: string & Brand<"ExtensionId">;
19
+ promptPresentation?: "footer";
20
+ attach?: (context) => Effect<void, Error, Scope>;
21
+ contribute?: (slot) => object;
22
+ }>;
23
+ ```
24
+
25
+ Product copy and controls belong to Goal; every host renders plain rows. The
26
+ footer shows only a live or paused goal; finished goals are chat lines.