@hanzo/build 0.2.80 → 0.2.82
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.
- package/README.md +13 -0
- package/lib/activity.d.ts +3 -7
- package/lib/activity.js +18 -5
- package/lib/api/agents.d.ts +1 -20
- package/lib/api/agents.js +16 -8
- package/lib/api/auto.d.ts +3 -23
- package/lib/api/auto.js +39 -22
- package/lib/api/billing.d.ts +0 -35
- package/lib/api/billing.js +6 -5
- package/lib/api/call.d.ts +16 -8
- package/lib/api/call.js +32 -1
- package/lib/api/capabilities.d.ts +0 -11
- package/lib/api/capabilities.js +2 -1
- package/lib/api/codebases.d.ts +0 -10
- package/lib/api/codebases.js +3 -2
- package/lib/api/coding.d.ts +3 -32
- package/lib/api/coding.js +13 -7
- package/lib/api/connectors.d.ts +1 -17
- package/lib/api/connectors.js +5 -4
- package/lib/api/environment.d.ts +6 -20
- package/lib/api/environment.js +22 -19
- package/lib/api/github.d.ts +0 -22
- package/lib/api/github.js +3 -2
- package/lib/api/keys.d.ts +0 -14
- package/lib/api/keys.js +4 -3
- package/lib/api/library.d.ts +3 -17
- package/lib/api/library.js +23 -22
- package/lib/api/links.d.ts +1 -1
- package/lib/api/links.js +1 -1
- package/lib/api/machines.d.ts +0 -15
- package/lib/api/machines.js +6 -5
- package/lib/api/mcp.d.ts +0 -9
- package/lib/api/mcp.js +3 -2
- package/lib/api/members.d.ts +0 -15
- package/lib/api/members.js +4 -3
- package/lib/api/memory.d.ts +0 -11
- package/lib/api/memory.js +2 -1
- package/lib/api/places.d.ts +1 -9
- package/lib/api/places.js +12 -1
- package/lib/api/plugins.d.ts +1 -16
- package/lib/api/plugins.js +4 -3
- package/lib/api/profile.d.ts +0 -10
- package/lib/api/profile.js +5 -4
- package/lib/api/projects.d.ts +0 -14
- package/lib/api/projects.js +11 -10
- package/lib/api/provider.d.ts +2 -14
- package/lib/api/provider.js +12 -10
- package/lib/api/sandbox.d.ts +0 -17
- package/lib/api/sandbox.js +5 -4
- package/lib/api/sessions.d.ts +0 -17
- package/lib/api/sessions.js +5 -4
- package/lib/api/skills.d.ts +1 -15
- package/lib/api/skills.js +5 -4
- package/lib/api/studio.d.ts +0 -14
- package/lib/api/studio.js +6 -5
- package/lib/api/turn.d.ts +6 -28
- package/lib/api/turn.js +105 -49
- package/lib/api/verdict.d.ts +0 -9
- package/lib/api/verdict.js +2 -1
- package/lib/api/webhooks.d.ts +1 -14
- package/lib/api/webhooks.js +5 -4
- package/lib/ask.js +7 -4
- package/lib/automations.d.ts +5 -4
- package/lib/automations.js +95 -74
- package/lib/back.js +10 -4
- package/lib/builder.js +7 -5
- package/lib/carry.js +20 -16
- package/lib/customize/agents.js +78 -31
- package/lib/customize/connectors.js +62 -48
- package/lib/customize/index.js +43 -10
- package/lib/customize/plugins.js +34 -22
- package/lib/customize/say.d.ts +13 -1
- package/lib/customize/say.js +15 -21
- package/lib/customize/skills.js +31 -22
- package/lib/customize/ui.d.ts +5 -9
- package/lib/customize/ui.js +26 -16
- package/lib/data.d.ts +1 -1
- package/lib/data.js +3 -2
- package/lib/desk.js +45 -33
- package/lib/door.js +35 -10
- package/lib/environment.js +25 -19
- package/lib/files.js +43 -34
- package/lib/find.js +12 -9
- package/lib/foot.js +7 -4
- package/lib/forge.js +61 -40
- package/lib/gear.d.ts +2 -1
- package/lib/gear.js +6 -4
- package/lib/git.js +29 -19
- package/lib/landing.d.ts +5 -5
- package/lib/landing.js +52 -44
- package/lib/library.js +73 -51
- package/lib/merge.d.ts +2 -2
- package/lib/meter.d.ts +1 -1
- package/lib/meter.js +14 -5
- package/lib/mic.js +12 -5
- package/lib/mind.d.ts +1 -0
- package/lib/mind.js +5 -3
- package/lib/nav.d.ts +6 -5
- package/lib/nav.js +37 -30
- package/lib/panel.d.ts +2 -1
- package/lib/panel.js +52 -36
- package/lib/plan.d.ts +4 -20
- package/lib/plan.js +26 -10
- package/lib/plans.js +49 -30
- package/lib/plugins/design.js +3 -2
- package/lib/plugins/index.d.ts +23 -4
- package/lib/plugins/index.js +11 -26
- package/lib/plugins/pdf.js +2 -1
- package/lib/plugins/project.js +7 -4
- package/lib/plugins/research.js +3 -2
- package/lib/plugins/sketch.js +6 -3
- package/lib/plugins/slides.js +3 -2
- package/lib/plugins/template.js +6 -3
- package/lib/plus.js +25 -13
- package/lib/prefs.d.ts +0 -14
- package/lib/prefs.js +2 -1
- package/lib/project.js +69 -62
- package/lib/prompt.d.ts +12 -11
- package/lib/prompt.js +38 -20
- package/lib/publish.js +17 -12
- package/lib/reply.js +6 -3
- package/lib/run.js +72 -54
- package/lib/say.d.ts +2 -0
- package/lib/say.js +7 -0
- package/lib/scheduled.js +54 -43
- package/lib/section.d.ts +1 -0
- package/lib/section.js +8 -2
- package/lib/settings/account.d.ts +1 -0
- package/lib/settings/account.js +31 -21
- package/lib/settings/billing.js +55 -28
- package/lib/settings/capabilities.js +26 -15
- package/lib/settings/card.js +19 -12
- package/lib/settings/code.js +22 -11
- package/lib/settings/credits.d.ts +4 -4
- package/lib/settings/credits.js +34 -21
- package/lib/settings/environments.js +21 -14
- package/lib/settings/general.js +26 -14
- package/lib/settings/index.js +6 -3
- package/lib/settings/integrations.js +42 -28
- package/lib/settings/keys.js +37 -19
- package/lib/settings/list.d.ts +0 -5
- package/lib/settings/list.js +24 -15
- package/lib/settings/machines.d.ts +3 -0
- package/lib/settings/machines.js +63 -38
- package/lib/settings/members.js +23 -14
- package/lib/settings/memory.js +12 -6
- package/lib/settings/notifications.js +32 -19
- package/lib/settings/plan.d.ts +1 -1
- package/lib/settings/plan.js +40 -17
- package/lib/settings/privacy.js +26 -13
- package/lib/settings/ui.d.ts +3 -2
- package/lib/settings/ui.js +9 -3
- package/lib/settings/usage.js +7 -3
- package/lib/shelf.js +20 -17
- package/lib/side.d.ts +1 -26
- package/lib/side.js +11 -5
- package/lib/standing.d.ts +2 -10
- package/lib/standing.js +5 -3
- package/lib/suggest.d.ts +8 -28
- package/lib/suggest.js +39 -4
- package/lib/suggestions.js +14 -5
- package/lib/summary.d.ts +1 -1
- package/lib/summary.js +4 -1
- package/lib/sync.js +22 -12
- package/lib/tools.d.ts +4 -3
- package/lib/tools.js +10 -7
- package/lib/transcript.js +10 -8
- package/package.json +4 -2
package/lib/api/turn.d.ts
CHANGED
|
@@ -1,26 +1,4 @@
|
|
|
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
|
-
*/
|
|
1
|
+
import type { Say } from '@hanzo/i18n/react';
|
|
24
2
|
import type { Event } from './sessions.ts';
|
|
25
3
|
/** The payload as an object. A live frame may carry it as a JSON string. */
|
|
26
4
|
export declare function decode(payload: unknown): Record<string, unknown> | string | null;
|
|
@@ -32,17 +10,17 @@ export declare function decode(payload: unknown): Record<string, unknown> | stri
|
|
|
32
10
|
*/
|
|
33
11
|
export declare function vendor(error: string): boolean;
|
|
34
12
|
/** An error as the run page may show it: its own words, or the plain line when they are a vendor's. */
|
|
35
|
-
export declare const scrub: (error: string) => string;
|
|
13
|
+
export declare const scrub: (error: string, t?: Say) => string;
|
|
36
14
|
/**
|
|
37
15
|
* A run's error as one plain line with what to do, never the log it came from:
|
|
38
16
|
* that goes in the Error step beside it (cards), unless it is a vendor's.
|
|
39
17
|
*/
|
|
40
|
-
export declare function plain(error: string): string;
|
|
18
|
+
export declare function plain(error: string, t?: Say): string;
|
|
41
19
|
/**
|
|
42
20
|
* One event's sentence, or '' when it says nothing a person needs. `mode` is
|
|
43
21
|
* the run's, from its record: a plan run's final status says the plan.
|
|
44
22
|
*/
|
|
45
|
-
export declare function said(e: Pick<Event, 'kind' | 'payload'>, mode?: string): string;
|
|
23
|
+
export declare function said(e: Pick<Event, 'kind' | 'payload'>, mode?: string, t?: Say): string;
|
|
46
24
|
/** One line of the shell: a command the run started, or output that followed it. */
|
|
47
25
|
export interface ShellLine {
|
|
48
26
|
role: 'cmd' | 'out';
|
|
@@ -89,7 +67,7 @@ export interface Outcome {
|
|
|
89
67
|
*/
|
|
90
68
|
export declare function outcome(events: Pick<Event, 'kind' | 'payload' | 'seq'>[]): Outcome;
|
|
91
69
|
/** Why the run failed, as its last status says it, or '' when that status is not a failure. */
|
|
92
|
-
export declare function failure(events: Pick<Event, 'kind' | 'payload' | 'seq'>[]): string;
|
|
70
|
+
export declare function failure(events: Pick<Event, 'kind' | 'payload' | 'seq'>[], t?: Say): string;
|
|
93
71
|
/** The turns, ordered and deduped: a recorded read and the live feed overlap. */
|
|
94
72
|
export declare function merge<T extends Pick<Event, 'id' | 'seq'>>(...lists: T[][]): T[];
|
|
95
73
|
/** The actor, short enough to label a block: `hanzo/2d4d67ab`, not the whole subject. */
|
|
@@ -176,7 +154,7 @@ export type Card = {
|
|
|
176
154
|
* is drawn only if the turn then fails. The final status carries the agent's
|
|
177
155
|
* answer, drawn once. `log` is never drawn here.
|
|
178
156
|
*/
|
|
179
|
-
export declare function cards(events: Pick<Event, 'kind' | 'payload' | 'seq'>[], mode?: string): Card[];
|
|
157
|
+
export declare function cards(events: Pick<Event, 'kind' | 'payload' | 'seq'>[], mode?: string, t?: Say): Card[];
|
|
180
158
|
/** The plan a plan run answered with, from its final status, or ''. */
|
|
181
159
|
export declare function answer(events: Pick<Event, 'kind' | 'payload' | 'seq'>[]): string;
|
|
182
160
|
export interface Settled {
|
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
|
-
|
|
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 ?
|
|
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
|
|
48
|
-
return
|
|
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 ?
|
|
109
|
+
return branch && b.changed ? t('Stopped — work kept on {branch}', { branch }) : t('Stopped');
|
|
54
110
|
case 'paused':
|
|
55
|
-
return branch && b.changed ?
|
|
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
|
-
?
|
|
112
|
-
:
|
|
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': {
|
package/lib/api/verdict.d.ts
CHANGED
|
@@ -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>;
|
package/lib/api/verdict.js
CHANGED
|
@@ -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
|
}
|
package/lib/api/webhooks.d.ts
CHANGED
|
@@ -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>;
|
package/lib/api/webhooks.js
CHANGED
|
@@ -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:
|
|
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":
|
|
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:
|
|
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
|
}
|
package/lib/automations.d.ts
CHANGED
|
@@ -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
|
|
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;
|