@alexkroman1/aai-cli 5.14.0 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/dist/{_agent-C8Jk-ZcP.mjs → _agent-vGW5SBnX.mjs} +23 -5
  2. package/dist/_agent.d.ts +18 -0
  3. package/dist/{_api-client-BX8Qv51n.mjs → _api-client-LgLksMhN.mjs} +45 -8
  4. package/dist/_api-client.d.ts +39 -0
  5. package/dist/{_bundler-BuIyDdvs.mjs → _bundler-BapCUUJN.mjs} +42 -14
  6. package/dist/_bundler.d.ts +43 -5
  7. package/dist/_cli-common.d.ts +67 -3
  8. package/dist/{_config-CzwAWOWr.mjs → _config-D_s09e7g.mjs} +36 -18
  9. package/dist/_deploy.d.ts +2 -5
  10. package/dist/_dev-restart.d.ts +6 -1
  11. package/dist/{_dev-server-Ch7K8e8i.mjs → _dev-server-DQ1t9sbw.mjs} +94 -38
  12. package/dist/_dev-server.d.ts +30 -2
  13. package/dist/_e2e-test-utils.d.ts +80 -0
  14. package/dist/_fault-mode.d.ts +175 -0
  15. package/dist/{_init-CbkrE2wq.mjs → _init-CpISqoR8.mjs} +3 -3
  16. package/dist/{_output-CC300DzW.mjs → _output-CKkmWs7i.mjs} +8 -1
  17. package/dist/_output.d.ts +9 -2
  18. package/dist/{_server-common-61fL__39.mjs → _server-common-6e0QI4mq.mjs} +1 -1
  19. package/dist/{_slug-api-D30zPmsn.mjs → _slug-api-D2heILuC.mjs} +2 -2
  20. package/dist/{_studio-D2ciIhbi.mjs → _studio-zAJycZ8j.mjs} +3 -3
  21. package/dist/{_templates-B1kt3BGt.mjs → _templates-iDGjGiPf.mjs} +4 -6
  22. package/dist/{_typecheck-gate-4v9UBZHh.mjs → _typecheck-gate-BXvUNnfs.mjs} +1 -1
  23. package/dist/{_utils-0DHbcqUb.mjs → _utils-B8QmtFhK.mjs} +21 -7
  24. package/dist/_utils.d.ts +18 -2
  25. package/dist/{_vite-env-Dg_QlVv0.mjs → _vite-env-BNveawd1.mjs} +31 -1
  26. package/dist/_vite-env.d.ts +30 -0
  27. package/dist/build-BO1Ni6oJ.mjs +62 -0
  28. package/dist/build.d.ts +19 -0
  29. package/dist/cli-workflow.d.ts +10 -0
  30. package/dist/cli.d.ts +1 -2
  31. package/dist/cli.mjs +406 -224
  32. package/dist/{client-bundler-C9qXL8A2.mjs → client-bundler-B8Q9F8gJ.mjs} +3 -22
  33. package/dist/client-bundler.mjs +1 -1
  34. package/dist/{delete-DCRX3d96.mjs → delete-4I0uNR4a.mjs} +6 -7
  35. package/dist/delete.d.ts +2 -8
  36. package/dist/{deploy-DjsEV-40.mjs → deploy-DJ3HRcia.mjs} +13 -14
  37. package/dist/{dev-CvPH5dbF.mjs → dev-C6SWaAZP.mjs} +3 -3
  38. package/dist/{eject-LgBRfnbH.mjs → eject-Zrzk5KV3.mjs} +41 -15
  39. package/dist/eject.d.ts +30 -3
  40. package/dist/{init-BppxMR8r.mjs → init-BTRGiPQr.mjs} +61 -26
  41. package/dist/init.d.ts +11 -0
  42. package/dist/{login-BQQaxJhL.mjs → login-k0Z3VQu9.mjs} +5 -5
  43. package/dist/project-config.mjs +1 -1
  44. package/dist/scaffold/CLAUDE.md +498 -91
  45. package/dist/scaffold/package.json +11 -8
  46. package/dist/scaffold/pnpm-workspace.yaml +8 -0
  47. package/dist/scaffold/server.mjs +53 -57
  48. package/dist/{secret-Ds9dvqAj.mjs → secret-DzSQx1Ds.mjs} +6 -3
  49. package/dist/{storage-DbrQSHFk.mjs → storage-C-Do0mIA.mjs} +18 -6
  50. package/dist/{studio-GSFd4s5O.mjs → studio-BGVmCA2G.mjs} +10 -10
  51. package/dist/templates/code-interpreter/agent.ts +0 -2
  52. package/dist/templates/dispatch-center/agent.test.ts +17 -19
  53. package/dist/templates/dispatch-center/agent.ts +2 -29
  54. package/dist/templates/dispatch-center/client.tsx +33 -16
  55. package/dist/templates/dispatch-center/shared.ts +53 -19
  56. package/dist/templates/dispatch-center/tools/incident_add_note.ts +12 -14
  57. package/dist/templates/dispatch-center/tools/incident_create.ts +41 -44
  58. package/dist/templates/dispatch-center/tools/incident_escalate.ts +59 -61
  59. package/dist/templates/dispatch-center/tools/incident_get.ts +3 -4
  60. package/dist/templates/dispatch-center/tools/incident_triage.ts +43 -45
  61. package/dist/templates/dispatch-center/tools/incident_update_status.ts +39 -41
  62. package/dist/templates/dispatch-center/tools/ops_dashboard.ts +2 -5
  63. package/dist/templates/dispatch-center/tools/ops_protocols.ts +1 -1
  64. package/dist/templates/dispatch-center/tools/ops_run_scenario.ts +20 -23
  65. package/dist/templates/dispatch-center/tools/resources_dispatch.ts +52 -54
  66. package/dist/templates/dispatch-center/tools/resources_get_available.ts +2 -4
  67. package/dist/templates/dispatch-center/tools/resources_update_status.ts +39 -42
  68. package/dist/templates/embedded-assets/agent.test.ts +83 -0
  69. package/dist/templates/embedded-assets/agent.ts +1 -48
  70. package/dist/templates/embedded-assets/shared.ts +17 -0
  71. package/dist/templates/embedded-assets/system-prompt.md +13 -0
  72. package/dist/templates/embedded-assets/tools/list_topics.ts +9 -0
  73. package/dist/templates/embedded-assets/tools/search_knowledge.ts +26 -0
  74. package/dist/templates/health-assistant/agent.test.ts +169 -0
  75. package/dist/templates/health-assistant/agent.ts +1 -166
  76. package/dist/templates/health-assistant/fda.ts +100 -0
  77. package/dist/templates/health-assistant/tools/check_drug_interaction.ts +59 -0
  78. package/dist/templates/health-assistant/tools/medication_lookup.ts +31 -0
  79. package/dist/templates/infocom-adventure/agent.test.ts +205 -0
  80. package/dist/templates/infocom-adventure/agent.ts +3 -106
  81. package/dist/templates/infocom-adventure/client.tsx +28 -12
  82. package/dist/templates/infocom-adventure/shared.ts +28 -11
  83. package/dist/templates/infocom-adventure/tools/game_state_drop.ts +13 -0
  84. package/dist/templates/infocom-adventure/tools/game_state_flag.ts +13 -0
  85. package/dist/templates/infocom-adventure/tools/game_state_get.ts +16 -0
  86. package/dist/templates/infocom-adventure/tools/game_state_history.ts +14 -0
  87. package/dist/templates/infocom-adventure/tools/game_state_move.ts +14 -0
  88. package/dist/templates/infocom-adventure/tools/game_state_restart.ts +13 -0
  89. package/dist/templates/infocom-adventure/tools/game_state_score.ts +13 -0
  90. package/dist/templates/infocom-adventure/tools/game_state_take.ts +13 -0
  91. package/dist/templates/link-digest/agent.test.ts +223 -0
  92. package/dist/templates/link-digest/agent.ts +79 -0
  93. package/dist/templates/link-digest/client.tsx +146 -0
  94. package/dist/templates/link-digest/workflows/digest.ts +248 -0
  95. package/dist/templates/math-buddy/agent.ts +0 -2
  96. package/dist/templates/night-owl/agent.test.ts +80 -0
  97. package/dist/templates/night-owl/agent.ts +1 -68
  98. package/dist/templates/night-owl/system-prompt.md +10 -0
  99. package/dist/templates/night-owl/tools/recommend.ts +64 -0
  100. package/dist/templates/personal-finance/agent.ts +0 -2
  101. package/dist/templates/pizza-ordering/agent.test.ts +52 -47
  102. package/dist/templates/pizza-ordering/agent.ts +9 -158
  103. package/dist/templates/pizza-ordering/shared.ts +35 -12
  104. package/dist/templates/pizza-ordering/tools/add_pizza.ts +31 -0
  105. package/dist/templates/pizza-ordering/tools/place_order.ts +22 -0
  106. package/dist/templates/pizza-ordering/tools/remove_pizza.ts +22 -0
  107. package/dist/templates/pizza-ordering/tools/set_customer_name.ts +13 -0
  108. package/dist/templates/pizza-ordering/tools/update_pizza.ts +28 -0
  109. package/dist/templates/pizza-ordering/tools/view_order.ts +21 -0
  110. package/dist/templates/plan-and-execute/agent.test.ts +411 -0
  111. package/dist/templates/plan-and-execute/agent.ts +23 -0
  112. package/dist/templates/plan-and-execute/client.tsx +115 -0
  113. package/dist/templates/plan-and-execute/graph.ts +178 -0
  114. package/dist/templates/plan-and-execute/prompts.ts +110 -0
  115. package/dist/templates/plan-and-execute/shared.ts +161 -0
  116. package/dist/templates/plan-and-execute/system-prompt.md +18 -0
  117. package/dist/templates/plan-and-execute/tools/plan_status.ts +20 -0
  118. package/dist/templates/plan-and-execute/tools/revise_plan.ts +63 -0
  119. package/dist/templates/plan-and-execute/tools/start_plan.ts +51 -0
  120. package/dist/templates/plan-and-execute/tools/work_next_step.ts +101 -0
  121. package/dist/templates/recap-workflow/agent.test.ts +762 -0
  122. package/dist/templates/recap-workflow/agent.ts +95 -0
  123. package/dist/templates/recap-workflow/shared.ts +43 -0
  124. package/dist/templates/recap-workflow/tools/cancel_recap.ts +23 -0
  125. package/dist/templates/recap-workflow/tools/keep_transcript.ts +31 -0
  126. package/dist/templates/recap-workflow/tools/recap_progress.ts +27 -0
  127. package/dist/templates/recap-workflow/tools/recap_status.ts +46 -0
  128. package/dist/templates/recap-workflow/tools/request_recap.ts +43 -0
  129. package/dist/templates/recap-workflow/workflows/recap.ts +544 -0
  130. package/dist/templates/recap-workflow/workflows/tokens.ts +26 -0
  131. package/dist/templates/redline/agent.test.ts +222 -0
  132. package/dist/templates/redline/agent.ts +89 -0
  133. package/dist/templates/redline/client.tsx +184 -0
  134. package/dist/templates/redline/workflows/prompts.ts +68 -0
  135. package/dist/templates/redline/workflows/redline.ts +258 -0
  136. package/dist/templates/research-workflow/agent.test.ts +525 -0
  137. package/dist/templates/research-workflow/agent.ts +94 -0
  138. package/dist/templates/research-workflow/shared.ts +35 -0
  139. package/dist/templates/research-workflow/tools/file_it_now.ts +22 -0
  140. package/dist/templates/research-workflow/tools/request_research.ts +33 -0
  141. package/dist/templates/research-workflow/tools/research_progress.ts +26 -0
  142. package/dist/templates/research-workflow/tools/research_status.ts +40 -0
  143. package/dist/templates/research-workflow/workflows/prompts.ts +143 -0
  144. package/dist/templates/research-workflow/workflows/research.ts +558 -0
  145. package/dist/templates/retail/agent.test.ts +236 -172
  146. package/dist/templates/retail/agent.ts +5 -42
  147. package/dist/templates/retail/client.tsx +33 -11
  148. package/dist/templates/retail/registry.test.ts +31 -16
  149. package/dist/templates/retail/resolve.ts +28 -64
  150. package/dist/templates/retail/shared.test.ts +4 -3
  151. package/dist/templates/retail/shared.ts +24 -7
  152. package/dist/templates/retail/store.test.ts +12 -10
  153. package/dist/templates/retail/store.ts +69 -30
  154. package/dist/templates/retail/tools/cancel_pending_order.ts +4 -9
  155. package/dist/templates/retail/tools/exchange_delivered_order_items.ts +22 -11
  156. package/dist/templates/retail/tools/find_user_id_by_email.ts +5 -9
  157. package/dist/templates/retail/tools/find_user_id_by_name_zip.ts +5 -7
  158. package/dist/templates/retail/tools/get_item_details.ts +5 -7
  159. package/dist/templates/retail/tools/get_order_details.ts +5 -7
  160. package/dist/templates/retail/tools/get_product_details.ts +4 -7
  161. package/dist/templates/retail/tools/get_user_details.ts +4 -7
  162. package/dist/templates/retail/tools/list_all_product_types.ts +5 -7
  163. package/dist/templates/retail/tools/modify_pending_order_address.ts +4 -9
  164. package/dist/templates/retail/tools/modify_pending_order_items.ts +4 -16
  165. package/dist/templates/retail/tools/modify_pending_order_payment.ts +3 -9
  166. package/dist/templates/retail/tools/modify_user_address.ts +4 -9
  167. package/dist/templates/retail/tools/return_delivered_order_items.ts +3 -9
  168. package/dist/templates/retail/tools/transfer_to_human_agents.ts +1 -1
  169. package/dist/templates/solo-rpg/agent.test.ts +152 -29
  170. package/dist/templates/solo-rpg/agent.ts +3 -21
  171. package/dist/templates/solo-rpg/client.tsx +19 -6
  172. package/dist/templates/solo-rpg/shared.ts +19 -11
  173. package/dist/templates/solo-rpg/tools/action_roll.ts +2 -4
  174. package/dist/templates/solo-rpg/tools/burn_momentum.ts +2 -4
  175. package/dist/templates/solo-rpg/tools/check_state.ts +6 -6
  176. package/dist/templates/solo-rpg/tools/load_game.ts +1 -1
  177. package/dist/templates/solo-rpg/tools/oracle.ts +18 -11
  178. package/dist/templates/solo-rpg/tools/save_game.ts +10 -7
  179. package/dist/templates/solo-rpg/tools/setup_character.ts +1 -1
  180. package/dist/templates/solo-rpg/tools/update_state.ts +3 -4
  181. package/dist/templates/support-line/agent.test.ts +343 -0
  182. package/dist/templates/support-line/agent.ts +27 -0
  183. package/dist/templates/support-line/client.tsx +122 -0
  184. package/dist/templates/support-line/graph.ts +224 -0
  185. package/dist/templates/support-line/knowledge.json +65 -0
  186. package/dist/templates/support-line/prompts.ts +95 -0
  187. package/dist/templates/support-line/shared.ts +240 -0
  188. package/dist/templates/support-line/system-prompt.md +17 -0
  189. package/dist/templates/support-line/tools/answer_question.ts +72 -0
  190. package/dist/templates/support-line/tools/list_topics.ts +22 -0
  191. package/dist/templates/support-line/tools/log_ticket.ts +30 -0
  192. package/dist/templates/transcription-workflow/agent.test.ts +563 -0
  193. package/dist/templates/transcription-workflow/agent.ts +92 -0
  194. package/dist/templates/transcription-workflow/client.tsx +234 -0
  195. package/dist/templates/transcription-workflow/workflows/transcribe.ts +416 -0
  196. package/dist/templates/transcription-workflow/workflows/wav.ts +314 -0
  197. package/dist/templates/travel-concierge/agent.test.ts +338 -0
  198. package/dist/templates/travel-concierge/agent.ts +29 -0
  199. package/dist/templates/travel-concierge/client.tsx +161 -0
  200. package/dist/templates/travel-concierge/routing.ts +138 -0
  201. package/dist/templates/travel-concierge/shared.ts +547 -0
  202. package/dist/templates/travel-concierge/system-prompt.md +24 -0
  203. package/dist/templates/travel-concierge/tools/book_car_rental.ts +20 -0
  204. package/dist/templates/travel-concierge/tools/book_excursion.ts +18 -0
  205. package/dist/templates/travel-concierge/tools/book_hotel.ts +20 -0
  206. package/dist/templates/travel-concierge/tools/cancel_action.ts +7 -0
  207. package/dist/templates/travel-concierge/tools/cancel_ticket.ts +16 -0
  208. package/dist/templates/travel-concierge/tools/complete_or_escalate.ts +7 -0
  209. package/dist/templates/travel-concierge/tools/confirm_action.ts +7 -0
  210. package/dist/templates/travel-concierge/tools/lookup_booking.ts +35 -0
  211. package/dist/templates/travel-concierge/tools/search_car_rentals.ts +33 -0
  212. package/dist/templates/travel-concierge/tools/search_excursions.ts +37 -0
  213. package/dist/templates/travel-concierge/tools/search_flights.ts +43 -0
  214. package/dist/templates/travel-concierge/tools/search_hotels.ts +36 -0
  215. package/dist/templates/travel-concierge/tools/to_car_rental_assistant.ts +11 -0
  216. package/dist/templates/travel-concierge/tools/to_excursion_assistant.ts +11 -0
  217. package/dist/templates/travel-concierge/tools/to_flight_assistant.ts +11 -0
  218. package/dist/templates/travel-concierge/tools/to_hotel_assistant.ts +11 -0
  219. package/dist/templates/travel-concierge/tools/update_ticket.ts +22 -0
  220. package/dist/templates/web-researcher/agent.ts +0 -2
  221. package/dist/templates/web-researcher/system-prompt.md +10 -0
  222. package/dist/{test-2LWBcXvY.mjs → test-B6ZBxSpk.mjs} +2 -2
  223. package/dist/typecheck.mjs +17 -15
  224. package/dist/worker-bundler-CIdDhZ0c.mjs +398 -0
  225. package/dist/worker-bundler.d.ts +14 -0
  226. package/dist/worker-bundler.mjs +1 -108
  227. package/dist/workflow-B-O97AqI.mjs +125 -0
  228. package/dist/workflow-bundler.d.ts +133 -0
  229. package/dist/workflow.d.ts +67 -0
  230. package/package.json +13 -9
  231. package/dist/build-DQJ1ZSm9.mjs +0 -39
@@ -0,0 +1,95 @@
1
+ // Copyright 2026 the AAI authors. MIT license.
2
+ /**
3
+ * A voice agent over a durable, compensating workflow — the Temporal patterns
4
+ * ported to a phone call.
5
+ *
6
+ * The desk transcribes a recording and writes it up. That takes minutes, and
7
+ * the caller is on the line for seconds, so the shape is `research-workflow`'s: a
8
+ * tool starts a run and answers the turn, the run outlives the call, and the
9
+ * finished run takes an unprompted turn to read the result back.
10
+ *
11
+ * What this template is FOR is the other half — the four things a caller can do
12
+ * to a run in flight, which are the Temporal Workflow-API samples with a
13
+ * microphone in front of them:
14
+ *
15
+ * | Temporal sample | Ported here as |
16
+ * | --- | --- |
17
+ * | `signals-queries` — Query | `recap_status`, reading a run snapshot aloud |
18
+ * | `signals-queries` — Workflow Cancellation | `cancel_recap` |
19
+ * | workflow-id reuse / `mutex` — one run per entity | the live-run check in `request_recap` |
20
+ * | `timer-progress` — progress reporting | `recap_progress`, over the run's own stream |
21
+ *
22
+ * The durable half — the saga, the poll loop, the timer race — is in
23
+ * `workflows/recap.ts`, which carries its own table. Each of the five tools is
24
+ * its own file under `tools/`, named for the tool the model calls; the
25
+ * declaration they share is in `shared.ts`, because a tool reaches a run by
26
+ * passing the DEFINITION rather than its name.
27
+ *
28
+ * ## Why a voice call is the honest front door for these
29
+ *
30
+ * Every one of these patterns exists because SOMEBODY IS WAITING and the work
31
+ * is not done. A phone call makes that concrete in a way a form does not: the
32
+ * caller cannot see a spinner, cannot refresh, and will ask "is it done yet?"
33
+ * out loud — which is a Query — and "forget it, cancel that" — which is a
34
+ * Cancellation. The Temporal samples model an operator with a CLI. This models
35
+ * the same operator with a phone, and the mechanism underneath is identical.
36
+ *
37
+ * ## The gate is why the SDK grew `ctx.workflows.signal()`
38
+ *
39
+ * `expense` is the most voice-native sample Temporal ships — a run that waits
40
+ * for a person to say yes — and it was unportable here until this template
41
+ * asked for it. The DevKit's only reachable waitpoint was `createWebhook()`,
42
+ * whose URL is minted for a THIRD PARTY with a callback to make; the caller is
43
+ * not that, they are on the line right now, and the thing that should resume
44
+ * the run is a tool. `signal(token, payload)` is that, and
45
+ * `tools/keep_transcript.ts` is four lines because of it.
46
+ *
47
+ * ## One thing still does NOT port, and it matters
48
+ *
49
+ * **Cancellation is not cooperative.** Temporal delivers cancellation INTO the
50
+ * workflow, so the saga's `catch` runs and the compensations unwind.
51
+ * `ctx.workflows.cancel` marks the run cancelled and stops replaying it — the
52
+ * body's `catch` never runs, so a cancelled recap leaves its transcript on the
53
+ * account. `cancel_recap` says so rather than pretending otherwise, and the
54
+ * compensation stack covers the case it really does cover: FAILURE.
55
+ *
56
+ * The gate is what a cooperative stop would be built from — a hook the body
57
+ * races alongside its work, signalled instead of cancelling — and this template
58
+ * deliberately stops at one hook. Racing a stop into every wait is a second
59
+ * lesson, and it would cost this one its shape.
60
+ *
61
+ * ## What it needs
62
+ *
63
+ * `ASSEMBLYAI_API_KEY` in the agent env — `.env` under `aai dev`, `aai secret
64
+ * put ASSEMBLYAI_API_KEY` once deployed. The same key the voice pipeline uses;
65
+ * the run really submits the recording, really polls it, and really deletes it
66
+ * when it has to.
67
+ *
68
+ * Requires storage (`aai storage enable`, or `DATABASE_URL` under `aai dev`) —
69
+ * runs and the correlation-key index both live there.
70
+ */
71
+
72
+ import { agent } from "@alexkroman1/aai";
73
+ import { recap } from "./shared.ts";
74
+
75
+ export default agent({
76
+ name: "Recap Desk",
77
+ greeting: "Recap desk. Want me to write up a recording?",
78
+ systemPrompt: [
79
+ "You take recordings over the phone, hand them to a transcription run, and read back recaps.",
80
+ "When someone asks you to write up a recording, call request_recap and tell them you have",
81
+ "started it — do NOT wait for it or promise a time. You WILL be told when it lands, so it is",
82
+ "safe to say you will let them know.",
83
+ "When the run asks whether to keep the transcript, relay the question and call",
84
+ "keep_transcript with their answer.",
85
+ "If they ask how it is going, call recap_progress. If they ask about earlier work, call",
86
+ "recap_status. If they say to stop or forget it, call cancel_recap.",
87
+ "Keep replies to one or two sentences; this is a voice call.",
88
+ ].join(" "),
89
+
90
+ workflows: { recap },
91
+
92
+ // Checked at deploy time: the steps read this key with `requireStepEnv`, and a
93
+ // missing one should fail the deploy rather than the first run.
94
+ requiredEnv: ["ASSEMBLYAI_API_KEY"],
95
+ });
@@ -0,0 +1,43 @@
1
+ // Copyright 2026 the AAI authors. MIT license.
2
+ /**
3
+ * The workflow DECLARATION and the recording it defaults to, in a module both
4
+ * `agent.ts` and the tools can import.
5
+ *
6
+ * It lives here rather than in `agent.ts` because four of the five tools name it:
7
+ * `ctx.workflows.start(recap, …)` and `find(recap, …)` take the DEFINITION rather
8
+ * than the string `"recap"`, which is what types the input against this schema and
9
+ * makes a typo a compile error instead of a rejected promise the model reads as a
10
+ * tool failure. A tool is its own file, so the declaration needs a home that is
11
+ * neither the agent nor any one tool.
12
+ *
13
+ * The `"use workflow"` BODY stays in `workflows/recap.ts`: the Workflow DevKit
14
+ * builder scans that directory and rewrites what it finds, and a body written
15
+ * anywhere else runs inline once with no durability and nothing saying so.
16
+ */
17
+
18
+ import { workflow } from "@alexkroman1/aai";
19
+ import { z } from "zod";
20
+ import { recapFlow } from "./workflows/recap.ts";
21
+
22
+ /**
23
+ * What the desk works on when the caller does not name something else.
24
+ *
25
+ * A phone caller cannot read a URL aloud, which is the practical reason this
26
+ * exists — and it is a real, public, documented sample file, so the template
27
+ * transcribes something on the first call instead of asking for a URL it cannot
28
+ * be given. A real desk replaces this with a lookup against its own recording
29
+ * store: the caller says "yesterday's board meeting" and the tool resolves the
30
+ * name.
31
+ */
32
+ export const SAMPLE_RECORDING = "https://assembly.ai/wildfires.mp3";
33
+
34
+ /** The declaration: schema, description, and the directive body. */
35
+ export const recap = workflow({
36
+ description:
37
+ "Transcribe a recording with the batch API, poll it to completion, and write up what was said",
38
+ input: z.object({
39
+ url: z.url().describe("The recording to write up"),
40
+ requestedBy: z.string().describe("Who asked — carried through to the finished recap"),
41
+ }),
42
+ run: recapFlow,
43
+ });
@@ -0,0 +1,23 @@
1
+ import { tool } from "@alexkroman1/aai";
2
+ import { recap } from "../shared.ts";
3
+
4
+ export default tool({
5
+ description: "Stop the recap that is running. Use when the caller says to forget it.",
6
+ execute: async (_args, ctx) => {
7
+ const [latest] = await ctx.workflows.find(recap, ctx.sessionId, { limit: 1 });
8
+ if (!latest) return { cancelled: false, note: "Nothing started yet." };
9
+ const cancelled = await ctx.workflows.cancel(latest.runId);
10
+ // `false` is an ANSWER, not a failure: the run was already terminal, so
11
+ // there was nothing to stop. Worth distinguishing out loud — "already
12
+ // done" and "stopped" are different things to a caller.
13
+ return cancelled
14
+ ? {
15
+ cancelled: true,
16
+ // Said plainly because it is true: a cancelled run does not run
17
+ // its compensations (see `agent.ts`'s module doc), so the
18
+ // transcript it had already created stays on the account.
19
+ note: "Stopped it. The partial transcript is left behind — cancelling does not roll back.",
20
+ }
21
+ : { cancelled: false, note: "That one had already finished." };
22
+ },
23
+ });
@@ -0,0 +1,31 @@
1
+ import { tool } from "@alexkroman1/aai";
2
+ import { z } from "zod";
3
+ import { retentionToken } from "../workflows/tokens.ts";
4
+
5
+ export default tool({
6
+ description:
7
+ "Answer the desk's question about the transcript. Use when the caller says to keep it, save it, or delete it.",
8
+ inputSchema: z.object({
9
+ keep: z.boolean().describe("True to keep the transcript on file, false to delete it"),
10
+ }),
11
+ execute: async ({ keep }, ctx) => {
12
+ // The SIGNAL, and the whole reason this template exists in the shape it
13
+ // does. The run is parked on a hook whose token both sides derive from
14
+ // the session — see `workflows/tokens.ts` — so the tool needs no runId
15
+ // and no bookkeeping of its own.
16
+ const delivered = await ctx.workflows.signal(retentionToken(ctx.sessionId), { keep });
17
+ // `false` is the ORDINARY answer, not a failure: the window closed, or
18
+ // the caller answered a question nobody asked. Say which.
19
+ if (!delivered) {
20
+ return {
21
+ answered: false,
22
+ note: "Nothing is waiting on that — it has already been settled.",
23
+ };
24
+ }
25
+ return {
26
+ answered: true,
27
+ keep,
28
+ note: keep ? "Keeping the transcript on file." : "Deleting the transcript.",
29
+ };
30
+ },
31
+ });
@@ -0,0 +1,27 @@
1
+ import { tool } from "@alexkroman1/aai";
2
+ import { recap } from "../shared.ts";
3
+
4
+ export default tool({
5
+ description: "Say what the transcription is doing right now, for a run still in flight.",
6
+ execute: async (_args, ctx) => {
7
+ const [latest] = await ctx.workflows.find(recap, ctx.sessionId, { limit: 1 });
8
+ if (!latest) return { note: "Nothing started yet." };
9
+ // `recap_status` reports the run's STATUS; this reports what the run has
10
+ // WRITTEN. Between "still working on it" and a finished recap there is
11
+ // otherwise nothing to say — and this run has real news in between,
12
+ // since every poll narrates.
13
+ //
14
+ // `streamTail` FIRST, and not as an optimization: a progress channel is
15
+ // never closed — no step knows it is the last one — so reading a stream
16
+ // with nothing in it waits forever rather than ending. `-1` is "nothing
17
+ // written yet", and it is the only safe way to learn that.
18
+ if ((await ctx.workflows.streamTail(latest.runId)) < 0) {
19
+ return { note: "Submitted, nothing to report yet." };
20
+ }
21
+ // A negative `startIndex` reads from the END, which is what a voice
22
+ // reply wants — the last line, not a recital of the whole log.
23
+ const stream = await ctx.workflows.stream(latest.runId, { startIndex: -1 });
24
+ for await (const line of stream) return { progress: String(line) };
25
+ return { note: "Submitted, nothing to report yet." };
26
+ },
27
+ });
@@ -0,0 +1,46 @@
1
+ import {
2
+ isTerminal,
3
+ tool,
4
+ type WorkflowOutputOf,
5
+ type WorkflowRunSnapshot,
6
+ } from "@alexkroman1/aai";
7
+ import { recap } from "../shared.ts";
8
+
9
+ /** How many past runs the status tool will look at. Newest first. */
10
+ const RECENT_RUNS = 3;
11
+
12
+ /**
13
+ * One line a voice agent can read aloud about a run.
14
+ *
15
+ * This is the QUERY, and `isTerminal` is what makes it typed: it narrows to the
16
+ * three finished statuses, which is what puts `run.output` and `run.error`
17
+ * within reach without a cast. `WorkflowOutputOf` names the output type from the
18
+ * declaration, so this signature never reaches past it into the body.
19
+ */
20
+ function describeRun(run: WorkflowRunSnapshot<WorkflowOutputOf<typeof recap>>): string {
21
+ if (!isTerminal(run)) return "Still working on that one.";
22
+ switch (run.status) {
23
+ case "completed": {
24
+ // The gate's outcome is part of the answer: a caller who never got round
25
+ // to answering should hear that the transcript is gone, not just the recap.
26
+ const fate = run.output.kept ? "transcript kept" : "transcript deleted";
27
+ return `Done: ${run.output.spoken} (${fate})`;
28
+ }
29
+ case "failed":
30
+ // The run compensated before it failed — see `workflows/recap.ts` — so
31
+ // there is nothing left to clean up and nothing for the caller to do
32
+ // beyond asking again.
33
+ return `That one failed and was rolled back: ${run.error}`;
34
+ default:
35
+ return "That one was cancelled.";
36
+ }
37
+ }
38
+
39
+ export default tool({
40
+ description: "Report on recaps started earlier in this call.",
41
+ execute: async (_args, ctx) => {
42
+ const runs = await ctx.workflows.find(recap, ctx.sessionId, { limit: RECENT_RUNS });
43
+ if (runs.length === 0) return { runs: [] as string[], note: "Nothing started yet." };
44
+ return { runs: runs.map(describeRun) };
45
+ },
46
+ });
@@ -0,0 +1,43 @@
1
+ import { isTerminal, tool } from "@alexkroman1/aai";
2
+ import { z } from "zod";
3
+ import { recap, SAMPLE_RECORDING } from "../shared.ts";
4
+
5
+ export default tool({
6
+ description:
7
+ "Start writing up a recording. Returns immediately; the work continues after the call.",
8
+ inputSchema: z.object({
9
+ url: z.url().optional().describe("The recording, if the caller named one"),
10
+ }),
11
+ execute: async ({ url }, ctx) => {
12
+ // Temporal's workflow-id reuse policy, spelled with what this SDK has:
13
+ // the desk allows ONE live recap per caller, so a caller who asks twice
14
+ // is told about the run they already have instead of paying for a second
15
+ // transcription of the same audio. `find` searches the correlation-key
16
+ // index — the same key `start` writes below.
17
+ const [live] = await ctx.workflows.find(recap, ctx.sessionId, { limit: 1 });
18
+ if (live && !isTerminal(live)) {
19
+ return { started: false, runId: live.runId, note: "One is already running for you." };
20
+ }
21
+
22
+ const runId = await ctx.workflows.start(
23
+ recap,
24
+ { url: url ?? SAMPLE_RECORDING, requestedBy: ctx.sessionId },
25
+ {
26
+ // The durable handle. A `runId` kept in a `sessionSlot` would be
27
+ // swept shortly after the caller hangs up, while the run outlives the
28
+ // call — so the key is what a later turn (or a later call) finds it
29
+ // by. `ctx.sessionId` keys THIS call; a real desk keys on the
30
+ // caller's number, and nothing else changes.
31
+ key: ctx.sessionId,
32
+ // What makes "I'll let you know" true: when the run settles, this
33
+ // session takes an unprompted, interruptible turn built from the
34
+ // run's own output. The instruction is a sentence for the MODEL —
35
+ // it is the only thing that knows what this caller has been told.
36
+ notify:
37
+ "Tell them the recap is ready, read the one-sentence version, then ask whether " +
38
+ "to keep the transcript on file or delete it.",
39
+ },
40
+ );
41
+ return { started: true, runId };
42
+ },
43
+ });