@indemn/cli 1.6.0 → 1.7.1

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 (311) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/.claude-plugin/plugin.json +9 -4
  3. package/.github/workflows/ci.yml +10 -0
  4. package/.github/workflows/publish.yml +2 -2
  5. package/.mcp.json +1 -4
  6. package/CONTRIBUTING.md +3 -1
  7. package/README.md +69 -176
  8. package/dist/cli/agents.d.ts.map +1 -1
  9. package/dist/cli/agents.js +226 -18
  10. package/dist/cli/agents.js.map +1 -1
  11. package/dist/cli/analytics.d.ts +3 -0
  12. package/dist/cli/analytics.d.ts.map +1 -0
  13. package/dist/cli/analytics.js +133 -0
  14. package/dist/cli/analytics.js.map +1 -0
  15. package/dist/cli/auth.d.ts.map +1 -1
  16. package/dist/cli/auth.js +62 -17
  17. package/dist/cli/auth.js.map +1 -1
  18. package/dist/cli/billing.d.ts +3 -0
  19. package/dist/cli/billing.d.ts.map +1 -0
  20. package/dist/cli/billing.js +23 -0
  21. package/dist/cli/billing.js.map +1 -0
  22. package/dist/cli/campaigns.d.ts +3 -0
  23. package/dist/cli/campaigns.d.ts.map +1 -0
  24. package/dist/cli/campaigns.js +34 -0
  25. package/dist/cli/campaigns.js.map +1 -0
  26. package/dist/cli/chat.d.ts.map +1 -1
  27. package/dist/cli/chat.js +69 -102
  28. package/dist/cli/chat.js.map +1 -1
  29. package/dist/cli/config.d.ts.map +1 -1
  30. package/dist/cli/config.js +71 -27
  31. package/dist/cli/config.js.map +1 -1
  32. package/dist/cli/conversations.d.ts +3 -0
  33. package/dist/cli/conversations.d.ts.map +1 -0
  34. package/dist/cli/conversations.js +129 -0
  35. package/dist/cli/conversations.js.map +1 -0
  36. package/dist/cli/distribution.d.ts +3 -0
  37. package/dist/cli/distribution.d.ts.map +1 -0
  38. package/dist/cli/distribution.js +122 -0
  39. package/dist/cli/distribution.js.map +1 -0
  40. package/dist/cli/eval.d.ts.map +1 -1
  41. package/dist/cli/eval.js +315 -71
  42. package/dist/cli/eval.js.map +1 -1
  43. package/dist/cli/functions.d.ts.map +1 -1
  44. package/dist/cli/functions.js +109 -38
  45. package/dist/cli/functions.js.map +1 -1
  46. package/dist/cli/index.js +63 -54
  47. package/dist/cli/index.js.map +1 -1
  48. package/dist/cli/init.d.ts +27 -0
  49. package/dist/cli/init.d.ts.map +1 -0
  50. package/dist/cli/init.js +152 -0
  51. package/dist/cli/init.js.map +1 -0
  52. package/dist/cli/kb.d.ts.map +1 -1
  53. package/dist/cli/kb.js +141 -15
  54. package/dist/cli/kb.js.map +1 -1
  55. package/dist/cli/link.d.ts +21 -0
  56. package/dist/cli/link.d.ts.map +1 -0
  57. package/dist/cli/link.js +112 -0
  58. package/dist/cli/link.js.map +1 -0
  59. package/dist/cli/org.d.ts.map +1 -1
  60. package/dist/cli/org.js +79 -67
  61. package/dist/cli/org.js.map +1 -1
  62. package/dist/cli/platform.d.ts +3 -0
  63. package/dist/cli/platform.d.ts.map +1 -0
  64. package/dist/cli/platform.js +133 -0
  65. package/dist/cli/platform.js.map +1 -0
  66. package/dist/cli/tickets.d.ts +3 -0
  67. package/dist/cli/tickets.d.ts.map +1 -0
  68. package/dist/cli/tickets.js +125 -0
  69. package/dist/cli/tickets.js.map +1 -0
  70. package/dist/cli/utils/output.d.ts +15 -9
  71. package/dist/cli/utils/output.d.ts.map +1 -1
  72. package/dist/cli/utils/output.js +53 -46
  73. package/dist/cli/utils/output.js.map +1 -1
  74. package/dist/cli/voice.d.ts +3 -0
  75. package/dist/cli/voice.d.ts.map +1 -0
  76. package/dist/cli/voice.js +206 -0
  77. package/dist/cli/voice.js.map +1 -0
  78. package/dist/core/diff.d.ts +16 -0
  79. package/dist/core/diff.d.ts.map +1 -0
  80. package/dist/core/diff.js +57 -0
  81. package/dist/core/diff.js.map +1 -0
  82. package/dist/core/org-resolver.d.ts +37 -0
  83. package/dist/core/org-resolver.d.ts.map +1 -0
  84. package/dist/core/org-resolver.js +73 -0
  85. package/dist/core/org-resolver.js.map +1 -0
  86. package/dist/core/runtime.d.ts +36 -0
  87. package/dist/core/runtime.d.ts.map +1 -0
  88. package/dist/core/runtime.js +62 -0
  89. package/dist/core/runtime.js.map +1 -0
  90. package/dist/core/scope.d.ts +33 -0
  91. package/dist/core/scope.d.ts.map +1 -0
  92. package/dist/core/scope.js +37 -0
  93. package/dist/core/scope.js.map +1 -0
  94. package/dist/mcp/registry.d.ts +67 -0
  95. package/dist/mcp/registry.d.ts.map +1 -0
  96. package/dist/mcp/registry.js +195 -0
  97. package/dist/mcp/registry.js.map +1 -0
  98. package/dist/mcp/server.d.ts +9 -0
  99. package/dist/mcp/server.d.ts.map +1 -1
  100. package/dist/mcp/server.js +87 -2
  101. package/dist/mcp/server.js.map +1 -1
  102. package/dist/mcp/tool-meta.d.ts +21 -0
  103. package/dist/mcp/tool-meta.d.ts.map +1 -0
  104. package/dist/mcp/tool-meta.js +203 -0
  105. package/dist/mcp/tool-meta.js.map +1 -0
  106. package/dist/mcp/tools.d.ts +2 -1
  107. package/dist/mcp/tools.d.ts.map +1 -1
  108. package/dist/mcp/tools.js +1462 -215
  109. package/dist/mcp/tools.js.map +1 -1
  110. package/dist/sdk/agent-bundle.d.ts +99 -0
  111. package/dist/sdk/agent-bundle.d.ts.map +1 -0
  112. package/dist/sdk/agent-bundle.js +211 -0
  113. package/dist/sdk/agent-bundle.js.map +1 -0
  114. package/dist/sdk/agents.d.ts +54 -1
  115. package/dist/sdk/agents.d.ts.map +1 -1
  116. package/dist/sdk/agents.js +59 -5
  117. package/dist/sdk/agents.js.map +1 -1
  118. package/dist/sdk/analytics.d.ts +158 -0
  119. package/dist/sdk/analytics.d.ts.map +1 -0
  120. package/dist/sdk/analytics.js +185 -0
  121. package/dist/sdk/analytics.js.map +1 -0
  122. package/dist/sdk/auth.d.ts +34 -12
  123. package/dist/sdk/auth.d.ts.map +1 -1
  124. package/dist/sdk/auth.js +62 -79
  125. package/dist/sdk/auth.js.map +1 -1
  126. package/dist/sdk/billing.d.ts +25 -0
  127. package/dist/sdk/billing.d.ts.map +1 -0
  128. package/dist/sdk/billing.js +61 -0
  129. package/dist/sdk/billing.js.map +1 -0
  130. package/dist/sdk/campaigns.d.ts +35 -0
  131. package/dist/sdk/campaigns.d.ts.map +1 -0
  132. package/dist/sdk/campaigns.js +59 -0
  133. package/dist/sdk/campaigns.js.map +1 -0
  134. package/dist/sdk/chat.d.ts +25 -2
  135. package/dist/sdk/chat.d.ts.map +1 -1
  136. package/dist/sdk/chat.js +37 -10
  137. package/dist/sdk/chat.js.map +1 -1
  138. package/dist/sdk/client.d.ts +93 -5
  139. package/dist/sdk/client.d.ts.map +1 -1
  140. package/dist/sdk/client.js +362 -100
  141. package/dist/sdk/client.js.map +1 -1
  142. package/dist/sdk/config-change.d.ts +74 -0
  143. package/dist/sdk/config-change.d.ts.map +1 -0
  144. package/dist/sdk/config-change.js +117 -0
  145. package/dist/sdk/config-change.js.map +1 -0
  146. package/dist/sdk/config.d.ts.map +1 -1
  147. package/dist/sdk/config.js +2 -1
  148. package/dist/sdk/config.js.map +1 -1
  149. package/dist/sdk/conversations.d.ts +101 -0
  150. package/dist/sdk/conversations.d.ts.map +1 -0
  151. package/dist/sdk/conversations.js +155 -0
  152. package/dist/sdk/conversations.js.map +1 -0
  153. package/dist/sdk/credentials.d.ts +25 -0
  154. package/dist/sdk/credentials.d.ts.map +1 -0
  155. package/dist/sdk/credentials.js +44 -0
  156. package/dist/sdk/credentials.js.map +1 -0
  157. package/dist/sdk/distribution.d.ts +94 -0
  158. package/dist/sdk/distribution.d.ts.map +1 -0
  159. package/dist/sdk/distribution.js +100 -0
  160. package/dist/sdk/distribution.js.map +1 -0
  161. package/dist/sdk/eval.d.ts +81 -0
  162. package/dist/sdk/eval.d.ts.map +1 -1
  163. package/dist/sdk/eval.js +117 -0
  164. package/dist/sdk/eval.js.map +1 -1
  165. package/dist/sdk/functions.d.ts +14 -1
  166. package/dist/sdk/functions.d.ts.map +1 -1
  167. package/dist/sdk/functions.js +48 -5
  168. package/dist/sdk/functions.js.map +1 -1
  169. package/dist/sdk/index.d.ts +2 -0
  170. package/dist/sdk/index.d.ts.map +1 -1
  171. package/dist/sdk/index.js +2 -0
  172. package/dist/sdk/index.js.map +1 -1
  173. package/dist/sdk/jarvis-chat.d.ts +28 -0
  174. package/dist/sdk/jarvis-chat.d.ts.map +1 -0
  175. package/dist/sdk/jarvis-chat.js +117 -0
  176. package/dist/sdk/jarvis-chat.js.map +1 -0
  177. package/dist/sdk/kb.d.ts +69 -1
  178. package/dist/sdk/kb.d.ts.map +1 -1
  179. package/dist/sdk/kb.js +111 -24
  180. package/dist/sdk/kb.js.map +1 -1
  181. package/dist/sdk/orgs.d.ts +13 -0
  182. package/dist/sdk/orgs.d.ts.map +1 -0
  183. package/dist/sdk/orgs.js +59 -0
  184. package/dist/sdk/orgs.js.map +1 -0
  185. package/dist/sdk/platform.d.ts +62 -0
  186. package/dist/sdk/platform.d.ts.map +1 -0
  187. package/dist/sdk/platform.js +95 -0
  188. package/dist/sdk/platform.js.map +1 -0
  189. package/dist/sdk/session.d.ts +25 -0
  190. package/dist/sdk/session.d.ts.map +1 -0
  191. package/dist/sdk/session.js +69 -0
  192. package/dist/sdk/session.js.map +1 -0
  193. package/dist/sdk/skills.d.ts +46 -0
  194. package/dist/sdk/skills.d.ts.map +1 -0
  195. package/dist/sdk/skills.js +203 -0
  196. package/dist/sdk/skills.js.map +1 -0
  197. package/dist/sdk/test-chat.d.ts +52 -0
  198. package/dist/sdk/test-chat.d.ts.map +1 -0
  199. package/dist/sdk/test-chat.js +134 -0
  200. package/dist/sdk/test-chat.js.map +1 -0
  201. package/dist/sdk/tickets.d.ts +98 -0
  202. package/dist/sdk/tickets.d.ts.map +1 -0
  203. package/dist/sdk/tickets.js +91 -0
  204. package/dist/sdk/tickets.js.map +1 -0
  205. package/dist/sdk/types.d.ts +91 -6
  206. package/dist/sdk/types.d.ts.map +1 -1
  207. package/dist/sdk/voice.d.ts +147 -0
  208. package/dist/sdk/voice.d.ts.map +1 -0
  209. package/dist/sdk/voice.js +236 -0
  210. package/dist/sdk/voice.js.map +1 -0
  211. package/package.json +21 -4
  212. package/scripts/check-skills.mjs +25 -0
  213. package/skills/agent-builder/SKILL.md +89 -252
  214. package/skills/evaluations/SKILL.md +23 -234
  215. package/skills/evaluations/references/analysis.md +95 -0
  216. package/skills/evaluations/references/cli-reference.md +28 -0
  217. package/skills/evaluations/references/json-formats.md +100 -0
  218. package/src/cli/agents.ts +202 -22
  219. package/src/cli/analytics.ts +138 -0
  220. package/src/cli/auth.ts +56 -18
  221. package/src/cli/billing.ts +25 -0
  222. package/src/cli/campaigns.ts +33 -0
  223. package/src/cli/chat.ts +66 -115
  224. package/src/cli/config.ts +65 -31
  225. package/src/cli/conversations.ts +133 -0
  226. package/src/cli/distribution.ts +116 -0
  227. package/src/cli/eval.ts +254 -70
  228. package/src/cli/functions.ts +105 -39
  229. package/src/cli/index.ts +58 -55
  230. package/src/cli/init.ts +154 -0
  231. package/src/cli/kb.ts +120 -17
  232. package/src/cli/link.ts +117 -0
  233. package/src/cli/org.ts +81 -75
  234. package/src/cli/platform.ts +128 -0
  235. package/src/cli/tickets.ts +130 -0
  236. package/src/cli/utils/output.ts +51 -42
  237. package/src/cli/voice.ts +204 -0
  238. package/src/core/diff.ts +52 -0
  239. package/src/core/org-resolver.ts +113 -0
  240. package/src/core/runtime.ts +73 -0
  241. package/src/core/scope.ts +64 -0
  242. package/src/mcp/registry.ts +236 -0
  243. package/src/mcp/server.ts +84 -2
  244. package/src/mcp/tool-meta.ts +241 -0
  245. package/src/mcp/tools.ts +1529 -265
  246. package/src/sdk/agent-bundle.ts +245 -0
  247. package/src/sdk/agents.ts +74 -5
  248. package/src/sdk/analytics.ts +220 -0
  249. package/src/sdk/auth.ts +89 -109
  250. package/src/sdk/billing.ts +59 -0
  251. package/src/sdk/campaigns.ts +60 -0
  252. package/src/sdk/chat.ts +44 -10
  253. package/src/sdk/client.ts +373 -102
  254. package/src/sdk/config-change.ts +148 -0
  255. package/src/sdk/config.ts +2 -1
  256. package/src/sdk/conversations.ts +199 -0
  257. package/src/sdk/credentials.ts +53 -0
  258. package/src/sdk/distribution.ts +132 -0
  259. package/src/sdk/eval.ts +140 -0
  260. package/src/sdk/functions.ts +52 -6
  261. package/src/sdk/index.ts +2 -0
  262. package/src/sdk/jarvis-chat.ts +112 -0
  263. package/src/sdk/kb.ts +116 -29
  264. package/src/sdk/orgs.ts +62 -0
  265. package/src/sdk/platform.ts +115 -0
  266. package/src/sdk/session.ts +90 -0
  267. package/src/sdk/skills.ts +188 -0
  268. package/src/sdk/test-chat.ts +151 -0
  269. package/src/sdk/tickets.ts +120 -0
  270. package/src/sdk/types.ts +88 -6
  271. package/src/sdk/voice.ts +262 -0
  272. package/test/cli/entry.test.ts +34 -0
  273. package/test/cli/init.test.ts +66 -0
  274. package/test/cli/link.test.ts +57 -0
  275. package/test/core/org-resolver.test.ts +92 -0
  276. package/test/core/runtime.test.ts +30 -0
  277. package/test/core/scope.test.ts +93 -0
  278. package/test/harness.test.ts +24 -0
  279. package/test/helpers/config-home.ts +22 -0
  280. package/test/helpers/fake-middleware.ts +56 -0
  281. package/test/helpers/fetch-recorder.ts +75 -0
  282. package/test/helpers/jwt.ts +9 -0
  283. package/test/helpers/mcp-pair.ts +38 -0
  284. package/test/mcp/__snapshots__/tools-snapshot.test.ts.snap +145 -0
  285. package/test/mcp/askers.test.ts +60 -0
  286. package/test/mcp/elicit-timeout.test.ts +29 -0
  287. package/test/mcp/registry.test.ts +169 -0
  288. package/test/mcp/shaping.test.ts +41 -0
  289. package/test/mcp/tools-snapshot.test.ts +42 -0
  290. package/test/sdk/agents.test.ts +232 -0
  291. package/test/sdk/analytics.test.ts +89 -0
  292. package/test/sdk/auth.test.ts +70 -0
  293. package/test/sdk/billing.test.ts +47 -0
  294. package/test/sdk/campaigns.test.ts +43 -0
  295. package/test/sdk/client.test.ts +80 -0
  296. package/test/sdk/config-change.test.ts +142 -0
  297. package/test/sdk/conversations.test.ts +80 -0
  298. package/test/sdk/credentials.test.ts +33 -0
  299. package/test/sdk/distribution.test.ts +55 -0
  300. package/test/sdk/eval.test.ts +155 -0
  301. package/test/sdk/kb-upload.test.ts +50 -0
  302. package/test/sdk/kb.test.ts +95 -0
  303. package/test/sdk/orgs.test.ts +48 -0
  304. package/test/sdk/platform.test.ts +89 -0
  305. package/test/sdk/renewal.test.ts +115 -0
  306. package/test/sdk/session.test.ts +60 -0
  307. package/test/sdk/skills.test.ts +235 -0
  308. package/test/sdk/test-chat.test.ts +112 -0
  309. package/test/sdk/tickets.test.ts +42 -0
  310. package/test/sdk/voice.test.ts +147 -0
  311. package/vitest.config.ts +11 -0
@@ -0,0 +1,147 @@
1
+ import type { IndemnClient } from './client.js';
2
+ export interface VoiceSettingsInput {
3
+ provider: string;
4
+ voice_id: string;
5
+ name: string;
6
+ gender: string;
7
+ language: string;
8
+ countryCode: string;
9
+ model?: string;
10
+ settings?: {
11
+ speed?: number;
12
+ };
13
+ public_owner_id?: string;
14
+ }
15
+ interface PhoneConfig {
16
+ _id?: string;
17
+ phoneNumber?: string;
18
+ friendlyName?: string;
19
+ modelSettings?: Record<string, unknown>;
20
+ is_active?: boolean;
21
+ [key: string]: unknown;
22
+ }
23
+ /** A number offered for sale (Twilio's record, as voice-service returns it). */
24
+ export interface AvailableNumber {
25
+ phoneNumber?: string;
26
+ friendlyName?: string;
27
+ locality?: string;
28
+ region?: string;
29
+ postalCode?: string;
30
+ isoCountry?: string;
31
+ capabilities?: Record<string, boolean>;
32
+ [key: string]: unknown;
33
+ }
34
+ /** +E.164 from what a person typed: "(331) 204-4919" or "331 204 4919" in the US/Canada, or "+44 20 ...". */
35
+ export declare function toE164(input: string, country?: string): string;
36
+ /**
37
+ * Voices, voice models, phone numbers and voice previews of agents.
38
+ * Several copilot voice routes do not check that the agent belongs to the
39
+ * caller's org, so every agent-level call here checks that first.
40
+ */
41
+ export declare class VoiceSDK {
42
+ private client;
43
+ /**
44
+ * Numbers this session detached, by org and number, with their saved details. copilot's
45
+ * owned-numbers list can come back empty (its cached org id does not match the query), and a
46
+ * number just detached from an agent of the org is owned: re-attaching it never buys.
47
+ */
48
+ private detached;
49
+ constructor(client: IndemnClient);
50
+ private assertAgent;
51
+ /** Voices of a TTS provider (cartesia default, or elevenlabs), filterable. */
52
+ listVoices(opts?: {
53
+ provider?: string;
54
+ language?: string;
55
+ gender?: string;
56
+ q?: string;
57
+ limit?: number;
58
+ cursor?: string;
59
+ }): Promise<{
60
+ data?: unknown[];
61
+ has_more?: boolean;
62
+ next_page?: unknown;
63
+ }>;
64
+ /** Allowed filter values (languages, genders, accents) of a provider. */
65
+ voiceFilters(provider: string): Promise<unknown>;
66
+ /**
67
+ * Speech sample of a voice (audio bytes). The platform only speaks Cartesia voices; for ElevenLabs the
68
+ * voice's own preview recording is used, as in the dashboard (it cannot say custom text).
69
+ */
70
+ playVoice(voiceId: string, text?: string, speed?: number, opts?: {
71
+ provider?: string;
72
+ name?: string;
73
+ language?: string;
74
+ }): Promise<{
75
+ contentType: string;
76
+ data: Buffer;
77
+ }>;
78
+ /** Speech-to-text or text-to-speech provider and model catalog. */
79
+ voiceModels(kind: 'stt' | 'tts'): Promise<unknown[]>;
80
+ /** Phone numbers attached to an agent, with their voice settings. */
81
+ agentNumbers(agentId: string): Promise<PhoneConfig[]>;
82
+ /** The agent's voice settings. Voice settings live on its phone number, so an agent without one has none. */
83
+ getAgentVoice(agentId: string): Promise<Record<string, unknown>>;
84
+ /**
85
+ * Set the text-to-speech voice of an agent. voice-service replaces the saved voice settings whole, so a
86
+ * speed that is not given keeps the saved one (the dashboard always sends it).
87
+ */
88
+ setAgentVoice(agentId: string, input: VoiceSettingsInput & Record<string, unknown>): Promise<unknown>;
89
+ /** Set the speech-to-text transcriber (provider, model, language, key terms) of an agent, as the dashboard does. */
90
+ setAgentTranscriber(agentId: string, stt: {
91
+ provider: string;
92
+ model: string;
93
+ language: string;
94
+ keyterms?: string[];
95
+ }): Promise<unknown>;
96
+ /** Numbers the org owns (is_active: attached to some agent). */
97
+ orgNumbers(): Promise<PhoneConfig[]>;
98
+ /**
99
+ * Attach a number the org already owns. Never buys one: copilot would buy a
100
+ * Twilio number for an unknown number, which costs money, so unknown numbers
101
+ * are refused here. Re-attaching resets the number's voice settings.
102
+ */
103
+ attachNumber(agentId: string, phoneNumber: string, type?: string): Promise<unknown>;
104
+ /**
105
+ * Numbers available to buy, as the dashboard's "Pick a new phone number" lists them (Twilio through
106
+ * voice-service). Free: nothing is bought. `contains` narrows to numbers containing those digits.
107
+ */
108
+ searchNumbers(opts?: {
109
+ areaCode?: string;
110
+ contains?: string;
111
+ country?: string;
112
+ tollFree?: boolean;
113
+ limit?: number;
114
+ }): Promise<AvailableNumber[]>;
115
+ /** The agent's phone number with its location and a summary of its voice settings. */
116
+ numberDetails(agentId: string): Promise<Record<string, unknown>>;
117
+ /**
118
+ * Buy a number and attach it to a voice agent, as the dashboard's "Pick a new phone number" does:
119
+ * copilot buys it from Twilio through voice-service. The org pays for it every month and it cannot be
120
+ * undone from here, so callers must have a person's confirmation of this exact number. The number is
121
+ * looked up again first so the purchase uses Twilio's current record.
122
+ */
123
+ buyNumber(agentId: string, number: string, opts?: {
124
+ country?: string;
125
+ tollFree?: boolean;
126
+ }): Promise<{
127
+ phone_number: string;
128
+ name?: string;
129
+ locality?: string;
130
+ region?: string;
131
+ agent: string;
132
+ }>;
133
+ /** Detach a number from an agent; the org keeps owning it. */
134
+ detachNumber(agentId: string, phoneNumber: string): Promise<unknown>;
135
+ /**
136
+ * A test voice call in the browser: a LiveKit room joined with the same
137
+ * attributes as the dashboard's web call, always marked as a test.
138
+ */
139
+ voicePreview(agentId: string): Promise<{
140
+ server_url: string;
141
+ room_name: string;
142
+ token: string;
143
+ join_url: string;
144
+ }>;
145
+ }
146
+ export {};
147
+ //# sourceMappingURL=voice.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice.d.ts","sourceRoot":"","sources":["../../src/sdk/voice.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,236 @@
1
+ import { randomBytes } from 'node:crypto';
2
+ import { AgentsSDK } from './agents.js';
3
+ import { CliError, EXIT } from '../core/runtime.js';
4
+ const SEARCH_COUNTRIES = ['US', 'CA', 'GB', 'AU'];
5
+ /** +E.164 from what a person typed: "(331) 204-4919" or "331 204 4919" in the US/Canada, or "+44 20 ...". */
6
+ export function toE164(input, country = 'US') {
7
+ const digits = input.replace(/\D/g, '');
8
+ if (input.trim().startsWith('+'))
9
+ return `+${digits}`;
10
+ if ((country === 'US' || country === 'CA') && digits.length === 10)
11
+ return `+1${digits}`;
12
+ return `+${digits}`;
13
+ }
14
+ /** A Twilio-shaped call id, as the dashboard's web call sends it. */
15
+ function callSid() {
16
+ return 'CA' + randomBytes(16).toString('hex').toUpperCase();
17
+ }
18
+ /**
19
+ * Voices, voice models, phone numbers and voice previews of agents.
20
+ * Several copilot voice routes do not check that the agent belongs to the
21
+ * caller's org, so every agent-level call here checks that first.
22
+ */
23
+ export class VoiceSDK {
24
+ client;
25
+ /**
26
+ * Numbers this session detached, by org and number, with their saved details. copilot's
27
+ * owned-numbers list can come back empty (its cached org id does not match the query), and a
28
+ * number just detached from an agent of the org is owned: re-attaching it never buys.
29
+ */
30
+ detached = new Map();
31
+ constructor(client) {
32
+ this.client = client;
33
+ }
34
+ async assertAgent(agentId) {
35
+ const agent = await new AgentsSDK(this.client).getAgent(agentId).catch(() => undefined);
36
+ if (!agent)
37
+ throw new CliError(`Agent ${agentId} is not in the organization this command acts on.`);
38
+ }
39
+ /** Voices of a TTS provider (cartesia default, or elevenlabs), filterable. */
40
+ listVoices(opts = {}) {
41
+ const q = { provider: opts.provider ?? 'cartesia', limit: String(opts.limit ?? 50) };
42
+ if (opts.language)
43
+ q.language = opts.language;
44
+ if (opts.gender)
45
+ q.gender = opts.gender;
46
+ if (opts.q)
47
+ q.q = opts.q;
48
+ if (opts.cursor)
49
+ q.starting_after = opts.cursor;
50
+ return this.client.copilotGet('/voices', q);
51
+ }
52
+ /** Allowed filter values (languages, genders, accents) of a provider. */
53
+ voiceFilters(provider) {
54
+ return this.client.copilotGet(`/voices/settings/${provider}`, { service: 'tts' });
55
+ }
56
+ /**
57
+ * Speech sample of a voice (audio bytes). The platform only speaks Cartesia voices; for ElevenLabs the
58
+ * voice's own preview recording is used, as in the dashboard (it cannot say custom text).
59
+ */
60
+ async playVoice(voiceId, text, speed, opts = {}) {
61
+ if (opts.provider === 'elevenlabs') {
62
+ const found = await this.listVoices({ provider: 'elevenlabs', q: opts.name ?? voiceId, limit: 50 });
63
+ const url = found.data?.find((v) => v.voice_id === voiceId)?.preview_url;
64
+ if (!url)
65
+ throw new CliError(`No preview recording found for ElevenLabs voice ${opts.name ?? voiceId}.`);
66
+ const res = await fetch(url);
67
+ if (!res.ok)
68
+ throw new CliError(`Could not download the preview of ${opts.name ?? voiceId} (${res.status}).`);
69
+ return { contentType: res.headers.get('content-type') ?? 'audio/mpeg', data: Buffer.from(await res.arrayBuffer()) };
70
+ }
71
+ return this.client.copilotBinary('POST', '/voices/play', { voice_id: voiceId, ...(text ? { text } : {}), ...(speed ? { speed } : {}), ...(opts.language ? { language: opts.language } : {}) });
72
+ }
73
+ /** Speech-to-text or text-to-speech provider and model catalog. */
74
+ voiceModels(kind) {
75
+ return this.client.copilotGet('/organization/:org_id/ai-studio/voice-models', { kind });
76
+ }
77
+ /** Phone numbers attached to an agent, with their voice settings. */
78
+ async agentNumbers(agentId) {
79
+ await this.assertAgent(agentId);
80
+ return this.client.copilotGet(`/organization/:org_id/ai-studio/bots/${agentId}/configurations/voice/numbers`);
81
+ }
82
+ /** The agent's voice settings. Voice settings live on its phone number, so an agent without one has none. */
83
+ async getAgentVoice(agentId) {
84
+ const numbers = await this.agentNumbers(agentId);
85
+ if (!numbers.length)
86
+ throw new CliError(`Agent ${agentId} has no phone number, so it has no voice settings yet. Attach one with \`indemn agents numbers attach\`.`, EXIT.NEEDS_INPUT);
87
+ return (numbers[0].modelSettings ?? {});
88
+ }
89
+ /**
90
+ * Set the text-to-speech voice of an agent. voice-service replaces the saved voice settings whole, so a
91
+ * speed that is not given keeps the saved one (the dashboard always sends it).
92
+ */
93
+ async setAgentVoice(agentId, input) {
94
+ const current = await this.getAgentVoice(agentId); // fails clearly when there is no number
95
+ const body = { ...input, countryCode: input.countryCode.toLowerCase(), settings: { ...(current.tts?.settings ?? {}), ...(input.settings ?? {}) } };
96
+ return this.client.copilotPost(`/organization/:org_id/ai-studio/bots/${agentId}/voices`, body);
97
+ }
98
+ /** Set the speech-to-text transcriber (provider, model, language, key terms) of an agent, as the dashboard does. */
99
+ async setAgentTranscriber(agentId, stt) {
100
+ await this.getAgentVoice(agentId); // fails clearly when there is no number
101
+ const keyterms = (stt.keyterms ?? []).map((k) => k.trim()).filter(Boolean);
102
+ if (keyterms.length > 50 || keyterms.some((k) => k.length > 100))
103
+ throw new CliError('Up to 50 key terms of at most 100 characters each.', EXIT.NEEDS_INPUT);
104
+ return this.client.copilotPost(`/organization/:org_id/ai-studio/bots/${agentId}/voices`, {
105
+ stt: { provider: stt.provider, model: stt.model, language: stt.language, config: { keyterm: keyterms } },
106
+ });
107
+ }
108
+ /** Numbers the org owns (is_active: attached to some agent). */
109
+ orgNumbers() {
110
+ return this.client.copilotGet('/organization/:org_id/voice/configurations/numbers');
111
+ }
112
+ /**
113
+ * Attach a number the org already owns. Never buys one: copilot would buy a
114
+ * Twilio number for an unknown number, which costs money, so unknown numbers
115
+ * are refused here. Re-attaching resets the number's voice settings.
116
+ */
117
+ async attachNumber(agentId, phoneNumber, type = 'local') {
118
+ const agent = await new AgentsSDK(this.client).getAgent(agentId).catch(() => undefined);
119
+ if (!agent)
120
+ throw new CliError(`Agent ${agentId} is not in the organization this command acts on.`);
121
+ const channels = (agent.channels ?? []).map((c) => String(typeof c === 'string' ? c : c.type ?? '').toUpperCase());
122
+ if (!channels.includes('VOICE'))
123
+ throw new CliError(`"${agent.name}" does not answer the phone (no VOICE channel), so a number would not reach it.`);
124
+ const existing = await this.agentNumbers(agentId);
125
+ if (existing.length)
126
+ throw new CliError(`"${agent.name}" already has ${existing[0].phoneNumber}. Detach it first; an agent has one number.`);
127
+ const key = `${await this.client.currentOrgId()}:${phoneNumber}`;
128
+ const owned = (await this.orgNumbers()).find((n) => n.phoneNumber === phoneNumber) ?? this.detached.get(key);
129
+ if (!owned) {
130
+ throw new CliError(`${phoneNumber} is not a number this org owns. Buying numbers is not available from the CLI; buy it in the dashboard first.`);
131
+ }
132
+ if (owned.is_active)
133
+ throw new CliError(`${phoneNumber} is already attached to an agent. Detach it there first.`);
134
+ // copilot overwrites the number's details with what it is sent: send the saved ones back.
135
+ const result = await this.client.copilotPost(`/organization/:org_id/ai-studio/bots/${agentId}/configurations/voice/numbers`, {
136
+ type: typeof owned.type === 'string' ? owned.type : type, phoneNumber,
137
+ ...(owned.friendlyName ? { friendlyName: owned.friendlyName } : {}),
138
+ ...(owned.additionalDetails ? { payload: owned.additionalDetails } : {}),
139
+ });
140
+ this.detached.delete(key);
141
+ return result;
142
+ }
143
+ /**
144
+ * Numbers available to buy, as the dashboard's "Pick a new phone number" lists them (Twilio through
145
+ * voice-service). Free: nothing is bought. `contains` narrows to numbers containing those digits.
146
+ */
147
+ async searchNumbers(opts = {}) {
148
+ const country = (opts.country ?? 'US').toUpperCase();
149
+ if (!SEARCH_COUNTRIES.includes(country))
150
+ throw new CliError(`Numbers can be searched in ${SEARCH_COUNTRIES.join(', ')}.`, EXIT.NEEDS_INPUT);
151
+ const limit = Math.min(Math.max(opts.limit ?? 5, 1), 20);
152
+ const q = { countryCode: country, limit: String(limit) };
153
+ if (opts.areaCode)
154
+ q.areaCode = opts.areaCode.replace(/\D/g, '').slice(0, 3);
155
+ if (opts.contains)
156
+ q.pattern = opts.contains.replace(/\D/g, '');
157
+ const rows = await this.client.copilotGet(`/organization/:org_id/voice/configurations/numbers/${opts.tollFree ? 'toll-free' : 'local'}`, q);
158
+ return (rows ?? []).slice(0, limit);
159
+ }
160
+ /** The agent's phone number with its location and a summary of its voice settings. */
161
+ async numberDetails(agentId) {
162
+ const [num] = await this.agentNumbers(agentId);
163
+ if (!num)
164
+ throw new CliError(`Agent ${agentId} has no phone number. Find one with \`indemn agents numbers search\`.`, EXIT.NEEDS_INPUT);
165
+ const d = (num.additionalDetails ?? {});
166
+ const m = (num.modelSettings ?? {});
167
+ return {
168
+ phone_number: num.phoneNumber, name: num.friendlyName, type: num.type, country: num.isoCountry ?? d.isoCountry,
169
+ locality: d.locality, region: d.region, test_number: Boolean(num.isTestNumber),
170
+ voice: m.tts ? { provider: m.tts.provider, name: m.tts.name, speed: m.tts.settings?.speed } : undefined,
171
+ transcriber: m.stt ? { provider: m.stt.provider, model: m.stt.model, language: m.stt.language } : undefined,
172
+ };
173
+ }
174
+ /**
175
+ * Buy a number and attach it to a voice agent, as the dashboard's "Pick a new phone number" does:
176
+ * copilot buys it from Twilio through voice-service. The org pays for it every month and it cannot be
177
+ * undone from here, so callers must have a person's confirmation of this exact number. The number is
178
+ * looked up again first so the purchase uses Twilio's current record.
179
+ */
180
+ async buyNumber(agentId, number, opts = {}) {
181
+ const country = (opts.country ?? 'US').toUpperCase();
182
+ const phoneNumber = toE164(number, country);
183
+ const agent = await new AgentsSDK(this.client).getAgent(agentId).catch(() => undefined);
184
+ if (!agent)
185
+ throw new CliError(`Agent ${agentId} is not in the organization this command acts on.`);
186
+ const channels = (agent.channels ?? []).map((c) => String(typeof c === 'string' ? c : c.type ?? '').toUpperCase());
187
+ if (!channels.includes('VOICE'))
188
+ throw new CliError(`"${agent.name}" does not answer the phone (no VOICE channel), so a number would not reach it. Nothing was bought.`);
189
+ const existing = await this.agentNumbers(agentId);
190
+ if (existing.length)
191
+ throw new CliError(`"${agent.name}" already has ${existing[0].phoneNumber}. Nothing was bought.`);
192
+ if ((await this.orgNumbers()).some((o) => o.phoneNumber === phoneNumber)) {
193
+ throw new CliError(`The org already owns ${phoneNumber}; attach it with \`indemn agents numbers attach\` instead of buying it. Nothing was bought.`);
194
+ }
195
+ const digits = phoneNumber.replace(/\D/g, '');
196
+ const offered = await this.searchNumbers({ country, tollFree: opts.tollFree, contains: digits.slice(-7), limit: 20,
197
+ ...((country === 'US' || country === 'CA') && !opts.tollFree ? { areaCode: digits.slice(1, 4) } : {}) });
198
+ const pick = offered.find((o) => o.phoneNumber === phoneNumber);
199
+ if (!pick)
200
+ throw new CliError(`${phoneNumber} is no longer available. Search again with \`indemn agents numbers search\`. Nothing was bought.`);
201
+ await this.client.copilotPost(`/organization/:org_id/ai-studio/bots/${agentId}/configurations/voice/numbers`, {
202
+ type: opts.tollFree ? 'toll-free' : 'local', friendlyName: pick.friendlyName ?? phoneNumber, phoneNumber, payload: pick,
203
+ });
204
+ return { phone_number: phoneNumber, name: pick.friendlyName, locality: pick.locality, region: pick.region, agent: agent.name };
205
+ }
206
+ /** Detach a number from an agent; the org keeps owning it. */
207
+ async detachNumber(agentId, phoneNumber) {
208
+ const attached = await this.agentNumbers(agentId);
209
+ const number = attached.find((n) => n.phoneNumber === phoneNumber);
210
+ if (!number)
211
+ throw new CliError(`${phoneNumber} is not attached to agent ${agentId}.`);
212
+ const result = await this.client.copilotRequestRaw('DELETE', `/organization/:org_id/ai-studio/bots/${agentId}/configurations/voice/numbers`, { phoneNumber });
213
+ // Kept so it can be attached to another agent (moved), whatever the owned-numbers list says.
214
+ this.detached.set(`${await this.client.currentOrgId()}:${phoneNumber}`, { ...number, is_active: false });
215
+ return result;
216
+ }
217
+ /**
218
+ * A test voice call in the browser: a LiveKit room joined with the same
219
+ * attributes as the dashboard's web call, always marked as a test.
220
+ */
221
+ async voicePreview(agentId) {
222
+ // The call service finds the agent by its phone number: without one the agent never joins the room.
223
+ const numbers = await this.agentNumbers(agentId);
224
+ if (!numbers.length)
225
+ throw new CliError(`Agent ${agentId} has no phone number, so it cannot take a test call. Attach one with \`indemn agents numbers attach\`.`, EXIT.NEEDS_INPUT);
226
+ const res = await this.client.copilotPost('/livekit/token', {
227
+ bot_id: agentId,
228
+ user_attributes: { 'sip.twilio.callSid': callSid(), isTestMode: 'true', ...(numbers[0].phoneNumber ? { 'sip.trunkPhoneNumber': numbers[0].phoneNumber } : {}) },
229
+ });
230
+ const join = new URL('https://meet.livekit.io/custom');
231
+ join.searchParams.set('liveKitUrl', res.server_url);
232
+ join.searchParams.set('token', res.token);
233
+ return { ...res, join_url: join.toString() };
234
+ }
235
+ }
236
+ //# sourceMappingURL=voice.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice.js","sourceRoot":"","sources":["../../src/sdk/voice.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indemn/cli",
3
- "version": "1.6.0",
3
+ "version": "1.7.1",
4
4
  "description": "CLI, MCP server, and plugin for managing Indemn AI agents",
5
5
  "type": "module",
6
6
  "main": "./dist/sdk/index.js",
@@ -12,7 +12,8 @@
12
12
  "postbuild": "cp -r src/report/assets dist/report/assets",
13
13
  "dev": "tsx --watch src/cli/index.ts",
14
14
  "test": "vitest run --passWithNoTests",
15
- "test:watch": "vitest"
15
+ "test:watch": "vitest",
16
+ "check:skills": "node scripts/check-skills.mjs"
16
17
  },
17
18
  "keywords": [
18
19
  "ai-agents",
@@ -28,13 +29,14 @@
28
29
  "url": "git+https://github.com/indemn-ai/indemn-cli.git"
29
30
  },
30
31
  "dependencies": {
32
+ "@firebase/app": "^0.13.2",
33
+ "@firebase/auth": "^1.10.8",
31
34
  "@modelcontextprotocol/sdk": "^1.25.1",
32
35
  "@react-pdf/renderer": "^4.3.2",
33
36
  "chalk": "^5.4.1",
34
37
  "cli-table3": "^0.6.5",
35
38
  "commander": "^13.1.0",
36
39
  "conf": "^13.1.0",
37
- "firebase": "^11.6.0",
38
40
  "ora": "^8.2.0",
39
41
  "react": "^19.2.4",
40
42
  "socket.io-client": "^4.8.3",
@@ -43,8 +45,23 @@
43
45
  "devDependencies": {
44
46
  "@types/node": "^22.15.0",
45
47
  "@types/react": "^19.2.14",
48
+ "socket.io": "^4.8.3",
46
49
  "tsx": "^4.19.0",
47
50
  "typescript": "^5.9.3",
48
- "vitest": "^3.1.0"
51
+ "vitest": "^5.0.0",
52
+ "ws": "8.21.0"
53
+ },
54
+ "overrides": {
55
+ "@hono/node-server": "2.0.11",
56
+ "body-parser": "2.3.0",
57
+ "fast-uri": "3.1.8",
58
+ "hono": "^4.13.5",
59
+ "ip-address": "10.7.2",
60
+ "qs": "6.16.0",
61
+ "websocket-driver": "0.7.5",
62
+ "ws": "8.21.0",
63
+ "vite": "7.3.6",
64
+ "esbuild": "0.28.1",
65
+ "postcss": "8.5.23"
49
66
  }
50
67
  }
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env node
2
+ // Checks every skill against the Agent Skills guidelines the reference
3
+ // validator does not enforce: SKILL.md under 500 lines, a description
4
+ // saying when to use the skill, and a name matching its folder.
5
+ import { readdirSync, readFileSync } from 'node:fs';
6
+ import { join } from 'node:path';
7
+
8
+ const root = new URL('../skills/', import.meta.url).pathname;
9
+ let failed = false;
10
+ for (const dir of readdirSync(root, { withFileTypes: true }).filter((d) => d.isDirectory())) {
11
+ const text = readFileSync(join(root, dir.name, 'SKILL.md'), 'utf8');
12
+ const lines = text.split('\n').length;
13
+ const front = /^---\n([\s\S]*?)\n---/.exec(text)?.[1] ?? '';
14
+ const name = /^name:\s*(.+)$/m.exec(front)?.[1]?.trim();
15
+ const description = /^description:\s*(.+)$/m.exec(front)?.[1]?.trim() ?? '';
16
+ const problems = [];
17
+ if (lines > 500) problems.push(`SKILL.md has ${lines} lines (max 500); move detail into references/`);
18
+ if (name !== dir.name) problems.push(`name "${name}" does not match folder "${dir.name}"`);
19
+ if (!/\buse (when|for)\b/i.test(description)) problems.push('description should say when to use the skill ("Use when ...")');
20
+ if (description.length > 1024) problems.push('description is over 1024 characters');
21
+ console.log(`${problems.length ? 'FAIL' : 'ok '} ${dir.name} (${lines} lines)`);
22
+ for (const p of problems) console.log(` - ${p}`);
23
+ if (problems.length) failed = true;
24
+ }
25
+ process.exit(failed ? 1 : 0);