@alexkroman1/aai 0.6.1 → 0.7.3

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 (79) hide show
  1. package/dist/cli.js +422 -707
  2. package/dist/sdk/_internal_types.d.ts +4 -18
  3. package/dist/sdk/_internal_types.d.ts.map +1 -1
  4. package/dist/sdk/_internal_types.js +2 -1
  5. package/dist/sdk/_internal_types.js.map +1 -1
  6. package/dist/sdk/_mock_ws.js +1 -1
  7. package/dist/sdk/_mock_ws.js.map +1 -1
  8. package/dist/sdk/builtin_tools.d.ts +6 -2
  9. package/dist/sdk/builtin_tools.d.ts.map +1 -1
  10. package/dist/sdk/builtin_tools.js +1 -8
  11. package/dist/sdk/builtin_tools.js.map +1 -1
  12. package/dist/sdk/capnweb.d.ts +1 -1
  13. package/dist/sdk/capnweb.d.ts.map +1 -1
  14. package/dist/sdk/capnweb.js +43 -10
  15. package/dist/sdk/capnweb.js.map +1 -1
  16. package/dist/sdk/define_agent.d.ts +1 -1
  17. package/dist/sdk/define_agent.d.ts.map +1 -1
  18. package/dist/sdk/define_agent.js +26 -17
  19. package/dist/sdk/define_agent.js.map +1 -1
  20. package/dist/sdk/direct_executor.d.ts +2 -0
  21. package/dist/sdk/direct_executor.d.ts.map +1 -1
  22. package/dist/sdk/direct_executor.js +6 -1
  23. package/dist/sdk/direct_executor.js.map +1 -1
  24. package/dist/sdk/mod.d.ts +2 -1
  25. package/dist/sdk/mod.d.ts.map +1 -1
  26. package/dist/sdk/protocol.d.ts +88 -7
  27. package/dist/sdk/protocol.d.ts.map +1 -1
  28. package/dist/sdk/protocol.js.map +1 -1
  29. package/dist/sdk/runtime.d.ts +6 -4
  30. package/dist/sdk/runtime.d.ts.map +1 -1
  31. package/dist/sdk/runtime.js.map +1 -1
  32. package/dist/sdk/s2s.d.ts +2 -1
  33. package/dist/sdk/s2s.d.ts.map +1 -1
  34. package/dist/sdk/s2s.js +112 -73
  35. package/dist/sdk/s2s.js.map +1 -1
  36. package/dist/sdk/server.d.ts.map +1 -1
  37. package/dist/sdk/server.js +47 -43
  38. package/dist/sdk/server.js.map +1 -1
  39. package/dist/sdk/session.d.ts.map +1 -1
  40. package/dist/sdk/session.js +47 -44
  41. package/dist/sdk/session.js.map +1 -1
  42. package/dist/sdk/system_prompt.d.ts.map +1 -1
  43. package/dist/sdk/system_prompt.js +1 -1
  44. package/dist/sdk/system_prompt.js.map +1 -1
  45. package/dist/sdk/types.d.ts +8 -50
  46. package/dist/sdk/types.d.ts.map +1 -1
  47. package/dist/sdk/types.js +0 -8
  48. package/dist/sdk/types.js.map +1 -1
  49. package/dist/sdk/winterc_server.d.ts +4 -1
  50. package/dist/sdk/winterc_server.d.ts.map +1 -1
  51. package/dist/sdk/winterc_server.js +3 -2
  52. package/dist/sdk/winterc_server.js.map +1 -1
  53. package/dist/sdk/worker_entry.d.ts +3 -1
  54. package/dist/sdk/worker_entry.d.ts.map +1 -1
  55. package/dist/sdk/worker_entry.js +24 -17
  56. package/dist/sdk/worker_entry.js.map +1 -1
  57. package/dist/sdk/worker_shim.d.ts.map +1 -1
  58. package/dist/sdk/worker_shim.js +62 -9
  59. package/dist/sdk/worker_shim.js.map +1 -1
  60. package/dist/sdk/ws_handler.d.ts.map +1 -1
  61. package/dist/sdk/ws_handler.js +65 -58
  62. package/dist/sdk/ws_handler.js.map +1 -1
  63. package/dist/ui/_components/message_list.d.ts.map +1 -1
  64. package/dist/ui/_components/message_list.js +10 -6
  65. package/dist/ui/_components/message_list.js.map +1 -1
  66. package/dist/ui/audio.js +1 -1
  67. package/dist/ui/audio.js.map +1 -1
  68. package/dist/ui/mod.d.ts +10 -2
  69. package/dist/ui/mod.d.ts.map +1 -1
  70. package/dist/ui/mod.js +5 -2
  71. package/dist/ui/mod.js.map +1 -1
  72. package/dist/ui/session.d.ts.map +1 -1
  73. package/dist/ui/session.js +3 -1
  74. package/dist/ui/session.js.map +1 -1
  75. package/package.json +4 -9
  76. package/dist/sdk/_timeout.d.ts +0 -14
  77. package/dist/sdk/_timeout.d.ts.map +0 -1
  78. package/dist/sdk/_timeout.js +0 -24
  79. package/dist/sdk/_timeout.js.map +0 -1
package/dist/cli.js CHANGED
@@ -65,13 +65,13 @@ __export(new_exports, {
65
65
  listTemplates: () => listTemplates,
66
66
  runNew: () => runNew
67
67
  });
68
- import fs5 from "node:fs/promises";
68
+ import fs4 from "node:fs/promises";
69
69
  import path4 from "node:path";
70
70
  import glob from "fast-glob";
71
71
  import fsExtra from "fs-extra";
72
72
  async function listTemplates(dir) {
73
73
  const templates = [];
74
- const entries = await fs5.readdir(dir, { withFileTypes: true });
74
+ const entries = await fs4.readdir(dir, { withFileTypes: true });
75
75
  for (const entry of entries) {
76
76
  if (entry.isDirectory() && !entry.name.startsWith("_")) {
77
77
  templates.push(entry.name);
@@ -84,10 +84,10 @@ async function copyDirNoOverwrite(src, dest) {
84
84
  for (const file of files) {
85
85
  const destPath = path4.join(dest, file);
86
86
  try {
87
- await fs5.access(destPath);
87
+ await fs4.access(destPath);
88
88
  } catch {
89
- await fs5.mkdir(path4.dirname(destPath), { recursive: true });
90
- await fs5.copyFile(path4.join(src, file), destPath);
89
+ await fs4.mkdir(path4.dirname(destPath), { recursive: true });
90
+ await fs4.copyFile(path4.join(src, file), destPath);
91
91
  }
92
92
  }
93
93
  }
@@ -101,12 +101,12 @@ async function runNew(opts) {
101
101
  await fsExtra.copy(path4.join(templatesDir, template), targetDir, { overwrite: true });
102
102
  await copyDirNoOverwrite(path4.join(templatesDir, "_shared"), targetDir);
103
103
  try {
104
- await fs5.copyFile(path4.join(targetDir, ".env.example"), path4.join(targetDir, ".env"));
104
+ await fs4.copyFile(path4.join(targetDir, ".env.example"), path4.join(targetDir, ".env"));
105
105
  } catch {
106
106
  }
107
107
  const readmePath = path4.join(targetDir, "README.md");
108
108
  try {
109
- await fs5.access(readmePath);
109
+ await fs4.access(readmePath);
110
110
  } catch {
111
111
  const slug = path4.basename(path4.resolve(targetDir));
112
112
  const readme = `# ${slug}
@@ -138,7 +138,7 @@ Access secrets in your agent via \`ctx.env.MY_KEY\`.
138
138
 
139
139
  See \`CLAUDE.md\` for the full agent API reference.
140
140
  `;
141
- await fs5.writeFile(readmePath, readme);
141
+ await fs4.writeFile(readmePath, readme);
142
142
  }
143
143
  _internals2.step("Done", targetDir);
144
144
  return targetDir;
@@ -483,16 +483,16 @@ function getBuiltinToolSchemas(names) {
483
483
  {
484
484
  name,
485
485
  description: def.description,
486
- parameters: z3.toJSONSchema(def.parameters ?? EMPTY_PARAMS2)
486
+ parameters: z3.toJSONSchema(def.parameters ?? EMPTY_PARAMS)
487
487
  }
488
488
  ];
489
489
  });
490
490
  }
491
- var EMPTY_PARAMS2, webSearchParams, BRAVE_SEARCH_URL, BraveSearchResponseSchema, MAX_PAGE_CHARS, MAX_HTML_BYTES, visitWebpageParams, fetchJsonParams, runCodeParams, vectorSearchParams, TOOL_CREATORS;
491
+ var webSearchParams, BRAVE_SEARCH_URL, BraveSearchResponseSchema, MAX_PAGE_CHARS, MAX_HTML_BYTES, visitWebpageParams, fetchJsonParams, runCodeParams, vectorSearchParams, TOOL_CREATORS;
492
492
  var init_builtin_tools = __esm({
493
493
  "dist/sdk/builtin_tools.js"() {
494
494
  "use strict";
495
- EMPTY_PARAMS2 = z3.object({});
495
+ init_internal_types();
496
496
  webSearchParams = z3.object({
497
497
  query: z3.string().describe("The search query"),
498
498
  max_results: z3.number().describe("Maximum number of results to return (default 5)").optional()
@@ -601,6 +601,7 @@ var init_kv = __esm({
601
601
  });
602
602
 
603
603
  // dist/sdk/s2s.js
604
+ import { z as z4 } from "zod";
604
605
  function uint8ToBase64(bytes) {
605
606
  const CHUNK = 32768;
606
607
  const parts = [];
@@ -617,6 +618,73 @@ function base64ToUint8(base64) {
617
618
  }
618
619
  return bytes;
619
620
  }
621
+ function dispatchS2sMessage(target, msg) {
622
+ switch (msg.type) {
623
+ case "session.ready":
624
+ target.dispatchEvent(new CustomEvent("ready", {
625
+ detail: { session_id: msg.session_id }
626
+ }));
627
+ break;
628
+ case "session.updated":
629
+ target.dispatchEvent(new CustomEvent("session_updated", { detail: msg }));
630
+ break;
631
+ case "input.speech.started":
632
+ target.dispatchEvent(new CustomEvent("speech_started"));
633
+ break;
634
+ case "input.speech.stopped":
635
+ target.dispatchEvent(new CustomEvent("speech_stopped"));
636
+ break;
637
+ case "transcript.user.delta":
638
+ target.dispatchEvent(new CustomEvent("user_transcript_delta", {
639
+ detail: { text: msg.text }
640
+ }));
641
+ break;
642
+ case "transcript.user":
643
+ target.dispatchEvent(new CustomEvent("user_transcript", {
644
+ detail: {
645
+ item_id: msg.item_id,
646
+ text: msg.text
647
+ }
648
+ }));
649
+ break;
650
+ case "reply.started":
651
+ target.dispatchEvent(new CustomEvent("reply_started", {
652
+ detail: { reply_id: msg.reply_id }
653
+ }));
654
+ break;
655
+ case "reply.audio": {
656
+ const audioBytes = base64ToUint8(msg.data);
657
+ target.dispatchEvent(new CustomEvent("audio", { detail: { audio: audioBytes } }));
658
+ break;
659
+ }
660
+ case "transcript.agent":
661
+ target.dispatchEvent(new CustomEvent("agent_transcript", {
662
+ detail: { text: msg.text }
663
+ }));
664
+ break;
665
+ case "tool.call":
666
+ target.dispatchEvent(new CustomEvent("tool_call", {
667
+ detail: {
668
+ call_id: msg.call_id,
669
+ name: msg.name,
670
+ args: msg.args
671
+ }
672
+ }));
673
+ break;
674
+ case "reply.done":
675
+ target.dispatchEvent(new CustomEvent("reply_done", {
676
+ detail: { status: msg.status }
677
+ }));
678
+ break;
679
+ case "session.error": {
680
+ const isExpired = msg.code === "session_not_found" || msg.code === "session_forbidden";
681
+ target.dispatchEvent(new CustomEvent(isExpired ? "session_expired" : "error", {
682
+ detail: { code: msg.code, message: msg.message }
683
+ }));
684
+ break;
685
+ }
686
+ }
687
+ }
620
688
  function connectS2s(opts) {
621
689
  const { apiKey, config, createWebSocket, logger: log = consoleLogger } = opts;
622
690
  return new Promise((resolve, reject) => {
@@ -629,8 +697,7 @@ function connectS2s(opts) {
629
697
  function send(msg) {
630
698
  if (ws.readyState !== WS_OPEN)
631
699
  return;
632
- const type = msg.type;
633
- if (type !== "input.audio") {
700
+ if (msg.type !== "input.audio") {
634
701
  log.info(`S2S >> ${JSON.stringify(msg)}`);
635
702
  }
636
703
  ws.send(JSON.stringify(msg));
@@ -659,86 +726,26 @@ function connectS2s(opts) {
659
726
  resolve(handle);
660
727
  });
661
728
  ws.on("message", (data) => {
662
- let msg;
729
+ let raw;
663
730
  try {
664
- msg = JSON.parse(String(data));
731
+ raw = JSON.parse(String(data));
665
732
  } catch {
666
733
  return;
667
734
  }
668
- const type = msg.type;
669
- if (type !== "reply.audio") {
670
- log.info(`S2S << ${JSON.stringify(msg)}`);
735
+ const parsed = S2sServerMessageSchema.safeParse(raw);
736
+ if (!parsed.success) {
737
+ log.info(`S2S << unrecognised message: ${JSON.stringify(raw)}`);
738
+ return;
671
739
  }
672
- switch (type) {
673
- case "session.ready":
674
- target.dispatchEvent(new CustomEvent("ready", {
675
- detail: { session_id: msg.session_id }
676
- }));
677
- break;
678
- case "session.updated":
679
- target.dispatchEvent(new CustomEvent("session_updated", { detail: msg }));
680
- break;
681
- case "input.speech.started":
682
- target.dispatchEvent(new CustomEvent("speech_started"));
683
- break;
684
- case "input.speech.stopped":
685
- target.dispatchEvent(new CustomEvent("speech_stopped"));
686
- break;
687
- case "transcript.user.delta":
688
- target.dispatchEvent(new CustomEvent("user_transcript_delta", {
689
- detail: { text: msg.text }
690
- }));
691
- break;
692
- case "transcript.user":
693
- target.dispatchEvent(new CustomEvent("user_transcript", {
694
- detail: {
695
- item_id: msg.item_id,
696
- text: msg.text
697
- }
698
- }));
699
- break;
700
- case "reply.started":
701
- target.dispatchEvent(new CustomEvent("reply_started", {
702
- detail: { reply_id: msg.reply_id }
703
- }));
704
- break;
705
- case "reply.audio": {
706
- const audioBytes = base64ToUint8(msg.data);
707
- target.dispatchEvent(new CustomEvent("audio", { detail: { audio: audioBytes } }));
708
- break;
709
- }
710
- case "transcript.agent":
711
- target.dispatchEvent(new CustomEvent("agent_transcript", {
712
- detail: { text: msg.text }
713
- }));
714
- break;
715
- case "tool.call":
716
- target.dispatchEvent(new CustomEvent("tool_call", {
717
- detail: {
718
- call_id: msg.call_id,
719
- name: msg.name,
720
- args: msg.args ?? {}
721
- }
722
- }));
723
- break;
724
- case "reply.done":
725
- target.dispatchEvent(new CustomEvent("reply_done", {
726
- detail: { status: msg.status ?? void 0 }
727
- }));
728
- break;
729
- case "session.error": {
730
- const code = msg.code;
731
- const isExpired = code === "session_not_found" || code === "session_forbidden";
732
- target.dispatchEvent(new CustomEvent(isExpired ? "session_expired" : "error", {
733
- detail: { code, message: msg.message }
734
- }));
735
- break;
736
- }
740
+ const msg = parsed.data;
741
+ if (msg.type !== "reply.audio") {
742
+ log.info(`S2S << ${JSON.stringify(msg)}`);
737
743
  }
744
+ dispatchS2sMessage(target, msg);
738
745
  });
739
746
  ws.on("close", (code, reason) => {
740
747
  log.info("S2S WebSocket closed", {
741
- code,
748
+ code: typeof code === "number" ? code : 0,
742
749
  reason: reason instanceof Uint8Array ? new TextDecoder().decode(reason) : String(reason ?? "")
743
750
  });
744
751
  target.dispatchEvent(new CustomEvent("close"));
@@ -756,21 +763,51 @@ function connectS2s(opts) {
756
763
  });
757
764
  });
758
765
  }
759
- var WS_OPEN;
766
+ var WS_OPEN, S2sServerMessageSchema;
760
767
  var init_s2s = __esm({
761
768
  "dist/sdk/s2s.js"() {
762
769
  "use strict";
763
770
  init_runtime();
764
771
  WS_OPEN = 1;
772
+ S2sServerMessageSchema = z4.discriminatedUnion("type", [
773
+ z4.object({ type: z4.literal("session.ready"), session_id: z4.string() }),
774
+ z4.object({ type: z4.literal("session.updated") }).passthrough(),
775
+ z4.object({ type: z4.literal("input.speech.started") }),
776
+ z4.object({ type: z4.literal("input.speech.stopped") }),
777
+ z4.object({ type: z4.literal("transcript.user.delta"), text: z4.string() }),
778
+ z4.object({
779
+ type: z4.literal("transcript.user"),
780
+ item_id: z4.string(),
781
+ text: z4.string()
782
+ }),
783
+ z4.object({ type: z4.literal("reply.started"), reply_id: z4.string() }),
784
+ z4.object({ type: z4.literal("reply.audio"), data: z4.string() }),
785
+ z4.object({ type: z4.literal("transcript.agent"), text: z4.string() }),
786
+ z4.object({
787
+ type: z4.literal("tool.call"),
788
+ call_id: z4.string(),
789
+ name: z4.string(),
790
+ args: z4.record(z4.string(), z4.unknown()).optional().default({})
791
+ }),
792
+ z4.object({
793
+ type: z4.literal("reply.done"),
794
+ status: z4.string().optional()
795
+ }),
796
+ z4.object({
797
+ type: z4.literal("session.error"),
798
+ code: z4.string(),
799
+ message: z4.string()
800
+ })
801
+ ]);
765
802
  }
766
803
  });
767
804
 
768
805
  // dist/sdk/types.js
769
- var DEFAULT_INSTRUCTIONS2;
806
+ var DEFAULT_INSTRUCTIONS;
770
807
  var init_types = __esm({
771
808
  "dist/sdk/types.js"() {
772
809
  "use strict";
773
- DEFAULT_INSTRUCTIONS2 = `You are AAI, a helpful AI assistant.
810
+ DEFAULT_INSTRUCTIONS = `You are AAI, a helpful AI assistant.
774
811
 
775
812
  Voice-First Rules:
776
813
  - Optimize for natural speech. Avoid jargon unless central to the answer. Use short, punchy sentences.
@@ -787,7 +824,7 @@ Voice-First Rules:
787
824
  // dist/sdk/system_prompt.js
788
825
  function buildSystemPrompt(config, opts) {
789
826
  const { hasTools } = opts;
790
- const agentInstructions = config.instructions ? `
827
+ const agentInstructions = config.instructions && config.instructions !== DEFAULT_INSTRUCTIONS ? `
791
828
 
792
829
  Agent-Specific Instructions:
793
830
  ${config.instructions}` : "";
@@ -798,7 +835,7 @@ ${config.instructions}` : "";
798
835
  month: "long",
799
836
  day: "numeric"
800
837
  });
801
- return DEFAULT_INSTRUCTIONS2 + `
838
+ return DEFAULT_INSTRUCTIONS + `
802
839
 
803
840
  Today's date is ${today}.` + agentInstructions + toolPreamble + (opts?.voice ? VOICE_RULES : "");
804
841
  }
@@ -844,10 +881,10 @@ function createS2sSession(opts) {
844
881
  return null;
845
882
  }
846
883
  }
847
- async function invokeHook(hook, ...args) {
884
+ function invokeHook(hook, arg) {
848
885
  if (!hookInvoker)
849
886
  return;
850
- try {
887
+ const run = async () => {
851
888
  switch (hook) {
852
889
  case "onConnect":
853
890
  await hookInvoker.onConnect(id, HOOK_TIMEOUT_MS);
@@ -856,20 +893,21 @@ function createS2sSession(opts) {
856
893
  await hookInvoker.onDisconnect(id, HOOK_TIMEOUT_MS);
857
894
  break;
858
895
  case "onTurn":
859
- await hookInvoker.onTurn(id, args[0], HOOK_TIMEOUT_MS);
896
+ await hookInvoker.onTurn(id, arg, HOOK_TIMEOUT_MS);
860
897
  break;
861
898
  case "onError":
862
- await hookInvoker.onError(id, args[0], HOOK_TIMEOUT_MS);
899
+ await hookInvoker.onError(id, arg, HOOK_TIMEOUT_MS);
863
900
  break;
864
901
  case "onStep":
865
- await hookInvoker.onStep(id, args[0], HOOK_TIMEOUT_MS);
902
+ await hookInvoker.onStep(id, arg, HOOK_TIMEOUT_MS);
866
903
  break;
867
904
  }
868
- } catch (err) {
905
+ };
906
+ run().catch((err) => {
869
907
  log.warn(`${hook} hook failed`, {
870
908
  err: err instanceof Error ? err.message : String(err)
871
909
  });
872
- }
910
+ });
873
911
  }
874
912
  async function handleToolCall(detail) {
875
913
  const { call_id, name, args: parsedArgs } = detail;
@@ -929,6 +967,9 @@ function createS2sSession(opts) {
929
967
  pendingTools.push({ call_id, result });
930
968
  client.event({ type: "tool_call_done", toolCallId: call_id, result });
931
969
  }
970
+ function on(target, event, handler) {
971
+ target.addEventListener(event, handler);
972
+ }
932
973
  async function connectAndSetup() {
933
974
  try {
934
975
  const handle = await _internals3.connectS2s({
@@ -942,54 +983,55 @@ function createS2sSession(opts) {
942
983
  session_id: s2sSessionId
943
984
  });
944
985
  handle.resumeSession(s2sSessionId);
986
+ } else {
987
+ handle.updateSession({
988
+ system_prompt: systemPrompt,
989
+ tools: s2sTools,
990
+ ...agentConfig.greeting ? { greeting: agentConfig.greeting } : {}
991
+ });
945
992
  }
946
- handle.updateSession({
947
- system_prompt: systemPrompt,
948
- tools: s2sTools,
949
- ...agentConfig.greeting ? { greeting: agentConfig.greeting } : {}
950
- });
951
- handle.addEventListener("ready", ((e) => {
993
+ on(handle, "ready", (e) => {
952
994
  s2sSessionId = e.detail.session_id;
953
995
  log.info("S2S session ready", { session_id: s2sSessionId });
954
- }));
955
- handle.addEventListener("session_expired", (() => {
996
+ });
997
+ on(handle, "session_expired", () => {
956
998
  log.info("S2S session expired, reconnecting fresh");
957
999
  s2sSessionId = null;
958
1000
  handle.close();
959
- }));
1001
+ });
960
1002
  handle.addEventListener("speech_started", () => {
961
1003
  client.event({ type: "speech_started" });
962
1004
  });
963
1005
  handle.addEventListener("speech_stopped", () => {
964
1006
  client.event({ type: "speech_stopped" });
965
1007
  });
966
- handle.addEventListener("user_transcript_delta", ((e) => {
1008
+ on(handle, "user_transcript_delta", (e) => {
967
1009
  client.event({
968
1010
  type: "transcript",
969
1011
  text: e.detail.text,
970
1012
  isFinal: false
971
1013
  });
972
- }));
973
- handle.addEventListener("user_transcript", ((e) => {
1014
+ });
1015
+ on(handle, "user_transcript", (e) => {
974
1016
  const { text } = e.detail;
975
1017
  log.info("S2S user transcript", { text });
976
1018
  client.event({ type: "transcript", text, isFinal: true });
977
1019
  client.event({ type: "turn", text });
978
1020
  conversationMessages.push({ role: "user", content: text });
979
1021
  invokeHook("onTurn", text);
980
- }));
1022
+ });
981
1023
  handle.addEventListener("reply_started", () => {
982
1024
  toolCallCount = 0;
983
1025
  });
984
- handle.addEventListener("audio", ((e) => {
1026
+ on(handle, "audio", (e) => {
985
1027
  client.playAudioChunk(e.detail.audio);
986
- }));
987
- handle.addEventListener("agent_transcript", ((e) => {
1028
+ });
1029
+ on(handle, "agent_transcript", (e) => {
988
1030
  const { text } = e.detail;
989
1031
  client.event({ type: "chat", text });
990
1032
  conversationMessages.push({ role: "assistant", content: text });
991
- }));
992
- handle.addEventListener("tool_call", ((e) => {
1033
+ });
1034
+ on(handle, "tool_call", (e) => {
993
1035
  const p = handleToolCall(e.detail).catch((err) => {
994
1036
  log.error("Tool call handler failed", {
995
1037
  err: err instanceof Error ? err.message : String(err)
@@ -999,25 +1041,23 @@ function createS2sSession(opts) {
999
1041
  turnPromise = (prev ?? Promise.resolve()).then(() => p).finally(() => {
1000
1042
  turnPromise = null;
1001
1043
  });
1002
- }));
1003
- handle.addEventListener("reply_done", ((e) => {
1044
+ });
1045
+ on(handle, "reply_done", (e) => {
1004
1046
  if (e.detail.status === "interrupted") {
1005
1047
  log.info("S2S reply interrupted (barge-in)");
1006
1048
  pendingTools = [];
1007
1049
  client.event({ type: "cancelled" });
1008
- } else {
1009
- if (pendingTools.length > 0) {
1010
- for (const tool of pendingTools) {
1011
- s2s?.sendToolResult(tool.call_id, tool.result);
1012
- }
1013
- pendingTools = [];
1014
- } else {
1015
- client.playAudioDone();
1016
- client.event({ type: "tts_done" });
1050
+ } else if (pendingTools.length > 0) {
1051
+ for (const tool of pendingTools) {
1052
+ s2s?.sendToolResult(tool.call_id, tool.result);
1017
1053
  }
1054
+ pendingTools = [];
1055
+ } else {
1056
+ client.playAudioDone();
1057
+ client.event({ type: "tts_done" });
1018
1058
  }
1019
- }));
1020
- handle.addEventListener("error", ((e) => {
1059
+ });
1060
+ on(handle, "error", (e) => {
1021
1061
  log.error("S2S error", {
1022
1062
  code: e.detail.code,
1023
1063
  message: e.detail.message
@@ -1027,7 +1067,7 @@ function createS2sSession(opts) {
1027
1067
  code: "internal",
1028
1068
  message: e.detail.message
1029
1069
  });
1030
- }));
1070
+ });
1031
1071
  handle.addEventListener("close", () => {
1032
1072
  log.info("S2S closed");
1033
1073
  s2s = null;
@@ -1106,31 +1146,80 @@ var init_session = __esm({
1106
1146
  }
1107
1147
  });
1108
1148
 
1149
+ // dist/sdk/vector.js
1150
+ function createMemoryVectorStore() {
1151
+ const store = /* @__PURE__ */ new Map();
1152
+ return {
1153
+ upsert(id, data, metadata) {
1154
+ store.set(id, { data, metadata });
1155
+ return Promise.resolve();
1156
+ },
1157
+ query(text, options) {
1158
+ const topK = options?.topK ?? 10;
1159
+ const query = text.toLowerCase();
1160
+ const results = [];
1161
+ for (const [id, entry] of store) {
1162
+ const data = entry.data.toLowerCase();
1163
+ const words = query.split(/\s+/).filter(Boolean);
1164
+ const matches = words.filter((w) => data.includes(w)).length;
1165
+ if (matches > 0) {
1166
+ results.push({
1167
+ id,
1168
+ score: matches / Math.max(words.length, 1),
1169
+ data: entry.data,
1170
+ metadata: entry.metadata
1171
+ });
1172
+ }
1173
+ }
1174
+ results.sort((a, b) => b.score - a.score);
1175
+ return Promise.resolve(results.slice(0, topK));
1176
+ },
1177
+ remove(ids) {
1178
+ const idArray = Array.isArray(ids) ? ids : [ids];
1179
+ for (const id of idArray) {
1180
+ store.delete(id);
1181
+ }
1182
+ return Promise.resolve();
1183
+ }
1184
+ };
1185
+ }
1186
+ var init_vector = __esm({
1187
+ "dist/sdk/vector.js"() {
1188
+ "use strict";
1189
+ }
1190
+ });
1191
+
1109
1192
  // dist/sdk/worker_entry.js
1110
- import { z as z4 } from "zod";
1193
+ function buildToolContext(opts) {
1194
+ const { env, sessionId, state, kv, vector, messages } = opts;
1195
+ return {
1196
+ sessionId: sessionId ?? "",
1197
+ env: { ...env },
1198
+ abortSignal: AbortSignal.timeout(TOOL_HANDLER_TIMEOUT),
1199
+ state: state ?? {},
1200
+ get kv() {
1201
+ if (!kv)
1202
+ throw new Error("KV not available");
1203
+ return kv;
1204
+ },
1205
+ get vector() {
1206
+ if (!vector)
1207
+ throw new Error("Vector store not available");
1208
+ return vector;
1209
+ },
1210
+ messages: messages ?? []
1211
+ };
1212
+ }
1111
1213
  async function executeToolCall(name, args, options) {
1112
- const { tool, env, sessionId, state, kv, messages } = options;
1113
- const schema = tool.parameters ?? z4.object({});
1214
+ const { tool } = options;
1215
+ const schema = tool.parameters ?? EMPTY_PARAMS;
1114
1216
  const parsed = schema.safeParse(args);
1115
1217
  if (!parsed.success) {
1116
1218
  const issues = (parsed.error?.issues ?? []).map((i) => `${i.path.map(String).join(".")}: ${i.message}`).join(", ");
1117
1219
  return `Error: Invalid arguments for tool "${name}": ${issues}`;
1118
1220
  }
1119
1221
  try {
1120
- const abortSignal = AbortSignal.timeout(TOOL_HANDLER_TIMEOUT);
1121
- const envCopy = { ...env };
1122
- const ctx = {
1123
- sessionId: sessionId ?? "",
1124
- env: envCopy,
1125
- abortSignal,
1126
- state: state ?? {},
1127
- get kv() {
1128
- if (!kv)
1129
- throw new Error("KV not available");
1130
- return kv;
1131
- },
1132
- messages: messages ?? []
1133
- };
1222
+ const ctx = buildToolContext(options);
1134
1223
  const result = await Promise.resolve(tool.execute(parsed.data, ctx));
1135
1224
  if (result == null)
1136
1225
  return "null";
@@ -1148,6 +1237,7 @@ var TOOL_HANDLER_TIMEOUT;
1148
1237
  var init_worker_entry = __esm({
1149
1238
  "dist/sdk/worker_entry.js"() {
1150
1239
  "use strict";
1240
+ init_internal_types();
1151
1241
  TOOL_HANDLER_TIMEOUT = 3e4;
1152
1242
  }
1153
1243
  });
@@ -1173,7 +1263,7 @@ function buildAgentConfig(agent) {
1173
1263
  return config;
1174
1264
  }
1175
1265
  function createDirectExecutor(opts) {
1176
- const { agent, env, kv = createMemoryKv(), vectorSearch, createWebSocket, logger = consoleLogger, metrics = noopMetrics, s2sConfig = DEFAULT_S2S_CONFIG } = opts;
1266
+ const { agent, env, kv = createMemoryKv(), vector = createMemoryVectorStore(), vectorSearch, createWebSocket, logger = consoleLogger, metrics = noopMetrics, s2sConfig = DEFAULT_S2S_CONFIG } = opts;
1177
1267
  const agentConfig = buildAgentConfig(agent);
1178
1268
  const builtinDefs = getBuiltinToolDefs(agent.builtinTools ?? [], vectorSearch ? { vectorSearch } : void 0);
1179
1269
  const allTools = {
@@ -1198,6 +1288,9 @@ function createDirectExecutor(opts) {
1198
1288
  state: getState(sessionId),
1199
1289
  get kv() {
1200
1290
  return kv;
1291
+ },
1292
+ get vector() {
1293
+ return vector;
1201
1294
  }
1202
1295
  };
1203
1296
  }
@@ -1211,6 +1304,7 @@ function createDirectExecutor(opts) {
1211
1304
  sessionId,
1212
1305
  state: getState(sessionId ?? ""),
1213
1306
  kv,
1307
+ vector,
1214
1308
  messages
1215
1309
  });
1216
1310
  };
@@ -1283,6 +1377,7 @@ var init_direct_executor = __esm({
1283
1377
  init_kv();
1284
1378
  init_runtime();
1285
1379
  init_session();
1380
+ init_vector();
1286
1381
  init_worker_entry();
1287
1382
  }
1288
1383
  });
@@ -1313,6 +1408,64 @@ function createClientSink(ws) {
1313
1408
  }
1314
1409
  };
1315
1410
  }
1411
+ function isBinaryData(data) {
1412
+ return globalThis.Buffer?.isBuffer(data) || data instanceof ArrayBuffer || data instanceof Uint8Array;
1413
+ }
1414
+ function toUint8Array(data) {
1415
+ if (data instanceof Uint8Array)
1416
+ return data;
1417
+ if (data instanceof ArrayBuffer)
1418
+ return new Uint8Array(data);
1419
+ const buf = data;
1420
+ return new Uint8Array(buf.buffer ?? data, buf.byteOffset ?? 0, buf.byteLength);
1421
+ }
1422
+ function handleBinaryAudio(data, session, log, ctx, sid) {
1423
+ if (!isBinaryData(data))
1424
+ return false;
1425
+ const chunk = toUint8Array(data);
1426
+ if (!isValidAudioChunk(chunk)) {
1427
+ log.warn("Invalid audio chunk, dropping", {
1428
+ ...ctx,
1429
+ sid,
1430
+ bytes: chunk.byteLength,
1431
+ aligned: chunk.byteLength % 2 === 0
1432
+ });
1433
+ return true;
1434
+ }
1435
+ session.onAudio(chunk);
1436
+ return true;
1437
+ }
1438
+ function handleTextMessage(data, session, log, ctx, sid) {
1439
+ if (typeof data !== "string")
1440
+ return;
1441
+ let json;
1442
+ try {
1443
+ json = JSON.parse(data);
1444
+ } catch {
1445
+ log.warn("Invalid JSON from client", { ...ctx, sid });
1446
+ return;
1447
+ }
1448
+ const parsed = ClientMessageSchema.safeParse(json);
1449
+ if (!parsed.success) {
1450
+ log.warn("Invalid client message", { ...ctx, sid, error: parsed.error.message });
1451
+ return;
1452
+ }
1453
+ const msg = parsed.data;
1454
+ switch (msg.type) {
1455
+ case "audio_ready":
1456
+ session.onAudioReady();
1457
+ break;
1458
+ case "cancel":
1459
+ session.onCancel();
1460
+ break;
1461
+ case "reset":
1462
+ session.onReset();
1463
+ break;
1464
+ case "history":
1465
+ session.onHistory(msg.messages);
1466
+ break;
1467
+ }
1468
+ }
1316
1469
  function wireSessionSocket(ws, opts) {
1317
1470
  const { sessions, logger: log = consoleLogger } = opts;
1318
1471
  const sessionId = crypto.randomUUID();
@@ -1337,56 +1490,10 @@ function wireSessionSocket(ws, opts) {
1337
1490
  ws.addEventListener("message", (event) => {
1338
1491
  if (!session)
1339
1492
  return;
1340
- const msgEvent = event;
1341
- const { data } = msgEvent;
1342
- const isBinary = globalThis.Buffer?.isBuffer(data) || data instanceof ArrayBuffer || data instanceof Uint8Array;
1343
- if (isBinary) {
1344
- const chunk = data instanceof Uint8Array ? data : new Uint8Array(data.buffer ?? data, data.byteOffset ?? 0, data.byteLength ?? data.byteLength);
1345
- if (!isValidAudioChunk(chunk)) {
1346
- log.warn("Invalid audio chunk, dropping", {
1347
- ...ctx,
1348
- sid,
1349
- bytes: chunk.byteLength,
1350
- aligned: chunk.byteLength % 2 === 0
1351
- });
1352
- return;
1353
- }
1354
- session.onAudio(chunk);
1355
- return;
1356
- }
1357
- if (typeof data !== "string")
1358
- return;
1359
- let json;
1360
- try {
1361
- json = JSON.parse(data);
1362
- } catch {
1363
- log.warn("Invalid JSON from client", { ...ctx, sid });
1493
+ const { data } = event;
1494
+ if (handleBinaryAudio(data, session, log, ctx, sid))
1364
1495
  return;
1365
- }
1366
- const parsed = ClientMessageSchema.safeParse(json);
1367
- if (!parsed.success) {
1368
- log.warn("Invalid client message", {
1369
- ...ctx,
1370
- sid,
1371
- error: parsed.error.message
1372
- });
1373
- return;
1374
- }
1375
- const msg = parsed.data;
1376
- switch (msg.type) {
1377
- case "audio_ready":
1378
- session.onAudioReady();
1379
- break;
1380
- case "cancel":
1381
- session.onCancel();
1382
- break;
1383
- case "reset":
1384
- session.onReset();
1385
- break;
1386
- case "history":
1387
- session.onHistory(msg.messages);
1388
- break;
1389
- }
1496
+ handleTextMessage(data, session, log, ctx, sid);
1390
1497
  });
1391
1498
  ws.addEventListener("close", () => {
1392
1499
  log.info("Session disconnected", { ...ctx, sid });
@@ -1414,11 +1521,12 @@ var init_ws_handler = __esm({
1414
1521
 
1415
1522
  // dist/sdk/winterc_server.js
1416
1523
  function createWintercServer(options) {
1417
- const { agent, env, kv = createMemoryKv(), vectorSearch, clientHtml, logger = consoleLogger, metrics = noopMetrics, s2sConfig = DEFAULT_S2S_CONFIG } = options;
1524
+ const { agent, env, kv = createMemoryKv(), vector = createMemoryVectorStore(), vectorSearch, clientHtml, logger = consoleLogger, metrics = noopMetrics, s2sConfig = DEFAULT_S2S_CONFIG } = options;
1418
1525
  const executor = createDirectExecutor({
1419
1526
  agent,
1420
1527
  env,
1421
1528
  kv,
1529
+ vector,
1422
1530
  ...vectorSearch ? { vectorSearch } : {},
1423
1531
  createWebSocket: options.createWebSocket,
1424
1532
  logger,
@@ -1430,8 +1538,7 @@ function createWintercServer(options) {
1430
1538
  protocolVersion: PROTOCOL_VERSION,
1431
1539
  audioFormat: AUDIO_FORMAT,
1432
1540
  sampleRate: s2sConfig.inputSampleRate,
1433
- ttsSampleRate: s2sConfig.outputSampleRate,
1434
- mode: "s2s"
1541
+ ttsSampleRate: s2sConfig.outputSampleRate
1435
1542
  };
1436
1543
  return {
1437
1544
  async fetch(request) {
@@ -1479,6 +1586,7 @@ var init_winterc_server = __esm({
1479
1586
  init_kv();
1480
1587
  init_protocol();
1481
1588
  init_runtime();
1589
+ init_vector();
1482
1590
  init_ws_handler();
1483
1591
  }
1484
1592
  });
@@ -1522,7 +1630,9 @@ function createServer(options) {
1522
1630
  agent,
1523
1631
  env,
1524
1632
  ...kv ? { kv } : {},
1525
- createWebSocket: wsFactory,
1633
+ createWebSocket: wsFactory ?? (() => {
1634
+ throw new Error("WebSocket factory not loaded");
1635
+ }),
1526
1636
  ...clientHtml !== void 0 ? { clientHtml } : {},
1527
1637
  logger,
1528
1638
  s2sConfig
@@ -1539,46 +1649,9 @@ function createServer(options) {
1539
1649
  await getWsFactory();
1540
1650
  const http = await import("node:http");
1541
1651
  const nodeServer = http.createServer(async (req, res) => {
1542
- try {
1543
- const protocol = req.socket.encrypted ? "https" : "http";
1544
- const host = req.headers.host ?? `localhost:${port}`;
1545
- const url = new URL(req.url ?? "/", `${protocol}://${host}`);
1546
- const headers = new Headers();
1547
- for (const [key, val] of Object.entries(req.headers)) {
1548
- if (val)
1549
- headers.set(key, Array.isArray(val) ? val[0] : val);
1550
- }
1551
- const request = new Request(url, {
1552
- method: req.method ?? "GET",
1553
- headers
1554
- });
1555
- const response = await getWinterc().fetch(request);
1556
- res.writeHead(response.status, Object.fromEntries(response.headers));
1557
- const body = await response.text();
1558
- res.end(body);
1559
- } catch (err) {
1560
- res.writeHead(500);
1561
- res.end(err instanceof Error ? err.message : "Internal Server Error");
1562
- }
1652
+ await nodeHttpHandler(req, res, port, getWinterc);
1563
1653
  });
1564
- try {
1565
- const wsMod = await import("ws");
1566
- const WSServer = wsMod.WebSocketServer;
1567
- if (WSServer) {
1568
- const wss = new WSServer({ noServer: true });
1569
- nodeServer.on("upgrade", (req, socket, head) => {
1570
- wss.handleUpgrade(req, socket, head, (ws) => {
1571
- const reqUrl = new URL(req.url ?? "/", `http://localhost:${port}`);
1572
- const resume = reqUrl.searchParams.has("resume");
1573
- getWinterc().handleWebSocket(ws, {
1574
- skipGreeting: resume
1575
- });
1576
- });
1577
- });
1578
- }
1579
- } catch {
1580
- logger.warn("ws package not available for Node.js WebSocket upgrade");
1581
- }
1654
+ attachWsUpgrade(nodeServer, port, getWinterc, logger);
1582
1655
  await new Promise((resolve) => {
1583
1656
  nodeServer.listen(port, () => {
1584
1657
  logger.info(`Agent "${agent.name}" listening on http://localhost:${port}`);
@@ -1599,6 +1672,43 @@ function createServer(options) {
1599
1672
  }
1600
1673
  };
1601
1674
  }
1675
+ async function nodeHttpHandler(req, res, port, getWinterc) {
1676
+ try {
1677
+ const protocol = req.socket.encrypted ? "https" : "http";
1678
+ const host = req.headers.host ?? `localhost:${port}`;
1679
+ const url = new URL(req.url ?? "/", `${protocol}://${host}`);
1680
+ const headers = new Headers();
1681
+ for (const [key, val] of Object.entries(req.headers)) {
1682
+ if (val)
1683
+ headers.set(key, Array.isArray(val) ? val[0] ?? "" : val);
1684
+ }
1685
+ const request = new Request(url, { method: req.method ?? "GET", headers });
1686
+ const response = await getWinterc().fetch(request);
1687
+ res.writeHead(response.status, Object.fromEntries(response.headers));
1688
+ res.end(await response.text());
1689
+ } catch (err) {
1690
+ res.writeHead(500);
1691
+ res.end(err instanceof Error ? err.message : "Internal Server Error");
1692
+ }
1693
+ }
1694
+ function attachWsUpgrade(nodeServer, port, getWinterc, logger) {
1695
+ import("ws").then((wsMod) => {
1696
+ const WSServer = wsMod.WebSocketServer;
1697
+ if (!WSServer)
1698
+ return;
1699
+ const wss = new WSServer({ noServer: true });
1700
+ nodeServer.on("upgrade", (req, socket, head) => {
1701
+ wss.handleUpgrade(req, socket, head, (ws) => {
1702
+ const reqUrl = new URL(req.url ?? "/", `http://localhost:${port}`);
1703
+ getWinterc().handleWebSocket(ws, {
1704
+ skipGreeting: reqUrl.searchParams.has("resume")
1705
+ });
1706
+ });
1707
+ });
1708
+ }).catch(() => {
1709
+ logger.warn("ws package not available for Node.js WebSocket upgrade");
1710
+ });
1711
+ }
1602
1712
  var init_server = __esm({
1603
1713
  "dist/sdk/server.js"() {
1604
1714
  init_runtime();
@@ -1844,9 +1954,7 @@ async function loadAgent(dir) {
1844
1954
  slug,
1845
1955
  dir,
1846
1956
  entryPoint: path.join(dir, "agent.ts"),
1847
- env: {},
1848
- clientEntry,
1849
- transport: ["websocket"]
1957
+ clientEntry
1850
1958
  };
1851
1959
  }
1852
1960
  async function ensureClaudeMd(targetDir) {
@@ -1880,7 +1988,7 @@ init_output();
1880
1988
  var _internals = {
1881
1989
  fetch: globalThis.fetch.bind(globalThis)
1882
1990
  };
1883
- async function attemptDeploy(url, slug, apiKey, env, transport, worker, html, config, toolSchemas) {
1991
+ async function attemptDeploy(url, slug, apiKey, env, worker, html) {
1884
1992
  return await _internals.fetch(`${url}/${slug}/deploy`, {
1885
1993
  method: "POST",
1886
1994
  headers: {
@@ -1890,21 +1998,14 @@ async function attemptDeploy(url, slug, apiKey, env, transport, worker, html, co
1890
1998
  body: JSON.stringify({
1891
1999
  env,
1892
2000
  worker,
1893
- html,
1894
- transport,
1895
- config,
1896
- toolSchemas
2001
+ html
1897
2002
  })
1898
2003
  });
1899
2004
  }
1900
2005
  var MAX_RETRIES = 20;
1901
2006
  async function runDeploy(opts) {
1902
- const manifest = JSON.parse(opts.bundle.manifest);
1903
2007
  const worker = opts.bundle.worker;
1904
2008
  const html = opts.bundle.html;
1905
- const transport = manifest.transport ?? ["websocket"];
1906
- const config = manifest.config;
1907
- const toolSchemas = manifest.toolSchemas;
1908
2009
  let slug = opts.slug;
1909
2010
  if (opts.dryRun) {
1910
2011
  stepInfo("Dry run", "would deploy:");
@@ -1912,17 +2013,7 @@ async function runDeploy(opts) {
1912
2013
  return { slug };
1913
2014
  }
1914
2015
  for (let i = 0; i < MAX_RETRIES; i++) {
1915
- const resp = await attemptDeploy(
1916
- opts.url,
1917
- slug,
1918
- opts.apiKey,
1919
- opts.env,
1920
- transport,
1921
- worker,
1922
- html,
1923
- config,
1924
- toolSchemas
1925
- );
2016
+ const resp = await attemptDeploy(opts.url, slug, opts.apiKey, opts.env, worker, html);
1926
2017
  if (resp.ok) {
1927
2018
  step("Deploy", `${slug} -> ${opts.url}/${slug}`);
1928
2019
  try {
@@ -2078,365 +2169,16 @@ async function runWithInk(label, fn) {
2078
2169
  }
2079
2170
 
2080
2171
  // cli/build.ts
2081
- import fs4 from "node:fs/promises";
2172
+ import fs3 from "node:fs/promises";
2082
2173
  import path3 from "node:path";
2083
2174
 
2084
2175
  // cli/_bundler.ts
2085
- import fs3 from "node:fs/promises";
2176
+ import fs2 from "node:fs/promises";
2086
2177
  import path2 from "node:path";
2087
2178
  import preact from "@preact/preset-vite";
2088
2179
  import tailwindcss from "@tailwindcss/vite";
2089
2180
  import { build } from "vite";
2090
2181
  import { viteSingleFile } from "vite-plugin-singlefile";
2091
-
2092
- // cli/_static_config.ts
2093
- import fs2 from "node:fs/promises";
2094
- import {
2095
- Project,
2096
- SyntaxKind
2097
- } from "ts-morph";
2098
-
2099
- // sdk/types.ts
2100
- var DEFAULT_INSTRUCTIONS = `You are AAI, a helpful AI assistant.
2101
-
2102
- Voice-First Rules:
2103
- - Optimize for natural speech. Avoid jargon unless central to the answer. Use short, punchy sentences.
2104
- - Never mention "search results," "sources," or "the provided text." Speak as if the knowledge is your own.
2105
- - No visual formatting. Do not say "bullet point," "bold," or "bracketed one." If you need to list items, say "First," "Next," and "Finally."
2106
- - Start with the most important information. No introductory filler.
2107
- - Be concise. Keep answers to 1-3 sentences. For complex topics, provide a high-level summary.
2108
- - Be confident. Avoid hedging phrases like "It seems that" or "I believe."
2109
- - If you don't have enough information, say so directly rather than guessing.
2110
- - Never use exclamation points. Keep your tone calm and conversational.`;
2111
- var DEFAULT_GREETING = "Hey there. I'm a voice assistant. What can I help you with?";
2112
-
2113
- // cli/_static_config.ts
2114
- var project = new Project({ useInMemoryFileSystem: true });
2115
- async function extractStaticConfig(agentPath) {
2116
- const source = await fs2.readFile(agentPath, "utf-8");
2117
- return extractStaticConfigFromSource(source, agentPath);
2118
- }
2119
- function extractStaticConfigFromSource(source, fileName = "agent.ts") {
2120
- const sf = project.createSourceFile(fileName, source, { overwrite: true });
2121
- const call = findDefineAgentCall(sf);
2122
- if (!call) {
2123
- throw new BundleError(
2124
- `Could not find a defineAgent({...}) call in ${fileName}. Make sure your agent.ts has \`export default defineAgent({...})\`.`
2125
- );
2126
- }
2127
- const args = call.getArguments();
2128
- const arg = args[0];
2129
- if (!arg || !arg.isKind(SyntaxKind.ObjectLiteralExpression)) {
2130
- throw new BundleError("The argument to defineAgent() must be an inline object literal");
2131
- }
2132
- const obj = arg.asKindOrThrow(SyntaxKind.ObjectLiteralExpression);
2133
- const config = extractConfig(obj, fileName);
2134
- const toolSchemas = extractToolSchemas(obj, fileName);
2135
- return { config, toolSchemas };
2136
- }
2137
- function findDefineAgentCall(sf) {
2138
- return sf.getFirstDescendant((node) => {
2139
- if (!node.isKind(SyntaxKind.CallExpression)) return false;
2140
- const expr = node.getExpression();
2141
- return expr.isKind(SyntaxKind.Identifier) && expr.getText() === "defineAgent";
2142
- });
2143
- }
2144
- function extractConfig(obj, fileName) {
2145
- const name = requireString(obj, "name", fileName);
2146
- const config = {
2147
- name,
2148
- instructions: optionalString(obj, "instructions", fileName) ?? DEFAULT_INSTRUCTIONS,
2149
- greeting: optionalString(obj, "greeting", fileName) ?? DEFAULT_GREETING,
2150
- voice: optionalString(obj, "voice", fileName) ?? ""
2151
- };
2152
- const mode = optionalString(obj, "mode", fileName);
2153
- config.mode = mode ?? "s2s";
2154
- const sttPrompt = optionalString(obj, "sttPrompt", fileName);
2155
- if (sttPrompt !== void 0) config.sttPrompt = sttPrompt;
2156
- const maxStepsProp = getProperty(obj, "maxSteps");
2157
- if (maxStepsProp) {
2158
- const init = maxStepsProp.getInitializer();
2159
- if (init.isKind(SyntaxKind.NumericLiteral)) {
2160
- config.maxSteps = Number(init.getLiteralValue());
2161
- }
2162
- }
2163
- const toolChoiceProp = getProperty(obj, "toolChoice");
2164
- if (toolChoiceProp) {
2165
- config.toolChoice = evalLiteral(
2166
- toolChoiceProp.getInitializer(),
2167
- "toolChoice",
2168
- fileName
2169
- );
2170
- }
2171
- const builtinToolsProp = getProperty(obj, "builtinTools");
2172
- if (builtinToolsProp) {
2173
- config.builtinTools = evalStringArray(
2174
- builtinToolsProp.getInitializer(),
2175
- "builtinTools",
2176
- fileName
2177
- );
2178
- }
2179
- const activeToolsProp = getProperty(obj, "activeTools");
2180
- if (activeToolsProp) {
2181
- config.activeTools = evalStringArray(
2182
- activeToolsProp.getInitializer(),
2183
- "activeTools",
2184
- fileName
2185
- );
2186
- }
2187
- const transportProp = getProperty(obj, "transport");
2188
- if (transportProp) {
2189
- const init = transportProp.getInitializer();
2190
- if (init.isKind(SyntaxKind.StringLiteral)) {
2191
- config.transport = [init.getLiteralValue()];
2192
- } else if (init.isKind(SyntaxKind.ArrayLiteralExpression)) {
2193
- config.transport = evalStringArray(init, "transport", fileName);
2194
- } else {
2195
- throw new BundleError(
2196
- `${fileName}: \`transport\` must be a string literal or array of strings.`
2197
- );
2198
- }
2199
- }
2200
- return config;
2201
- }
2202
- function extractToolSchemas(obj, fileName) {
2203
- const toolsProp = getProperty(obj, "tools");
2204
- if (!toolsProp) return [];
2205
- const init = toolsProp.getInitializer();
2206
- if (!init.isKind(SyntaxKind.ObjectLiteralExpression)) {
2207
- throw new BundleError(`${fileName}: \`tools\` must be an inline object literal.`);
2208
- }
2209
- const toolsObj = init.asKindOrThrow(SyntaxKind.ObjectLiteralExpression);
2210
- const schemas = [];
2211
- for (const member of toolsObj.getProperties()) {
2212
- if (member.isKind(SyntaxKind.SpreadAssignment)) {
2213
- const text = member.getExpression().getText();
2214
- throw new BundleError(
2215
- `${fileName}: Spread expressions like \`...${text}\` in tools cannot be statically analyzed. Define each tool directly in the \`tools\` object.`
2216
- );
2217
- }
2218
- if (!member.isKind(SyntaxKind.PropertyAssignment)) continue;
2219
- const prop = member;
2220
- const toolName = prop.getName();
2221
- const toolInit = prop.getInitializer();
2222
- if (!toolInit.isKind(SyntaxKind.ObjectLiteralExpression)) {
2223
- throw new BundleError(`${fileName}: Tool \`${toolName}\` must be an inline object literal.`);
2224
- }
2225
- const toolObj = toolInit.asKindOrThrow(SyntaxKind.ObjectLiteralExpression);
2226
- const descProp = getProperty(toolObj, "description");
2227
- if (!descProp) {
2228
- throw new BundleError(`${fileName}: Tool \`${toolName}\` is missing a \`description\`.`);
2229
- }
2230
- const description = evalStringLiteral(descProp.getInitializer(), toolName, fileName);
2231
- const paramsProp = getProperty(toolObj, "parameters");
2232
- const parameters = paramsProp ? zodAstToJsonSchema(paramsProp.getInitializer(), toolName, fileName) : { type: "object", properties: {}, additionalProperties: false };
2233
- schemas.push({ name: toolName, description, parameters });
2234
- }
2235
- return schemas;
2236
- }
2237
- function zodAstToJsonSchema(node, toolName, fileName) {
2238
- return parseZodExpr(node, toolName, fileName).schema;
2239
- }
2240
- function parseZodExpr(node, toolName, fileName) {
2241
- if (!node.isKind(SyntaxKind.CallExpression)) {
2242
- throw zodError(node, toolName, fileName);
2243
- }
2244
- const call = node.asKindOrThrow(SyntaxKind.CallExpression);
2245
- const expr = call.getExpression();
2246
- if (expr.isKind(SyntaxKind.PropertyAccessExpression)) {
2247
- const propAccess = expr.asKindOrThrow(SyntaxKind.PropertyAccessExpression);
2248
- const obj = propAccess.getExpression();
2249
- const method = propAccess.getName();
2250
- if (obj.isKind(SyntaxKind.Identifier) && obj.getText() === "z") {
2251
- return parseZodBase(method, call, toolName, fileName);
2252
- }
2253
- if (method === "describe") {
2254
- const result = parseZodExpr(obj, toolName, fileName);
2255
- const args = call.getArguments();
2256
- if (args[0]) {
2257
- result.schema.description = evalStringLiteral(args[0], toolName, fileName);
2258
- }
2259
- return result;
2260
- }
2261
- if (method === "optional") {
2262
- const result = parseZodExpr(obj, toolName, fileName);
2263
- result.optional = true;
2264
- return result;
2265
- }
2266
- if (method === "default" || method === "nullable") {
2267
- return parseZodExpr(obj, toolName, fileName);
2268
- }
2269
- return parseZodExpr(obj, toolName, fileName);
2270
- }
2271
- throw zodError(node, toolName, fileName);
2272
- }
2273
- function parseZodBase(method, call, toolName, fileName) {
2274
- switch (method) {
2275
- case "string":
2276
- return { schema: { type: "string" }, optional: false };
2277
- case "number":
2278
- return { schema: { type: "number" }, optional: false };
2279
- case "boolean":
2280
- return { schema: { type: "boolean" }, optional: false };
2281
- case "enum": {
2282
- const args = call.getArguments();
2283
- const arg = args[0];
2284
- if (!arg || !arg.isKind(SyntaxKind.ArrayLiteralExpression)) {
2285
- throw new BundleError(
2286
- `${fileName}: Tool \`${toolName}\`: z.enum() requires an array literal argument.`
2287
- );
2288
- }
2289
- const arr = arg.asKindOrThrow(SyntaxKind.ArrayLiteralExpression);
2290
- const values = arr.getElements().map((el) => {
2291
- if (!el.isKind(SyntaxKind.StringLiteral)) {
2292
- throw new BundleError(
2293
- `${fileName}: Tool \`${toolName}\`: z.enum() values must be string literals.`
2294
- );
2295
- }
2296
- return el.asKindOrThrow(SyntaxKind.StringLiteral).getLiteralValue();
2297
- });
2298
- return {
2299
- schema: { type: "string", enum: values },
2300
- optional: false
2301
- };
2302
- }
2303
- case "array": {
2304
- const args = call.getArguments();
2305
- const arg = args[0];
2306
- if (!arg) {
2307
- return { schema: { type: "array" }, optional: false };
2308
- }
2309
- const items = parseZodExpr(arg, toolName, fileName);
2310
- return {
2311
- schema: { type: "array", items: items.schema },
2312
- optional: false
2313
- };
2314
- }
2315
- case "object": {
2316
- const args = call.getArguments();
2317
- const arg = args[0];
2318
- if (!arg || !arg.isKind(SyntaxKind.ObjectLiteralExpression)) {
2319
- return {
2320
- schema: {
2321
- type: "object",
2322
- properties: {},
2323
- additionalProperties: false
2324
- },
2325
- optional: false
2326
- };
2327
- }
2328
- const objLit = arg.asKindOrThrow(SyntaxKind.ObjectLiteralExpression);
2329
- const properties = {};
2330
- const required = [];
2331
- for (const member of objLit.getProperties()) {
2332
- if (!member.isKind(SyntaxKind.PropertyAssignment)) continue;
2333
- const prop = member;
2334
- const propName = prop.getName();
2335
- const result = parseZodExpr(prop.getInitializer(), toolName, fileName);
2336
- properties[propName] = result.schema;
2337
- if (!result.optional) {
2338
- required.push(propName);
2339
- }
2340
- }
2341
- const schema = {
2342
- type: "object",
2343
- properties,
2344
- additionalProperties: false
2345
- };
2346
- if (required.length > 0) {
2347
- schema.required = required;
2348
- }
2349
- return { schema, optional: false };
2350
- }
2351
- default:
2352
- throw new BundleError(
2353
- `${fileName}: Tool \`${toolName}\`: unsupported Zod type \`z.${method}()\`. Supported: z.string(), z.number(), z.boolean(), z.enum([...]), z.array(...), z.object({...}).`
2354
- );
2355
- }
2356
- }
2357
- function zodError(node, toolName, fileName) {
2358
- const text = node.getText().slice(0, 60);
2359
- return new BundleError(
2360
- `${fileName}: Tool \`${toolName}\`: unsupported Zod pattern \`${text}\`. Supported: z.string(), z.number(), z.boolean(), z.enum([...]), z.array(...), z.object({...}), .describe(), .optional().`
2361
- );
2362
- }
2363
- function getProperty(obj, name) {
2364
- const prop = obj.getProperty(name);
2365
- if (!prop) return void 0;
2366
- if (!prop.isKind(SyntaxKind.PropertyAssignment)) return void 0;
2367
- return prop;
2368
- }
2369
- function requireString(obj, field, fileName) {
2370
- const prop = getProperty(obj, field);
2371
- if (!prop) {
2372
- throw new BundleError(`${fileName}: The \`${field}\` field is required in defineAgent({...}).`);
2373
- }
2374
- return evalStringLiteral(prop.getInitializer(), field, fileName);
2375
- }
2376
- function optionalString(obj, field, fileName) {
2377
- const prop = getProperty(obj, field);
2378
- if (!prop) return void 0;
2379
- return evalStringLiteral(prop.getInitializer(), field, fileName);
2380
- }
2381
- function evalStringLiteral(node, context, fileName) {
2382
- if (node.isKind(SyntaxKind.StringLiteral)) {
2383
- return node.asKindOrThrow(SyntaxKind.StringLiteral).getLiteralValue();
2384
- }
2385
- if (node.isKind(SyntaxKind.NoSubstitutionTemplateLiteral)) {
2386
- return node.asKindOrThrow(SyntaxKind.NoSubstitutionTemplateLiteral).getLiteralValue();
2387
- }
2388
- if (node.isKind(SyntaxKind.TemplateExpression)) {
2389
- throw new BundleError(
2390
- `${fileName}: \`${context}\` uses template expressions with substitutions, which cannot be statically analyzed. Use a plain string literal.`
2391
- );
2392
- }
2393
- throw new BundleError(
2394
- `${fileName}: \`${context}\` must be a static string literal. Dynamic expressions cannot be analyzed at build time.`
2395
- );
2396
- }
2397
- function evalStringArray(node, context, fileName) {
2398
- if (!node.isKind(SyntaxKind.ArrayLiteralExpression)) {
2399
- throw new BundleError(`${fileName}: \`${context}\` must be an array literal.`);
2400
- }
2401
- const arr = node.asKindOrThrow(SyntaxKind.ArrayLiteralExpression);
2402
- return arr.getElements().map((el) => evalStringLiteral(el, context, fileName));
2403
- }
2404
- function evalLiteral(node, context, fileName) {
2405
- if (node.isKind(SyntaxKind.StringLiteral)) {
2406
- return node.asKindOrThrow(SyntaxKind.StringLiteral).getLiteralValue();
2407
- }
2408
- if (node.isKind(SyntaxKind.NoSubstitutionTemplateLiteral)) {
2409
- return node.asKindOrThrow(SyntaxKind.NoSubstitutionTemplateLiteral).getLiteralValue();
2410
- }
2411
- if (node.isKind(SyntaxKind.NumericLiteral)) {
2412
- return Number(node.asKindOrThrow(SyntaxKind.NumericLiteral).getLiteralValue());
2413
- }
2414
- if (node.isKind(SyntaxKind.TrueKeyword)) return true;
2415
- if (node.isKind(SyntaxKind.FalseKeyword)) return false;
2416
- if (node.isKind(SyntaxKind.ArrayLiteralExpression)) {
2417
- return node.asKindOrThrow(SyntaxKind.ArrayLiteralExpression).getElements().map((el) => evalLiteral(el, context, fileName));
2418
- }
2419
- if (node.isKind(SyntaxKind.ObjectLiteralExpression)) {
2420
- const obj = node.asKindOrThrow(SyntaxKind.ObjectLiteralExpression);
2421
- const result = {};
2422
- for (const member of obj.getProperties()) {
2423
- if (member.isKind(SyntaxKind.PropertyAssignment)) {
2424
- const prop = member;
2425
- result[prop.getName()] = evalLiteral(
2426
- prop.getInitializer(),
2427
- context,
2428
- fileName
2429
- );
2430
- }
2431
- }
2432
- return result;
2433
- }
2434
- throw new BundleError(
2435
- `${fileName}: \`${context}\` must be a static literal value. Dynamic expressions cannot be analyzed at build time.`
2436
- );
2437
- }
2438
-
2439
- // cli/_bundler.ts
2440
2182
  var BundleError = class extends Error {
2441
2183
  constructor(message) {
2442
2184
  super(message);
@@ -2558,14 +2300,13 @@ var INDEX_HTML = `<!DOCTYPE html>
2558
2300
  async function bundleAgent(agent, opts) {
2559
2301
  const aaiDir = path2.join(agent.dir, ".aai");
2560
2302
  const buildDir = path2.join(aaiDir, "build");
2561
- await fs3.mkdir(aaiDir, { recursive: true });
2562
- const { config: agentConfig, toolSchemas } = await extractStaticConfig(agent.entryPoint);
2563
- await fs3.writeFile(path2.join(aaiDir, "index.html"), INDEX_HTML);
2303
+ await fs2.mkdir(aaiDir, { recursive: true });
2304
+ await fs2.writeFile(path2.join(aaiDir, "index.html"), INDEX_HTML);
2564
2305
  const stylesPath = path2.join(agent.dir, "styles.css");
2565
2306
  try {
2566
- await fs3.access(stylesPath);
2307
+ await fs2.access(stylesPath);
2567
2308
  } catch {
2568
- await fs3.writeFile(stylesPath, DEFAULT_STYLES_CSS);
2309
+ await fs2.writeFile(stylesPath, DEFAULT_STYLES_CSS);
2569
2310
  }
2570
2311
  try {
2571
2312
  await build({
@@ -2610,22 +2351,12 @@ async function bundleAgent(agent, opts) {
2610
2351
  throw new BundleError(err instanceof Error ? err.message : String(err));
2611
2352
  }
2612
2353
  }
2613
- const worker = await fs3.readFile(path2.join(buildDir, "worker.js"), "utf-8");
2354
+ const worker = await fs2.readFile(path2.join(buildDir, "worker.js"), "utf-8");
2614
2355
  const htmlPath = skipClient ? path2.join(aaiDir, "index.html") : path2.join(buildDir, "index.html");
2615
- const html = await fs3.readFile(htmlPath, "utf-8");
2616
- const manifest = JSON.stringify(
2617
- {
2618
- transport: agentConfig.transport ?? agent.transport,
2619
- config: agentConfig,
2620
- toolSchemas
2621
- },
2622
- null,
2623
- 2
2624
- );
2356
+ const html = await fs2.readFile(htmlPath, "utf-8");
2625
2357
  return {
2626
2358
  worker,
2627
2359
  html,
2628
- manifest,
2629
2360
  workerBytes: Buffer.byteLength(worker)
2630
2361
  };
2631
2362
  }
@@ -2634,46 +2365,17 @@ async function bundleAgent(agent, opts) {
2634
2365
  init_output();
2635
2366
  async function writeBuildOutput(agentDir, bundle) {
2636
2367
  const buildDir = path3.join(agentDir, ".aai", "build");
2637
- await fs4.mkdir(buildDir, { recursive: true });
2368
+ await fs3.mkdir(buildDir, { recursive: true });
2638
2369
  await Promise.all([
2639
- fs4.writeFile(path3.join(buildDir, "worker.js"), bundle.worker),
2640
- fs4.writeFile(path3.join(buildDir, "manifest.json"), bundle.manifest),
2641
- fs4.writeFile(path3.join(buildDir, "index.html"), bundle.html)
2370
+ fs3.writeFile(path3.join(buildDir, "worker.js"), bundle.worker),
2371
+ fs3.writeFile(path3.join(buildDir, "index.html"), bundle.html)
2642
2372
  ]);
2643
2373
  }
2644
- async function checkAgent(agentDir) {
2645
- const userFiles = ["agent.ts"];
2646
- for (const f of ["client.tsx", "components.tsx"]) {
2647
- try {
2648
- await fs4.stat(path3.join(agentDir, f));
2649
- userFiles.push(f);
2650
- } catch {
2651
- }
2652
- }
2653
- const checks = [{ args: ["--noEmit", ...userFiles], label: "Type-check" }];
2654
- const results = await Promise.allSettled(
2655
- checks.map(({ args }) => execFileAsync("npx", ["tsc", ...args], { cwd: agentDir }))
2656
- );
2657
- const errors = [];
2658
- for (let i = 0; i < results.length; i++) {
2659
- const r = results[i];
2660
- if (r.status === "rejected") {
2661
- const msg = r.reason.stderr?.trim() ?? String(r.reason);
2662
- error2(`${checks[i].label}: ${msg}`);
2663
- errors.push(checks[i].label);
2664
- }
2665
- }
2666
- if (errors.length > 0) {
2667
- throw new Error(`${errors.join(", ")} failed \u2014 fix the errors above`);
2668
- }
2669
- }
2670
2374
  async function runBuild(opts) {
2671
2375
  const agent = await loadAgent(opts.agentDir);
2672
2376
  if (!agent) {
2673
2377
  throw new Error("No agent found \u2014 run `aai new` first");
2674
2378
  }
2675
- step("Check", agent.slug);
2676
- await checkAgent(opts.agentDir);
2677
2379
  step("Bundle", agent.slug);
2678
2380
  let bundle;
2679
2381
  try {
@@ -2691,7 +2393,7 @@ async function runBuild(opts) {
2691
2393
 
2692
2394
  // cli/new.tsx
2693
2395
  init_colors();
2694
- import fs6 from "node:fs/promises";
2396
+ import fs5 from "node:fs/promises";
2695
2397
  import path5 from "node:path";
2696
2398
  import { fileURLToPath as fileURLToPath2 } from "node:url";
2697
2399
  import minimist from "minimist";
@@ -2767,14 +2469,14 @@ async function runNewCommand(args, version) {
2767
2469
  if (isDevMode()) {
2768
2470
  const monorepoRoot = path5.join(cliDir2, "..");
2769
2471
  const pkgJsonPath2 = path5.join(cwd, "package.json");
2770
- const pkgJson2 = JSON.parse(await fs6.readFile(pkgJsonPath2, "utf-8"));
2472
+ const pkgJson2 = JSON.parse(await fs5.readFile(pkgJsonPath2, "utf-8"));
2771
2473
  for (const pkg of ["sdk", "ui"]) {
2772
2474
  const localPkgPath = path5.join(monorepoRoot, pkg, "package.json");
2773
- const localPkg = JSON.parse(await fs6.readFile(localPkgPath, "utf-8"));
2475
+ const localPkg = JSON.parse(await fs5.readFile(localPkgPath, "utf-8"));
2774
2476
  const pkgName = localPkg.name;
2775
2477
  pkgJson2.dependencies[pkgName] = `file:${path5.join(monorepoRoot, pkg)}`;
2776
2478
  }
2777
- await fs6.writeFile(pkgJsonPath2, `${JSON.stringify(pkgJson2, null, 2)}
2479
+ await fs5.writeFile(pkgJsonPath2, `${JSON.stringify(pkgJson2, null, 2)}
2778
2480
  `);
2779
2481
  }
2780
2482
  await ensureClaudeMd(cwd);
@@ -2868,7 +2570,9 @@ async function loadAgentDef(cwd) {
2868
2570
  }
2869
2571
  }
2870
2572
  async function resolveServerEnv() {
2871
- const env = { ...process.env };
2573
+ const env = Object.fromEntries(
2574
+ Object.entries(process.env).filter((e) => e[1] !== void 0)
2575
+ );
2872
2576
  if (!env.ASSEMBLYAI_API_KEY) {
2873
2577
  try {
2874
2578
  env.ASSEMBLYAI_API_KEY = await getApiKey();
@@ -3042,14 +2746,26 @@ async function runRag(opts) {
3042
2746
  log(/* @__PURE__ */ jsx4(Step, { action: "Parsed", msg: `${pages.length} pages` }));
3043
2747
  const { RecursiveChunker } = await import("@chonkiejs/core");
3044
2748
  const chunker = await RecursiveChunker.create({ chunkSize });
3045
- const allChunks = [];
3046
2749
  const siteSlug = slugify(origin);
2750
+ const allChunks = await chunkPages(pages, chunker, origin, siteSlug);
2751
+ log(/* @__PURE__ */ jsx4(Step, { action: "Chunked", msg: `${allChunks.length} chunks` }));
2752
+ const vectorUrl = `${serverUrl}/${slug}/vector`;
2753
+ log(/* @__PURE__ */ jsx4(Info, { msg: `target: ${vectorUrl}` }));
2754
+ const result = await upsertChunks(allChunks, vectorUrl, apiKey, setProgress);
2755
+ log(/* @__PURE__ */ jsx4(Step, { action: "Done", msg: `${result.upserted} chunks upserted` }));
2756
+ if (result.errors > 0) {
2757
+ log(/* @__PURE__ */ jsx4(Warn, { msg: `${result.errors} failed` }));
2758
+ if (result.lastError) log(/* @__PURE__ */ jsx4(Info, { msg: `last error: ${result.lastError}` }));
2759
+ }
2760
+ log(/* @__PURE__ */ jsx4(Detail, { msg: `Agent: ${slug}` }));
2761
+ }
2762
+ async function chunkPages(pages, chunker, origin, siteSlug) {
2763
+ const allChunks = [];
3047
2764
  for (const page of pages) {
3048
2765
  page.body = stripNoise(page.body);
3049
2766
  if (!page.body) continue;
3050
2767
  const raw = await chunker.chunk(page.body);
3051
- for (let i = 0; i < raw.length; i++) {
3052
- const c = raw[i];
2768
+ for (const [i, c] of raw.entries()) {
3053
2769
  const data = page.title ? `${page.title}
3054
2770
 
3055
2771
  ${c.text}` : c.text;
@@ -3065,10 +2781,10 @@ ${c.text}` : c.text;
3065
2781
  });
3066
2782
  }
3067
2783
  }
3068
- log(/* @__PURE__ */ jsx4(Step, { action: "Chunked", msg: `${allChunks.length} chunks` }));
3069
- const vectorUrl = `${serverUrl}/${slug}/vector`;
3070
- log(/* @__PURE__ */ jsx4(Info, { msg: `target: ${vectorUrl}` }));
3071
- const total = allChunks.length;
2784
+ return allChunks;
2785
+ }
2786
+ async function upsertChunks(chunks, vectorUrl, apiKey, setProgress) {
2787
+ const total = chunks.length;
3072
2788
  let completed = 0;
3073
2789
  let upserted = 0;
3074
2790
  let errors = 0;
@@ -3076,7 +2792,7 @@ ${c.text}` : c.text;
3076
2792
  setProgress({ completed: 0, total });
3077
2793
  const limit = pLimit(5);
3078
2794
  await Promise.all(
3079
- allChunks.map(
2795
+ chunks.map(
3080
2796
  (chunk) => limit(async () => {
3081
2797
  try {
3082
2798
  const r = await fetch(vectorUrl, {
@@ -3107,12 +2823,7 @@ ${c.text}` : c.text;
3107
2823
  })
3108
2824
  )
3109
2825
  );
3110
- log(/* @__PURE__ */ jsx4(Step, { action: "Done", msg: `${upserted} chunks upserted` }));
3111
- if (errors > 0) {
3112
- log(/* @__PURE__ */ jsx4(Warn, { msg: `${errors} failed` }));
3113
- if (lastError) log(/* @__PURE__ */ jsx4(Info, { msg: `last error: ${lastError}` }));
3114
- }
3115
- log(/* @__PURE__ */ jsx4(Detail, { msg: `Agent: ${slug}` }));
2826
+ return { upserted, errors, lastError };
3116
2827
  }
3117
2828
  async function runRagCommand(args, version) {
3118
2829
  const parsed = minimist4(args, {
@@ -3170,34 +2881,38 @@ function splitPages(content) {
3170
2881
  for (const section of raw) {
3171
2882
  const trimmed = section.trim();
3172
2883
  if (!trimmed) continue;
3173
- let title = "";
3174
- let body = trimmed;
3175
- const dashIndex = trimmed.search(/^-{3,}$/m);
3176
- if (dashIndex !== -1) {
3177
- const frontmatter = trimmed.slice(0, dashIndex);
3178
- body = trimmed.slice(dashIndex).replace(/^-+$/m, "").trim();
3179
- const titleMatch = frontmatter.match(/^title:\s*(.+)$/m);
3180
- if (titleMatch) {
3181
- title = titleMatch[1].trim();
3182
- }
2884
+ const page = parsePage(trimmed);
2885
+ if (page.body.length > 0) {
2886
+ pages.push(page);
3183
2887
  }
3184
- if (!title) {
3185
- const titleLineMatch = body.match(/^#{1,2}\s+title:\s*(.+)$/m);
3186
- if (titleLineMatch) {
3187
- title = titleLineMatch[1].trim();
3188
- body = body.replace(/^#{1,2}\s+title:\s*.+\n?/m, "").trim();
3189
- } else {
3190
- const headingMatch = body.match(/^(#{1,3})\s+(.+)$/m);
3191
- if (headingMatch) {
3192
- title = headingMatch[2].trim();
3193
- }
2888
+ }
2889
+ return pages;
2890
+ }
2891
+ function parsePage(trimmed) {
2892
+ let title = "";
2893
+ let body = trimmed;
2894
+ const dashIndex = trimmed.search(/^-{3,}$/m);
2895
+ if (dashIndex !== -1) {
2896
+ const frontmatter = trimmed.slice(0, dashIndex);
2897
+ body = trimmed.slice(dashIndex).replace(/^-+$/m, "").trim();
2898
+ const titleMatch = frontmatter.match(/^title:\s*(.+)$/m);
2899
+ if (titleMatch) {
2900
+ title = titleMatch[1]?.trim() ?? "";
2901
+ }
2902
+ }
2903
+ if (!title) {
2904
+ const titleLineMatch = body.match(/^#{1,2}\s+title:\s*(.+)$/m);
2905
+ if (titleLineMatch) {
2906
+ title = titleLineMatch[1]?.trim() ?? "";
2907
+ body = body.replace(/^#{1,2}\s+title:\s*.+\n?/m, "").trim();
2908
+ } else {
2909
+ const headingMatch = body.match(/^(#{1,3})\s+(.+)$/m);
2910
+ if (headingMatch) {
2911
+ title = headingMatch[2]?.trim() ?? "";
3194
2912
  }
3195
2913
  }
3196
- if (body.length > 0) {
3197
- pages.push({ title, body });
3198
- }
3199
2914
  }
3200
- return pages;
2915
+ return { title, body };
3201
2916
  }
3202
2917
  function stripNoise(text) {
3203
2918
  return text.replace(/^(`{3,}|~{3,}).*[\s\S]*?^\1/gm, "").replace(/^(?:[ ]{4,}|\t).+$/gm, "").replace(/`[^`]+`/g, "").replace(/\{\/\*[\s\S]*?\*\/\}/g, "").replace(/<[^>]+>/g, "").replace(/^\s*\}[^}\n]*$/gm, "").replace(/^\s+$/gm, "").replace(/\n{3,}/g, "\n\n").trim();
@@ -3247,7 +2962,7 @@ async function runSecretCommand(args, version) {
3247
2962
  }
3248
2963
  switch (sub) {
3249
2964
  case "put":
3250
- await secretPut(cwd, String(parsed._[1] ?? ""), secretValue);
2965
+ await secretPut(cwd, String(parsed._[1] ?? ""), secretValue ?? "");
3251
2966
  break;
3252
2967
  case "delete":
3253
2968
  await secretDelete(cwd, String(parsed._[1] ?? ""));
@@ -3326,11 +3041,11 @@ import minimist6 from "minimist";
3326
3041
 
3327
3042
  // cli/_start.ts
3328
3043
  init_output();
3329
- import fs7 from "node:fs/promises";
3044
+ import fs6 from "node:fs/promises";
3330
3045
  import path9 from "node:path";
3331
3046
  async function _startProductionServer(cwd, port) {
3332
3047
  const buildDir = path9.join(cwd, ".aai", "build");
3333
- const html = await fs7.readFile(path9.join(buildDir, "index.html"), "utf-8");
3048
+ const html = await fs6.readFile(path9.join(buildDir, "index.html"), "utf-8");
3334
3049
  step("Load", "agent");
3335
3050
  const agentDef = await loadAgentDef(cwd);
3336
3051
  const env = await resolveServerEnv();