@hanzo/build 0.2.80 → 0.2.81

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 (165) hide show
  1. package/README.md +13 -0
  2. package/lib/activity.d.ts +3 -7
  3. package/lib/activity.js +18 -5
  4. package/lib/api/agents.d.ts +1 -20
  5. package/lib/api/agents.js +16 -8
  6. package/lib/api/auto.d.ts +3 -23
  7. package/lib/api/auto.js +39 -22
  8. package/lib/api/billing.d.ts +0 -35
  9. package/lib/api/billing.js +6 -5
  10. package/lib/api/call.d.ts +16 -8
  11. package/lib/api/call.js +32 -1
  12. package/lib/api/capabilities.d.ts +0 -11
  13. package/lib/api/capabilities.js +2 -1
  14. package/lib/api/codebases.d.ts +0 -10
  15. package/lib/api/codebases.js +3 -2
  16. package/lib/api/coding.d.ts +3 -32
  17. package/lib/api/coding.js +13 -7
  18. package/lib/api/connectors.d.ts +1 -17
  19. package/lib/api/connectors.js +5 -4
  20. package/lib/api/environment.d.ts +6 -20
  21. package/lib/api/environment.js +22 -19
  22. package/lib/api/github.d.ts +0 -22
  23. package/lib/api/github.js +3 -2
  24. package/lib/api/keys.d.ts +0 -14
  25. package/lib/api/keys.js +4 -3
  26. package/lib/api/library.d.ts +3 -17
  27. package/lib/api/library.js +23 -22
  28. package/lib/api/machines.d.ts +0 -15
  29. package/lib/api/machines.js +6 -5
  30. package/lib/api/mcp.d.ts +0 -9
  31. package/lib/api/mcp.js +3 -2
  32. package/lib/api/members.d.ts +0 -15
  33. package/lib/api/members.js +4 -3
  34. package/lib/api/memory.d.ts +0 -11
  35. package/lib/api/memory.js +2 -1
  36. package/lib/api/places.d.ts +1 -9
  37. package/lib/api/places.js +12 -1
  38. package/lib/api/plugins.d.ts +1 -16
  39. package/lib/api/plugins.js +4 -3
  40. package/lib/api/profile.d.ts +0 -10
  41. package/lib/api/profile.js +5 -4
  42. package/lib/api/projects.d.ts +0 -14
  43. package/lib/api/projects.js +2 -1
  44. package/lib/api/provider.d.ts +2 -14
  45. package/lib/api/provider.js +12 -10
  46. package/lib/api/sandbox.d.ts +0 -17
  47. package/lib/api/sandbox.js +5 -4
  48. package/lib/api/sessions.d.ts +0 -17
  49. package/lib/api/sessions.js +5 -4
  50. package/lib/api/skills.d.ts +1 -15
  51. package/lib/api/skills.js +5 -4
  52. package/lib/api/studio.d.ts +0 -14
  53. package/lib/api/studio.js +6 -5
  54. package/lib/api/turn.d.ts +6 -28
  55. package/lib/api/turn.js +105 -49
  56. package/lib/api/verdict.d.ts +0 -9
  57. package/lib/api/verdict.js +2 -1
  58. package/lib/api/webhooks.d.ts +1 -14
  59. package/lib/api/webhooks.js +5 -4
  60. package/lib/ask.js +7 -4
  61. package/lib/automations.d.ts +5 -4
  62. package/lib/automations.js +95 -74
  63. package/lib/back.js +10 -4
  64. package/lib/builder.js +7 -5
  65. package/lib/carry.js +20 -16
  66. package/lib/customize/agents.js +78 -31
  67. package/lib/customize/connectors.js +62 -48
  68. package/lib/customize/index.js +43 -10
  69. package/lib/customize/plugins.js +34 -22
  70. package/lib/customize/say.d.ts +13 -1
  71. package/lib/customize/say.js +15 -21
  72. package/lib/customize/skills.js +31 -22
  73. package/lib/customize/ui.d.ts +5 -9
  74. package/lib/customize/ui.js +26 -16
  75. package/lib/data.d.ts +1 -1
  76. package/lib/data.js +3 -2
  77. package/lib/desk.js +45 -33
  78. package/lib/door.js +35 -10
  79. package/lib/environment.js +25 -19
  80. package/lib/files.js +43 -34
  81. package/lib/find.js +12 -9
  82. package/lib/foot.js +7 -4
  83. package/lib/forge.js +61 -40
  84. package/lib/gear.d.ts +2 -1
  85. package/lib/gear.js +6 -4
  86. package/lib/git.js +29 -19
  87. package/lib/landing.d.ts +5 -5
  88. package/lib/landing.js +52 -44
  89. package/lib/library.js +73 -51
  90. package/lib/meter.d.ts +1 -1
  91. package/lib/meter.js +14 -5
  92. package/lib/mic.js +12 -5
  93. package/lib/mind.d.ts +1 -0
  94. package/lib/mind.js +5 -3
  95. package/lib/nav.d.ts +6 -5
  96. package/lib/nav.js +37 -30
  97. package/lib/panel.d.ts +2 -1
  98. package/lib/panel.js +52 -36
  99. package/lib/plan.d.ts +4 -20
  100. package/lib/plan.js +26 -10
  101. package/lib/plans.js +49 -30
  102. package/lib/plugins/design.js +3 -2
  103. package/lib/plugins/index.d.ts +23 -4
  104. package/lib/plugins/index.js +11 -26
  105. package/lib/plugins/pdf.js +2 -1
  106. package/lib/plugins/project.js +6 -3
  107. package/lib/plugins/research.js +3 -2
  108. package/lib/plugins/sketch.js +6 -3
  109. package/lib/plugins/slides.js +3 -2
  110. package/lib/plugins/template.js +6 -3
  111. package/lib/plus.js +25 -13
  112. package/lib/prefs.d.ts +0 -14
  113. package/lib/prefs.js +2 -1
  114. package/lib/project.js +69 -62
  115. package/lib/prompt.d.ts +12 -11
  116. package/lib/prompt.js +38 -20
  117. package/lib/publish.js +17 -12
  118. package/lib/reply.js +6 -3
  119. package/lib/run.js +72 -54
  120. package/lib/say.d.ts +2 -0
  121. package/lib/say.js +7 -0
  122. package/lib/scheduled.js +54 -43
  123. package/lib/section.d.ts +1 -0
  124. package/lib/section.js +8 -2
  125. package/lib/settings/account.d.ts +1 -0
  126. package/lib/settings/account.js +31 -21
  127. package/lib/settings/billing.js +55 -28
  128. package/lib/settings/capabilities.js +26 -15
  129. package/lib/settings/card.js +19 -12
  130. package/lib/settings/code.js +22 -11
  131. package/lib/settings/credits.d.ts +4 -4
  132. package/lib/settings/credits.js +34 -21
  133. package/lib/settings/environments.js +21 -14
  134. package/lib/settings/general.js +26 -14
  135. package/lib/settings/index.js +6 -3
  136. package/lib/settings/integrations.js +42 -28
  137. package/lib/settings/keys.js +37 -19
  138. package/lib/settings/list.d.ts +0 -5
  139. package/lib/settings/list.js +24 -15
  140. package/lib/settings/machines.d.ts +3 -0
  141. package/lib/settings/machines.js +63 -38
  142. package/lib/settings/members.js +23 -14
  143. package/lib/settings/memory.js +12 -6
  144. package/lib/settings/notifications.js +32 -19
  145. package/lib/settings/plan.d.ts +1 -1
  146. package/lib/settings/plan.js +40 -17
  147. package/lib/settings/privacy.js +26 -13
  148. package/lib/settings/ui.d.ts +3 -2
  149. package/lib/settings/ui.js +9 -3
  150. package/lib/settings/usage.js +7 -3
  151. package/lib/shelf.js +18 -15
  152. package/lib/side.d.ts +1 -26
  153. package/lib/side.js +11 -5
  154. package/lib/standing.d.ts +2 -10
  155. package/lib/standing.js +5 -3
  156. package/lib/suggest.d.ts +8 -28
  157. package/lib/suggest.js +39 -4
  158. package/lib/suggestions.js +14 -5
  159. package/lib/summary.d.ts +1 -1
  160. package/lib/summary.js +4 -1
  161. package/lib/sync.js +22 -12
  162. package/lib/tools.d.ts +4 -3
  163. package/lib/tools.js +10 -7
  164. package/lib/transcript.js +10 -8
  165. package/package.json +4 -2
package/lib/api/turn.js CHANGED
@@ -1,3 +1,34 @@
1
+ /**
2
+ * What a run's events SAY, as text a person reads.
3
+ *
4
+ * A curated projection, never a dump: an event carries the machinery a run
5
+ * happened on — hosts, paths, whole file bodies — and printing it would put
6
+ * someone's filesystem in front of anyone who can read the run. Each kind gets a
7
+ * sentence built from the few fields that describe the outcome; the rest is
8
+ * dropped by omission, because a projection cannot leak a field it never reads.
9
+ *
10
+ * Every string here is rendered as TEXT by the transcript. Nothing is HTML.
11
+ *
12
+ * The coding plane's vocabulary (apps/coding): `status` for a lifecycle move
13
+ * (started, routed, done, error, stopped, paused), `tool-call` for a step of the
14
+ * run itself, `event` for one line of the agent's own structured narration (the
15
+ * harness's JSON stream: its messages, reasoning, commands, edits, tool calls and
16
+ * plan), and `log` for raw output, which only the Terminal's log shows. A
17
+ * person's steering is a `control` {command, message}. A run on a project with a
18
+ * site ends `done` with `live` when it published what it pushed, or `unpublished`
19
+ * saying why it did not.
20
+ *
21
+ * `cards` is the transcript as it is drawn: the run's steps and the agent's
22
+ * items, never its log.
23
+ *
24
+ * The sentences are this client's, said in the language of the `t` a caller
25
+ * hands (@hanzo/i18n; English without one); what the run and the agent said
26
+ * is drawn as given. A step's name is a name the transcript keys on (`Error`
27
+ * opens itself), so it stays English, marked (`phrase`), and the transcript
28
+ * draws it through `t`.
29
+ */
30
+ import { phrase } from '@hanzo/i18n';
31
+ import { english } from '../say.js';
1
32
  const str = (v) => (typeof v === 'string' ? v : '');
2
33
  const obj = (v) => (v && typeof v === 'object' ? v : {});
3
34
  /** The payload as an object. A live frame may carry it as a JSON string. */
@@ -22,40 +53,65 @@ const base = (path) => {
22
53
  const cut = path.replace(/\/+$/, '');
23
54
  return cut.slice(cut.lastIndexOf('/') + 1);
24
55
  };
25
- function status(b, mode) {
56
+ /**
57
+ * A finished run's line, by whether it pushed a branch (Done when it did not),
58
+ * its pull request (none, one that could not be opened, its address) and its
59
+ * site (none, not published and why, published): each a whole line, so a
60
+ * language puts the parts in its own order.
61
+ */
62
+ const FINISHED = {
63
+ pushed: {
64
+ none: { none: phrase('Pushed {branch}'), out: phrase('Pushed {branch} — not published: {why}'), live: phrase('Pushed {branch} — published') },
65
+ broke: {
66
+ none: phrase('Pushed {branch} — the pull request could not be opened'),
67
+ out: phrase('Pushed {branch} — the pull request could not be opened — not published: {why}'),
68
+ live: phrase('Pushed {branch} — the pull request could not be opened — published'),
69
+ },
70
+ pr: { none: phrase('Pushed {branch} — {pr}'), out: phrase('Pushed {branch} — {pr} — not published: {why}'), live: phrase('Pushed {branch} — {pr} — published') },
71
+ },
72
+ done: {
73
+ none: { none: phrase('Done'), out: phrase('Done — not published: {why}'), live: phrase('Done — published') },
74
+ broke: {
75
+ none: phrase('Done — the pull request could not be opened'),
76
+ out: phrase('Done — the pull request could not be opened — not published: {why}'),
77
+ live: phrase('Done — the pull request could not be opened — published'),
78
+ },
79
+ pr: { none: phrase('Done — {pr}'), out: phrase('Done — {pr} — not published: {why}'), live: phrase('Done — {pr} — published') },
80
+ },
81
+ };
82
+ function status(b, mode, t) {
26
83
  const branch = str(b.branch);
27
84
  switch (str(b.status)) {
28
85
  case 'started':
29
- return branch ? `Started on ${branch}` : 'Started';
86
+ return branch ? t('Started on {branch}', { branch }) : t('Started');
30
87
  case 'routed':
31
- return 'Sent to a machine';
88
+ return t('Sent to a machine');
32
89
  case 'done': {
33
90
  // A plan's answer IS its final status: the run read and wrote nothing.
34
91
  // Whether the run planned is the RECORD's word — any member of the org
35
92
  // can append an event saying `mode: plan`, and its text is not an answer.
36
93
  // A setup is a plan put to one question, and answers the same way.
37
94
  if (mode === 'plan')
38
- return str(b.plan) || 'Planned — the run answered with no plan';
95
+ return str(b.plan) || t('Planned — the run answered with no plan');
39
96
  if (mode === 'setup')
40
- return str(b.plan) || 'Set up — the run answered with no environment';
97
+ return str(b.plan) || t('Set up — the run answered with no environment');
41
98
  if (b.changed === false)
42
- return 'Done — nothing to change';
99
+ return t('Done — nothing to change');
43
100
  const pr = str(b.pr);
44
- const tail = str(b.prError) ? ' — the pull request could not be opened' : pr ? ` — ${pr}` : '';
45
101
  // A run on a project with a site publishes what it pushed, or says why not.
46
102
  const why = str(b.unpublished);
47
- const site = why ? ` — not published: ${why}` : str(b.live) ? ' — published' : '';
48
- return branch ? `Pushed ${branch}${tail}${site}` : `Done${tail}${site}`;
103
+ const line = FINISHED[branch ? 'pushed' : 'done'][str(b.prError) ? 'broke' : pr ? 'pr' : 'none'][why ? 'out' : str(b.live) ? 'live' : 'none'];
104
+ return t(line, { branch, pr, why });
49
105
  }
50
106
  case 'error':
51
- return plain(str(b.error));
107
+ return plain(str(b.error), t);
52
108
  case 'stopped':
53
- return branch && b.changed ? `Stopped — work kept on ${branch}` : 'Stopped';
109
+ return branch && b.changed ? t('Stopped — work kept on {branch}', { branch }) : t('Stopped');
54
110
  case 'paused':
55
- return branch && b.changed ? `Paused — work kept on ${branch}` : 'Paused';
111
+ return branch && b.changed ? t('Paused — work kept on {branch}', { branch }) : t('Paused');
56
112
  case 'followed':
57
113
  // A run redirected from a chat thread is carried on by a follow-up (apps/coding steer.go).
58
- return str(b.next) ? 'Continued in a follow-up run' : 'The follow-up run could not start';
114
+ return str(b.next) ? t('Continued in a follow-up run') : t('The follow-up run could not start');
59
115
  }
60
116
  return str(b.status);
61
117
  }
@@ -69,35 +125,35 @@ export function vendor(error) {
69
125
  return /open\s?router|anthropic|openai|azure|bedrock|vertex|gemini|mistral|cohere|deepinfra|fireworks|together\.ai|groq|x-ratelimit|upstream|\bprovider\b|\bsk-[A-Za-z0-9_-]{6,}|"(error|code|message)"\s*:/i.test(error);
70
126
  }
71
127
  /** An error as the run page may show it: its own words, or the plain line when they are a vendor's. */
72
- export const scrub = (error) => (vendor(error) ? plain(error) : error);
128
+ export const scrub = (error, t = english) => (vendor(error) ? plain(error, t) : error);
73
129
  /**
74
130
  * A run's error as one plain line with what to do, never the log it came from:
75
131
  * that goes in the Error step beside it (cards), unless it is a vendor's.
76
132
  */
77
- export function plain(error) {
133
+ export function plain(error, t = english) {
78
134
  if (!error)
79
- return 'The run hit an error';
135
+ return t('The run hit an error');
80
136
  const ours = /providers_exhausted|every provider refused|temporarily unavailable/i.test(error);
81
137
  if (/free sandboxes .*are used/i.test(error))
82
- return 'This plan’s free sandboxes are used for now. Add credit to keep building, or try again later.';
138
+ return t('This plan’s free sandboxes are used for now. Add credit to keep building, or try again later.');
83
139
  if (!ours && /\b402 Payment Required|insufficient (credit|balance)|top up/i.test(error))
84
- return 'Your balance is out of credit. Add credit, then try again.';
140
+ return t('Your balance is out of credit. Add credit, then try again.');
85
141
  if (ours || /\b(429 Too Many Requests|503 Service Unavailable)|stream disconnected|retries exhausted|rate limit/i.test(error))
86
- return 'The model did not answer. Try again in a moment, or pick another model.';
87
- return 'The run stopped with an error. Try again, or follow up with what to change.';
142
+ return t('The model did not answer. Try again in a moment, or pick another model.');
143
+ return t('The run stopped with an error. Try again, or follow up with what to change.');
88
144
  }
89
145
  /**
90
146
  * One event's sentence, or '' when it says nothing a person needs. `mode` is
91
147
  * the run's, from its record: a plan run's final status says the plan.
92
148
  */
93
- export function said(e, mode = '') {
149
+ export function said(e, mode = '', t = english) {
94
150
  const body = decode(e.payload);
95
151
  if (typeof body === 'string')
96
152
  return body;
97
153
  if (!body)
98
154
  return '';
99
155
  if (e.kind === 'status')
100
- return status(body, mode);
156
+ return status(body, mode, t);
101
157
  for (const key of ['message', 'text', 'content', 'result', 'command']) {
102
158
  const v = body[key];
103
159
  if (typeof v === 'string' && v)
@@ -106,13 +162,13 @@ export function said(e, mode = '') {
106
162
  if (str(body.type) === 'done' && Array.isArray(body.changed)) {
107
163
  const names = body.changed.map((f) => base(str(f))).filter(Boolean);
108
164
  return names.length === 0
109
- ? 'Done — no files changed'
165
+ ? t('Done — no files changed')
110
166
  : names.length <= 3
111
- ? `Done — changed ${names.join(', ')}`
112
- : `Done — changed ${names.length} files`;
167
+ ? t('Done — changed {files}', { files: names.join(', ') })
168
+ : t('Done — changed {n} files', { n: names.length });
113
169
  }
114
170
  if (str(body.type) === 'error')
115
- return scrub(str(body.error)) || 'The run hit an error';
171
+ return scrub(str(body.error), t) || t('The run hit an error');
116
172
  return str(body.step) || str(body.name);
117
173
  }
118
174
  /**
@@ -200,7 +256,7 @@ export function outcome(events) {
200
256
  return out;
201
257
  }
202
258
  /** Why the run failed, as its last status says it, or '' when that status is not a failure. */
203
- export function failure(events) {
259
+ export function failure(events, t = english) {
204
260
  let out = '';
205
261
  for (const e of [...events].sort((a, b) => a.seq - b.seq)) {
206
262
  if (e.kind !== 'status')
@@ -208,7 +264,7 @@ export function failure(events) {
208
264
  const b = decode(e.payload);
209
265
  if (!b || typeof b === 'string' || !str(b.status))
210
266
  continue;
211
- out = str(b.status) === 'error' ? scrub(str(b.error)) || 'The run hit an error' : '';
267
+ out = str(b.status) === 'error' ? scrub(str(b.error), t) || t('The run hit an error') : '';
212
268
  }
213
269
  return out;
214
270
  }
@@ -242,19 +298,19 @@ export function pull(url, repo) {
242
298
  return { href: '', label: '' };
243
299
  return { href: url, label: `#${m[3]}` };
244
300
  }
245
- /** What the run's own steps are called on a card. */
301
+ /** What the run's own steps are called on a card: English, marked (`phrase`); the transcript draws them through `t`. */
246
302
  const NAMES = {
247
- lease: 'Sandbox',
248
- workspace: 'Workspace',
249
- clone: 'Clone',
250
- branch: 'Branch',
251
- secrets: 'Secrets',
252
- install: 'Install',
253
- start: 'Start',
254
- skills: 'Skills',
255
- artifacts: 'Save artifacts',
256
- push: 'Push',
257
- kept: 'Keep the sandbox',
303
+ lease: phrase('Sandbox'),
304
+ workspace: phrase('Workspace'),
305
+ clone: phrase('Clone'),
306
+ branch: phrase('Branch'),
307
+ secrets: phrase('Secrets'),
308
+ install: phrase('Install'),
309
+ start: phrase('Start'),
310
+ skills: phrase('Skills'),
311
+ artifacts: phrase('Save artifacts'),
312
+ push: phrase('Push'),
313
+ kept: phrase('Keep the sandbox'),
258
314
  };
259
315
  /** Steps another card already says: `leased` finishes the lease, `done` is the final status, `ended` and `exit` are housekeeping. */
260
316
  const QUIET = new Set(['leased', 'done', 'ended', 'exit']);
@@ -290,9 +346,9 @@ function item(it, key) {
290
346
  return { kind: 'edit', key, files: changes.map((c) => rel(str(obj(c).path))).filter(Boolean), ran: itemRan(it) };
291
347
  }
292
348
  case 'mcp_tool_call':
293
- return { kind: 'step', key, name: str(it.tool) || 'Tool', detail: str(it.server), output: '', ran: itemRan(it) };
349
+ return { kind: 'step', key, name: str(it.tool) || phrase('Tool'), detail: str(it.server), output: '', ran: itemRan(it) };
294
350
  case 'web_search':
295
- return { kind: 'step', key, name: 'Search', detail: str(it.query), output: '', ran: 'done' };
351
+ return { kind: 'step', key, name: phrase('Search'), detail: str(it.query), output: '', ran: 'done' };
296
352
  case 'todo_list': {
297
353
  const items = Array.isArray(it.items) ? it.items : [];
298
354
  return { kind: 'todo', key, items: items.map((x) => ({ text: str(obj(x).text), done: obj(x).completed === true })).filter((x) => x.text) };
@@ -313,7 +369,7 @@ function item(it, key) {
313
369
  * is drawn only if the turn then fails. The final status carries the agent's
314
370
  * answer, drawn once. `log` is never drawn here.
315
371
  */
316
- export function cards(events, mode = '') {
372
+ export function cards(events, mode = '', t = english) {
317
373
  const out = [];
318
374
  let seq = 0;
319
375
  let n = 0;
@@ -334,10 +390,10 @@ export function cards(events, mode = '') {
334
390
  if (failures.has(message))
335
391
  return;
336
392
  failures.add(message);
337
- out.push({ kind: 'note', key: mint(), text: plain(message) });
393
+ out.push({ kind: 'note', key: mint(), text: plain(message, t) });
338
394
  // The reason, read whole, when it is the run's own; a vendor's words stay off the page.
339
395
  if (message && !vendor(message))
340
- out.push({ kind: 'step', key: mint(), name: 'Error', detail: '', output: message, ran: 'error' });
396
+ out.push({ kind: 'step', key: mint(), name: phrase('Error'), detail: '', output: message, ran: 'error' });
341
397
  };
342
398
  for (const e of [...events].sort((a, b) => a.seq - b.seq)) {
343
399
  seq = e.seq;
@@ -421,7 +477,7 @@ export function cards(events, mode = '') {
421
477
  failed(str(b.error));
422
478
  break;
423
479
  }
424
- const line = status(b, mode);
480
+ const line = status(b, mode, t);
425
481
  if (line)
426
482
  out.push({ kind: 'note', key: mint(), text: line });
427
483
  break;
@@ -434,11 +490,11 @@ export function cards(events, mode = '') {
434
490
  if (command === 'message' && said)
435
491
  steered.add(person(said));
436
492
  else if (command === 'pause')
437
- out.push({ kind: 'note', key: mint(), text: 'Pause asked' });
493
+ out.push({ kind: 'note', key: mint(), text: t('Pause asked') });
438
494
  else if (command === 'resume')
439
- out.push({ kind: 'note', key: mint(), text: 'Resume asked' });
495
+ out.push({ kind: 'note', key: mint(), text: t('Resume asked') });
440
496
  else if (command === 'stop')
441
- out.push({ kind: 'note', key: mint(), text: 'Stop asked' });
497
+ out.push({ kind: 'note', key: mint(), text: t('Stop asked') });
442
498
  break;
443
499
  }
444
500
  case 'message': {
@@ -1,12 +1,3 @@
1
- /**
2
- * A person's verdict on what a run said, recorded on the platform's own event
3
- * bus in the org it was said in.
4
- *
5
- * POST /v1/event {type: 'track', event: 'build.verdict', sessionId, properties}
6
- *
7
- * The receipt says whether it landed; a verdict that did not is reported, not
8
- * shown as recorded.
9
- */
10
1
  import { type Target } from './call.ts';
11
2
  export type Verdict = 'up' | 'down' | null;
12
3
  export declare function verdict(t: Target, session: string, project: string, v: Verdict): Promise<void>;
@@ -7,6 +7,7 @@
7
7
  * The receipt says whether it landed; a verdict that did not is reported, not
8
8
  * shown as recorded.
9
9
  */
10
+ import { phrase } from '@hanzo/i18n';
10
11
  import { call } from './call.js';
11
12
  export async function verdict(t, session, project, v) {
12
13
  const out = await call(t, 'POST', '/v1/event', {
@@ -16,5 +17,5 @@ export async function verdict(t, session, project, v) {
16
17
  properties: { verdict: v ?? 'cleared', project },
17
18
  });
18
19
  if (!out || !out.accepted)
19
- throw new Error('The verdict was not recorded');
20
+ throw new Error(phrase('The verdict was not recorded'));
20
21
  }
@@ -1,16 +1,3 @@
1
- /**
2
- * The organization's webhooks: https endpoints that each matching platform event
3
- * is POSTed to, signed.
4
- *
5
- * GET /v1/webhook {data: [endpoint]}, newest first, secrets withheld
6
- * POST /v1/webhook {url, events, description} → 201, the secret shown this once
7
- * DELETE /v1/webhook/{id} 204
8
- * POST /v1/webhook/{id}/test one signed test event, sent now → {delivered, httpStatus, durationMs, error}
9
- * GET /v1/webhook/{id}/deliveries {data: [attempt]}, newest first
10
- *
11
- * The org is the caller's; an endpoint another org owns reads as not found.
12
- * Events are subject patterns (`commerce.order.>`); none means every event.
13
- */
14
1
  import { type Target } from './call.ts';
15
2
  export interface Endpoint {
16
3
  id: string;
@@ -36,7 +23,7 @@ export interface Draft {
36
23
  events: string[];
37
24
  description: string;
38
25
  }
39
- /** Why a draft cannot be sent, or ''. The platform refuses the same things. */
26
+ /** Why a draft cannot be sent, or ''. The platform refuses the same things. English, marked (`phrase`): a screen says it through `t`. */
40
27
  export declare function refuse(d: Draft): string;
41
28
  export declare function add(t: Target, d: Draft): Promise<Endpoint>;
42
29
  export declare function remove(t: Target, id: string): Promise<void>;
@@ -11,6 +11,7 @@
11
11
  * The org is the caller's; an endpoint another org owns reads as not found.
12
12
  * Events are subject patterns (`commerce.order.>`); none means every event.
13
13
  */
14
+ import { phrase } from '@hanzo/i18n';
14
15
  import { call, query, seg } from './call.js';
15
16
  const str = (v) => (typeof v === 'string' ? v : '');
16
17
  const num = (v) => (typeof v === 'number' && Number.isFinite(v) ? v : 0);
@@ -38,19 +39,19 @@ export async function endpoints(t) {
38
39
  export function patterns(typed) {
39
40
  return [...new Set(typed.split(/[\s,]+/).map((s) => s.trim()).filter(Boolean))];
40
41
  }
41
- /** Why a draft cannot be sent, or ''. The platform refuses the same things. */
42
+ /** Why a draft cannot be sent, or ''. The platform refuses the same things. English, marked (`phrase`): a screen says it through `t`. */
42
43
  export function refuse(d) {
43
44
  let u;
44
45
  try {
45
46
  u = new URL(d.url.trim());
46
47
  }
47
48
  catch {
48
- return 'Enter the https address to deliver to';
49
+ return phrase('Enter the https address to deliver to');
49
50
  }
50
51
  if (u.protocol !== 'https:')
51
- return 'A webhook is delivered over https only';
52
+ return phrase('A webhook is delivered over https only');
52
53
  if (d.events.length > 64)
53
- return 'At most 64 event patterns';
54
+ return phrase('At most 64 event patterns');
54
55
  return '';
55
56
  }
56
57
  export async function add(t, d) {
package/lib/ask.js CHANGED
@@ -5,6 +5,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
5
5
  * the reason is read where the act was asked for.
6
6
  */
7
7
  import { SizableText, XStack } from '@hanzo/gui';
8
+ import { useI18n } from '@hanzo/i18n/react';
8
9
  import { Button, Dialog, DialogContent, DialogTitle, Input } from '@hanzo/ui';
9
10
  import { useEffect, useState } from 'react';
10
11
  /** One act in flight, and what refused it. */
@@ -32,6 +33,7 @@ function Said({ note }) {
32
33
  return (_jsx(SizableText, { size: "$1", color: "$soft", role: "status", children: note }));
33
34
  }
34
35
  export function Confirm({ open, onOpenChange, title, says, act, run, }) {
36
+ const { t } = useI18n();
35
37
  const { working, note, setNote, go } = useAct(() => onOpenChange(false));
36
38
  const close = (o) => {
37
39
  if (working)
@@ -39,9 +41,10 @@ export function Confirm({ open, onOpenChange, title, says, act, run, }) {
39
41
  setNote('');
40
42
  onOpenChange(o);
41
43
  };
42
- return (_jsx(Dialog, { open: open, onOpenChange: close, children: _jsxs(DialogContent, { maxW: 420, showCloseButton: false, children: [_jsx(DialogTitle, { children: title }), _jsx(SizableText, { size: "$2", color: "$soft", children: says }), _jsx(Said, { note: note }), _jsxs(XStack, { gap: "$2", justify: "flex-end", children: [_jsx(Button, { size: "sm", variant: "ghost", disabled: working, onPress: () => close(false), children: "Cancel" }), _jsx(Button, { size: "sm", variant: "destructive", disabled: working, onPress: () => void go(run), children: act })] })] }) }));
44
+ return (_jsx(Dialog, { open: open, onOpenChange: close, children: _jsxs(DialogContent, { maxW: 420, showCloseButton: false, children: [_jsx(DialogTitle, { children: title }), _jsx(SizableText, { size: "$2", color: "$soft", children: says }), _jsx(Said, { note: note }), _jsxs(XStack, { gap: "$2", justify: "flex-end", children: [_jsx(Button, { size: "sm", variant: "ghost", disabled: working, onPress: () => close(false), children: t('Cancel') }), _jsx(Button, { size: "sm", variant: "destructive", disabled: working, onPress: () => void go(run), children: act })] })] }) }));
43
45
  }
44
46
  export function Rename({ open, onOpenChange, title, name, run, }) {
47
+ const { t } = useI18n();
45
48
  const [value, setValue] = useState(name);
46
49
  const { working, note, setNote, go } = useAct(() => onOpenChange(false));
47
50
  useEffect(() => {
@@ -57,13 +60,13 @@ export function Rename({ open, onOpenChange, title, name, run, }) {
57
60
  const save = () => {
58
61
  const next = value.trim();
59
62
  if (!next)
60
- return setNote('It needs a name');
63
+ return setNote(t('It needs a name'));
61
64
  if (next === name)
62
65
  return close(false);
63
66
  void go(() => run(next));
64
67
  };
65
- return (_jsx(Dialog, { open: open, onOpenChange: close, children: _jsxs(DialogContent, { maxW: 420, showCloseButton: false, children: [_jsx(DialogTitle, { children: title }), _jsx(Input, { autoFocus: true, value: value, onChangeText: setValue, "aria-label": "Name", onKeyDown: (e) => {
68
+ return (_jsx(Dialog, { open: open, onOpenChange: close, children: _jsxs(DialogContent, { maxW: 420, showCloseButton: false, children: [_jsx(DialogTitle, { children: title }), _jsx(Input, { autoFocus: true, value: value, onChangeText: setValue, "aria-label": t('Name'), onKeyDown: (e) => {
66
69
  if (e.key === 'Enter')
67
70
  save();
68
- } }), _jsx(Said, { note: note }), _jsxs(XStack, { gap: "$2", justify: "flex-end", children: [_jsx(Button, { size: "sm", variant: "ghost", disabled: working, onPress: () => close(false), children: "Cancel" }), _jsx(Button, { size: "sm", disabled: working, onPress: save, children: "Save" })] })] }) }));
71
+ } }), _jsx(Said, { note: note }), _jsxs(XStack, { gap: "$2", justify: "flex-end", children: [_jsx(Button, { size: "sm", variant: "ghost", disabled: working, onPress: () => close(false), children: t('Cancel') }), _jsx(Button, { size: "sm", disabled: working, onPress: save, children: t('Save') })] })] }) }));
69
72
  }
@@ -1,25 +1,26 @@
1
1
  import { type SessionStatus } from '@hanzo/ui/chat';
2
2
  import { type Draft, type Kind, type Schedule } from './api/auto.ts';
3
3
  export declare const zone: () => string;
4
+ /** The lists' words are English, marked (`phrase`), and drawn through `t`. */
4
5
  export declare const KINDS: readonly {
5
6
  id: Kind;
6
7
  label: string;
7
8
  }[];
8
- /** A run's status as the rail's dot draws it. */
9
+ /** A run's status as the rail's dot draws it, and in words (marked, drawn through `t`). */
9
10
  export declare const DOT: Record<string, SessionStatus>;
10
11
  export declare const WORD: Record<string, string>;
11
12
  export declare const live: (s: string) => boolean;
12
13
  /** The schedule a kind starts from, keeping whatever of `was` still applies. */
13
14
  export declare function shaped(kind: Kind, was: Schedule): Schedule;
14
- /** What is wrong with a schedule before it is sent, or ''. */
15
+ /** What is wrong with a schedule before it is sent, or '': English, marked (`phrase`), so a screen says it through `t`. */
15
16
  export declare function unready(s: Schedule): string;
16
17
  /** A schedule as the platform reads it: an hourly minute in two digits. */
17
18
  export declare function tidy(d: Draft): Draft;
18
19
  /** A local time and date for an RFC 3339 instant. */
19
20
  export declare const local: (iso: string) => string;
20
- /** A run the platform refused for want of a plan: a free org with no credit for the run fee. */
21
+ /** A run the platform refused for want of a plan: a free org with no credit for the run fee. `PLAN` says so, marked, drawn through `t`. */
21
22
  export declare const unplanned: (e: unknown) => boolean;
22
- export declare const PLAN = "Automations run on a paid plan; on Free each run needs $1 of credit, and this organization has none. Upgrade to run it.";
23
+ export declare const PLAN: string;
23
24
  /** When a task runs, chosen: how often, the day and time, and the zone it is read in. */
24
25
  export declare function When({ s, onChange, disabled }: {
25
26
  s: Schedule;