toolroll 0.9.55 → 0.9.57

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 (223) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +24 -8
  3. package/dist/action-ledger.d.ts +2 -4
  4. package/dist/action-ledger.js +2 -10
  5. package/dist/approval-policy.d.ts +5 -5
  6. package/dist/approval-policy.js +4 -4
  7. package/dist/approval-rules-ui.js +2 -2
  8. package/dist/assignment-adapters.d.ts +5 -0
  9. package/dist/assignment.d.ts +24 -3
  10. package/dist/assignment.js +36 -10
  11. package/dist/browser/workspace.js +5 -5
  12. package/dist/browser-workspace.d.ts +12 -12
  13. package/dist/browser-workspace.js +1 -1
  14. package/dist/budget-alerts.js +3 -3
  15. package/dist/chat-actions.d.ts +23 -18
  16. package/dist/chat-actions.js +110 -88
  17. package/dist/chat-ask.d.ts +2 -2
  18. package/dist/chat-ask.js +5 -5
  19. package/dist/chat-channel.d.ts +15 -15
  20. package/dist/chat-channel.js +20 -20
  21. package/dist/chat-controls.d.ts +0 -4
  22. package/dist/chat-controls.js +0 -1
  23. package/dist/chat-core.js +1 -1
  24. package/dist/chat-delivery-state.js +2 -2
  25. package/dist/chat-delivery.d.ts +2 -2
  26. package/dist/chat-delivery.js +30 -37
  27. package/dist/chat-flow.js +3 -3
  28. package/dist/chat-messages.d.ts +1 -1
  29. package/dist/chat-messages.js +4 -4
  30. package/dist/chat-migration.d.ts +1 -1
  31. package/dist/chat-migration.js +11 -11
  32. package/dist/chat-rooms.js +3 -3
  33. package/dist/chat-voice.js +1 -1
  34. package/dist/chat-warmth.d.ts +2 -2
  35. package/dist/check-levels.d.ts +3 -0
  36. package/dist/check-levels.js +5 -0
  37. package/dist/cli.d.ts +1 -1
  38. package/dist/cli.js +6 -7
  39. package/dist/contracts/chat-actions.d.ts +32 -27
  40. package/dist/contracts/chat-actions.js +29 -11
  41. package/dist/contracts/chat-content.d.ts +1 -1
  42. package/dist/contracts/chat-content.js +1 -1
  43. package/dist/contracts/chat-tables.js +4 -4
  44. package/dist/contracts/console-api.d.ts +6 -6
  45. package/dist/contracts/console-api.js +7 -7
  46. package/dist/contracts/flow-propose.d.ts +3 -3
  47. package/dist/contracts/flow.d.ts +132 -125
  48. package/dist/contracts/flow.js +27 -12
  49. package/dist/contracts/lead-context.d.ts +1 -1
  50. package/dist/contracts/lead-context.js +2 -2
  51. package/dist/contracts/lead-tools.d.ts +20 -18
  52. package/dist/contracts/lead-tools.js +15 -15
  53. package/dist/contracts/stage-output.d.ts +1 -1
  54. package/dist/contracts/stage-output.js +1 -1
  55. package/dist/contracts/store-json.d.ts +23 -22
  56. package/dist/contracts/store-json.js +17 -17
  57. package/dist/contracts/{teammate-turn.d.ts → subagent-turn.d.ts} +5 -5
  58. package/dist/contracts/{teammate-turn.js → subagent-turn.js} +7 -7
  59. package/dist/converse.d.ts +23 -23
  60. package/dist/converse.js +28 -28
  61. package/dist/coordinator-proposals.d.ts +2 -2
  62. package/dist/coordinator-proposals.js +1 -1
  63. package/dist/coordinator.js +1 -1
  64. package/dist/deprecations.d.ts +12 -0
  65. package/dist/deprecations.js +20 -0
  66. package/dist/desktop-update-gate.js +8 -4
  67. package/dist/desktop-update.js +6 -1
  68. package/dist/discord-chat.js +6 -6
  69. package/dist/dispatch.d.ts +1 -1
  70. package/dist/dispatch.js +1 -1
  71. package/dist/dispose.js +0 -5
  72. package/dist/envelope.js +0 -1
  73. package/dist/export-ui.js +1 -1
  74. package/dist/export.js +7 -7
  75. package/dist/flow-engine.d.ts +2 -2
  76. package/dist/flow-engine.js +21 -21
  77. package/dist/flow-insights.d.ts +1 -1
  78. package/dist/flow-share.js +13 -8
  79. package/dist/flow-steps.d.ts +5 -5
  80. package/dist/flow-steps.js +19 -19
  81. package/dist/flow-triggers.d.ts +1 -1
  82. package/dist/flow-triggers.js +1 -1
  83. package/dist/flows-cli.js +1 -1
  84. package/dist/flows-ui.js +20 -20
  85. package/dist/flows.js +19 -19
  86. package/dist/guides.js +4 -3
  87. package/dist/invoke.js +1 -1
  88. package/dist/kits-ui.js +5 -5
  89. package/dist/kits.d.ts +12 -12
  90. package/dist/kits.js +31 -31
  91. package/dist/{mate-cli.d.ts → lead-cli.d.ts} +11 -11
  92. package/dist/{mate-cli.js → lead-cli.js} +38 -38
  93. package/dist/lead-commitments.js +4 -4
  94. package/dist/lead-context.d.ts +2 -2
  95. package/dist/lead-context.js +9 -9
  96. package/dist/{mate-contract.d.ts → lead-contract.d.ts} +3 -3
  97. package/dist/{mate-contract.js → lead-contract.js} +7 -6
  98. package/dist/{mate-doors.d.ts → lead-doors.d.ts} +6 -6
  99. package/dist/{mate-doors.js → lead-doors.js} +24 -24
  100. package/dist/lead-follow.d.ts +5 -5
  101. package/dist/lead-follow.js +9 -9
  102. package/dist/lead-people.d.ts +5 -5
  103. package/dist/lead-people.js +14 -14
  104. package/dist/{mate-progress.d.ts → lead-progress.d.ts} +9 -9
  105. package/dist/{mate-progress.js → lead-progress.js} +3 -3
  106. package/dist/lead-status.d.ts +1 -1
  107. package/dist/lead-status.js +2 -2
  108. package/dist/{mate-tools.d.ts → lead-tools.d.ts} +19 -19
  109. package/dist/{mate-tools.js → lead-tools.js} +109 -101
  110. package/dist/{mate.d.ts → lead.d.ts} +27 -27
  111. package/dist/{mate.js → lead.js} +102 -102
  112. package/dist/limits-ui.d.ts +1 -1
  113. package/dist/limits-ui.js +1 -1
  114. package/dist/mcp-connect.d.ts +1 -1
  115. package/dist/mcp-connect.js +3 -3
  116. package/dist/mcp-core.js +1 -1
  117. package/dist/memory-pass.d.ts +2 -2
  118. package/dist/memory-pass.js +7 -7
  119. package/dist/notification-rows.d.ts +2 -2
  120. package/dist/operate.d.ts +3 -3
  121. package/dist/operate.js +52 -42
  122. package/dist/policy.d.ts +1 -1
  123. package/dist/principal.d.ts +1 -1
  124. package/dist/principal.js +2 -2
  125. package/dist/project-delete-ui.js +1 -1
  126. package/dist/project-delete.d.ts +1 -1
  127. package/dist/project-delete.js +26 -26
  128. package/dist/project-memory.js +1 -1
  129. package/dist/project-tools.d.ts +1 -1
  130. package/dist/project-tools.js +1 -1
  131. package/dist/proof.d.ts +9 -0
  132. package/dist/proof.js +12 -0
  133. package/dist/recipe-ui.js +1 -1
  134. package/dist/release-coverage.d.ts +16 -0
  135. package/dist/release-coverage.js +92 -0
  136. package/dist/retention.js +4 -4
  137. package/dist/scope.d.ts +2 -2
  138. package/dist/scout-report.d.ts +1 -1
  139. package/dist/scout-report.js +1 -1
  140. package/dist/serve.js +40 -45
  141. package/dist/server/chat.d.ts +4 -4
  142. package/dist/server/chat.js +105 -103
  143. package/dist/server/chrome.js +3 -3
  144. package/dist/server/flows.js +69 -62
  145. package/dist/server/guards.js +3 -3
  146. package/dist/server/http.d.ts +3 -3
  147. package/dist/server/http.js +1 -1
  148. package/dist/server/live.js +6 -6
  149. package/dist/server/people-tokens.js +1 -1
  150. package/dist/server/remote.js +12 -10
  151. package/dist/server/render-chat.d.ts +30 -30
  152. package/dist/server/render-chat.js +33 -33
  153. package/dist/server/render-pages.js +2 -2
  154. package/dist/server/render-results.d.ts +4 -1
  155. package/dist/server/render-results.js +23 -9
  156. package/dist/server/render-settings.d.ts +7 -0
  157. package/dist/server/render-settings.js +3 -0
  158. package/dist/server/route-table.js +9 -7
  159. package/dist/server/runtime.d.ts +13 -13
  160. package/dist/server/settings.js +14 -13
  161. package/dist/server/tasks.js +34 -30
  162. package/dist/setup-guide.d.ts +2 -2
  163. package/dist/slack-chat.d.ts +2 -2
  164. package/dist/slack-chat.js +6 -6
  165. package/dist/spend-ui.d.ts +3 -3
  166. package/dist/spend-ui.js +9 -9
  167. package/dist/spend.d.ts +14 -14
  168. package/dist/spend.js +31 -31
  169. package/dist/store-baseline.d.ts +19 -0
  170. package/dist/store-baseline.js +2873 -0
  171. package/dist/store.d.ts +200 -254
  172. package/dist/store.js +830 -3152
  173. package/dist/subagent-admin.d.ts +53 -0
  174. package/dist/{teammate-admin.js → subagent-admin.js} +37 -37
  175. package/dist/{teammate-desk.d.ts → subagent-desk.d.ts} +22 -23
  176. package/dist/{teammate-desk.js → subagent-desk.js} +26 -35
  177. package/dist/{teammate-memory.d.ts → subagent-memory.d.ts} +17 -17
  178. package/dist/{teammate-memory.js → subagent-memory.js} +41 -41
  179. package/dist/{teammate-question.d.ts → subagent-question.d.ts} +6 -6
  180. package/dist/{teammate-question.js → subagent-question.js} +17 -17
  181. package/dist/{teammate-tools.d.ts → subagent-tools.d.ts} +18 -18
  182. package/dist/{teammate-tools.js → subagent-tools.js} +36 -36
  183. package/dist/{teammate-week.d.ts → subagent-week.d.ts} +10 -10
  184. package/dist/{teammate-week.js → subagent-week.js} +23 -23
  185. package/dist/{teammate-work.d.ts → subagent-work.d.ts} +21 -21
  186. package/dist/{teammate-work.js → subagent-work.js} +50 -50
  187. package/dist/subagents-ui.d.ts +22 -0
  188. package/dist/{teammates-ui.js → subagents-ui.js} +45 -45
  189. package/dist/{teammates.d.ts → subagents.d.ts} +11 -11
  190. package/dist/{teammates.js → subagents.js} +21 -21
  191. package/dist/subscription-chat.d.ts +13 -13
  192. package/dist/subscription-chat.js +19 -19
  193. package/dist/surface.d.ts +19 -2
  194. package/dist/surface.js +7 -31
  195. package/dist/task-outcome-cli.js +3 -1
  196. package/dist/task-status.d.ts +59 -7
  197. package/dist/task-status.js +132 -16
  198. package/dist/team-cli.d.ts +1 -0
  199. package/dist/team-cli.js +14 -2
  200. package/dist/team-leads.js +13 -13
  201. package/dist/team-runtime.d.ts +2 -2
  202. package/dist/team-runtime.js +9 -9
  203. package/dist/teams-chat.js +6 -6
  204. package/dist/telegram-flow.d.ts +3 -3
  205. package/dist/telegram-flow.js +3 -3
  206. package/dist/{telegram-mate.d.ts → telegram-lead.d.ts} +5 -5
  207. package/dist/{telegram-mate.js → telegram-lead.js} +27 -27
  208. package/dist/telegram-status.d.ts +11 -4
  209. package/dist/telegram-status.js +18 -11
  210. package/dist/telegram-team.d.ts +1 -1
  211. package/dist/telegram-team.js +5 -5
  212. package/dist/telegram.d.ts +1 -1
  213. package/dist/telegram.js +13 -34
  214. package/dist/text-limits.d.ts +18 -18
  215. package/dist/text-limits.js +18 -18
  216. package/dist/toolroll-update.d.ts +8 -0
  217. package/dist/toolroll-update.js +45 -8
  218. package/dist/work-index.d.ts +6 -1
  219. package/dist/work-index.js +50 -8
  220. package/dist/workspace-ui.js +2 -1
  221. package/package.json +1 -2
  222. package/dist/teammate-admin.d.ts +0 -53
  223. package/dist/teammates-ui.d.ts +0 -21
@@ -765,7 +765,7 @@ export type BrowserRunChecks = {
765
765
  export type BrowserFlowStage = {
766
766
  id: string;
767
767
  title: string;
768
- kind: "inbox" | "task" | "report" | "approval" | "check" | "pull-request" | "update" | "notify" | "sort" | "draft" | "request" | "email" | "tool" | "wait" | "teammate" | "send" | "choose" | "done";
768
+ kind: "inbox" | "task" | "report" | "approval" | "check" | "pull-request" | "update" | "notify" | "sort" | "draft" | "request" | "email" | "tool" | "wait" | "subagent" | "send" | "choose" | "done";
769
769
  zone: {
770
770
  x: number;
771
771
  y: number;
@@ -835,9 +835,9 @@ export type BrowserFlowStage = {
835
835
  minutes: number;
836
836
  to: string | null;
837
837
  } | undefined;
838
- /** v92: the AI teammate who decides (an approval zone) or handles (a teammate zone) it. */
839
- teammate?: string | undefined;
840
- /** v96: a teammate zone sends what the teammate writes back to whoever asked. */
838
+ /** v92: the subagent who decides (an approval zone) or handles (a subagent zone) it. */
839
+ subagent?: string | undefined;
840
+ /** v96: a subagent zone sends what the subagent writes back to whoever asked. */
841
841
  reply?: boolean | undefined;
842
842
  /** A "Person chooses" zone's buttons: each one's words and the zone it leads to ("end" ignores the card). */
843
843
  options?: {
@@ -921,7 +921,7 @@ export type BrowserFlowCard = {
921
921
  at: string;
922
922
  label: string;
923
923
  } | null;
924
- /** v92: a teammate's open question about this visit, and whether the viewer is the one asked. */
924
+ /** v92: a subagent's open question about this visit, and whether the viewer is the one asked. */
925
925
  question?: {
926
926
  id: number;
927
927
  from: string;
@@ -932,13 +932,13 @@ export type BrowserFlowCard = {
932
932
  }[];
933
933
  askedOf: string;
934
934
  mine: boolean;
935
- /** v94: a tool call waiting for approval — why the teammate wants it, and why it needs approval. */
935
+ /** v94: a tool call waiting for approval — why the subagent wants it, and why it needs approval. */
936
936
  call?: {
937
937
  why: string;
938
938
  rule: string;
939
939
  } | null;
940
940
  } | null;
941
- /** v92: what the teammate said when it handed this decision to a person. */
941
+ /** v92: what the subagent said when it handed this decision to a person. */
942
942
  handoff?: {
943
943
  from: string;
944
944
  note: string;
@@ -973,7 +973,7 @@ export type BrowserFlowCard = {
973
973
  person: string;
974
974
  at: string;
975
975
  } | null;
976
- /** v94: every tool call teammates made or asked to make on this card, oldest first: the receipts. */
976
+ /** v94: every tool call subagents made or asked to make on this card, oldest first: the receipts. */
977
977
  calls?: {
978
978
  id: number;
979
979
  who: string;
@@ -983,8 +983,8 @@ export type BrowserFlowCard = {
983
983
  why: string;
984
984
  result: string | null;
985
985
  at: string;
986
- /** v97: the teammate's id and the action that undoes this call, when a person can press Undo. */
987
- teammate?: number;
986
+ /** v97: the subagent's id and the action that undoes this call, when a person can press Undo. */
987
+ subagent?: number;
988
988
  undo?: string | null;
989
989
  }[];
990
990
  };
@@ -1065,8 +1065,8 @@ export type BrowserFlowView = {
1065
1065
  me: string;
1066
1066
  /** Whether sort zones can run: an OpenRouter key is saved in Settings → AI providers. */
1067
1067
  sortReady: boolean;
1068
- /** v92: the project's AI teammates, to staff zones with. */
1069
- teammates?: {
1068
+ /** v92: the project's subagents, to staff zones with. */
1069
+ subagents?: {
1070
1070
  handle: string;
1071
1071
  label: string;
1072
1072
  name: string;
@@ -19,7 +19,7 @@ export function browserCrewOf(store, now, access, options = {}) {
19
19
  return { crew: [], crewTruncated: false };
20
20
  const limit = Number.isFinite(options.limit)
21
21
  ? Math.max(1, Math.min(BROWSER_CREW_LIMIT, Math.floor(options.limit))) : BROWSER_CREW_LIMIT;
22
- const page = workIndexPage(store, now, access, { limit, project });
22
+ const page = workIndexPage(store, now, access, { limit, project, ...(options.evidenceRoot === undefined ? {} : { root: options.evidenceRoot }) });
23
23
  return browserCrewFromIndex(page);
24
24
  }
25
25
  /** Navigation input must already be admitted by the caller. No extra project
@@ -1,9 +1,9 @@
1
- import { budgetLabel, teammateNames, usd } from "./spend.js";
1
+ import { budgetLabel, subagentNames, usd } from "./spend.js";
2
2
  const MARKS = [100, 80, 50];
3
3
  export function budgetAlertPass(store, now) {
4
4
  const { month, budgets } = store.monthSpend(now);
5
5
  const sent = [];
6
- const names = teammateNames(store.handle);
6
+ const names = subagentNames(store.handle);
7
7
  for (const budget of budgets) {
8
8
  const mark = MARKS.find(one => budget.percent >= one);
9
9
  if (mark === undefined)
@@ -13,7 +13,7 @@ export function budgetAlertPass(store, now) {
13
13
  // A higher mark already sent this month covers this one.
14
14
  if (MARKS.filter(one => one >= mark).some(one => store.handle.prepare("SELECT 1 AS hit FROM notification WHERE dedupe_key = ?").get(key(one)) !== undefined))
15
15
  continue;
16
- const label = budgetLabel(budget, budget.scope === "teammate" ? names.get(Number(budget.key)) : undefined);
16
+ const label = budgetLabel(budget, budget.scope === "subagent" ? names.get(Number(budget.key)) : undefined);
17
17
  const fresh = store.enqueueNotification({
18
18
  dedupeKey: key(mark), kind: "budget-alert", pushClass: "attention", link: `/spend?month=${month}`,
19
19
  subject: `${label} budget: ${mark}% used`,
@@ -143,48 +143,53 @@ export declare const CHAT_ACTIONS: {
143
143
  readonly protected: false;
144
144
  readonly password: false;
145
145
  };
146
- readonly teammate_create: {
147
- readonly label: "Add teammate";
146
+ readonly subagent_create: {
147
+ readonly label: "Add subagent";
148
148
  readonly protected: false;
149
149
  readonly password: false;
150
150
  };
151
- readonly teammate_soul: {
151
+ readonly subagent_soul: {
152
152
  readonly label: "Update soul file";
153
153
  readonly protected: false;
154
154
  readonly password: false;
155
155
  };
156
- readonly teammate_state: {
157
- readonly label: "Change teammate";
156
+ readonly subagent_state: {
157
+ readonly label: "Change subagent";
158
158
  readonly protected: false;
159
159
  readonly password: false;
160
160
  };
161
- readonly teammate_note: {
162
- readonly label: "Tell teammate";
161
+ readonly subagent_note: {
162
+ readonly label: "Tell subagent";
163
163
  readonly protected: false;
164
164
  readonly password: false;
165
165
  };
166
- readonly teammate_answer: {
167
- readonly label: "Answer teammate";
166
+ readonly subagent_ask: {
167
+ readonly label: "Ask subagent";
168
168
  readonly protected: false;
169
169
  readonly password: false;
170
170
  };
171
- readonly teammate_tools: {
172
- readonly label: "Change teammate's tools";
171
+ readonly subagent_answer: {
172
+ readonly label: "Answer subagent";
173
173
  readonly protected: false;
174
174
  readonly password: false;
175
175
  };
176
- readonly teammate_memory: {
177
- readonly label: "Change teammate's memory";
176
+ readonly subagent_tools: {
177
+ readonly label: "Change subagent's tools";
178
178
  readonly protected: false;
179
179
  readonly password: false;
180
180
  };
181
- readonly teammate_routine: {
182
- readonly label: "Change teammate's routines";
181
+ readonly subagent_memory: {
182
+ readonly label: "Change subagent's memory";
183
183
  readonly protected: false;
184
184
  readonly password: false;
185
185
  };
186
- readonly teammate_undo: {
187
- readonly label: "Undo teammate's call";
186
+ readonly subagent_routine: {
187
+ readonly label: "Change subagent's routines";
188
+ readonly protected: false;
189
+ readonly password: false;
190
+ };
191
+ readonly subagent_undo: {
192
+ readonly label: "Undo subagent's call";
188
193
  readonly protected: false;
189
194
  readonly password: false;
190
195
  };
@@ -251,7 +256,7 @@ export declare function sharedActionReviewPath(id: number): string;
251
256
  export declare function mintSharedActionReview(store: Store, who: VerifiedApprover, id: number, root: string, now: Date): {
252
257
  payload: {
253
258
  version: 1;
254
- operation: "decision_record" | "decision_retire" | "flow_card_add" | "flow_card_approve" | "flow_card_assign" | "flow_card_cancel" | "flow_card_choose" | "flow_card_comment" | "flow_card_move" | "flow_card_send_back" | "flow_card_watch" | "flow_create" | "flow_edit" | "flow_script_save" | "flow_starter" | "flow_trigger_add" | "flow_trigger_pause" | "flow_trigger_remove" | "flow_trigger_resume" | "kit_setup" | "knowledge_instructions" | "knowledge_remove" | "knowledge_restore" | "knowledge_save" | "lead_about_you" | "result_accept" | "scope_approve" | "skill_disable" | "skill_enable" | "skill_import" | "skill_restore" | "skill_test" | "task_cancel" | "task_resume" | "teammate_answer" | "teammate_create" | "teammate_memory" | "teammate_note" | "teammate_routine" | "teammate_soul" | "teammate_state" | "teammate_tools" | "teammate_undo" | "tool_add" | "tool_remove";
259
+ operation: "decision_record" | "decision_retire" | "flow_card_add" | "flow_card_approve" | "flow_card_assign" | "flow_card_cancel" | "flow_card_choose" | "flow_card_comment" | "flow_card_move" | "flow_card_send_back" | "flow_card_watch" | "flow_create" | "flow_edit" | "flow_script_save" | "flow_starter" | "flow_trigger_add" | "flow_trigger_pause" | "flow_trigger_remove" | "flow_trigger_resume" | "kit_setup" | "knowledge_instructions" | "knowledge_remove" | "knowledge_restore" | "knowledge_save" | "lead_about_you" | "result_accept" | "scope_approve" | "skill_disable" | "skill_enable" | "skill_import" | "skill_restore" | "skill_test" | "subagent_answer" | "subagent_ask" | "subagent_create" | "subagent_memory" | "subagent_note" | "subagent_routine" | "subagent_soul" | "subagent_state" | "subagent_tools" | "subagent_undo" | "task_cancel" | "task_resume" | "tool_add" | "tool_remove";
255
260
  request: {
256
261
  [x: string]: unknown;
257
262
  };
@@ -5,7 +5,7 @@ import { TEXT_LIMITS } from "./text-limits.js";
5
5
  import { publicChatText } from "./chat-display.js";
6
6
  import { gateWords } from "./approval-policy.js";
7
7
  import { createHash, randomBytes } from "node:crypto";
8
- import { mateTurnKeepsProposals, verifiedAuthor } from "./store.js";
8
+ import { leadTurnKeepsProposals, verifiedAuthor } from "./store.js";
9
9
  import { isVerifiedApprover, reproveApprover, } from "./principal.js";
10
10
  import { changeSkills, importSkill, skillsView, skillsVersion, testSkill, validateSkill, } from "./project-skills.js";
11
11
  import { changeKnowledge, knowledgeVersion, knowledgeView, } from "./project-knowledge.js";
@@ -25,15 +25,15 @@ import { assignFlowCard, commentOnFlowCard, flowPeople, mentionsIn, watchFlowCar
25
25
  import { addFlowTriggerTo, describeTrigger, readLinearKey, removeFlowTrigger, scheduleFromWords, takesDeliveries, triggerConfigOf, validateTriggerConfig } from "./flow-triggers.js";
26
26
  import { describeSchedule, parseSchedule } from "./flow-schedule.js";
27
27
  import { dirname } from "node:path";
28
- import { handleOf, parseSoul, SOUL_CHARS, TEAMMATE_TEMPLATES, teammateLabel } from "./teammates.js";
29
- import { createTeammateFrom, labelOf, nameOf, renamedSoul, saveSoul, setTeammateState } from "./teammate-admin.js";
30
- import { cleanMemory, editMemory, forgetMemory, tellTeammate } from "./teammate-memory.js";
31
- import { addRoutine, removeRoutine, routineSchedule, routinesOf } from "./teammate-desk.js";
32
- import { requestUndo, undoFor } from "./teammate-week.js";
28
+ import { handleOf, parseSoul, SOUL_CHARS, SUBAGENT_TEMPLATES, subagentLabel } from "./subagents.js";
29
+ import { createSubagentFrom, labelOf, nameOf, renamedSoul, saveSoul, setSubagentState } from "./subagent-admin.js";
30
+ import { cleanMemory, editMemory, forgetMemory, tellSubagent } from "./subagent-memory.js";
31
+ import { addRoutine, askSubagent, removeRoutine, routineSchedule, routinesOf } from "./subagent-desk.js";
32
+ import { requestUndo, undoFor } from "./subagent-week.js";
33
33
  import { kitInstalled, kitOf, KITS, setUpKitNow } from "./kits.js";
34
34
  import { starterFlowOf, starterOf, startersFor, starterTerms, STARTER_FLOWS, switchOnStarter } from "./flow-starters.js";
35
- import { answerTeammateQuestion } from "./teammate-work.js";
36
- import { callWords, checkRule, defaultRule, grantListed, revokeTool, ruleWords, setToolRules } from "./teammate-tools.js";
35
+ import { answerSubagentQuestion } from "./subagent-work.js";
36
+ import { callWords, checkRule, defaultRule, grantListed, revokeTool, ruleWords, setToolRules } from "./subagent-tools.js";
37
37
  import { aboutYouOf, checkAboutYouLine, saveAboutYou, withAboutYouLine } from "./lead-about.js";
38
38
  import { CHAT_ACTION_FIELDS, readChatActionRequest, readSharedAction, SHARED_ACTION_VERSION } from "./contracts/chat-actions.js";
39
39
  export { CHAT_ACTION_FIELDS };
@@ -101,15 +101,16 @@ export const CHAT_ACTIONS = {
101
101
  flow_trigger_pause: { label: "Pause trigger", protected: false, password: false },
102
102
  flow_trigger_resume: { label: "Turn trigger on", protected: false, password: false },
103
103
  flow_trigger_remove: { label: "Remove trigger", protected: false, password: false },
104
- teammate_create: { label: "Add teammate", protected: false, password: false },
105
- teammate_soul: { label: "Update soul file", protected: false, password: false },
106
- teammate_state: { label: "Change teammate", protected: false, password: false },
107
- teammate_note: { label: "Tell teammate", protected: false, password: false },
108
- teammate_answer: { label: "Answer teammate", protected: false, password: false },
109
- teammate_tools: { label: "Change teammate's tools", protected: false, password: false },
110
- teammate_memory: { label: "Change teammate's memory", protected: false, password: false },
111
- teammate_routine: { label: "Change teammate's routines", protected: false, password: false },
112
- teammate_undo: { label: "Undo teammate's call", protected: false, password: false },
104
+ subagent_create: { label: "Add subagent", protected: false, password: false },
105
+ subagent_soul: { label: "Update soul file", protected: false, password: false },
106
+ subagent_state: { label: "Change subagent", protected: false, password: false },
107
+ subagent_note: { label: "Tell subagent", protected: false, password: false },
108
+ subagent_ask: { label: "Ask subagent", protected: false, password: false },
109
+ subagent_answer: { label: "Answer subagent", protected: false, password: false },
110
+ subagent_tools: { label: "Change subagent's tools", protected: false, password: false },
111
+ subagent_memory: { label: "Change subagent's memory", protected: false, password: false },
112
+ subagent_routine: { label: "Change subagent's routines", protected: false, password: false },
113
+ subagent_undo: { label: "Undo subagent's call", protected: false, password: false },
113
114
  kit_setup: { label: "Set up kit", protected: false, password: false },
114
115
  decision_record: { label: "Record decision", protected: false, password: false },
115
116
  decision_retire: { label: "Retire decision", protected: false, password: false },
@@ -262,19 +263,19 @@ export function prepareSharedAction(store, who, operation, input, root, now = ne
262
263
  const stamp = hash({ operation, request, repo: "", state, terms, actor: who.name, generation: who.generation, ceiling: who.ceilingDigest });
263
264
  return { version: SHARED_ACTION_VERSION, operation, request, repo: "", title, terms, stamp, state };
264
265
  }
265
- const task = operation.startsWith("skill_") || operation.startsWith("knowledge_") || operation.startsWith("decision_") || operation.startsWith("tool_") || operation.startsWith("flow_") || operation.startsWith("teammate_") || operation.startsWith("kit_")
266
+ const task = operation.startsWith("skill_") || operation.startsWith("knowledge_") || operation.startsWith("decision_") || operation.startsWith("tool_") || operation.startsWith("flow_") || operation.startsWith("subagent_") || operation.startsWith("kit_")
266
267
  ? null
267
268
  : text(input, "task", 64);
268
269
  const flowTarget = operation.startsWith("flow_") && operation !== "flow_create" && operation !== "flow_script_save" && operation !== "flow_starter" ? flowTargetOf(store, input) : null;
269
- // v92: a teammate names its project; a question names it through its card's flow.
270
- const mateTarget = operation.startsWith("teammate_") && operation !== "teammate_create" && operation !== "teammate_answer" ? store.getTeammate(integer(input, "teammate")) : null;
271
- if (mateTarget !== null && mateTarget.state === "removed")
272
- throw Error("That teammate is off the team.");
273
- const questionTarget = operation === "teammate_answer" ? store.teammateQuestion(integer(input, "question")) : null;
270
+ // v92: a subagent names its project; a question names it through its card's flow.
271
+ const subagentTarget = operation.startsWith("subagent_") && operation !== "subagent_create" && operation !== "subagent_answer" ? store.getSubagent(integer(input, "subagent")) : null;
272
+ if (subagentTarget !== null && subagentTarget.state === "removed")
273
+ throw Error("That subagent is off the team.");
274
+ const questionTarget = operation === "subagent_answer" ? store.subagentQuestion(integer(input, "question")) : null;
274
275
  const questionFlow = questionTarget === null ? null : store.getFlow(store.getFlowCard(questionTarget.card)?.flow ?? -1);
275
- if (operation === "teammate_answer" && (questionTarget === null || questionFlow === null))
276
+ if (operation === "subagent_answer" && (questionTarget === null || questionFlow === null))
276
277
  throw Error("That question isn't open any more.");
277
- const repo = flowTarget !== null ? flowTarget.flow.repo : mateTarget !== null ? mateTarget.repo : questionFlow !== null ? questionFlow.repo : task === null ? text(input, "repo", 4096) : store.lookupRef(task)?.repo;
278
+ const repo = flowTarget !== null ? flowTarget.flow.repo : subagentTarget !== null ? subagentTarget.repo : questionFlow !== null ? questionFlow.repo : task === null ? text(input, "repo", 4096) : store.lookupRef(task)?.repo;
278
279
  if (!repo)
279
280
  throw Error("Choose an available project.");
280
281
  requireActor(store, who, repo);
@@ -358,23 +359,23 @@ export function prepareSharedAction(store, who, operation, input, root, now = ne
358
359
  }
359
360
  }
360
361
  else if (operation === "kit_setup") {
361
- // a starter kit — its teammate, its flow and its buttons.
362
+ // a starter kit — its subagent, its flow and its buttons.
362
363
  const project = repo.split(/[\\/]/).filter(Boolean).at(-1) ?? repo;
363
364
  const kit = kitOf(String(input["kit"] ?? ""));
364
365
  if (kit === null)
365
366
  throw Error(`Choose a kit: ${KITS.map(one => one.id).join(", ")}.`);
366
367
  if (kitInstalled(store, kit, repo) !== null)
367
368
  throw Error(`${kit.name} is already set up in ${project}.`);
368
- const template = TEAMMATE_TEMPLATES.find(one => one.id === kit.teammate.template);
369
+ const template = SUBAGENT_TEMPLATES.find(one => one.id === kit.subagent.template);
369
370
  title = `Set up ${kit.name} in ${project}`;
370
- terms.push(kit.promise, `Adds ${kit.teammate.handle.charAt(0).toUpperCase()}${kit.teammate.handle.slice(1)} (${template?.label.toLowerCase() ?? "a teammate"}) and the ${kit.flowName} flow${kit.buttons.length === 0 ? "" : ` with its ${kit.buttons.map(one => `“${one.label}”`).join(" and ")} button`}. Nothing goes out without your approval.`);
371
+ terms.push(kit.promise, `Adds ${kit.subagent.handle.charAt(0).toUpperCase()}${kit.subagent.handle.slice(1)} (${template?.label.toLowerCase() ?? "a subagent"}) and the ${kit.flowName} flow${kit.buttons.length === 0 ? "" : ` with its ${kit.buttons.map(one => `“${one.label}”`).join(" and ")} button`}. Nothing goes out without your approval.`);
371
372
  state = {};
372
373
  }
373
- else if (operation.startsWith("teammate_")) {
374
+ else if (operation.startsWith("subagent_")) {
374
375
  const project = repo.split(/[\\/]/).filter(Boolean).at(-1) ?? repo;
375
- const mate = mateTarget;
376
- if (operation === "teammate_create") {
377
- const template = TEAMMATE_TEMPLATES.find(one => one.id === input["template"]);
376
+ const mate = subagentTarget;
377
+ if (operation === "subagent_create") {
378
+ const template = SUBAGENT_TEMPLATES.find(one => one.id === input["template"]);
378
379
  const given = typeof input["soul"] === "string" && input["soul"].trim() !== "" ? text(input, "soul", SOUL_CHARS) : null;
379
380
  if ((template === undefined) === (given === null))
380
381
  throw Error("Start from a template, or write the whole soul file, not both.");
@@ -384,29 +385,29 @@ export function prepareSharedAction(store, who, operation, input, root, now = ne
384
385
  const read = parseSoul(soul);
385
386
  if (!read.ok)
386
387
  throw Error(read.problem);
387
- if (store.teammateByHandle(repo, handleOf(read.soul.name)) !== null)
388
- throw Error(`There's already a teammate called ${read.soul.name} in ${project}.`);
388
+ if (store.subagentByHandle(repo, handleOf(read.soul.name)) !== null)
389
+ throw Error(`There's already a subagent called ${read.soul.name} in ${project}.`);
389
390
  Object.assign(request, { soul });
390
391
  delete request["template"];
391
392
  delete request["name"];
392
393
  state = { handle: handleOf(read.soul.name) };
393
- title = `Add ${teammateLabel(read.soul)} to the team in ${project}`;
394
- terms.push(soul.trim(), `${read.soul.name} decides only within these rules and asks you when they say to. Teammates never approve code tasks or merges.`);
394
+ title = `Add ${subagentLabel(read.soul)} to the team in ${project}`;
395
+ terms.push(soul.trim(), `${read.soul.name} decides only within these rules and asks you when they say to. Subagents never approve code tasks or merges.`);
395
396
  }
396
- else if (operation === "teammate_soul") {
397
+ else if (operation === "subagent_soul") {
397
398
  const soul = text(input, "soul", SOUL_CHARS);
398
399
  const read = parseSoul(soul);
399
400
  if (!read.ok)
400
401
  throw Error(read.problem);
401
402
  if (handleOf(read.soul.name) !== mate.handle)
402
- throw Error("Keep the teammate's name; make a new teammate for another name.");
403
+ throw Error("Keep the subagent's name; make a new subagent for another name.");
403
404
  if (soul.trim() === mate.soul.trim())
404
405
  throw Error("That's already its soul file.");
405
406
  state = { version: mate.version };
406
- title = `Update ${teammateLabel(read.soul)}'s soul file`;
407
+ title = `Update ${subagentLabel(read.soul)}'s soul file`;
407
408
  terms.push(soul.trim(), `Replaces version ${mate.version}. Its next turn reads this.`);
408
409
  }
409
- else if (operation === "teammate_state") {
410
+ else if (operation === "subagent_state") {
410
411
  const wanted = input["state"];
411
412
  if (wanted !== "active" && wanted !== "paused" && wanted !== "removed")
412
413
  throw Error("Choose pause, resume or remove.");
@@ -414,13 +415,13 @@ export function prepareSharedAction(store, who, operation, input, root, now = ne
414
415
  title = `${wanted === "paused" ? "Pause" : wanted === "active" ? "Resume" : "Remove"} ${labelOf(mate)}`;
415
416
  terms.push(wanted === "paused" ? "Its decisions go to people and the zones it handles wait until you resume it." : wanted === "active" ? "It picks up its zones' cards again." : "It leaves the team: zones that name it go to people.");
416
417
  }
417
- else if (operation === "teammate_tools") {
418
+ else if (operation === "subagent_tools") {
418
419
  // v94: which project tools it may use, and its rule for one action.
419
420
  const tool = text(input, "tool", 40);
420
421
  const change = input["change"];
421
- const grant = store.teammateGrant(mate.id, tool);
422
+ const grant = store.subagentGrant(mate.id, tool);
422
423
  const name = nameOf(mate);
423
- const grants = store.teammateGrants(mate.id);
424
+ const grants = store.subagentGrants(mate.id);
424
425
  const uses = grants.length === 0 ? ` ${name} doesn't use any tools yet.` : ` ${name} uses ${grants.map(one => `${one.tool} (actions: ${one.actions.map(each => each.name).join(", ")})`).join("; ")}.`;
425
426
  if (change === "grant") {
426
427
  const found = projectToolsOf(store, repo).find(one => one.name === tool);
@@ -458,17 +459,17 @@ export function prepareSharedAction(store, who, operation, input, root, now = ne
458
459
  else
459
460
  throw Error("Choose grant, revoke or rule.");
460
461
  }
461
- else if (operation === "teammate_undo") {
462
+ else if (operation === "subagent_undo") {
462
463
  // v97: undo one of its tool calls with the action its manager named for that.
463
- const call = store.teammateCall(integer(input, "call"));
464
- const undo = call === null || call.teammate !== mate.id ? null : undoFor(store, call);
464
+ const call = store.subagentCall(integer(input, "call"));
465
+ const undo = call === null || call.subagent !== mate.id ? null : undoFor(store, call);
465
466
  if (call === null || undo === null)
466
- throw Error(call?.undoneBy ? `${call.undoneBy} already undid it.` : "That call can't be undone: its action has no undo set on the teammate's Tools.");
467
+ throw Error(call?.undoneBy ? `${call.undoneBy} already undid it.` : "That call can't be undone: its action has no undo set on the subagent's Tools.");
467
468
  title = `Undo ${nameOf(mate)}'s ${call.action}`;
468
469
  terms.push(`Undoes: ${callWords(call.tool, call.action, call.input, 300)}`, `By calling: ${callWords(call.tool, undo, call.input, 300)}`, "It's made as you, with the same input, and both calls keep their receipts.");
469
470
  state = { call: call.id };
470
471
  }
471
- else if (operation === "teammate_routine") {
472
+ else if (operation === "subagent_routine") {
472
473
  // v96: a routine: on a schedule, a card on its desk saying what to do; its answer goes to its manager.
473
474
  const name = nameOf(mate);
474
475
  if (input["change"] === "add") {
@@ -494,10 +495,10 @@ export function prepareSharedAction(store, who, operation, input, root, now = ne
494
495
  else
495
496
  throw Error("Choose add or remove.");
496
497
  }
497
- else if (operation === "teammate_memory") {
498
+ else if (operation === "subagent_memory") {
498
499
  // v95: edit or forget one thing it remembers.
499
- const memory = store.teammateMemory(integer(input, "memory"));
500
- if (memory === null || memory.teammate !== mate.id)
500
+ const memory = store.subagentMemory(integer(input, "memory"));
501
+ if (memory === null || memory.subagent !== mate.id)
501
502
  throw Error(`${nameOf(mate)} doesn't remember that any more.`);
502
503
  if (input["change"] === "forget") {
503
504
  title = `${nameOf(mate)} forgets: ${memory.text.slice(0, 60)}`;
@@ -515,12 +516,24 @@ export function prepareSharedAction(store, who, operation, input, root, now = ne
515
516
  throw Error("Choose edit or forget.");
516
517
  state = { text: memory.text };
517
518
  }
518
- else if (operation === "teammate_note") {
519
+ else if (operation === "subagent_ask") {
520
+ // D5: the lead delegates. The card says exactly what goes to the subagent, which works it within its own rules.
521
+ const asked = text(input, "text", 4000).replace(/\r\n?/g, "\n").trim();
522
+ if (asked === "")
523
+ throw Error(`Say what to ask ${nameOf(mate)}.`);
524
+ if (mate.state !== "active")
525
+ throw Error(`${nameOf(mate)} is paused. Resume it first.`);
526
+ request["text"] = asked;
527
+ state = { subagent: mate.id, version: mate.version };
528
+ title = `Ask ${nameOf(mate)}`;
529
+ terms.push(asked, `${nameOf(mate)} works on it within its own rules and tools, asks you first where they say to, and its answer comes back to you. It never approves code tasks or merges.`);
530
+ }
531
+ else if (operation === "subagent_note") {
519
532
  const note = cleanMemory(text(input, "note", 1000));
520
533
  if (!note.ok)
521
534
  throw Error(note.said);
522
535
  request["note"] = note.text;
523
- state = { teammate: mate.id };
536
+ state = { subagent: mate.id };
524
537
  title = `Tell ${nameOf(mate)}`;
525
538
  terms.push(note.text, "It keeps this in its memory: every turn reads the latest ten things people told it.");
526
539
  }
@@ -536,8 +549,8 @@ export function prepareSharedAction(store, who, operation, input, root, now = ne
536
549
  throw Error("Pick one of its options or say the answer.");
537
550
  Object.assign(request, { choice: choice?.id ?? null, text: said || null });
538
551
  state = { question: question.id };
539
- const mateOf = store.getTeammate(question.teammate);
540
- title = `Answer ${mateOf === null ? "the teammate" : nameOf(mateOf)}`;
552
+ const subagentOf = store.getSubagent(question.subagent);
553
+ title = `Answer ${subagentOf === null ? "the subagent" : nameOf(subagentOf)}`;
541
554
  terms.push(question.question, `Your answer: ${[choice?.label, said].filter(Boolean).join(" — ")}`);
542
555
  }
543
556
  }
@@ -766,7 +779,7 @@ export function prepareSharedAction(store, who, operation, input, root, now = ne
766
779
  }
767
780
  else if (operation.startsWith("decision_")) {
768
781
  // The staleness fence: the newest decision id and the active count, so a
769
- // card drafted before a teammate recorded or retired one is refused.
782
+ // card drafted before a subagent recorded or retired one is refused.
770
783
  const stamp = store.handle.prepare("SELECT COALESCE(MAX(id),0) AS newest, COUNT(*) AS active FROM project_decision WHERE repo=? AND status='active'").get(repo);
771
784
  state = { newest: Number(stamp?.["newest"] ?? 0), active: Number(stamp?.["active"] ?? 0) };
772
785
  if (operation === "decision_record") {
@@ -952,22 +965,22 @@ export function sharedActionReviewPath(id) {
952
965
  function savedActionContext(store, who, id, state) {
953
966
  if (!isVerifiedApprover(who) || !reproveApprover(store, who).ok)
954
967
  throw Error("Your access changed. Sign in again.");
955
- const proposal = store.getMateProposal(id), payload = proposal?.kind === "action"
968
+ const proposal = store.getLeadProposal(id), payload = proposal?.kind === "action"
956
969
  ? sharedActionPayload(proposal.payload)
957
970
  : null;
958
971
  const shared = proposal && store.handle.prepare('SELECT id FROM team_conversation WHERE thread=?').get(proposal.thread);
959
- const session = shared && proposal ? store.teamMateSession(who.name, proposal.thread) : store.activeMateSession(who.name), turn = proposal ? store.getMateTurn(proposal.turn) : null;
972
+ const session = shared && proposal ? store.teamMateSession(who.name, proposal.thread) : store.activeLeadSession(who.name), turn = proposal ? store.getLeadTurn(proposal.turn) : null;
960
973
  if (!proposal ||
961
974
  !payload ||
962
975
  proposal.state !== state ||
963
- (shared ? !store.canUseTeamMateThread(who.name, who.generation, proposal.thread) : store.getMateThread(proposal.thread)?.approver !== who.name))
976
+ (shared ? !store.canUseTeamMateThread(who.name, who.generation, proposal.thread) : store.getLeadThread(proposal.thread)?.approver !== who.name))
964
977
  throw Error("This action is no longer waiting for your review.");
965
978
  if (!session ||
966
979
  session.approverGeneration !== who.generation ||
967
980
  session.ceilingDigest !== who.ceilingDigest ||
968
981
  proposal.ceilingDigest !== who.ceilingDigest ||
969
982
  (!shared && turn?.session !== session.id) ||
970
- !mateTurnKeepsProposals(turn))
983
+ !leadTurnKeepsProposals(turn))
971
984
  throw Error("This conversation ended or its project access changed. Ask for a fresh proposal.");
972
985
  requireActor(store, who, payload.repo, payload.operation);
973
986
  return payload;
@@ -1070,8 +1083,8 @@ export function executeSharedAction(store, who, id, payload, now, options) {
1070
1083
  throw Error(made.said);
1071
1084
  return { ok: true, taskId: null, said: `${made.said} Try it with a sample card from its page.`, href: `/kits/${kit.id}?repo=${encodeURIComponent(repo)}` };
1072
1085
  }
1073
- else if (payload.operation.startsWith("teammate_")) {
1074
- const done = runTeammateAction(store, payload, actor, now);
1086
+ else if (payload.operation.startsWith("subagent_")) {
1087
+ const done = runSubagentAction(store, payload, actor, now);
1075
1088
  return { ok: true, taskId: null, said: done.said, href: done.href };
1076
1089
  }
1077
1090
  else if (payload.operation === "tool_add") {
@@ -1181,50 +1194,59 @@ export function executeSharedAction(store, who, id, payload, now, options) {
1181
1194
  : "The action could not be completed.");
1182
1195
  }
1183
1196
  }
1184
- /** A confirmed teammate action (v92), through the same helpers the Teammates pages use. */
1185
- function runTeammateAction(store, payload, actor, now) {
1197
+ /** A confirmed subagent action (v92), through the same helpers the Subagents pages use. */
1198
+ function runSubagentAction(store, payload, actor, now) {
1186
1199
  const req = payload.request;
1187
- if (payload.operation === "teammate_create") {
1188
- const made = createTeammateFrom(store, { repo: payload.repo, soul: String(req["soul"]), by: actor }, now);
1200
+ if (payload.operation === "subagent_create") {
1201
+ const made = createSubagentFrom(store, { repo: payload.repo, soul: String(req["soul"]), by: actor }, now);
1189
1202
  if (!made.ok)
1190
1203
  throw Error(made.said);
1191
- return { said: made.said, href: `/teammates/${made.id}` };
1204
+ return { said: made.said, href: `/settings/lead/subagents/${made.id}` };
1192
1205
  }
1193
- if (payload.operation === "teammate_answer") {
1194
- const question = store.teammateQuestion(Number(req["question"]));
1195
- const answered = answerTeammateQuestion(store, Number(req["question"]), { choice: req["choice"] === null ? null : String(req["choice"]), text: req["text"] === null ? null : String(req["text"]), by: actor, via: "chat" }, now);
1206
+ if (payload.operation === "subagent_answer") {
1207
+ const question = store.subagentQuestion(Number(req["question"]));
1208
+ const answered = answerSubagentQuestion(store, Number(req["question"]), { choice: req["choice"] === null ? null : String(req["choice"]), text: req["text"] === null ? null : String(req["text"]), by: actor, via: "chat" }, now);
1196
1209
  if (!answered.ok)
1197
1210
  throw Error(answered.said);
1198
- return { said: answered.said, href: question === null ? "/teammates" : `/teammates/${question.teammate}` };
1211
+ return { said: answered.said, href: question === null ? "/settings/lead/subagents" : `/settings/lead/subagents/${question.subagent}` };
1199
1212
  }
1200
- const mate = store.getTeammate(Number(req["teammate"]));
1213
+ const mate = store.getSubagent(Number(req["subagent"]));
1201
1214
  if (mate === null || mate.state === "removed")
1202
- throw Error("That teammate is off the team.");
1203
- if (payload.operation === "teammate_undo") {
1215
+ throw Error("That subagent is off the team.");
1216
+ if (payload.operation === "subagent_ask") {
1217
+ // One card per confirmed proposal: the confirmation runs once, so a retried tap never asks twice.
1218
+ if (mate.version !== payload.state["version"])
1219
+ throw Error("Someone changed its soul file since. Ask for a fresh proposal.");
1220
+ const asked = askSubagent(store, mate, { who: actor, via: "the lead" }, String(req["text"]), now);
1221
+ if (!asked.ok)
1222
+ throw Error(asked.said);
1223
+ return { said: asked.said, href: asked.link.path };
1224
+ }
1225
+ if (payload.operation === "subagent_undo") {
1204
1226
  const asked = requestUndo(store, mate, Number(req["call"]), actor, now);
1205
1227
  if (!asked.ok)
1206
1228
  throw Error(asked.said);
1207
- return { said: `${asked.said} The receipt on the card shows how it went.`, href: `/teammates/${mate.id}#week` };
1229
+ return { said: `${asked.said} The receipt on the card shows how it went.`, href: `/settings/lead/subagents/${mate.id}#week` };
1208
1230
  }
1209
- if (payload.operation === "teammate_routine") {
1231
+ if (payload.operation === "subagent_routine") {
1210
1232
  const done = req["change"] === "add" ? addRoutine(store, mate, String(req["schedule"]), String(req["text"]), actor, now, null)
1211
1233
  : removeRoutine(store, mate, Number(req["routine"]), now, null);
1212
1234
  if (!done.ok)
1213
1235
  throw Error(done.said);
1214
- return { said: done.said, href: `/teammates/${mate.id}#desk` };
1236
+ return { said: done.said, href: `/settings/lead/subagents/${mate.id}#desk` };
1215
1237
  }
1216
- if (payload.operation === "teammate_memory") {
1217
- const memory = store.teammateMemory(Number(req["memory"]));
1238
+ if (payload.operation === "subagent_memory") {
1239
+ const memory = store.subagentMemory(Number(req["memory"]));
1218
1240
  if (memory === null || memory.text !== payload.state["text"])
1219
1241
  throw Error("That memory changed since. Ask for a fresh proposal.");
1220
1242
  const done = req["change"] === "forget" ? forgetMemory(store, mate, memory.id, actor, now) : editMemory(store, mate, memory.id, String(req["text"]), actor, now);
1221
1243
  if (!done.ok)
1222
1244
  throw Error(done.said);
1223
- return { said: done.said, href: `/teammates/${mate.id}#memory` };
1245
+ return { said: done.said, href: `/settings/lead/subagents/${mate.id}#memory` };
1224
1246
  }
1225
- if (payload.operation === "teammate_tools") {
1247
+ if (payload.operation === "subagent_tools") {
1226
1248
  const tool = String(req["tool"]);
1227
- const grant = store.teammateGrant(mate.id, tool);
1249
+ const grant = store.subagentGrant(mate.id, tool);
1228
1250
  if ((grant === null ? "" : JSON.stringify(grant.rules)) !== payload.state["rules"])
1229
1251
  throw Error("Someone changed its tools since. Ask for a fresh proposal.");
1230
1252
  const found = projectToolsOf(store, mate.repo).find(one => one.name === tool);
@@ -1234,16 +1256,16 @@ function runTeammateAction(store, payload, actor, now) {
1234
1256
  undo: req["undoWith"] ?? grant?.rules[String(req["action"])]?.undo ?? "" } }, actor, now);
1235
1257
  if (!done.ok)
1236
1258
  throw Error(done.said);
1237
- return { said: done.said, href: `/teammates/${mate.id}#tools` };
1259
+ return { said: done.said, href: `/settings/lead/subagents/${mate.id}#tools` };
1238
1260
  }
1239
- if (payload.operation === "teammate_soul" && mate.version !== payload.state["version"])
1261
+ if (payload.operation === "subagent_soul" && mate.version !== payload.state["version"])
1240
1262
  throw Error("Someone changed its soul file since. Ask for a fresh proposal.");
1241
- const done = payload.operation === "teammate_soul" ? saveSoul(store, mate, String(req["soul"]), actor, now)
1242
- : payload.operation === "teammate_state" ? setTeammateState(store, mate, req["state"], actor, now)
1243
- : tellTeammate(store, mate, String(req["note"]), actor, now);
1263
+ const done = payload.operation === "subagent_soul" ? saveSoul(store, mate, String(req["soul"]), actor, now)
1264
+ : payload.operation === "subagent_state" ? setSubagentState(store, mate, req["state"], actor, now)
1265
+ : tellSubagent(store, mate, String(req["note"]), actor, now);
1244
1266
  if (!done.ok)
1245
1267
  throw Error(done.said);
1246
- return { said: done.said, href: payload.operation === "teammate_state" && req["state"] === "removed" ? "/teammates" : `/teammates/${mate.id}` };
1268
+ return { said: done.said, href: payload.operation === "subagent_state" && req["state"] === "removed" ? "/settings/lead/subagents" : `/settings/lead/subagents/${mate.id}` };
1247
1269
  }
1248
1270
  /** A confirmed flow action, through the same helpers the canvas uses; then
1249
1271
  * the flow moves what it can right away, as it does after a canvas change. */
@@ -11,9 +11,9 @@
11
11
  * asked, and only while nobody has written in that thread since.
12
12
  */
13
13
  import type { ChatBinding, ChatEvent, ChatState } from "./chat-delivery-state.js";
14
- import { type MateAsk, type Store } from "./store.js";
14
+ import { type LeadAsk, type Store } from "./store.js";
15
15
  /** The question as text with its options, where no buttons are drawn. */
16
- export declare function chatAskText(ask: Pick<MateAsk, "question" | "options">): string;
16
+ export declare function chatAskText(ask: Pick<LeadAsk, "question" | "options">): string;
17
17
  /** The live buttons on one part, in the order they were minted: the options, then "Something else". None when the part
18
18
  * is not in its owner's own chat with Toolroll (a room), where a tap could not be their message. */
19
19
  export declare function chatAskButtons(state: ChatState, part: number, now: Date): Array<{