toolroll 0.9.54 → 0.9.56

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 (350) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +29 -12
  3. package/dist/action-ledger.d.ts +2 -4
  4. package/dist/action-ledger.js +2 -10
  5. package/dist/agent-onboard.js +4 -1
  6. package/dist/approval-policy.d.ts +5 -5
  7. package/dist/approval-policy.js +4 -4
  8. package/dist/approval-rules-ui.d.ts +3 -2
  9. package/dist/approval-rules-ui.js +17 -22
  10. package/dist/assignment-ui.d.ts +3 -2
  11. package/dist/assignment-ui.js +4 -11
  12. package/dist/backup-ui.d.ts +2 -1
  13. package/dist/backup-ui.js +16 -27
  14. package/dist/brand-mark.d.ts +3 -2
  15. package/dist/brand-mark.js +4 -4
  16. package/dist/browser/workspace.css +1 -1
  17. package/dist/browser/workspace.js +25 -25
  18. package/dist/browser-shell.d.ts +2 -1
  19. package/dist/browser-shell.js +9 -9
  20. package/dist/browser-workspace.d.ts +14 -15
  21. package/dist/browser-workspace.js +0 -3
  22. package/dist/budget-alerts.js +3 -3
  23. package/dist/chat-actions.d.ts +23 -18
  24. package/dist/chat-actions.js +110 -88
  25. package/dist/chat-ask.d.ts +2 -2
  26. package/dist/chat-ask.js +5 -5
  27. package/dist/chat-channel.d.ts +15 -15
  28. package/dist/chat-channel.js +20 -20
  29. package/dist/chat-controls.d.ts +0 -4
  30. package/dist/chat-controls.js +0 -1
  31. package/dist/chat-core.js +1 -1
  32. package/dist/chat-delivery-state.js +2 -2
  33. package/dist/chat-delivery.d.ts +2 -2
  34. package/dist/chat-delivery.js +27 -34
  35. package/dist/chat-flow.js +3 -3
  36. package/dist/chat-messages.d.ts +1 -1
  37. package/dist/chat-messages.js +4 -4
  38. package/dist/chat-migration.d.ts +1 -1
  39. package/dist/chat-migration.js +11 -11
  40. package/dist/chat-polish.d.ts +5 -4
  41. package/dist/chat-polish.js +9 -10
  42. package/dist/chat-rooms.js +3 -3
  43. package/dist/chat-warmth.d.ts +2 -2
  44. package/dist/check-levels-ui.d.ts +2 -1
  45. package/dist/check-levels-ui.js +26 -53
  46. package/dist/cli.d.ts +3 -1
  47. package/dist/cli.js +15 -10
  48. package/dist/coding-shipping-ui.d.ts +2 -1
  49. package/dist/coding-shipping-ui.js +6 -6
  50. package/dist/coding-ui.d.ts +3 -1
  51. package/dist/coding-ui.js +30 -29
  52. package/dist/contracts/chat-actions.d.ts +32 -27
  53. package/dist/contracts/chat-actions.js +29 -11
  54. package/dist/contracts/chat-content.d.ts +1 -1
  55. package/dist/contracts/chat-content.js +1 -1
  56. package/dist/contracts/chat-tables.js +4 -4
  57. package/dist/contracts/cli.d.ts +1 -3
  58. package/dist/contracts/console-api.d.ts +7 -7
  59. package/dist/contracts/console-api.js +13 -12
  60. package/dist/contracts/flow-propose.d.ts +3 -3
  61. package/dist/contracts/flow.d.ts +132 -125
  62. package/dist/contracts/flow.js +27 -12
  63. package/dist/contracts/health.d.ts +1 -3
  64. package/dist/contracts/lead-context.d.ts +1 -1
  65. package/dist/contracts/lead-context.js +2 -2
  66. package/dist/contracts/lead-tools.d.ts +20 -18
  67. package/dist/contracts/lead-tools.js +15 -15
  68. package/dist/contracts/stage-output.d.ts +1 -1
  69. package/dist/contracts/stage-output.js +1 -1
  70. package/dist/contracts/store-json.d.ts +23 -22
  71. package/dist/contracts/store-json.js +17 -17
  72. package/dist/contracts/{teammate-turn.d.ts → subagent-turn.d.ts} +5 -5
  73. package/dist/contracts/{teammate-turn.js → subagent-turn.js} +7 -7
  74. package/dist/control-ui.d.ts +5 -4
  75. package/dist/control-ui.js +9 -34
  76. package/dist/converse.d.ts +23 -23
  77. package/dist/converse.js +28 -28
  78. package/dist/coordinator-proposals.d.ts +2 -2
  79. package/dist/coordinator-proposals.js +1 -1
  80. package/dist/coordinator.js +1 -1
  81. package/dist/credentials-ui.d.ts +5 -4
  82. package/dist/credentials-ui.js +23 -24
  83. package/dist/demo-chat.d.ts +3 -3
  84. package/dist/demo-chat.js +29 -76
  85. package/dist/deprecations.d.ts +12 -0
  86. package/dist/deprecations.js +20 -0
  87. package/dist/desktop-update-gate.js +8 -4
  88. package/dist/desktop-update.js +6 -1
  89. package/dist/discord-chat.js +6 -6
  90. package/dist/discord-settings.d.ts +3 -2
  91. package/dist/discord-settings.js +17 -42
  92. package/dist/dispatch.d.ts +1 -1
  93. package/dist/dispatch.js +1 -1
  94. package/dist/envelope.js +10 -1
  95. package/dist/evidence-pack.d.ts +2 -1
  96. package/dist/evidence-pack.js +45 -49
  97. package/dist/export-ui.d.ts +7 -2
  98. package/dist/export-ui.js +4 -10
  99. package/dist/export.js +7 -7
  100. package/dist/flow-engine.d.ts +2 -2
  101. package/dist/flow-engine.js +21 -21
  102. package/dist/flow-gallery-ui.d.ts +4 -3
  103. package/dist/flow-gallery-ui.js +28 -43
  104. package/dist/flow-insights.d.ts +1 -1
  105. package/dist/flow-share.js +13 -8
  106. package/dist/flow-starters-ui.d.ts +2 -1
  107. package/dist/flow-starters-ui.js +12 -15
  108. package/dist/flow-steps.d.ts +5 -5
  109. package/dist/flow-steps.js +19 -19
  110. package/dist/flow-triggers.d.ts +2 -1
  111. package/dist/flow-triggers.js +17 -15
  112. package/dist/flows-cli.js +1 -1
  113. package/dist/flows-ui.d.ts +4 -3
  114. package/dist/flows-ui.js +38 -49
  115. package/dist/flows.js +21 -20
  116. package/dist/guides.js +112 -6
  117. package/dist/html.d.ts +76 -0
  118. package/dist/html.js +173 -0
  119. package/dist/integrations-ui.d.ts +2 -1
  120. package/dist/integrations-ui.js +19 -23
  121. package/dist/invoke.js +1 -1
  122. package/dist/kits-ui.d.ts +5 -4
  123. package/dist/kits-ui.js +22 -24
  124. package/dist/kits.d.ts +12 -12
  125. package/dist/kits.js +31 -31
  126. package/dist/knowledge-ui.d.ts +6 -5
  127. package/dist/knowledge-ui.js +26 -25
  128. package/dist/{mate-cli.d.ts → lead-cli.d.ts} +11 -11
  129. package/dist/{mate-cli.js → lead-cli.js} +38 -38
  130. package/dist/lead-commitments.js +4 -4
  131. package/dist/lead-context.d.ts +12 -2
  132. package/dist/lead-context.js +15 -17
  133. package/dist/{mate-contract.d.ts → lead-contract.d.ts} +3 -3
  134. package/dist/{mate-contract.js → lead-contract.js} +7 -6
  135. package/dist/{mate-doors.d.ts → lead-doors.d.ts} +6 -6
  136. package/dist/{mate-doors.js → lead-doors.js} +24 -24
  137. package/dist/lead-follow.d.ts +5 -5
  138. package/dist/lead-follow.js +9 -9
  139. package/dist/lead-people.d.ts +5 -5
  140. package/dist/lead-people.js +14 -14
  141. package/dist/{mate-progress.d.ts → lead-progress.d.ts} +9 -9
  142. package/dist/{mate-progress.js → lead-progress.js} +3 -3
  143. package/dist/{mate-tools.d.ts → lead-tools.d.ts} +19 -19
  144. package/dist/{mate-tools.js → lead-tools.js} +109 -101
  145. package/dist/{mate.d.ts → lead.d.ts} +27 -27
  146. package/dist/{mate.js → lead.js} +102 -102
  147. package/dist/ledger-view.d.ts +2 -1
  148. package/dist/ledger-view.js +27 -29
  149. package/dist/limits-ui.d.ts +3 -2
  150. package/dist/limits-ui.js +8 -8
  151. package/dist/live-bus.d.ts +50 -8
  152. package/dist/live-bus.js +133 -50
  153. package/dist/mcp-connect.d.ts +1 -1
  154. package/dist/mcp-connect.js +3 -3
  155. package/dist/mcp-core.js +1 -1
  156. package/dist/mcp-oauth.js +35 -36
  157. package/dist/memory-pass.d.ts +2 -2
  158. package/dist/memory-pass.js +7 -7
  159. package/dist/models-ui.d.ts +2 -1
  160. package/dist/models-ui.js +25 -35
  161. package/dist/monitoring-ui.d.ts +4 -3
  162. package/dist/monitoring-ui.js +13 -26
  163. package/dist/notification-rows.d.ts +2 -2
  164. package/dist/openrouter-models.d.ts +2 -1
  165. package/dist/openrouter-models.js +5 -9
  166. package/dist/operate.d.ts +3 -3
  167. package/dist/operate.js +46 -41
  168. package/dist/people-audit-ui.d.ts +2 -1
  169. package/dist/people-audit-ui.js +13 -13
  170. package/dist/policy-ui.d.ts +3 -2
  171. package/dist/policy-ui.js +17 -23
  172. package/dist/policy.d.ts +1 -1
  173. package/dist/principal.d.ts +1 -1
  174. package/dist/principal.js +2 -2
  175. package/dist/project-delete-ui.d.ts +4 -3
  176. package/dist/project-delete-ui.js +16 -28
  177. package/dist/project-delete.d.ts +1 -1
  178. package/dist/project-delete.js +26 -26
  179. package/dist/project-memory.js +1 -1
  180. package/dist/project-tools.d.ts +1 -1
  181. package/dist/project-tools.js +1 -1
  182. package/dist/pull-request-ui.d.ts +2 -1
  183. package/dist/pull-request-ui.js +17 -32
  184. package/dist/recipe-ui.d.ts +8 -7
  185. package/dist/recipe-ui.js +39 -32
  186. package/dist/release-adapters.d.ts +60 -0
  187. package/dist/release-adapters.js +435 -0
  188. package/dist/release-cli.d.ts +24 -0
  189. package/dist/release-cli.js +181 -0
  190. package/dist/release-gate.d.ts +80 -0
  191. package/dist/release-gate.js +150 -0
  192. package/dist/release-links.d.ts +29 -0
  193. package/dist/release-links.js +102 -0
  194. package/dist/release.d.ts +331 -0
  195. package/dist/release.js +550 -0
  196. package/dist/reply-shape.d.ts +2 -1
  197. package/dist/reply-shape.js +5 -5
  198. package/dist/repository-context-ui.d.ts +2 -1
  199. package/dist/repository-context-ui.js +2 -7
  200. package/dist/request-budget-ui.d.ts +2 -1
  201. package/dist/request-budget-ui.js +16 -16
  202. package/dist/result-review.d.ts +2 -3
  203. package/dist/result-review.js +3 -9
  204. package/dist/retention-ui.d.ts +7 -1
  205. package/dist/retention-ui.js +7 -11
  206. package/dist/retention.js +4 -4
  207. package/dist/scope.d.ts +2 -2
  208. package/dist/scout-report.d.ts +1 -1
  209. package/dist/scout-report.js +1 -1
  210. package/dist/serve.d.ts +11 -2
  211. package/dist/serve.js +105 -99
  212. package/dist/server/chat.d.ts +7 -10
  213. package/dist/server/chat.js +984 -1021
  214. package/dist/server/chrome.d.ts +291 -0
  215. package/dist/server/chrome.js +747 -0
  216. package/dist/server/console.css +2819 -0
  217. package/dist/server/flows.d.ts +2 -6
  218. package/dist/server/flows.js +854 -773
  219. package/dist/server/guards.d.ts +1 -1
  220. package/dist/server/guards.js +8 -5
  221. package/dist/server/handler-context.d.ts +1 -1
  222. package/dist/server/handler-context.js +1 -1
  223. package/dist/server/handler-registry.d.ts +8 -6
  224. package/dist/server/handler-registry.js +14 -2
  225. package/dist/server/http.d.ts +274 -0
  226. package/dist/server/http.js +239 -0
  227. package/dist/server/live.d.ts +34 -0
  228. package/dist/server/live.js +309 -0
  229. package/dist/server/pages.d.ts +2 -6
  230. package/dist/server/pages.js +808 -789
  231. package/dist/server/people-tokens.d.ts +1 -6
  232. package/dist/server/people-tokens.js +581 -573
  233. package/dist/server/remote.d.ts +4 -7
  234. package/dist/server/remote.js +39 -70
  235. package/dist/server/render-chat.d.ts +402 -0
  236. package/dist/server/render-chat.js +927 -0
  237. package/dist/server/render-pages.d.ts +535 -0
  238. package/dist/server/render-pages.js +1277 -0
  239. package/dist/server/render-people.d.ts +32 -0
  240. package/dist/server/render-people.js +121 -0
  241. package/dist/server/render-results.d.ts +744 -0
  242. package/dist/server/render-results.js +2237 -0
  243. package/dist/server/render-settings.d.ts +154 -0
  244. package/dist/server/render-settings.js +580 -0
  245. package/dist/server/render-tasks.d.ts +632 -0
  246. package/dist/server/render-tasks.js +2345 -0
  247. package/dist/server/request-context.d.ts +46 -0
  248. package/dist/server/request-context.js +17 -0
  249. package/dist/server/route-table.d.ts +25 -3
  250. package/dist/server/route-table.js +167 -77
  251. package/dist/server/runtime.d.ts +28 -20
  252. package/dist/server/runtime.js +7 -1
  253. package/dist/server/session.d.ts +138 -0
  254. package/dist/server/session.js +94 -0
  255. package/dist/server/settings.d.ts +1 -5
  256. package/dist/server/settings.js +2186 -2121
  257. package/dist/server/task-views.d.ts +11 -4
  258. package/dist/server/task-views.js +26 -22
  259. package/dist/server/tasks.d.ts +9 -9
  260. package/dist/server/tasks.js +1489 -1420
  261. package/dist/server-telemetry.d.ts +4 -3
  262. package/dist/server-telemetry.js +4 -8
  263. package/dist/setup-guide.d.ts +2 -2
  264. package/dist/skills-ui.d.ts +4 -3
  265. package/dist/skills-ui.js +14 -17
  266. package/dist/skills.d.ts +1 -1
  267. package/dist/skills.js +2 -1
  268. package/dist/slack-chat.d.ts +2 -2
  269. package/dist/slack-chat.js +6 -6
  270. package/dist/slack-settings.d.ts +3 -2
  271. package/dist/slack-settings.js +17 -42
  272. package/dist/spend-ui.d.ts +5 -4
  273. package/dist/spend-ui.js +17 -40
  274. package/dist/spend.d.ts +14 -14
  275. package/dist/spend.js +31 -31
  276. package/dist/sso-ui.d.ts +3 -2
  277. package/dist/sso-ui.js +26 -27
  278. package/dist/storage-ui.d.ts +2 -1
  279. package/dist/storage-ui.js +14 -33
  280. package/dist/store-baseline.d.ts +19 -0
  281. package/dist/store-baseline.js +2873 -0
  282. package/dist/store.d.ts +197 -249
  283. package/dist/store.js +747 -3084
  284. package/dist/subagent-admin.d.ts +53 -0
  285. package/dist/{teammate-admin.js → subagent-admin.js} +37 -37
  286. package/dist/{teammate-desk.d.ts → subagent-desk.d.ts} +22 -23
  287. package/dist/{teammate-desk.js → subagent-desk.js} +26 -35
  288. package/dist/{teammate-memory.d.ts → subagent-memory.d.ts} +17 -17
  289. package/dist/{teammate-memory.js → subagent-memory.js} +41 -41
  290. package/dist/{teammate-question.d.ts → subagent-question.d.ts} +6 -6
  291. package/dist/{teammate-question.js → subagent-question.js} +17 -17
  292. package/dist/{teammate-tools.d.ts → subagent-tools.d.ts} +18 -18
  293. package/dist/{teammate-tools.js → subagent-tools.js} +36 -36
  294. package/dist/{teammate-week.d.ts → subagent-week.d.ts} +10 -10
  295. package/dist/{teammate-week.js → subagent-week.js} +23 -23
  296. package/dist/{teammate-work.d.ts → subagent-work.d.ts} +21 -21
  297. package/dist/{teammate-work.js → subagent-work.js} +50 -50
  298. package/dist/subagents-ui.d.ts +22 -0
  299. package/dist/subagents-ui.js +137 -0
  300. package/dist/{teammates.d.ts → subagents.d.ts} +11 -11
  301. package/dist/{teammates.js → subagents.js} +21 -21
  302. package/dist/subscription-chat.d.ts +13 -13
  303. package/dist/subscription-chat.js +19 -19
  304. package/dist/surface.d.ts +19 -2
  305. package/dist/surface.js +20 -33
  306. package/dist/task-composer.d.ts +2 -1
  307. package/dist/task-composer.js +7 -7
  308. package/dist/task-status.d.ts +4 -3
  309. package/dist/task-status.js +15 -16
  310. package/dist/team-cli.d.ts +1 -0
  311. package/dist/team-cli.js +14 -2
  312. package/dist/team-http.d.ts +5 -9
  313. package/dist/team-http.js +5 -63
  314. package/dist/team-leads.js +13 -13
  315. package/dist/team-runtime.d.ts +2 -2
  316. package/dist/team-runtime.js +8 -8
  317. package/dist/team-ui.d.ts +2 -1
  318. package/dist/team-ui.js +2 -5
  319. package/dist/teams-chat.js +6 -6
  320. package/dist/teams-settings.d.ts +3 -2
  321. package/dist/teams-settings.js +20 -31
  322. package/dist/telegram-flow.d.ts +3 -3
  323. package/dist/telegram-flow.js +3 -3
  324. package/dist/{telegram-mate.d.ts → telegram-lead.d.ts} +5 -5
  325. package/dist/{telegram-mate.js → telegram-lead.js} +27 -27
  326. package/dist/telegram-settings.d.ts +3 -2
  327. package/dist/telegram-settings.js +14 -25
  328. package/dist/telegram-status.js +1 -1
  329. package/dist/telegram-team.d.ts +1 -1
  330. package/dist/telegram-team.js +5 -5
  331. package/dist/telegram.d.ts +1 -1
  332. package/dist/telegram.js +9 -30
  333. package/dist/text-limits.d.ts +18 -18
  334. package/dist/text-limits.js +18 -18
  335. package/dist/toolroll-update-ui.d.ts +3 -2
  336. package/dist/toolroll-update-ui.js +35 -39
  337. package/dist/toolroll-update.d.ts +8 -0
  338. package/dist/toolroll-update.js +45 -8
  339. package/dist/tools-ui.d.ts +5 -2
  340. package/dist/tools-ui.js +31 -31
  341. package/dist/when-html.d.ts +11 -3
  342. package/dist/when-html.js +5 -6
  343. package/dist/workspace-ui.d.ts +4 -2
  344. package/dist/workspace-ui.js +10 -10
  345. package/package.json +1 -2
  346. package/dist/server/shared.d.ts +0 -3151
  347. package/dist/server/shared.js +0 -12001
  348. package/dist/teammate-admin.d.ts +0 -53
  349. package/dist/teammates-ui.d.ts +0 -20
  350. package/dist/teammates-ui.js +0 -166
@@ -1,53 +0,0 @@
1
- /**
2
- * Looking after AI teammates (v92): making one from a template or a soul
3
- * file, editing its soul (a new version each time), pausing or removing it,
4
- * telling it something, and the daily summary it sends its manager.
5
- *
6
- * Shared by the Teammates pages and the lead chat, so both do the same thing.
7
- */
8
- import type { Store, TeammateRow } from "./store.js";
9
- export type Done = {
10
- ok: true;
11
- said: string;
12
- id?: number;
13
- } | {
14
- ok: false;
15
- said: string;
16
- };
17
- export declare const TEAMMATE_MODELS: readonly ["default", "sonnet", "opus", "haiku"];
18
- /** A soul file with a different name: the template's, renamed. */
19
- export declare function renamedSoul(soul: string, name: string): string;
20
- /** A new teammate in a project, from a template (optionally renamed) or a whole soul file. */
21
- export declare function createTeammateFrom(store: Store, input: {
22
- repo: string;
23
- template?: string | null;
24
- name?: string | null;
25
- soul?: string | null;
26
- by: string;
27
- }, now: Date): Done;
28
- /** Save a new version of a teammate's soul file. Its name stays: zones name it by handle. */
29
- export declare function saveSoul(store: Store, mate: TeammateRow, soul: string, by: string, now: Date): Done;
30
- /** Pause, resume or remove. Paused, its decisions go to people and the zones it handles wait. */
31
- export declare function setTeammateState(store: Store, mate: TeammateRow, state: "active" | "paused" | "removed", by: string, now: Date): Done;
32
- export declare function teammateSettings(store: Store, mate: TeammateRow, change: {
33
- model?: string;
34
- dailyTurns?: number;
35
- manager?: string;
36
- }, by: string, now: Date): Done;
37
- export declare const nameOf: (mate: TeammateRow) => string;
38
- export declare const labelOf: (mate: TeammateRow) => string;
39
- /** Every zone a teammate works, in every flow of its project. */
40
- export declare function zonesOf(store: Store, mate: TeammateRow): {
41
- flow: number;
42
- flowName: string;
43
- zone: string;
44
- title: string;
45
- kind: "decides" | "handles";
46
- }[];
47
- /** What a teammate did since a time, in words its manager reads at a glance. */
48
- export declare function summaryOf(store: Store, mate: TeammateRow, since: string | null): {
49
- said: string;
50
- quiet: boolean;
51
- };
52
- /** The daily summary, to each teammate's manager, once a day after 5 pm (this computer's time), or now when asked. */
53
- export declare function sendTeammateSummaries(store: Store, repo: string, now: Date, only?: number | null): number;
@@ -1,20 +0,0 @@
1
- /**
2
- * The Teammates pages (v92): who is on the team, and one page per teammate —
3
- * what it asks you, its soul file, what it did and why, what you told it,
4
- * and its settings. Server-rendered forms, like the other settings pages.
5
- */
6
- import type { Store, TeammateRow } from "./store.js";
7
- /** v94: the Tools section's rule rows; a limit's fields show only while "Up to a limit" is chosen. */
8
- export declare const TEAMMATE_CSS = ".teammate-tools .tool-grant{border-top:1px solid var(--so-line);padding-top:12px;margin-top:12px}.teammate-tools .tool-grant:first-of-type{border-top:0;margin-top:0;padding-top:0}.teammate-tools h3{font-size:1rem;margin:0 0 4px}.teammate-tools .tool-rule{display:grid;gap:6px;padding:10px 0;border-bottom:1px solid var(--so-line)}.teammate-tools .tool-rule:last-of-type{border-bottom:0}.teammate-tools .tool-rule .meta{display:block}.teammate-tools select,.teammate-tools input{max-width:100%;box-sizing:border-box}.teammate-tools .tool-limit{display:none;flex-wrap:wrap;align-items:center;gap:6px}.teammate-tools .tool-rule:has(option[value=\"limit\"]:checked) .tool-limit{display:flex}.teammate-tools .tool-rule>select{width:auto;min-width:16em}.teammate-tools .tool-limit select{width:auto}.teammate-tools .tool-limit input{width:7em}.teammate-tools .tool-buttons{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}.teammate-tools button{min-height:44px}.teammate-activity li{overflow-wrap:anywhere}.teammate-memory .memory-tell,.teammate-memory .memory-search{display:flex;flex-wrap:wrap;gap:8px;align-items:flex-end;margin:0 0 12px}.teammate-memory .memory-tell textarea{flex:1 1 280px}.teammate-memory .memory-search input{flex:1 1 220px}.teammate-memory button{min-height:44px}.teammate-memories{list-style:none;padding:0;margin:0}.teammate-memories li{padding:10px 0;border-top:1px solid var(--so-line);overflow-wrap:anywhere}.teammate-memories li:first-child{border-top:0}.teammate-memories .meta{display:block;font-size:.85rem}.teammate-memories details.memory-edit{border:0;padding:0;margin:2px 0 0;background:transparent;box-shadow:none}.memory-edit summary{cursor:pointer;min-height:32px;display:inline-flex;align-items:center;font-size:.85rem;font-weight:400;color:var(--so-muted)}.tool-undo{border:0;padding:0;margin:8px 0;background:transparent;box-shadow:none}.tool-undo summary{cursor:pointer;min-height:36px;display:inline-flex;align-items:center;font-size:.9rem}.tool-undo-row{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin:6px 0}.tool-undo-row select{width:auto}.teammate-overrides,.teammate-undo{padding-left:18px}.teammate-undo li{margin:6px 0}.teammate-undo form{display:inline}.teammate-week h3{font-size:1rem;margin:14px 0 4px}.teammate-week button{min-height:44px}.teammate-routines{list-style:none;padding:0;margin:8px 0}.teammate-routines li{display:grid;gap:4px;padding:10px 0;border-top:1px solid var(--so-line)}.teammate-routines li:first-child{border-top:0}.routine-buttons{display:flex;flex-wrap:wrap;gap:8px}.routine-buttons button,.routine-add button{min-height:44px}.routine-add{display:flex;flex-wrap:wrap;gap:8px;align-items:flex-end;margin:8px 0}.routine-add label{display:grid;gap:4px;flex:1 1 200px}.routine-add label:first-of-type{flex:0 1 180px}.teammate-actions,.question-options{display:flex;flex-wrap:wrap;gap:8px;margin:8px 0}.teammate-actions form,.question-options form{margin:0}.memory-edit form{display:grid;gap:8px;margin-top:6px}.memory-buttons{display:flex;flex-wrap:wrap;gap:8px}@media(max-width:600px){.teammate-tools select,.teammate-tools input{font-size:16px}}";
9
- /** A blank soul file: the sections a teammate reads, to fill in. */
10
- export declare const BLANK_SOUL = "---\nname: \nrole: \n---\n\n## Who you are\n\n\n## How you write\n\n\n## What you know\n\n\n## Decide on your own\n- \n\n## Ask first\n- \n\n## Never\n- \n";
11
- export declare function teammatesListHtml(store: Store, mates: readonly TeammateRow[], projects: readonly string[], projectName: (repo: string) => string, csrf: string, canCreate: boolean, notice: {
12
- said?: string | null;
13
- problem?: string | null;
14
- }): string;
15
- export declare function teammatePageHtml(store: Store, mate: TeammateRow, viewer: string, projectName: (repo: string) => string, csrf: string, canManage: boolean, approvers: readonly string[], notice: {
16
- said?: string | null;
17
- problem?: string | null;
18
- soulDraft?: string | null;
19
- query?: string | null;
20
- }): string;
@@ -1,166 +0,0 @@
1
- import { labelOf, nameOf, summaryOf, TEAMMATE_MODELS, zonesOf } from "./teammate-admin.js";
2
- import { TEAMMATE_TEMPLATES } from "./teammates.js";
3
- import { projectToolsOf } from "./project-tools.js";
4
- import { callWords, defaultRule, numberFields, receiptWords } from "./teammate-tools.js";
5
- import { MEMORY_CHARS, searchMemories } from "./teammate-memory.js";
6
- import { deskOf, localZone, routinesOf } from "./teammate-desk.js";
7
- import { weekOf, weekWords } from "./teammate-week.js";
8
- import { describeSchedule, parseSchedule } from "./flow-schedule.js";
9
- /** v94: the Tools section's rule rows; a limit's fields show only while "Up to a limit" is chosen. */
10
- export const TEAMMATE_CSS = `.teammate-tools .tool-grant{border-top:1px solid var(--so-line);padding-top:12px;margin-top:12px}.teammate-tools .tool-grant:first-of-type{border-top:0;margin-top:0;padding-top:0}.teammate-tools h3{font-size:1rem;margin:0 0 4px}.teammate-tools .tool-rule{display:grid;gap:6px;padding:10px 0;border-bottom:1px solid var(--so-line)}.teammate-tools .tool-rule:last-of-type{border-bottom:0}.teammate-tools .tool-rule .meta{display:block}.teammate-tools select,.teammate-tools input{max-width:100%;box-sizing:border-box}.teammate-tools .tool-limit{display:none;flex-wrap:wrap;align-items:center;gap:6px}.teammate-tools .tool-rule:has(option[value="limit"]:checked) .tool-limit{display:flex}.teammate-tools .tool-rule>select{width:auto;min-width:16em}.teammate-tools .tool-limit select{width:auto}.teammate-tools .tool-limit input{width:7em}.teammate-tools .tool-buttons{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}.teammate-tools button{min-height:44px}.teammate-activity li{overflow-wrap:anywhere}.teammate-memory .memory-tell,.teammate-memory .memory-search{display:flex;flex-wrap:wrap;gap:8px;align-items:flex-end;margin:0 0 12px}.teammate-memory .memory-tell textarea{flex:1 1 280px}.teammate-memory .memory-search input{flex:1 1 220px}.teammate-memory button{min-height:44px}.teammate-memories{list-style:none;padding:0;margin:0}.teammate-memories li{padding:10px 0;border-top:1px solid var(--so-line);overflow-wrap:anywhere}.teammate-memories li:first-child{border-top:0}.teammate-memories .meta{display:block;font-size:.85rem}.teammate-memories details.memory-edit{border:0;padding:0;margin:2px 0 0;background:transparent;box-shadow:none}.memory-edit summary{cursor:pointer;min-height:32px;display:inline-flex;align-items:center;font-size:.85rem;font-weight:400;color:var(--so-muted)}.tool-undo{border:0;padding:0;margin:8px 0;background:transparent;box-shadow:none}.tool-undo summary{cursor:pointer;min-height:36px;display:inline-flex;align-items:center;font-size:.9rem}.tool-undo-row{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin:6px 0}.tool-undo-row select{width:auto}.teammate-overrides,.teammate-undo{padding-left:18px}.teammate-undo li{margin:6px 0}.teammate-undo form{display:inline}.teammate-week h3{font-size:1rem;margin:14px 0 4px}.teammate-week button{min-height:44px}.teammate-routines{list-style:none;padding:0;margin:8px 0}.teammate-routines li{display:grid;gap:4px;padding:10px 0;border-top:1px solid var(--so-line)}.teammate-routines li:first-child{border-top:0}.routine-buttons{display:flex;flex-wrap:wrap;gap:8px}.routine-buttons button,.routine-add button{min-height:44px}.routine-add{display:flex;flex-wrap:wrap;gap:8px;align-items:flex-end;margin:8px 0}.routine-add label{display:grid;gap:4px;flex:1 1 200px}.routine-add label:first-of-type{flex:0 1 180px}.teammate-actions,.question-options{display:flex;flex-wrap:wrap;gap:8px;margin:8px 0}.teammate-actions form,.question-options form{margin:0}.memory-edit form{display:grid;gap:8px;margin-top:6px}.memory-buttons{display:flex;flex-wrap:wrap;gap:8px}@media(max-width:600px){.teammate-tools select,.teammate-tools input{font-size:16px}}`;
11
- const USES = [["free", "Do it"], ["limit", "Do it, up to a limit"], ["ask", "Ask first"], ["never", "Never"]];
12
- /** v94: which project tools it may use, and its rule for each action. */
13
- function toolsSection(store, mate, csrf, canManage) {
14
- const name = nameOf(mate);
15
- const tools = projectToolsOf(store, mate.repo);
16
- const grants = store.teammateGrants(mate.id);
17
- const toolsPage = `/settings/tools?repo=${encodeURIComponent(mate.repo)}`;
18
- const granted = grants.map(grant => {
19
- const gone = !tools.some(one => one.name === grant.tool);
20
- const rows = grant.actions.map(action => {
21
- const rule = grant.rules[action.name] ?? defaultRule(action);
22
- const use = rule.use === "free" && rule.limit !== undefined ? "limit" : rule.use;
23
- const numbers = numberFields(action);
24
- const words = rule.use === "never" ? "Never" : rule.use === "ask" ? "Ask first" : rule.limit === undefined ? "Do it" : `Do it up to ${rule.limit.field} ${rule.limit.over}, ask first above`;
25
- if (!canManage)
26
- return `<li class="tool-rule"><span><strong>${e(action.name)}</strong> · ${e(words)}</span>${action.about === "" ? "" : `<span class="meta">${e(action.about)}</span>`}</li>`;
27
- const field = `${grant.tool}-${action.name}`.replace(/[^A-Za-z0-9_-]/g, "-");
28
- return `<div class="tool-rule" data-tool-action="${e(action.name)}"><label for="use-${e(field)}"><strong>${e(action.name)}</strong>${action.about === "" ? "" : `<span class="meta">${e(action.about)}</span>`}</label>` +
29
- `<select id="use-${e(field)}" name="use.${e(action.name)}">${USES.filter(([value]) => value !== "limit" || numbers.length > 0).map(([value, label]) => `<option value="${value}"${value === use ? " selected" : ""}>${label}</option>`).join("")}</select>` +
30
- (numbers.length === 0 ? "" : `<span class="tool-limit">Ask first when <select name="field.${e(action.name)}" aria-label="The number the limit is on">${numbers.map(one => `<option value="${e(one)}"${rule.limit?.field === one ? " selected" : ""}>${e(one)}</option>`).join("")}</select> is over <input type="number" name="over.${e(action.name)}" min="0" step="any" value="${rule.limit === undefined ? "" : rule.limit.over}" aria-label="The limit"></span>`) +
31
- `</div>`;
32
- }).join("");
33
- const head = `<h3>${e(grant.tool)}</h3>${gone ? `<p class="problem">This project doesn't have ${e(grant.tool)} any more, so ${e(name)} can't use it.</p>` : ""}`;
34
- // v97: which action undoes which, for the Undo button on its receipts. Optional, so it's folded away.
35
- const undoing = grant.actions.filter(one => !one.readOnly).map(action => {
36
- const chosen = grant.rules[action.name]?.undo ?? "";
37
- return `<label class="tool-undo-row">${e(action.name)} is undone by<select name="undo.${e(action.name)}"><option value="">nothing</option>${grant.actions.filter(other => other.name !== action.name).map(other => `<option value="${e(other.name)}"${other.name === chosen ? " selected" : ""}>${e(other.name)}</option>`).join("")}</select></label>`;
38
- }).join("");
39
- const undoBox = undoing === "" ? "" : `<details class="tool-undo"${grant.actions.some(one => grant.rules[one.name]?.undo !== undefined) ? " open" : ""}><summary>Undo</summary><p class="meta">When an action has an opposite, a person can press Undo on its receipts: the opposite is called with the same input.</p>${undoing}</details>`;
40
- return canManage
41
- ? `<div class="tool-grant" data-tool-grant="${e(grant.tool)}">${head}<form method="post" action="/teammates/${mate.id}/tools">${hidden(csrf)}<input type="hidden" name="tool" value="${e(grant.tool)}">${rows}` +
42
- undoBox + `<div class="tool-buttons"><button name="op" value="rules">Save rules</button><button name="op" value="revoke" class="secondary">Stop using ${e(grant.tool)}</button></div></form></div>`
43
- : `<div class="tool-grant" data-tool-grant="${e(grant.tool)}">${head}<ul>${rows}</ul></div>`;
44
- }).join("");
45
- const open = tools.filter(one => !grants.some(grant => grant.tool === one.name));
46
- const add = !canManage ? "" : tools.length === 0 ? `<p class="meta">This project has no tools yet. <a href="${e(toolsPage)}">Add one</a>, then let ${e(name)} use it here.</p>`
47
- : open.length === 0 ? "" : `<form method="post" action="/teammates/${mate.id}/tools" class="tool-add">${hidden(csrf)}<input type="hidden" name="op" value="grant"><label>Let ${e(name)} use<select name="tool">${open.map(one => `<option value="${e(one.name)}">${e(one.name)}${one.spec.about === "" ? "" : ` — ${e(one.spec.about.slice(0, 80))}`}</option>`).join("")}</select></label><button>Add tool</button></form>`;
48
- if (grants.length === 0 && add === "")
49
- return "";
50
- return `<section class="card teammate-tools" id="tools"><h2>Tools</h2>${grants.length === 0 ? `<p class="meta">${e(name)} doesn't use any tools yet. Reading starts as “Do it”; everything else asks you first.</p>` : ""}${granted}${add}</section>`;
51
- }
52
- const e = (text) => text.replace(/[&<>"']/g, one => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[one]);
53
- const when = (at) => new Date(at).toLocaleString("en", { month: "short", day: "numeric", hour: "numeric", minute: "2-digit" });
54
- const hidden = (csrf) => `<input type="hidden" name="csrf" value="${e(csrf)}">`;
55
- const startOfDay = () => { const day = new Date(); day.setHours(0, 0, 0, 0); return day.toISOString(); };
56
- /** A blank soul file: the sections a teammate reads, to fill in. */
57
- export const BLANK_SOUL = `---\nname: \nrole: \n---\n\n## Who you are\n\n\n## How you write\n\n\n## What you know\n\n\n## Decide on your own\n- \n\n## Ask first\n- \n\n## Never\n- \n`;
58
- export function teammatesListHtml(store, mates, projects, projectName, csrf, canCreate, notice) {
59
- const rows = mates.map(mate => {
60
- const today = store.teammateTurnsSince(mate.id, startOfDay());
61
- const open = store.openTeammateQuestions([mate.id]).length;
62
- return `<article class="card" data-teammate="${e(mate.handle)}"><div class="flow-row"><h2><a href="/teammates/${mate.id}">${e(labelOf(mate))}</a></h2><span class="flow-counts">${e(projectName(mate.repo))} · ${mate.state === "active" ? "Working" : "Paused"} · ${today} today${open > 0 ? ` · ${open} question${open === 1 ? "" : "s"} for you` : ""}</span></div></article>`;
63
- }).join("");
64
- const create = canCreate && projects.length > 0
65
- ? `<details class="card"${mates.length === 0 ? " open" : ""}><summary>New teammate</summary><form method="post" action="/teammates/new" data-new-teammate>${hidden(csrf)}` +
66
- `<label>Start from<select name="template">${TEAMMATE_TEMPLATES.map(one => `<option value="${e(one.id)}">${e(one.label)}: ${e(one.about)}</option>`).join("")}<option value="blank">Blank: write its soul file yourself</option></select></label>` +
67
- `<label>Name<input name="name" maxlength="40" placeholder="keep the template's name"></label>` +
68
- (projects.length === 1 ? `<input type="hidden" name="repo" value="${e(projects[0])}">` : `<label>Project<select name="repo">${projects.map(repo => `<option value="${e(repo)}">${e(projectName(repo))}</option>`).join("")}</select></label>`) +
69
- `<button>Add teammate</button></form></details>`
70
- : "";
71
- const intro = `<p class="meta">AI teammates work your flows' cards within rules you write: they decide, reply and move cards on, and ask you when their rules say to. The quickest start is a <a href="/kits">starter kit</a>: a teammate and its flow, set up in one click.</p>`;
72
- return `<section class="teammates">${notice.problem ? `<p class="problem" role="alert">${e(notice.problem)}</p>` : ""}${notice.said ? `<p class="said" role="status">${e(notice.said)}</p>` : ""}${intro}${rows || '<p class="meta">No teammates yet.</p>'}${create}</section>`;
73
- }
74
- /** v97: its week: what it did and cost, what people overrode, and calls that can be undone. */
75
- function weekSection(store, mate, csrf, canManage) {
76
- const week = weekOf(store, mate, new Date());
77
- const overrides = week.overrides.length === 0 ? "" : `<h3>What you overrode</h3><ul class="teammate-overrides">${week.overrides.map(one => `<li>${e(one.said)}${one.href === null ? "" : ` · <a href="${e(one.href)}">open</a>`} <span class="meta">${when(one.at)}</span></li>`).join("")}</ul>`;
78
- const undo = week.undoable.length === 0 ? "" : `<h3>Undo</h3><ul class="teammate-undo">${week.undoable.map(one => `<li data-undo="${one.call}"><span>${e(one.words)}</span> <span class="meta">${when(one.at)}${one.href === null ? "" : ` · <a href="${e(one.href)}">open</a>`}</span>` +
79
- (canManage ? `<form method="post" action="/teammates/${mate.id}/week">${hidden(csrf)}<input type="hidden" name="id" value="${one.call}"><button name="op" value="undo" class="secondary">Undo with ${e(one.undo)}</button></form>` : "") + `</li>`).join("")}</ul>`;
80
- const send = canManage ? `<form method="post" action="/teammates/${mate.id}/week">${hidden(csrf)}<button name="op" value="send" class="secondary">Send the week's report</button></form>` : "";
81
- return `<details class="card teammate-week" id="week" open><summary>This week</summary><p class="teammate-week-said">${e(weekWords(mate, week)).replace(/\n/g, "<br>")}</p>${overrides}${undo}${send}</details>`;
82
- }
83
- /** v96: its desk — where messages to it by name and its routines land — and its routines. */
84
- function deskSection(store, mate, csrf, canManage) {
85
- const name = nameOf(mate);
86
- const desk = deskOf(store, mate);
87
- const routines = routinesOf(store, mate);
88
- const intro = `<p class="meta">Message ${e(name)} by name in your chat app, like “@${e(mate.handle)} where's order 1042?”. It lands on ${desk === null ? "its desk" : `<a href="/flows/${desk.id}">${e(name)}'s desk</a>`}, and the answer comes back to you.</p>`;
89
- const list = routines.length === 0 ? "" : `<ul class="teammate-routines">${routines.map(one => `<li data-routine="${one.id}"><span><strong>${e(scheduleWords(one.schedule))}</strong> · ${e(one.text)}</span>` +
90
- `<span class="meta">${one.state === "paused" ? "Paused" : one.nextAt === null ? "" : `Next ${when(one.nextAt)}`}${one.lastAt === null ? "" : ` · last ${when(one.lastAt)}${one.lastOutcome === null ? "" : `: ${e(one.lastOutcome)}`}`}</span>` +
91
- (canManage ? `<form method="post" action="/teammates/${mate.id}/routines" class="routine-buttons">${hidden(csrf)}<input type="hidden" name="id" value="${one.id}"><button name="op" value="run" class="secondary">Run now</button><button name="op" value="remove" class="secondary">Remove</button></form>` : "") + `</li>`).join("")}</ul>`;
92
- const add = canManage ? `<form method="post" action="/teammates/${mate.id}/routines" class="routine-add">${hidden(csrf)}<input type="hidden" name="op" value="add">` +
93
- `<label>When<input type="text" name="schedule" maxlength="80" placeholder="weekdays 09:00" required></label><label>What to do<input type="text" name="text" maxlength="200" placeholder="Look up yesterday's refunds and tell me the total." required></label><button>Add routine</button></form>` : "";
94
- return `<section class="card teammate-desk" id="desk"><h2>Desk and routines</h2>${intro}${list}${add}${canManage ? `<p class="meta">A routine puts a card on its desk on that schedule (“weekdays 09:00”, “daily 17:00”, “monday 09:00”, “every 2 hours”; times are this computer's, ${e(localZone())}, unless you name one); the answer goes to ${e(mate.manager)}.</p>` : ""}</section>`;
95
- }
96
- /** A schedule's stored form ("weekdays:09:00@Europe/London") in words. */
97
- const scheduleWords = (text) => { const parsed = parseSchedule(text); return parsed === null ? text : describeSchedule(parsed); };
98
- /** v95: what it remembers — what its people told it, and what it kept from cards — to search, edit and forget. */
99
- function memorySection(store, mate, csrf, canManage, query) {
100
- const name = nameOf(mate);
101
- const all = store.teammateMemories(mate.id, { limit: 500 });
102
- const shown = query === null || query.trim() === "" ? all.slice(0, 30) : searchMemories(store, mate, query);
103
- const tell = canManage ? `<form method="post" action="/teammates/${mate.id}/note" class="memory-tell">${hidden(csrf)}<label class="sr-only" for="teammate-note">Tell ${e(name)} something</label><textarea id="teammate-note" name="note" rows="2" maxlength="${MEMORY_CHARS}" placeholder="For example: this week, offer free shipping instead of a refund when you can."></textarea><button>Tell ${e(name)}</button></form>` : "";
104
- const search = all.length > 8 || (query ?? "") !== "" ? `<form method="get" action="/teammates/${mate.id}#memory" class="memory-search" role="search"><label class="sr-only" for="memory-q">Search what ${e(name)} remembers</label><input id="memory-q" type="search" name="q" value="${e(query ?? "")}" placeholder="Search what ${e(name)} remembers"><button class="secondary">Search</button></form>` : "";
105
- const items = shown.map(one => {
106
- const card = one.card === null ? null : store.getFlowCard(one.card);
107
- const whence = one.source === "person" ? `${e(one.createdBy)} told it` : card === null ? "it kept this" : `it kept this from <a href="/flows/${card.flow}?card=${card.id}">${e(card.title.slice(0, 60))}</a>`;
108
- const edit = canManage ? `<details class="memory-edit"><summary>Edit</summary><form method="post" action="/teammates/${mate.id}/memory">${hidden(csrf)}<input type="hidden" name="id" value="${one.id}"><label class="sr-only" for="memory-${one.id}">Memory</label><textarea id="memory-${one.id}" name="text" rows="2" maxlength="${MEMORY_CHARS}">${e(one.text)}</textarea><div class="memory-buttons"><button name="op" value="edit">Save</button><button name="op" value="forget" class="secondary">Forget</button></div></form></details>` : "";
109
- return `<li data-memory="${one.id}" data-source="${one.source}"><span>${e(one.text)}</span> <span class="meta">${whence} · ${when(one.updatedAt)}</span>${edit}</li>`;
110
- }).join("");
111
- const empty = (query ?? "") !== "" ? `<p class="meta">Nothing ${e(name)} remembers matches that.</p>` : `<p class="meta">Nothing yet. What you tell ${e(name)} is kept here, and it keeps short facts from the cards it works.</p>`;
112
- return `<section class="card teammate-memory" id="memory"><h2>Memory</h2>${tell}${search}${shown.length === 0 ? empty : `<ul class="teammate-memories">${items}</ul>`}${query === null && all.length > shown.length ? `<p class="meta">${all.length - shown.length} older ${all.length - shown.length === 1 ? "memory" : "memories"}: search to find them.</p>` : ""}</section>`;
113
- }
114
- export function teammatePageHtml(store, mate, viewer, projectName, csrf, canManage, approvers, notice) {
115
- const name = nameOf(mate);
116
- const questions = store.openTeammateQuestions([mate.id]);
117
- const asked = questions.map(question => {
118
- const card = store.getFlowCard(question.card);
119
- const flow = card === null ? null : store.getFlow(card.flow);
120
- const mine = question.askedOf === viewer;
121
- const cardLink = card === null || flow === null ? "a card" : `<a href="/flows/${flow.id}?card=${card.id}">${e(card.title)}</a>`;
122
- return `<article class="card teammate-question" data-question="${question.id}"${question.suggestion === null ? "" : " data-suggestion"}><p class="meta">${question.suggestion === null ? `About ${cardLink}` : "Suggests a rule change"} · ${when(question.createdAt)}${mine ? "" : ` · for ${e(question.askedOf)}`}</p><p><strong>${e(question.question)}</strong></p>` +
123
- (mine ? `<div class="question-options">${question.options.map(one => `<form method="post" action="/teammates/questions/${question.id}/answer">${hidden(csrf)}<input type="hidden" name="choice" value="${e(one.id)}"><button>${e(one.label)}</button></form>`).join("")}</div>` +
124
- `<form method="post" action="/teammates/questions/${question.id}/answer" class="question-reply">${hidden(csrf)}<label>Or answer in your words<textarea name="text" rows="2" maxlength="2000"></textarea></label><button>Answer</button></form>` : "") +
125
- `</article>`;
126
- }).join("");
127
- const zones = zonesOf(store, mate);
128
- const where = zones.length === 0
129
- ? `<p class="meta">Not on any zone yet. In a flow, choose ${e(name)} under “Who decides” on a “Person decides” zone, or add a “Teammate handles it” zone.</p>`
130
- : `<ul>${zones.map(one => `<li><a href="/flows/${one.flow}">${e(one.flowName)}</a> · ${one.kind === "decides" ? "decides" : "handles"} ${e(one.title)}</li>`).join("")}</ul>`;
131
- // What it did and why, with every tool call it made or asked to make (v94), newest first.
132
- const events = [
133
- ...store.teammateEvents(mate.id, 40).filter(one => one.kind !== "note").map(one => ({ kind: one.kind, said: one.said, card: one.card, at: one.at })),
134
- ...store.teammateCallsOf(mate.id, 40).map(one => ({ kind: "call", said: `Used ${callWords(one.tool, one.action, one.input, 200)} · ${receiptWords(store, one)}`, card: one.card, at: one.createdAt })),
135
- ].sort((a, b) => b.at.localeCompare(a.at)).slice(0, 40);
136
- const activity = events.length === 0 ? `<p class="meta">Nothing yet.</p>` : `<ul class="teammate-activity">${events.map(one => {
137
- const card = one.card === null ? null : store.getFlowCard(one.card);
138
- return `<li data-event="${one.kind}">${e(one.said)}${card === null ? "" : ` · <a href="/flows/${card.flow}?card=${card.id}">open</a>`} <span class="meta">${when(one.at)}</span></li>`;
139
- }).join("")}</ul>`;
140
- const versions = store.teammateVersions(mate.id);
141
- const latest = versions[0];
142
- const manage = canManage ? `<div class="teammate-actions">` +
143
- `<form method="post" action="/teammates/${mate.id}/state">${hidden(csrf)}<input type="hidden" name="state" value="${mate.state === "active" ? "paused" : "active"}"><button${mate.state === "active" ? ' class="secondary"' : ""}>${mate.state === "active" ? `Pause ${e(name)}` : `Resume ${e(name)}`}</button></form>` +
144
- `<form method="post" action="/teammates/${mate.id}/summary">${hidden(csrf)}<button class="secondary">Send today's summary</button></form></div>` : "";
145
- return [
146
- notice.problem ? `<p class="problem" role="alert">${e(notice.problem)}</p>` : "",
147
- notice.said ? `<p class="said" role="status">${e(notice.said)}</p>` : "",
148
- `<p class="meta">${e(projectName(mate.repo))} · ${mate.state === "active" ? "Working" : "Paused: its decisions go to people"} · reports to ${e(mate.manager)}</p>`,
149
- manage,
150
- questions.length === 0 ? "" : `<section><h2>Questions</h2>${asked}</section>`,
151
- `<section class="card"><h2>Today</h2><p class="teammate-summary">${e(summaryOf(store, mate, startOfDay()).said).replace(/\n/g, "<br>")}</p></section>`,
152
- weekSection(store, mate, csrf, canManage),
153
- `<section class="card"><h2>Works on</h2>${where}</section>`,
154
- toolsSection(store, mate, csrf, canManage),
155
- deskSection(store, mate, csrf, canManage),
156
- memorySection(store, mate, csrf, canManage, notice.query ?? null),
157
- `<details class="card"${canManage ? " open" : ""}><summary>Soul file</summary><p class="meta">Who ${e(name)} is and its rules, read every turn. Version ${mate.version}${latest === undefined ? "" : ` · saved by ${e(latest.savedBy)}, ${when(latest.savedAt)}`} · <a href="/teammates/${mate.id}/soul.md" download>Download</a></p>` +
158
- (canManage ? `<form method="post" action="/teammates/${mate.id}/soul" data-soul-form>${hidden(csrf)}<label class="sr-only" for="teammate-soul">Soul file</label><textarea id="teammate-soul" name="soul" rows="24" class="mono" maxlength="12000" spellcheck="false">${e(notice.soulDraft ?? mate.soul)}</textarea><button>Save</button></form>` : `<pre class="mono">${e(mate.soul)}</pre>`) + `</details>`,
159
- `<details class="card"><summary>What ${e(name)} did</summary>${activity}</details>`,
160
- canManage ? `<details class="card"><summary>Settings</summary><form method="post" action="/teammates/${mate.id}/settings">${hidden(csrf)}` +
161
- `<label>Model<select name="model">${TEAMMATE_MODELS.map(one => `<option value="${one}"${(mate.model ?? "default") === one ? " selected" : ""}>${one === "default" ? "The lead chat's model" : one[0].toUpperCase() + one.slice(1)}</option>`).join("")}</select></label>` +
162
- `<label>Turns a day, at most<input type="number" name="dailyTurns" min="1" max="2000" value="${mate.dailyTurns}"></label>` +
163
- `<label>Reports to<select name="manager">${[...new Set([mate.manager, ...approvers])].map(one => `<option value="${e(one)}"${one === mate.manager ? " selected" : ""}>${e(one)}</option>`).join("")}</select></label><button>Save settings</button></form>` +
164
- `<form method="post" action="/teammates/${mate.id}/state" class="danger-zone">${hidden(csrf)}<input type="hidden" name="state" value="removed"><button class="danger">Remove ${e(name)} from the team</button></form></details>` : "",
165
- ].join("");
166
- }