@fungi.computer/shiitake-extensions 0.3.0 → 0.5.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 (39) hide show
  1. package/README.md +20 -16
  2. package/dist/goal/contract.d.ts +6 -0
  3. package/dist/goal/contract.js +6 -0
  4. package/dist/goal/host.js +183 -31
  5. package/dist/loop/contract.d.ts +136 -2
  6. package/dist/loop/contract.js +45 -2
  7. package/dist/loop/host.js +23 -0
  8. package/dist/question/answer-flow.d.ts +27 -0
  9. package/dist/question/answer-flow.js +115 -0
  10. package/dist/question/client.d.ts +1 -1
  11. package/dist/question/client.js +22 -3
  12. package/dist/question/contract.d.ts +202 -60
  13. package/dist/question/contract.js +78 -22
  14. package/dist/question/host.d.ts +4 -0
  15. package/dist/question/host.js +348 -339
  16. package/dist/roster/conversation-agents.d.ts +21 -1
  17. package/dist/roster/conversation-agents.js +47 -2
  18. package/dist/roster.d.ts +5 -2
  19. package/dist/roster.js +16 -5
  20. package/dist/schedules.d.ts +178 -0
  21. package/dist/schedules.js +182 -0
  22. package/dist/subagents/client.js +64 -20
  23. package/dist/subagents/contract.d.ts +123 -10
  24. package/dist/subagents/contract.js +38 -5
  25. package/dist/subagents/host.d.ts +2 -4
  26. package/dist/subagents/host.js +152 -22
  27. package/docs/api/README.md +1 -0
  28. package/docs/api/goal/contract.md +1 -1
  29. package/docs/api/goal/host.md +22 -1
  30. package/docs/api/loop/contract.md +43 -31
  31. package/docs/api/question/client.md +2 -1
  32. package/docs/api/question/contract.md +183 -51
  33. package/docs/api/question/host.md +30 -0
  34. package/docs/api/roster/conversation-agents.md +34 -8
  35. package/docs/api/roster.md +39 -2
  36. package/docs/api/schedules.md +481 -0
  37. package/docs/api/subagents/contract.md +101 -28
  38. package/docs/api/subagents/host.md +5 -3
  39. package/package.json +9 -6
@@ -128,37 +128,49 @@ Loop's contract: Session-scope controls and one projection slot.
128
128
  const loopContract: object;
129
129
  ```
130
130
 
131
- Session-owned loop controls and their visible state.
131
+ Session-owned current-Loop controls and Agent-scoped identified-Loop controls.
132
132
 
133
133
  #### Type Declaration
134
134
 
135
- | Name | Type | Default value | Description |
136
- | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ---------------------------------------------------------- |
137
- | <a id="property-id"></a> `id` | `string` & `Brand`\<`"ExtensionId"`\> | - | Stable extension identity. |
138
- | <a id="property-commands"></a> `commands` | `object` | - | Loop operations admitted by the Session owner. |
139
- | `commands.loop` | `object` | - | Open or answer the human loop controls. |
140
- | `commands.loop.scope` | `"session"` | `"session"` | The Session owns this loop. |
141
- | `commands.loop.input` | `Union`\<readonly \[`Struct`\<\{ `action`: `Literal`\<`"start"`\>; `text`: `String`; `requestId`: `String`; \}\>, `Struct`\<\{ `action`: `Literals`\<readonly \[`"status"`, `"pause"`, `"resume"`, `"stop"`, `"stop-ask"`, `"new"`\]\>; `confirmed`: `optional`\<`Boolean`\>; \}\>, `Struct`\<\{ \}\>\]\> | `LoopCommandInput` | Decode the selected human action. |
142
- | `commands.loop.output` | `declare`\<`WhistleCatalogStepV1`, `WhistleCatalogStepV1`\> | `CatalogStep` | Return the server-owned conversation step. |
143
- | `commands.startSelfPaced` | `object` | - | Start a loop whose next occurrence is chosen by the model. |
144
- | `commands.startSelfPaced.scope` | `"session"` | `"session"` | The Session owns this loop. |
145
- | `commands.startSelfPaced.input` | `Struct`\<\{ `prompt`: `String`; `requestId`: `String`; \}\> | - | Decode the repeated prompt and command identity. |
146
- | `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. |
147
- | `commands.startFixedInterval` | `object` | - | Start a loop with a fixed cron cadence. |
148
- | `commands.startFixedInterval.scope` | `"session"` | `"session"` | The Session owns this loop. |
149
- | `commands.startFixedInterval.input` | `Struct`\<\{ `expression`: `String`; `timeZone`: `String`; `prompt`: `String`; `requestId`: `String`; \}\> | - | Decode the prompt, cadence and command identity. |
150
- | `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. |
151
- | `commands.pause` | `object` | - | Suspend the current loop. |
152
- | `commands.pause.scope` | `"session"` | `"session"` | The Session owns this loop. |
153
- | `commands.pause.input` | `Struct`\<\{ \}\> | - | No additional arguments are required. |
154
- | `commands.pause.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. |
155
- | `commands.resume` | `object` | - | Resume the current paused loop. |
156
- | `commands.resume.scope` | `"session"` | `"session"` | The Session owns this loop. |
157
- | `commands.resume.input` | `Struct`\<\{ \}\> | - | No additional arguments are required. |
158
- | `commands.resume.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. |
159
- | `commands.stop` | `object` | - | Stop future occurrences of the current loop. |
160
- | `commands.stop.scope` | `"session"` | `"session"` | The Session owns this loop. |
161
- | `commands.stop.input` | `Struct`\<\{ \}\> | - | No additional arguments are required. |
162
- | `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. |
163
- | <a id="property-projection"></a> `projection` | `object` | - | Current loop visible to Session clients. |
164
- | `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. |
135
+ | Name | Type | Default value | Description |
136
+ | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ------------------------------------------------------------------------ |
137
+ | <a id="property-id"></a> `id` | `string` & `Brand`\<`"ExtensionId"`\> | - | Stable extension identity. |
138
+ | <a id="property-commands"></a> `commands` | `object` | - | Loop operations admitted by their Agent or Session owner. |
139
+ | `commands.list` | `object` | - | Read an Agent's bounded Loop page, including each destination Session. |
140
+ | `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. |
143
+ | `commands.pauseLoop` | `object` | - | Pause an identified Loop; refuse a stale target after replacement. |
144
+ | `commands.pauseLoop.scope` | `"agent"` | `"agent"` | The Agent owns the identified Loop and its Session. |
145
+ | `commands.pauseLoop.input` | `Struct`\<\{ `sessionId`: `String`; `loopId`: `String`; \}\> | `LoopTarget` | The listed Session and Loop identities must both still match. |
146
+ | `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. |
147
+ | `commands.stopLoop` | `object` | - | Cancel an identified Loop's future occurrences, retaining accepted work. |
148
+ | `commands.stopLoop.scope` | `"agent"` | `"agent"` | The Agent owns the identified Loop and its Session. |
149
+ | `commands.stopLoop.input` | `Struct`\<\{ `sessionId`: `String`; `loopId`: `String`; \}\> | `LoopTarget` | The listed Session and Loop identities must both still match. |
150
+ | `commands.stopLoop.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 cancelled Loop; its Session and history remain. |
151
+ | `commands.loop` | `object` | - | Open or answer the human loop controls. |
152
+ | `commands.loop.scope` | `"session"` | `"session"` | The Session owns this loop. |
153
+ | `commands.loop.input` | `Union`\<readonly \[`Struct`\<\{ `action`: `Literal`\<`"start"`\>; `text`: `String`; `requestId`: `String`; \}\>, `Struct`\<\{ `action`: `Literals`\<readonly \[`"status"`, `"pause"`, `"resume"`, `"stop"`, `"stop-ask"`, `"new"`\]\>; `confirmed`: `optional`\<`Boolean`\>; \}\>, `Struct`\<\{ \}\>\]\> | `LoopCommandInput` | Decode the selected human action. |
154
+ | `commands.loop.output` | `declare`\<`WhistleCatalogStepV1`, `WhistleCatalogStepV1`\> | `CatalogStep` | Return the server-owned conversation step. |
155
+ | `commands.startSelfPaced` | `object` | - | Start a loop whose next occurrence is chosen by the model. |
156
+ | `commands.startSelfPaced.scope` | `"session"` | `"session"` | The Session owns this loop. |
157
+ | `commands.startSelfPaced.input` | `Struct`\<\{ `prompt`: `String`; `requestId`: `String`; \}\> | - | Decode the repeated prompt and command identity. |
158
+ | `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
+ | `commands.startFixedInterval` | `object` | - | Start a loop with a fixed cron cadence. |
160
+ | `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. |
162
+ | `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
+ | `commands.pause` | `object` | - | Suspend the current loop. |
164
+ | `commands.pause.scope` | `"session"` | `"session"` | The Session owns this loop. |
165
+ | `commands.pause.input` | `Struct`\<\{ \}\> | - | No additional arguments are required. |
166
+ | `commands.pause.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. |
167
+ | `commands.resume` | `object` | - | Resume the current paused loop. |
168
+ | `commands.resume.scope` | `"session"` | `"session"` | The Session owns this loop. |
169
+ | `commands.resume.input` | `Struct`\<\{ \}\> | - | No additional arguments are required. |
170
+ | `commands.resume.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. |
171
+ | `commands.stop` | `object` | - | Stop future occurrences of the current loop. |
172
+ | `commands.stop.scope` | `"session"` | `"session"` | The Session owns this loop. |
173
+ | `commands.stop.input` | `Struct`\<\{ \}\> | - | No additional arguments are required. |
174
+ | `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
+ | <a id="property-projection"></a> `projection` | `object` | - | Current loop visible to Session clients. |
176
+ | `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. |
@@ -22,4 +22,5 @@ default: Readonly<{
22
22
  }>;
23
23
  ```
24
24
 
25
- Pending decisions use the existing footer rows and advertised answer flow.
25
+ Pending decisions take over the composer; the footer row is where a postponed
26
+ one waits.
@@ -68,6 +68,26 @@ type HumanResult = Schema.Schema.Type<typeof HumanResult>;
68
68
 
69
69
  Decoded outcome of a human answer or decline.
70
70
 
71
+ ---
72
+
73
+ ### AgentAnswerResult
74
+
75
+ ```ts
76
+ type AgentAnswerResult = Schema.Schema.Type<typeof AgentAnswerResult>;
77
+ ```
78
+
79
+ Decoded result of an authenticated Agent answer.
80
+
81
+ ---
82
+
83
+ ### EscalateResult
84
+
85
+ ```ts
86
+ type EscalateResult = Schema.Schema.Type<typeof EscalateResult>;
87
+ ```
88
+
89
+ Decoded result of passing an Ask on.
90
+
71
91
  ## Variables
72
92
 
73
93
  ### Question
@@ -119,6 +139,13 @@ Bounded question set with distinct question identities.
119
139
  ```ts
120
140
  const OpenAsk: Struct<{
121
141
  askId: String;
142
+ waitingOn: optionalKey<
143
+ Struct<{
144
+ agentId: NonEmptyString;
145
+ sessionId: NonEmptyString;
146
+ name: NonEmptyString;
147
+ }>
148
+ >;
122
149
  questions: $Array<
123
150
  Struct<{
124
151
  id: String;
@@ -149,6 +176,11 @@ The complete question data shared by ordinary Session clients.
149
176
  const AskProjection: Struct<{
150
177
  asks: $Array<Struct<{
151
178
  askId: String;
179
+ waitingOn: optionalKey<Struct<{
180
+ agentId: NonEmptyString;
181
+ sessionId: NonEmptyString;
182
+ name: NonEmptyString;
183
+ }>>;
152
184
  questions: $Array<Struct<{
153
185
  id: String;
154
186
  header: String;
@@ -257,6 +289,7 @@ const HumanResult: Union<
257
289
  Struct<{
258
290
  result: Literal<"accepted">;
259
291
  via: Literals<readonly ["in_turn", "follow_up"]>;
292
+ commandId: optionalKey<String>;
260
293
  }>,
261
294
  Struct<{
262
295
  result: Literal<"closed">;
@@ -282,39 +315,128 @@ Admission, already-closed state, or absence returned to a human reply.
282
315
 
283
316
  ---
284
317
 
285
- ### AnswerFlowInput
318
+ ### SenderRefusal
286
319
 
287
320
  ```ts
288
- const AnswerFlowInput: Union<
321
+ const SenderRefusal: Struct<{
322
+ result: Literal<"refused">;
323
+ reason: Literal<"not_sender">;
324
+ }>;
325
+ ```
326
+
327
+ Only the Agent an Ask waits on may answer or escalate it.
328
+
329
+ ---
330
+
331
+ ### AgentAnswerResult
332
+
333
+ ```ts
334
+ const AgentAnswerResult: Union<
289
335
  readonly [
290
- Struct<{
291
- askId: String;
292
- requestId: String;
293
- index: Number;
294
- answers: $Record<
295
- String,
336
+ Union<
337
+ readonly [
296
338
  Struct<{
297
- selected: $Array<String>;
298
- text: optionalKey<String>;
299
- }>
300
- >;
301
- stage: Literal<"multiple">;
302
- selection: String;
339
+ result: Literal<"accepted">;
340
+ via: Literals<readonly ["in_turn", "follow_up"]>;
341
+ commandId: optionalKey<String>;
342
+ }>,
343
+ Struct<{
344
+ result: Literal<"closed">;
345
+ status: Literals<
346
+ readonly [
347
+ "answered",
348
+ "declined",
349
+ "withdrawn",
350
+ "expired",
351
+ "cancelled",
352
+ "undeliverable",
353
+ ]
354
+ >;
355
+ }>,
356
+ Struct<{
357
+ result: Literal<"not_found">;
358
+ }>,
359
+ ]
360
+ >,
361
+ Struct<{
362
+ result: Literal<"refused">;
363
+ reason: Literal<"not_sender">;
303
364
  }>,
365
+ ]
366
+ >;
367
+ ```
368
+
369
+ Outcome of the Agent an Ask waits on answering it.
370
+
371
+ ---
372
+
373
+ ### AnsweredBy
374
+
375
+ ```ts
376
+ const AnsweredBy: Struct<{
377
+ kind: Literal<"agent">;
378
+ agentId: String;
379
+ }>;
380
+ ```
381
+
382
+ The Agent that answered, as the host authenticated it.
383
+
384
+ ---
385
+
386
+ ### EscalateResult
387
+
388
+ ```ts
389
+ const EscalateResult: Union<
390
+ readonly [
304
391
  Struct<{
305
- askId: String;
306
- requestId: String;
307
- index: Number;
308
- answers: $Record<
309
- String,
310
- Struct<{
311
- selected: $Array<String>;
312
- text: optionalKey<String>;
313
- }>
392
+ result: Literal<"escalated">;
393
+ to: Literal<"person">;
394
+ }>,
395
+ Struct<{
396
+ result: Literal<"closed">;
397
+ status: Literals<
398
+ readonly [
399
+ "answered",
400
+ "declined",
401
+ "withdrawn",
402
+ "expired",
403
+ "cancelled",
404
+ "undeliverable",
405
+ ]
314
406
  >;
315
- stage: Literal<"selection">;
316
- selection: String;
317
407
  }>,
408
+ Struct<{
409
+ result: Literal<"not_found">;
410
+ }>,
411
+ Struct<{
412
+ result: Literal<"refused">;
413
+ reason: Literal<"not_sender">;
414
+ }>,
415
+ ]
416
+ >;
417
+ ```
418
+
419
+ Outcome of the Agent an Ask waits on passing it on.
420
+
421
+ ---
422
+
423
+ ### EscalateInput
424
+
425
+ ```ts
426
+ const EscalateInput: Struct<{
427
+ askId: String;
428
+ }>;
429
+ ```
430
+
431
+ The Agent's request to pass an Ask on; the caller is host context.
432
+
433
+ ---
434
+
435
+ ### AnswerFlowInput
436
+
437
+ ```ts
438
+ const AnswerFlowInput: Union<
439
+ readonly [
318
440
  Struct<{
319
441
  askId: String;
320
442
  requestId: String;
@@ -326,9 +448,11 @@ const AnswerFlowInput: Union<
326
448
  text: optionalKey<String>;
327
449
  }>
328
450
  >;
329
- stage: Literal<"text">;
330
- selected: $Array<String>;
331
- text: String;
451
+ stage: Literal<"decision">;
452
+ answer: Struct<{
453
+ selected: $Array<String>;
454
+ text: optionalKey<String>;
455
+ }>;
332
456
  }>,
333
457
  Struct<{
334
458
  askId: String;
@@ -338,7 +462,7 @@ const AnswerFlowInput: Union<
338
462
  >;
339
463
  ```
340
464
 
341
- The ordinary /answer conversation carries its draft between typed steps.
465
+ The answer conversation carries its draft between decision steps.
342
466
 
343
467
  ---
344
468
 
@@ -353,25 +477,33 @@ host.
353
477
 
354
478
  #### Type Declaration
355
479
 
356
- | Name | Type | Default value | Description |
357
- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------- | ------------------------------------------------------ |
358
- | <a id="property-id"></a> `id` | `string` & `Brand`\<`"ExtensionId"`\> | - | Stable extension identity. |
359
- | <a id="property-commands"></a> `commands` | `object` | - | Human question controls admitted by the Session owner. |
360
- | `commands.answerFlow` | `object` | - | Advance the server-owned answer conversation. |
361
- | `commands.answerFlow.scope` | `"session"` | `"session"` | The Session owns its asks and replies. |
362
- | `commands.answerFlow.input` | `Union`\<readonly \[`Struct`\<\{ `askId`: `String`; `requestId`: `String`; `index`: `Number`; `answers`: `$Record`\<`String`, `Struct`\<\{ `selected`: `$Array`\<...\>; `text`: `optionalKey`\<...\>; \}\>\>; `stage`: `Literal`\<`"multiple"`\>; `selection`: `String`; \}\>, `Struct`\<\{ `askId`: `String`; `requestId`: `String`; `index`: `Number`; `answers`: `$Record`\<`String`, `Struct`\<\{ `selected`: `$Array`\<...\>; `text`: `optionalKey`\<...\>; \}\>\>; `stage`: `Literal`\<`"selection"`\>; `selection`: `String`; \}\>, `Struct`\<\{ `askId`: `String`; `requestId`: `String`; `index`: `Number`; `answers`: `$Record`\<`String`, `Struct`\<\{ `selected`: `$Array`\<...\>; `text`: `optionalKey`\<...\>; \}\>\>; `stage`: `Literal`\<`"text"`\>; `selected`: `$Array`\<`String`\>; `text`: `String`; \}\>, `Struct`\<\{ `askId`: `String`; \}\>, `Struct`\<\{ \}\>\]\> | `AnswerFlowInput` | Decode the current answer-draft step. |
363
- | `commands.answerFlow.output` | `declare`\<`WhistleCatalogStepV1`, `WhistleCatalogStepV1`\> | `CatalogStep` | Return the next human conversation step. |
364
- | `commands.answer` | `object` | - | Submit a person's completed answers. |
365
- | `commands.answer.scope` | `"session"` | `"session"` | The Session owns this ask. |
366
- | `commands.answer.input` | `Struct`\<\{ `askId`: `String`; `requestId`: `String`; `answers`: `$Record`\<`String`, `Struct`\<\{ `selected`: `$Array`\<`String`\>; `text`: `optionalKey`\<`String`\>; \}\>\>; \}\> | `AnswerInput` | Decode the answer submission. |
367
- | `commands.answer.output` | `Union`\<readonly \[`Struct`\<\{ `result`: `Literal`\<`"accepted"`\>; `via`: `Literals`\<readonly \[`"in_turn"`, `"follow_up"`\]\>; \}\>, `Struct`\<\{ `result`: `Literal`\<`"closed"`\>; `status`: `Literals`\<readonly \[`"answered"`, `"declined"`, `"withdrawn"`, `"expired"`, `"cancelled"`, `"undeliverable"`\]\>; \}\>, `Struct`\<\{ `result`: `Literal`\<`"not_found"`\>; \}\>\]\> | `HumanResult` | Return admission or the ask's terminal state. |
368
- | `commands.decline` | `object` | - | Decline an ask with an optional note. |
369
- | `commands.decline.scope` | `"session"` | `"session"` | The Session owns this ask. |
370
- | `commands.decline.input` | `Struct`\<\{ `askId`: `String`; `requestId`: `String`; `note`: `optionalKey`\<`String`\>; \}\> | `DeclineInput` | Decode the decline submission. |
371
- | `commands.decline.output` | `Union`\<readonly \[`Struct`\<\{ `result`: `Literal`\<`"accepted"`\>; `via`: `Literals`\<readonly \[`"in_turn"`, `"follow_up"`\]\>; \}\>, `Struct`\<\{ `result`: `Literal`\<`"closed"`\>; `status`: `Literals`\<readonly \[`"answered"`, `"declined"`, `"withdrawn"`, `"expired"`, `"cancelled"`, `"undeliverable"`\]\>; \}\>, `Struct`\<\{ `result`: `Literal`\<`"not_found"`\>; \}\>\]\> | `HumanResult` | Return admission or the ask's terminal state. |
372
- | `commands.list` | `object` | - | Read the Session's open asks. |
373
- | `commands.list.scope` | `"session"` | `"session"` | The Session owns the ask collection. |
374
- | `commands.list.input` | `Struct`\<\{ \}\> | - | No additional arguments are required. |
375
- | `commands.list.output` | `Struct`\<\{ `asks`: `$Array`\<`Struct`\<\{ `askId`: `String`; `questions`: `$Array`\<`Struct`\<\{ `id`: ...; `header`: ...; `question`: ...; `options`: ...; `multiple`: ...; \}\>\>; `status`: `Literals`\<readonly \[`"live"`, `"parked"`\]\>; `createdAt`: `Number`; `expiresAt`: `NullOr`\<`Number`\>; \}\>\>; \}\> | `AskProjection` | Decode the currently visible asks. |
376
- | <a id="property-projection"></a> `projection` | `object` | - | Open asks visible to Session clients. |
377
- | `projection.schema` | `Struct`\<\{ `asks`: `$Array`\<`Struct`\<\{ `askId`: `String`; `questions`: `$Array`\<`Struct`\<\{ `id`: `String`; `header`: `String`; `question`: `String`; `options`: `$Array`\<...\>; `multiple`: `optionalKey`\<...\>; \}\>\>; `status`: `Literals`\<readonly \[`"live"`, `"parked"`\]\>; `createdAt`: `Number`; `expiresAt`: `NullOr`\<`Number`\>; \}\>\>; \}\> | `AskProjection` | Decoder for projected asks. |
480
+ | Name | Type | Default value | Description |
481
+ | --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | ----------------------------------------------------------------------- |
482
+ | <a id="property-id"></a> `id` | `string` & `Brand`\<`"ExtensionId"`\> | - | Stable extension identity. |
483
+ | <a id="property-commands"></a> `commands` | `object` | - | Human question controls admitted by the Session owner. |
484
+ | `commands.answerFlow` | `object` | - | Advance the server-owned answer conversation. |
485
+ | `commands.answerFlow.scope` | `"session"` | `"session"` | The Session owns its asks and replies. |
486
+ | `commands.answerFlow.input` | `Union`\<readonly \[`Struct`\<\{ `askId`: `String`; `requestId`: `String`; `index`: `Number`; `answers`: `$Record`\<`String`, `Struct`\<\{ `selected`: `$Array`\<...\>; `text`: `optionalKey`\<...\>; \}\>\>; `stage`: `Literal`\<`"decision"`\>; `answer`: `Struct`\<\{ `selected`: `$Array`\<`String`\>; `text`: `optionalKey`\<`String`\>; \}\>; \}\>, `Struct`\<\{ `askId`: `String`; \}\>, `Struct`\<\{ \}\>\]\> | `AnswerFlowInput` | Decode the current answer-draft step. |
487
+ | `commands.answerFlow.output` | `declare`\<`WhistleCatalogStepV1`, `WhistleCatalogStepV1`\> | `CatalogStep` | Return the next human conversation step. |
488
+ | `commands.answer` | `object` | - | Submit a person's completed answers. |
489
+ | `commands.answer.scope` | `"session"` | `"session"` | The Session owns this ask. |
490
+ | `commands.answer.input` | `Struct`\<\{ `askId`: `String`; `requestId`: `String`; `answers`: `$Record`\<`String`, `Struct`\<\{ `selected`: `$Array`\<`String`\>; `text`: `optionalKey`\<`String`\>; \}\>\>; \}\> | `AnswerInput` | Decode the answer submission. |
491
+ | `commands.answer.output` | `Union`\<readonly \[`Struct`\<\{ `result`: `Literal`\<`"accepted"`\>; `via`: `Literals`\<readonly \[`"in_turn"`, `"follow_up"`\]\>; `commandId`: `optionalKey`\<`String`\>; \}\>, `Struct`\<\{ `result`: `Literal`\<`"closed"`\>; `status`: `Literals`\<readonly \[`"answered"`, `"declined"`, `"withdrawn"`, `"expired"`, `"cancelled"`, `"undeliverable"`\]\>; \}\>, `Struct`\<\{ `result`: `Literal`\<`"not_found"`\>; \}\>\]\> | `HumanResult` | Return admission or the ask's terminal state. |
492
+ | `commands.answerAgent` | `object` | - | Submit the answer of the Agent this Ask waits on; never a human answer. |
493
+ | `commands.answerAgent.scope` | `"session"` | `"session"` | The child Session owns the Ask; caller authority is host context. |
494
+ | `commands.answerAgent.input` | `Struct`\<\{ `askId`: `String`; `requestId`: `String`; `answers`: `$Record`\<`String`, `Struct`\<\{ `selected`: `$Array`\<`String`\>; `text`: `optionalKey`\<`String`\>; \}\>\>; \}\> | `AnswerInput` | Decode the answer submission without any caller-supplied actor. |
495
+ | `commands.answerAgent.output` | `Struct`\<\{ `result`: `Union`\<readonly \[`Union`\<readonly \[`Struct`\<\{ `result`: ...; `via`: ...; `commandId`: ...; \}\>, `Struct`\<\{ `result`: ...; `status`: ...; \}\>, `Struct`\<\{ `result`: ...; \}\>\]\>, `Struct`\<\{ `result`: `Literal`\<`"refused"`\>; `reason`: `Literal`\<`"not_sender"`\>; \}\>\]\>; `answeredBy`: `Struct`\<\{ `kind`: `Literal`\<`"agent"`\>; `agentId`: `String`; \}\>; \}\> | - | Attribute the accepted answer to its authenticated Agent. |
496
+ | `commands.escalateAgent` | `object` | - | Pass the Ask on from the Agent it waits on; never a human action. |
497
+ | `commands.escalateAgent.scope` | `"session"` | `"session"` | The child Session owns the Ask; caller authority is host context. |
498
+ | `commands.escalateAgent.input` | `Struct`\<\{ `askId`: `String`; \}\> | `EscalateInput` | Decode the escalation without any caller-supplied recipient. |
499
+ | `commands.escalateAgent.output` | `Union`\<readonly \[`Struct`\<\{ `result`: `Literal`\<`"escalated"`\>; `to`: `Literal`\<`"person"`\>; \}\>, `Struct`\<\{ `result`: `Literal`\<`"closed"`\>; `status`: `Literals`\<readonly \[`"answered"`, `"declined"`, `"withdrawn"`, `"expired"`, `"cancelled"`, `"undeliverable"`\]\>; \}\>, `Struct`\<\{ `result`: `Literal`\<`"not_found"`\>; \}\>, `Struct`\<\{ `result`: `Literal`\<`"refused"`\>; `reason`: `Literal`\<`"not_sender"`\>; \}\>\]\> | `EscalateResult` | Where the Ask waits now, or why it did not move. |
500
+ | `commands.decline` | `object` | - | Decline an ask with an optional note. |
501
+ | `commands.decline.scope` | `"session"` | `"session"` | The Session owns this ask. |
502
+ | `commands.decline.input` | `Struct`\<\{ `askId`: `String`; `requestId`: `String`; `note`: `optionalKey`\<`String`\>; \}\> | `DeclineInput` | Decode the decline submission. |
503
+ | `commands.decline.output` | `Union`\<readonly \[`Struct`\<\{ `result`: `Literal`\<`"accepted"`\>; `via`: `Literals`\<readonly \[`"in_turn"`, `"follow_up"`\]\>; `commandId`: `optionalKey`\<`String`\>; \}\>, `Struct`\<\{ `result`: `Literal`\<`"closed"`\>; `status`: `Literals`\<readonly \[`"answered"`, `"declined"`, `"withdrawn"`, `"expired"`, `"cancelled"`, `"undeliverable"`\]\>; \}\>, `Struct`\<\{ `result`: `Literal`\<`"not_found"`\>; \}\>\]\> | `HumanResult` | Return admission or the ask's terminal state. |
504
+ | `commands.list` | `object` | - | Read the Session's open asks. |
505
+ | `commands.list.scope` | `"session"` | `"session"` | The Session owns the ask collection. |
506
+ | `commands.list.input` | `Struct`\<\{ \}\> | - | No additional arguments are required. |
507
+ | `commands.list.output` | `Struct`\<\{ `asks`: `$Array`\<`Struct`\<\{ `askId`: `String`; `waitingOn`: `optionalKey`\<`Struct`\<\{ `agentId`: ...; `sessionId`: ...; `name`: ...; \}\>\>; `questions`: `$Array`\<`Struct`\<\{ `id`: ...; `header`: ...; `question`: ...; `options`: ...; `multiple`: ...; \}\>\>; `status`: `Literals`\<readonly \[`"live"`, `"parked"`\]\>; `createdAt`: `Number`; `expiresAt`: `NullOr`\<`Number`\>; \}\>\>; \}\> | `AskProjection` | Decode the currently visible asks. |
508
+ | <a id="property-projection"></a> `projection` | `object` | - | Open asks visible to Session clients. |
509
+ | `projection.schema` | `Struct`\<\{ `asks`: `$Array`\<`Struct`\<\{ `askId`: `String`; `waitingOn`: `optionalKey`\<`Struct`\<\{ `agentId`: `NonEmptyString`; `sessionId`: `NonEmptyString`; `name`: `NonEmptyString`; \}\>\>; `questions`: `$Array`\<`Struct`\<\{ `id`: `String`; `header`: `String`; `question`: `String`; `options`: `$Array`\<...\>; `multiple`: `optionalKey`\<...\>; \}\>\>; `status`: `Literals`\<readonly \[`"live"`, `"parked"`\]\>; `createdAt`: `Number`; `expiresAt`: `NullOr`\<`Number`\>; \}\>\>; \}\> | `AskProjection` | Decoder for projected asks. |