wizards 0.4.7 → 0.5.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.
- package/README.md +45 -42
- package/apps/runtime/dist/agents/studio-assistant.js +8 -8
- package/apps/runtime/dist/app.js +7 -4
- package/apps/runtime/dist/assistant/primer.js +1 -1
- package/apps/runtime/dist/auth/index.js +2 -2
- package/apps/runtime/dist/authoring/guide.js +8 -8
- package/apps/runtime/dist/cli/account.js +31 -28
- package/apps/runtime/dist/cli/autostart.js +5 -3
- package/apps/runtime/dist/cli/clients.js +1 -1
- package/apps/runtime/dist/cli/connect.js +24 -24
- package/apps/runtime/dist/cli/features.js +6 -6
- package/apps/runtime/dist/cli/main.js +51 -39
- package/apps/runtime/dist/cli/mcp.js +5 -4
- package/apps/runtime/dist/cli/menu.js +32 -30
- package/apps/runtime/dist/cli/report.js +7 -9
- package/apps/runtime/dist/cli/setup.js +42 -38
- package/apps/runtime/dist/cli/start.js +16 -15
- package/apps/runtime/dist/cli/status.js +20 -20
- package/apps/runtime/dist/cli/ui.js +9 -2
- package/apps/runtime/dist/cli/update.js +6 -6
- package/apps/runtime/dist/cli/validate.js +1 -1
- package/apps/runtime/dist/connectors/external.js +3 -2
- package/apps/runtime/dist/connectors/index.js +5 -5
- package/apps/runtime/dist/connectors/plugin-connections.js +2 -2
- package/apps/runtime/dist/connectors/via-account.js +5 -5
- package/apps/runtime/dist/db/control-schema.js +14 -0
- package/apps/runtime/dist/db/migrations/control/0009_plugin_claim.sql +9 -0
- package/apps/runtime/dist/db/migrations/control/meta/0009_snapshot.json +561 -0
- package/apps/runtime/dist/db/migrations/control/meta/_journal.json +7 -0
- package/apps/runtime/dist/db/schema.js +9 -9
- package/apps/runtime/dist/docs/dev/index.md +16 -14
- package/apps/runtime/dist/docs/dev/plugins/connections.md +27 -24
- package/apps/runtime/dist/docs/dev/plugins/events.md +19 -17
- package/apps/runtime/dist/docs/dev/plugins/examples.md +13 -12
- package/apps/runtime/dist/docs/dev/plugins/index.md +29 -24
- package/apps/runtime/dist/docs/dev/plugins/layout.md +20 -19
- package/apps/runtime/dist/docs/dev/plugins/quick-start.md +16 -15
- package/apps/runtime/dist/docs/dev/plugins/reference.md +52 -40
- package/apps/runtime/dist/docs/dev/plugins/reloading.md +24 -23
- package/apps/runtime/dist/docs/dev/plugins/routes.md +26 -22
- package/apps/runtime/dist/docs/dev/plugins/runners.md +49 -44
- package/apps/runtime/dist/docs/dev/plugins/server.md +95 -43
- package/apps/runtime/dist/docs/dev/plugins/shipping.md +19 -16
- package/apps/runtime/dist/docs/dev/plugins/space.md +75 -69
- package/apps/runtime/dist/docs/dev/plugins/starters.md +22 -17
- package/apps/runtime/dist/docs/dev/plugins/studio.md +80 -37
- package/apps/runtime/dist/docs/dev/plugins/styling.md +44 -41
- package/apps/runtime/dist/docs/dev/plugins/tables.md +11 -11
- package/apps/runtime/dist/docs/dev/plugins/tools.md +26 -25
- package/apps/runtime/dist/docs/dev/wizard-format.md +35 -23
- package/apps/runtime/dist/docs/user/ai-apps.md +46 -43
- package/apps/runtime/dist/docs/user/assistant.md +41 -36
- package/apps/runtime/dist/docs/user/build-a-wizard.md +64 -39
- package/apps/runtime/dist/docs/user/command-line.md +47 -44
- package/apps/runtime/dist/docs/user/connectors.md +40 -35
- package/apps/runtime/dist/docs/user/create-account.md +27 -22
- package/apps/runtime/dist/docs/user/data.md +29 -29
- package/apps/runtime/dist/docs/user/first-start.md +26 -28
- package/apps/runtime/dist/docs/user/index.md +16 -17
- package/apps/runtime/dist/docs/user/install.md +28 -27
- package/apps/runtime/dist/docs/user/local-only.md +21 -17
- package/apps/runtime/dist/docs/user/models.md +92 -84
- package/apps/runtime/dist/docs/user/plugins.md +28 -23
- package/apps/runtime/dist/docs/user/run.md +51 -50
- package/apps/runtime/dist/docs/user/server.md +9 -9
- package/apps/runtime/dist/docs/user/space.md +87 -65
- package/apps/runtime/dist/docs/user/steps.md +73 -69
- package/apps/runtime/dist/docs/user/test-and-share.md +127 -105
- package/apps/runtime/dist/docs/user/troubleshooting.md +40 -38
- package/apps/runtime/dist/docs/user/wordpress.md +62 -54
- package/apps/runtime/dist/documents/parse.js +2 -2
- package/apps/runtime/dist/engenty/shims/web-ingest.js +17 -1
- package/apps/runtime/dist/engine/input.js +4 -4
- package/apps/runtime/dist/engine/push.js +2 -2
- package/apps/runtime/dist/engine/runner.js +8 -8
- package/apps/runtime/dist/engine/steps.js +4 -4
- package/apps/runtime/dist/engine/surface.js +1 -1
- package/apps/runtime/dist/film/step.js +3 -3
- package/apps/runtime/dist/harness/claude.js +1 -1
- package/apps/runtime/dist/harness/codex.js +1 -1
- package/apps/runtime/dist/harness/model.js +2 -2
- package/apps/runtime/dist/harness/terminal.js +3 -3
- package/apps/runtime/dist/mcp/handler.js +2 -2
- package/apps/runtime/dist/mcp/tools.js +9 -9
- package/apps/runtime/dist/models.js +15 -15
- package/apps/runtime/dist/plugins/claims.js +56 -0
- package/apps/runtime/dist/plugins/loader.js +2 -0
- package/apps/runtime/dist/plugins/public.js +2 -3
- package/apps/runtime/dist/plugins/runs.js +13 -8
- package/apps/runtime/dist/render/chromium.js +24 -11
- package/apps/runtime/dist/routes/api.js +16 -10
- package/apps/runtime/dist/routes/debug.js +1 -1
- package/apps/runtime/dist/routes/delivery.js +46 -0
- package/apps/runtime/dist/routes/lang.js +7 -0
- package/apps/runtime/dist/routes/marketplace.js +2 -1
- package/apps/runtime/dist/routes/plugin-public.js +2 -1
- package/apps/runtime/dist/routes/plugins.js +13 -14
- package/apps/runtime/dist/routes/runs.js +59 -49
- package/apps/runtime/dist/routes/studio.js +58 -28
- package/apps/runtime/dist/services/access.js +3 -3
- package/apps/runtime/dist/services/assistant-chats.js +1 -1
- package/apps/runtime/dist/services/brand.js +2 -2
- package/apps/runtime/dist/services/cloud.js +5 -4
- package/apps/runtime/dist/services/errors.js +2 -1
- package/apps/runtime/dist/services/knowledge-model.js +10 -10
- package/apps/runtime/dist/services/knowledge.js +19 -19
- package/apps/runtime/dist/services/marketplace.js +2 -2
- package/apps/runtime/dist/services/package-file.js +12 -9
- package/apps/runtime/dist/services/package.js +3 -3
- package/apps/runtime/dist/services/project-files.js +15 -17
- package/apps/runtime/dist/services/project-index.js +10 -10
- package/apps/runtime/dist/services/projects.js +13 -8
- package/apps/runtime/dist/services/relevance.js +3 -3
- package/apps/runtime/dist/services/runners.js +4 -3
- package/apps/runtime/dist/services/runs.js +3 -3
- package/apps/runtime/dist/services/site.js +10 -10
- package/apps/runtime/dist/services/space-categories.js +22 -22
- package/apps/runtime/dist/services/space-data.js +16 -16
- package/apps/runtime/dist/services/space-origin.js +4 -4
- package/apps/runtime/dist/services/spaces.js +10 -10
- package/apps/runtime/dist/services/wizards.js +5 -5
- package/apps/runtime/dist/tools/index.js +1 -1
- package/apps/runtime/dist/tools/net-guard.js +135 -24
- package/apps/runtime/dist/tools/pages.js +4 -4
- package/apps/runtime/dist/tools/plugin.js +1 -1
- package/apps/runtime/dist/tools/project.js +10 -10
- package/apps/runtime/dist/tools/store.js +1 -1
- package/apps/runtime/dist/widgets/step.js +1 -1
- package/apps/web/dist/assets/AboutDialog-DaYwk84X.js +1 -0
- package/apps/web/dist/assets/{ChangelogDialog-Cm25slr3.js → ChangelogDialog-CsYbEayb.js} +1 -1
- package/apps/web/dist/assets/{ChatView-BXtXWnqK.js → ChatView-BRD3fKZU.js} +1 -1
- package/apps/web/dist/assets/EditorPage-ocPlZD3E.js +3 -0
- package/apps/web/dist/assets/{FlowPreview-BsfjDVv8.js → FlowPreview-Bm7sv746.js} +1 -1
- package/apps/web/dist/assets/{Harness-B0hD5Pp7.js → Harness-DKE-YNA5.js} +1 -1
- package/apps/web/dist/assets/{NewWizardChannels-DMDp9Ao5.js → NewWizardChannels-CnWckqjO.js} +1 -1
- package/apps/web/dist/assets/{NewWizardPage-aOisxyk2.js → NewWizardPage-BXTpbHVM.js} +1 -1
- package/apps/web/dist/assets/{OnboardingPage-Czb0pOyy.js → OnboardingPage-3Rz5uOsa.js} +1 -1
- package/apps/web/dist/assets/{ProjectPage-DPCtb42K.js → ProjectPage-QdSJwm3k.js} +1 -1
- package/apps/web/dist/assets/{PublicRunner-CvyA-gkf.js → PublicRunner-DEpBer5g.js} +1 -1
- package/apps/web/dist/assets/ReadOnly-rr_RJD-a.js +1 -0
- package/apps/web/dist/assets/{RunDrawer-BCiPEz9g.js → RunDrawer-BsZt0tL9.js} +1 -1
- package/apps/web/dist/assets/{RunnerView-4z6DMzE6.js → RunnerView-BbRukEdE.js} +1 -1
- package/apps/web/dist/assets/SettingsPage-qkWsQIMN.js +1 -0
- package/apps/web/dist/assets/{SetupPage-YFoU_nXK.js → SetupPage-PzvPPLfM.js} +1 -1
- package/apps/web/dist/assets/{SharePage-BBHiJ34e.js → SharePage-7vdDWG1n.js} +1 -1
- package/apps/web/dist/assets/changelog-BFdAYD28.js +1 -0
- package/apps/web/dist/assets/{esm-hSq-jeOG.js → esm-g0kaGp8t.js} +1 -1
- package/apps/web/dist/assets/{index-CSeBGwy0.css → index-Bi2x2g7n.css} +1 -1
- package/apps/web/dist/assets/{index-DB_iwB35.js → index-BzPid1oQ.js} +4 -4
- package/apps/web/dist/assets/lock-BK9RYIft.js +1 -0
- package/apps/web/dist/assets/oss-credits-BJrR7BR1.js +1 -0
- package/apps/web/dist/assets/{phone-CeqyvwK-.js → phone-DtkY0NfU.js} +1 -1
- package/apps/web/dist/assets/{settings-menu-BK8WpcGv.js → settings-menu-7EJQRFOi.js} +1 -1
- package/apps/web/dist/assets/{ui-BbIh6SOJ.js → ui-B6S5hYPd.js} +3 -3
- package/apps/web/dist/assets/{upload-BQrAlHIG.js → upload-rYCAy7ox.js} +1 -1
- package/apps/web/dist/index.html +3 -3
- package/apps/web/dist/mcp/flow.html +4 -4
- package/bin/wizards.mjs +1 -1
- package/node_modules/@engenty-wizards/plugin-sdk/dist/index.d.ts +33 -14
- package/node_modules/@engenty-wizards/plugin-sdk/dist/studio.d.ts +3 -3
- package/node_modules/@engenty-wizards/shared/dist/definition.d.ts +690 -690
- package/node_modules/@engenty-wizards/shared/dist/definition.js +1 -1
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns.d.ts +76 -76
- package/node_modules/@engenty-wizards/shared/dist/feature-flags.d.ts +3 -3
- package/node_modules/@engenty-wizards/shared/dist/feature-flags.js +3 -3
- package/node_modules/@engenty-wizards/shared/dist/knowledge.d.ts +13 -13
- package/node_modules/@engenty-wizards/shared/dist/knowledge.js +4 -4
- package/node_modules/@engenty-wizards/shared/dist/marketplace.d.ts +4 -4
- package/node_modules/@engenty-wizards/shared/dist/projects.js +1 -1
- package/node_modules/@engenty-wizards/shared/dist/run.d.ts +48 -48
- package/node_modules/@engenty-wizards/shared/dist/run.js +48 -48
- package/node_modules/@engenty-wizards/shared/dist/space-data.d.ts +2 -2
- package/node_modules/@engenty-wizards/shared/dist/surface.d.ts +20 -20
- package/node_modules/@engenty-wizards/shared/dist/wizard-package.js +1 -1
- package/package.json +5 -4
- package/apps/web/dist/assets/AboutDialog-BtAuA44m.js +0 -1
- package/apps/web/dist/assets/EditorPage-B4jX_Ckc.js +0 -3
- package/apps/web/dist/assets/ReadOnly-DFysMEMF.js +0 -1
- package/apps/web/dist/assets/SettingsPage-BKkOfz6P.js +0 -1
- package/apps/web/dist/assets/changelog-D8WjOq7d.js +0 -1
- package/apps/web/dist/assets/circle-alert-BVj6idzu.js +0 -1
- package/apps/web/dist/assets/lock-BoWS-JhN.js +0 -1
- package/apps/web/dist/assets/oss-credits-BQQX0kvk.js +0 -1
|
@@ -138,7 +138,7 @@ async function pluginIssues(draft) {
|
|
|
138
138
|
if (!known.has(id)) {
|
|
139
139
|
issues.push({
|
|
140
140
|
stepId: step.id,
|
|
141
|
-
message: `Step
|
|
141
|
+
message: `Step “${step.id}”: the tool “${id}” isn’t available here – the plugin “${named.plugin}” isn’t installed or has no such tool.`,
|
|
142
142
|
});
|
|
143
143
|
}
|
|
144
144
|
}
|
|
@@ -221,7 +221,7 @@ export async function addMessage(wizardId, message, writer = { source: "studio"
|
|
|
221
221
|
export function parseDraft(raw, files) {
|
|
222
222
|
const parsed = wizardSchema.safeParse(raw);
|
|
223
223
|
if (!parsed.success) {
|
|
224
|
-
throw new ServiceError("invalid", "The wizard
|
|
224
|
+
throw new ServiceError("invalid", "The wizard doesn’t match the schema.", {
|
|
225
225
|
issues: shapeIssues(parsed.error, raw),
|
|
226
226
|
});
|
|
227
227
|
}
|
|
@@ -239,7 +239,7 @@ export async function createWizard(userId, input, writer = { source: "studio" })
|
|
|
239
239
|
? await marketplaceWizard(input.starterId, asLang(input.lang))
|
|
240
240
|
: undefined;
|
|
241
241
|
if (input.starterId && !starter) {
|
|
242
|
-
throw new ServiceError("invalid", `There
|
|
242
|
+
throw new ServiceError("invalid", bilingual(`Die Vorlage „${input.starterId}“ gibt es nicht.`, `There’s no template “${input.starterId}”.`));
|
|
243
243
|
}
|
|
244
244
|
const maker = input.lang?.toLowerCase().startsWith("de") ? "de" : "en";
|
|
245
245
|
const { draft, issues } = input.definition !== undefined
|
|
@@ -308,7 +308,7 @@ export async function writeDraft(userId, wizardId, input, writer = { source: "st
|
|
|
308
308
|
.returning({ revision: schema.wizard.revision });
|
|
309
309
|
if (!row) {
|
|
310
310
|
const current = await ownedWizard(userId, wizardId);
|
|
311
|
-
throw new ServiceError("revision_conflict", bilingual("Der Wizard wurde inzwischen geändert.", "The wizard
|
|
311
|
+
throw new ServiceError("revision_conflict", bilingual("Der Wizard wurde inzwischen geändert.", "The wizard was changed in the meantime."), {
|
|
312
312
|
revision: current.revision,
|
|
313
313
|
});
|
|
314
314
|
}
|
|
@@ -329,7 +329,7 @@ export async function writeDraft(userId, wizardId, input, writer = { source: "st
|
|
|
329
329
|
export async function editWizard(userId, wizardId, input, writer) {
|
|
330
330
|
const w = await writableWizard(userId, wizardId);
|
|
331
331
|
if (w.revision !== input.baseRevision) {
|
|
332
|
-
throw new ServiceError("revision_conflict", bilingual("Der Wizard wurde inzwischen geändert.", "The wizard
|
|
332
|
+
throw new ServiceError("revision_conflict", bilingual("Der Wizard wurde inzwischen geändert.", "The wizard was changed in the meantime."), {
|
|
333
333
|
revision: w.revision,
|
|
334
334
|
});
|
|
335
335
|
}
|
|
@@ -149,7 +149,7 @@ export async function buildStepTools(step, ctx, resolved, uploads) {
|
|
|
149
149
|
// The wizard's lists and files, the documents the person gave and the project's documents are
|
|
150
150
|
// always at hand. An installed client gets tools over an MCP bridge its CLI starts for every
|
|
151
151
|
// call, seconds of its own: a step with no use for the store goes without its tools, and
|
|
152
|
-
// without others (
|
|
152
|
+
// without others (Knowledge, a workspace file) the client answers without the bridge.
|
|
153
153
|
const idle = isHarnessVendor(resolved.vendor) &&
|
|
154
154
|
storeIdle(step, ctx.def.lists?.length ?? 0, uploads.length) &&
|
|
155
155
|
!(await hasStoreFiles(ctx.store));
|
|
@@ -1,19 +1,107 @@
|
|
|
1
1
|
import { lookup } from "node:dns/promises";
|
|
2
|
-
import { isIP } from "node:net";
|
|
2
|
+
import { BlockList, isIP } from "node:net";
|
|
3
|
+
import { Agent } from "undici";
|
|
3
4
|
const ALLOW_PRIVATE = process.env.ALLOW_PRIVATE_FETCH === "1";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
5
|
+
/** Ranges that are not the public internet: this server, its networks, and special purposes. */
|
|
6
|
+
const blocked = new BlockList();
|
|
7
|
+
for (const [net, prefix] of [
|
|
8
|
+
["0.0.0.0", 8], // "this" network
|
|
9
|
+
["10.0.0.0", 8],
|
|
10
|
+
["100.64.0.0", 10], // carrier-grade NAT
|
|
11
|
+
["127.0.0.0", 8], // loopback
|
|
12
|
+
["169.254.0.0", 16], // link-local, the cloud metadata service
|
|
13
|
+
["172.16.0.0", 12], // also the Docker networks, the browser's DevTools among them
|
|
14
|
+
["192.0.0.0", 24], // protocol assignments
|
|
15
|
+
["192.0.2.0", 24], // documentation
|
|
16
|
+
["192.88.99.0", 24], // 6to4 relays
|
|
17
|
+
["192.168.0.0", 16],
|
|
18
|
+
["198.18.0.0", 15], // benchmarking
|
|
19
|
+
["198.51.100.0", 24], // documentation
|
|
20
|
+
["203.0.113.0", 24], // documentation
|
|
21
|
+
["224.0.0.0", 4], // multicast
|
|
22
|
+
["240.0.0.0", 4], // reserved, and the broadcast address
|
|
23
|
+
]) {
|
|
24
|
+
blocked.addSubnet(net, prefix, "ipv4");
|
|
25
|
+
}
|
|
26
|
+
for (const [net, prefix] of [
|
|
27
|
+
["::", 128], // unspecified
|
|
28
|
+
["::1", 128], // loopback
|
|
29
|
+
["64:ff9b:1::", 48], // NAT64 for local use
|
|
30
|
+
["100::", 64], // discard
|
|
31
|
+
["2001::", 32], // Teredo: a tunnel to an IPv4 address
|
|
32
|
+
["2001:db8::", 32], // documentation
|
|
33
|
+
["fc00::", 7], // unique local
|
|
34
|
+
["fe80::", 10], // link-local
|
|
35
|
+
["fec0::", 10], // site-local
|
|
36
|
+
["ff00::", 8], // multicast
|
|
37
|
+
]) {
|
|
38
|
+
blocked.addSubnet(net, prefix, "ipv6");
|
|
39
|
+
}
|
|
40
|
+
/** The eight 16-bit words of an IPv6 address (the caller has checked it is one). */
|
|
41
|
+
function words(ip) {
|
|
42
|
+
let s = ip.split("%")[0].toLowerCase();
|
|
43
|
+
const v4 = /(\d+)\.(\d+)\.(\d+)\.(\d+)$/.exec(s);
|
|
44
|
+
if (v4) {
|
|
45
|
+
const [a, b, c, d] = v4.slice(1).map(Number);
|
|
46
|
+
s = `${s.slice(0, v4.index)}${(a * 256 + b).toString(16)}:${(c * 256 + d).toString(16)}`;
|
|
47
|
+
}
|
|
48
|
+
const [head, tail] = s.split("::");
|
|
49
|
+
const part = (x) => x ? x.split(":").map((w) => Number.parseInt(w, 16)) : [];
|
|
50
|
+
const h = part(head);
|
|
51
|
+
const t = part(tail);
|
|
52
|
+
return tail === undefined ? h : [...h, ...new Array(8 - h.length - t.length).fill(0), ...t];
|
|
53
|
+
}
|
|
54
|
+
const dotted = (hi, lo) => [Math.floor(hi / 256), hi % 256, Math.floor(lo / 256), lo % 256].join(".");
|
|
55
|
+
/**
|
|
56
|
+
* The IPv4 address an IPv6 address stands for: mapped (::ffff:a.b.c.d, also written
|
|
57
|
+
* ::ffff:a9fe:a9fe), translated, compatible (::a.b.c.d), NAT64 (64:ff9b::/96) and 6to4 (2002::/16).
|
|
58
|
+
* Connecting to any of them can reach that IPv4 address.
|
|
59
|
+
*/
|
|
60
|
+
function embeddedV4(w) {
|
|
61
|
+
const zero = (from, to) => w.slice(from, to).every((x) => x === 0);
|
|
62
|
+
if (zero(0, 5) && w[5] === 0xffff) {
|
|
63
|
+
return dotted(w[6], w[7]);
|
|
64
|
+
}
|
|
65
|
+
if (zero(0, 4) && w[4] === 0xffff && w[5] === 0) {
|
|
66
|
+
return dotted(w[6], w[7]);
|
|
67
|
+
}
|
|
68
|
+
if (zero(0, 6)) {
|
|
69
|
+
return dotted(w[6], w[7]);
|
|
70
|
+
}
|
|
71
|
+
if (w[0] === 0x64 && w[1] === 0xff9b && zero(2, 6)) {
|
|
72
|
+
return dotted(w[6], w[7]);
|
|
73
|
+
}
|
|
74
|
+
if (w[0] === 0x2002) {
|
|
75
|
+
return dotted(w[1], w[2]);
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
/** Whether an IP address is on the public internet. Anything that is not an IP address is not. */
|
|
80
|
+
export function isPublicAddress(ip) {
|
|
81
|
+
const bare = ip.replace(/^\[|\]$/g, "");
|
|
82
|
+
const family = isIP(bare);
|
|
83
|
+
if (family === 4) {
|
|
84
|
+
return !blocked.check(bare, "ipv4");
|
|
85
|
+
}
|
|
86
|
+
if (family !== 6) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
const w = words(bare);
|
|
90
|
+
const v4 = embeddedV4(w);
|
|
91
|
+
if (v4) {
|
|
92
|
+
return isPublicAddress(v4);
|
|
93
|
+
}
|
|
94
|
+
return !blocked.check(w.map((x) => x.toString(16)).join(":"), "ipv6");
|
|
95
|
+
}
|
|
96
|
+
const PRIVATE = "Private addresses are not reachable from a wizard.";
|
|
97
|
+
/** The host's addresses, each of them public; throws if any one is not. */
|
|
98
|
+
async function publicAddresses(host) {
|
|
99
|
+
const family = isIP(host);
|
|
100
|
+
const addresses = family ? [{ address: host, family }] : await lookup(host, { all: true });
|
|
101
|
+
if (!ALLOW_PRIVATE && (!addresses.length || addresses.some((a) => !isPublicAddress(a.address)))) {
|
|
102
|
+
throw new Error(PRIVATE);
|
|
103
|
+
}
|
|
104
|
+
return addresses;
|
|
17
105
|
}
|
|
18
106
|
/** Agents may reach the public internet, never this server's own network. */
|
|
19
107
|
export async function assertPublicUrl(raw) {
|
|
@@ -32,23 +120,46 @@ export async function assertPublicUrl(raw) {
|
|
|
32
120
|
}
|
|
33
121
|
const host = url.hostname.replace(/^\[|\]$/g, "");
|
|
34
122
|
if (host === "localhost" || host.endsWith(".localhost") || host.endsWith(".local")) {
|
|
35
|
-
throw new Error(
|
|
36
|
-
}
|
|
37
|
-
const addresses = isIP(host)
|
|
38
|
-
? [{ address: host, family: isIP(host) }]
|
|
39
|
-
: await lookup(host, { all: true });
|
|
40
|
-
for (const a of addresses) {
|
|
41
|
-
if (a.family === 4 ? privateV4(a.address) : privateV6(a.address)) {
|
|
42
|
-
throw new Error("Private addresses are not reachable from a wizard.");
|
|
43
|
-
}
|
|
123
|
+
throw new Error(PRIVATE);
|
|
44
124
|
}
|
|
125
|
+
await publicAddresses(host);
|
|
45
126
|
return url;
|
|
46
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Connects only to addresses that passed the check: the name is resolved and checked again at
|
|
130
|
+
* connect time, and the socket gets exactly those addresses, so a DNS answer that changes between
|
|
131
|
+
* the check and the connect (rebinding) cannot point it into the private network. TLS still
|
|
132
|
+
* verifies, and the Host header still names, the host of the URL.
|
|
133
|
+
*/
|
|
134
|
+
const pinned = new Agent({
|
|
135
|
+
connect: {
|
|
136
|
+
lookup(host, options, callback) {
|
|
137
|
+
publicAddresses(host).then((addresses) => {
|
|
138
|
+
const usable = options.family
|
|
139
|
+
? addresses.filter((a) => a.family === options.family)
|
|
140
|
+
: addresses;
|
|
141
|
+
if (!usable.length) {
|
|
142
|
+
callback(Object.assign(new Error(`No address for ${host}`), { code: "ENOTFOUND" }));
|
|
143
|
+
}
|
|
144
|
+
else if (options.all) {
|
|
145
|
+
callback(null, usable);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
callback(null, usable[0].address, usable[0].family);
|
|
149
|
+
}
|
|
150
|
+
}, callback);
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
});
|
|
47
154
|
/** fetch that re-checks every redirect hop, so a public URL cannot bounce into the private network. */
|
|
48
155
|
export async function safeFetch(raw, init = {}) {
|
|
49
156
|
let url = await assertPublicUrl(raw);
|
|
50
157
|
for (let hop = 0; hop < 6; hop++) {
|
|
51
|
-
const res = await fetch(url, {
|
|
158
|
+
const res = await fetch(url, {
|
|
159
|
+
...init,
|
|
160
|
+
redirect: "manual",
|
|
161
|
+
dispatcher: pinned,
|
|
162
|
+
});
|
|
52
163
|
const location = res.headers.get("location");
|
|
53
164
|
if (res.status < 300 || res.status >= 400 || !location) {
|
|
54
165
|
return res;
|
|
@@ -5,8 +5,8 @@ import { pageReadInput, readKnowledgePage } from "./project.js";
|
|
|
5
5
|
import { attempt, clip } from "./shared.js";
|
|
6
6
|
/**
|
|
7
7
|
* Pages for a step that lists "pages": Markdown its wizard keeps for every run — notes, a log, a
|
|
8
|
-
* summary that grows — its memory, shown in the studio's Memory tab and under Space →
|
|
9
|
-
* page_read also reads the pages of
|
|
8
|
+
* summary that grows — its memory, shown in the studio's Memory tab and under Space → Data. Its
|
|
9
|
+
* page_read also reads the pages of Knowledge, by path. A test run reads the wizard's pages but
|
|
10
10
|
* writes into a copy of its own in the run's state, which goes with the run.
|
|
11
11
|
*/
|
|
12
12
|
export function pageTools(ctx) {
|
|
@@ -26,7 +26,7 @@ export function pageTools(ctx) {
|
|
|
26
26
|
return {
|
|
27
27
|
page_read: createTool({
|
|
28
28
|
id: "page_read",
|
|
29
|
-
description: "Read a page: one this wizard wrote, by its title, or a page of
|
|
29
|
+
description: "Read a page: one this wizard wrote, by its title, or a page of Knowledge, by its path (pages/…). Without either it lists the wizard's pages.",
|
|
30
30
|
inputSchema: z.object({
|
|
31
31
|
title: z.string().optional().describe("A page this wizard wrote"),
|
|
32
32
|
path: pageReadInput.path.optional(),
|
|
@@ -52,7 +52,7 @@ export function pageTools(ctx) {
|
|
|
52
52
|
}),
|
|
53
53
|
page_write: createTool({
|
|
54
54
|
id: "page_write",
|
|
55
|
-
description: "Write a page of this wizard in Markdown, kept for every later run and shown to the admin in the studio. A page with the same title is replaced — or added to with append: true (a log, a list that grows). Pages of
|
|
55
|
+
description: "Write a page of this wizard in Markdown, kept for every later run and shown to the admin in the studio. A page with the same title is replaced — or added to with append: true (a log, a list that grows). Pages of Knowledge are read-only.",
|
|
56
56
|
inputSchema: z.object({
|
|
57
57
|
title: z.string().min(1).max(200),
|
|
58
58
|
markdown: z.string().max(200_000),
|
|
@@ -39,7 +39,7 @@ async function toolOf(id, ctx) {
|
|
|
39
39
|
const found = named && has.has(named.plugin) ? loadedPlugin(named.plugin)?.tools.get(named.tool) : undefined;
|
|
40
40
|
if (!(named && found)) {
|
|
41
41
|
const plugin = named?.plugin ?? id;
|
|
42
|
-
throw new StepError(bilingual(`Dieser Schritt braucht das Werkzeug „${id}“. Das Plugin „${plugin}“ ist hier nicht installiert.`, `This step needs the tool “${id}”. The plugin “${plugin}”
|
|
42
|
+
throw new StepError(bilingual(`Dieser Schritt braucht das Werkzeug „${id}“. Das Plugin „${plugin}“ ist hier nicht installiert.`, `This step needs the tool “${id}”. The plugin “${plugin}” isn’t installed here.`));
|
|
43
43
|
}
|
|
44
44
|
return { plugin: named.plugin, tool: found };
|
|
45
45
|
}
|
|
@@ -7,15 +7,15 @@ import { filePaths, knowledgeCounts, listForStep, readPage, readTable, resolvePa
|
|
|
7
7
|
import { documentText, hasIndexEntries, searchKnowledge } from "../services/project-index.js";
|
|
8
8
|
import { attempt, clip } from "./shared.js";
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* Knowledge, for every agent step of the space's wizards: search it (a question, filtered by
|
|
11
|
+
* categories first, checked by a classifier after), list it by categories, read a page, a table
|
|
12
12
|
* or a file whole by its path. Hits and reads look like files — a path, front matter, Markdown or
|
|
13
13
|
* CSV — so a model reads them as it reads files. The search also finds what the space's plugins
|
|
14
14
|
* put into the index.
|
|
15
15
|
*/
|
|
16
16
|
const where = whereSchema
|
|
17
17
|
.optional()
|
|
18
|
-
.describe('Filter by
|
|
18
|
+
.describe('Filter by categories before searching, by their names: a value ("Baustelle": "Graz Süd"), a list of values, a range of numbers ({ "gte": 20000 }) or of days ({ "after": "2026-03-01", "before": "2026-03-31" }), { "contains": "…" } for a text, true/false. project_list without arguments names the categories and their values.');
|
|
19
19
|
export const pageReadInput = {
|
|
20
20
|
path: z.string().describe("The page's path, as project_search or project_list give it: pages/…"),
|
|
21
21
|
section: z
|
|
@@ -24,7 +24,7 @@ export const pageReadInput = {
|
|
|
24
24
|
.describe("Only this section: a heading of the page, or the start of one"),
|
|
25
25
|
from: z.number().int().min(0).optional().describe("Character to continue a long page at"),
|
|
26
26
|
};
|
|
27
|
-
/** A page of
|
|
27
|
+
/** A page of Knowledge by its path, for a step: its front matter and Markdown, in parts. */
|
|
28
28
|
export function readKnowledgePage(ctx, input) {
|
|
29
29
|
return attempt(async () => {
|
|
30
30
|
const read = await readPage(ctx.project.id, input.path, input);
|
|
@@ -42,7 +42,7 @@ export async function projectTools(ctx) {
|
|
|
42
42
|
const tools = {
|
|
43
43
|
project_search: createTool({
|
|
44
44
|
id: "project_search",
|
|
45
|
-
description: "Search
|
|
45
|
+
description: "Search the space's Knowledge: its pages, tables and files, and what its plugins keep (wiki pages, questions and answers). Gives items with their path, categories and best section, each checked for relevance. Ask in their language, with the words they would use; filter with `where` when the task names a category's value. Then read the items you need whole with page_read or table_read.",
|
|
46
46
|
inputSchema: z.object({
|
|
47
47
|
query: z.string().describe("What to look for: a question or keywords"),
|
|
48
48
|
where,
|
|
@@ -66,7 +66,7 @@ export async function projectTools(ctx) {
|
|
|
66
66
|
hits: found.hits.map((h) => ({
|
|
67
67
|
...(h.path ? { path: h.path } : {}),
|
|
68
68
|
title: h.title,
|
|
69
|
-
...(h.categories.length ? {
|
|
69
|
+
...(h.categories.length ? { categories: h.categories } : {}),
|
|
70
70
|
...(h.heading ? { section: h.heading } : {}),
|
|
71
71
|
...(h.sheet ? { page: h.sheet } : {}),
|
|
72
72
|
...(h.relevance !== null ? { relevance: h.relevance } : {}),
|
|
@@ -80,7 +80,7 @@ export async function projectTools(ctx) {
|
|
|
80
80
|
}),
|
|
81
81
|
project_list: createTool({
|
|
82
82
|
id: "project_list",
|
|
83
|
-
description: "List
|
|
83
|
+
description: "List Knowledge by its categories. Without `where`: the categories with their values and how many items each has. With `where`: the items it leaves, with their paths — all of them, where project_search gives the best few.",
|
|
84
84
|
inputSchema: z.object({ where }),
|
|
85
85
|
execute: (input) => attempt(async () => {
|
|
86
86
|
const listed = await listForStep(projectId, input.where);
|
|
@@ -92,7 +92,7 @@ export async function projectTools(ctx) {
|
|
|
92
92
|
if (counts.pages) {
|
|
93
93
|
tools.page_read = createTool({
|
|
94
94
|
id: "page_read",
|
|
95
|
-
description: "Read a page of
|
|
95
|
+
description: "Read a page of Knowledge whole by its path: front matter (title, categories, its source and original, its parent and sub-pages) and its Markdown. Long pages come in parts: pass `from` to continue. `section` reads one section.",
|
|
96
96
|
inputSchema: z.object(pageReadInput),
|
|
97
97
|
execute: (input) => readKnowledgePage(ctx, input),
|
|
98
98
|
});
|
|
@@ -100,7 +100,7 @@ export async function projectTools(ctx) {
|
|
|
100
100
|
if (counts.tables) {
|
|
101
101
|
tools.table_read = createTool({
|
|
102
102
|
id: "table_read",
|
|
103
|
-
description: "Read a table of
|
|
103
|
+
description: "Read a table of Knowledge by its path: its rows as CSV, filtered by its columns (by their names, like `where` of project_search). A few hundred rows at a time: pass `offset` to continue.",
|
|
104
104
|
inputSchema: z.object({
|
|
105
105
|
path: z.string().describe("The table's path: tables/…"),
|
|
106
106
|
where: whereSchema.optional().describe("Filter by columns, by their names"),
|
|
@@ -118,7 +118,7 @@ export async function projectTools(ctx) {
|
|
|
118
118
|
if (counts.files) {
|
|
119
119
|
tools.project_document = createTool({
|
|
120
120
|
id: "project_document",
|
|
121
|
-
description: "Read a file of
|
|
121
|
+
description: "Read a file of Knowledge as text by its path (files/…): a file that is not a page, or the original a page was read from. Long files come in parts: pass `from` to continue.",
|
|
122
122
|
inputSchema: z.object({
|
|
123
123
|
path: z
|
|
124
124
|
.string()
|
|
@@ -206,7 +206,7 @@ export function storeTools(ctx, uploads, keeper) {
|
|
|
206
206
|
});
|
|
207
207
|
tools.scan_documents = createTool({
|
|
208
208
|
id: "scan_documents",
|
|
209
|
-
description: `Pull the key fields out of invoices or receipts, several at once: vendor, number, dates, net/tax/total, currency, VAT
|
|
209
|
+
description: `Pull the key fields out of invoices or receipts, several at once: vendor, number, dates, net/tax/total, currency, VAT ID. Cheaper and more exact than reading each document yourself. Amounts come back exactly as printed.${fileHint}`,
|
|
210
210
|
inputSchema: z.object({
|
|
211
211
|
files: z.array(z.string()).min(1).max(30),
|
|
212
212
|
kind: z.enum(["invoice", "receipt"]),
|
|
@@ -107,7 +107,7 @@ async function runFilmStep(step, ctx, html, data, media, origin) {
|
|
|
107
107
|
}
|
|
108
108
|
});
|
|
109
109
|
if (!film) {
|
|
110
|
-
throw new StepError(bilingual("Der Film
|
|
110
|
+
throw new StepError(bilingual("Der Film ließ sich nicht rendern. Dafür braucht es ffmpeg und eine Zeitleiste im Widget.", "The film couldn’t be rendered. It needs ffmpeg and a timeline in the widget."));
|
|
111
111
|
}
|
|
112
112
|
if (film.errors.length) {
|
|
113
113
|
await ctx.emit("info", {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-BNakU3Ej.js";import{$t as r,Kn as i,Qt as a,Vn as o,dn as s,en as c,gn as l,ln as u,on as d,pn as f,tn as p,vn as m}from"./ui-B6S5hYPd.js";import{t as h}from"./preload-helper-CNEI7N0N.js";import{H as g,U as _,W as v,_t as y}from"./index-BzPid1oQ.js";import{c as b,f as x}from"./settings-menu-7EJQRFOi.js";import{ReleaseNotes as S,loadReleases as C,releaseDate as w,releaseLabel as T}from"./ChangelogDialog-CsYbEayb.js";var E=e(t(),1),D=[{name:`engenty wizards`,description:{de:`KI-Wizards aus einer Beschreibung, mit einem Link geteilt.`,en:`AI wizards built from a description, shared with a link.`},homepage:`https://github.com/engenty/wizards`,license:`FSL-1.1-MIT`},{name:`engenty`,description:{de:`Connectors, Datentabellen, Suche und die Engenties stammen aus dem engenty-Framework.`,en:`Connectors, data tables, search and the engenties come from the engenty framework.`},homepage:`https://github.com/engenty/engenty`,license:`FSL-1.1-MIT`}],O=[{name:`Mastra`,description:{de:`Agent-Framework hinter den KI-Schritten.`,en:`Agent framework behind the AI steps.`},homepage:`https://github.com/mastra-ai/mastra`,license:`Apache-2.0`},{name:`AI SDK`,description:{de:`Modell-Aufrufe für Text, Bild, Video und Sprache.`,en:`Model calls for text, image, video and speech.`},homepage:`https://github.com/vercel/ai`,license:`Apache-2.0`},{name:`Model Context Protocol`,description:{de:`MCP-Server zum Bauen von Wizards, MCP-Client für Werkzeuge der Schritte.`,en:`MCP server for building wizards, MCP client for the steps' tools.`},homepage:`https://github.com/modelcontextprotocol/typescript-sdk`,license:`MIT`},{name:`Hono`,description:{de:`HTTP-API der Runtime.`,en:`The runtime's HTTP API.`},homepage:`https://github.com/honojs/hono`,license:`MIT`},{name:`Drizzle ORM`,description:{de:`Schema und Migrationen der Datenbanken.`,en:`Schema and migrations of the databases.`},homepage:`https://github.com/drizzle-team/drizzle-orm`,license:`Apache-2.0`},{name:`libSQL`,description:{de:`Eine Datenbank je Mandant, lokal als Datei oder bei Turso.`,en:`One database per tenant, a local file or at Turso.`},homepage:`https://github.com/tursodatabase/libsql`,license:`MIT`},{name:`Playwright`,description:{de:`Browser-Schritte sowie PDF- und PNG-Export.`,en:`Browser steps and the PDF and PNG export.`},homepage:`https://github.com/microsoft/playwright`,license:`Apache-2.0`},{name:`agentOS`,description:{de:`Sandbox für Code-Schritte ohne Docker.`,en:`Sandbox for code steps without Docker.`},homepage:`https://github.com/rivet-dev/agentos`,license:`Apache-2.0`},{name:`React`,description:{de:`UI-Bibliothek der Web-App.`,en:`UI library of the web app.`},homepage:`https://github.com/facebook/react`,license:`MIT`},{name:`Vite`,description:{de:`Build-Werkzeug der Web-App.`,en:`Build tool of the web app.`},homepage:`https://github.com/vitejs/vite`,license:`MIT`},{name:`Tailwind CSS`,description:{de:`Styling der Oberfläche.`,en:`Styling of the interface.`},homepage:`https://github.com/tailwindlabs/tailwindcss`,license:`MIT`},{name:`React Flow`,description:{de:`Das Diagramm der Schritte im Editor.`,en:`The diagram of steps in the editor.`},homepage:`https://github.com/xyflow/xyflow`,license:`MIT`},{name:`TanStack Query`,description:{de:`Server-Daten in der Web-App.`,en:`Server data in the web app.`},homepage:`https://github.com/TanStack/query`,license:`MIT`},{name:`xterm.js`,description:{de:`Das Terminal auf der Seite, in dem sich KI-Clients anmelden.`,en:`The terminal on the page where AI clients sign in.`},homepage:`https://github.com/xtermjs/xterm.js`,license:`MIT`},{name:`Lucide`,description:{de:`Icons.`,en:`Icons.`},homepage:`https://github.com/lucide-icons/lucide`,license:`ISC`},{name:`Geist & Geist Mono`,description:{de:`Schrift der Oberfläche.`,en:`Typeface of the interface.`},homepage:`https://github.com/vercel/geist-font`,license:`OFL-1.1`},{name:`Space Grotesk`,description:{de:`Schrift der Überschriften.`,en:`Typeface of the headings.`},homepage:`https://github.com/floriankarsten/space-grotesk`,license:`OFL-1.1`},{name:`git-cliff`,description:{de:`Erzeugt den Changelog aus den Commits.`,en:`Generates the changelog from the commits.`},homepage:`https://github.com/orhun/git-cliff`,license:`MIT OR Apache-2.0`}],k=e(n(),1),A=(e,...t)=>t.some(t=>t?.toLowerCase().includes(e));function j({name:e,homepage:t,version:n,license:r,description:i}){return(0,k.jsxs)(`li`,{className:`py-2.5`,children:[(0,k.jsxs)(`div`,{className:`flex flex-wrap items-baseline gap-x-2.5 gap-y-0.5`,children:[t?(0,k.jsxs)(`a`,{href:t,target:`_blank`,rel:`noreferrer`,className:`inline-flex items-center gap-1 font-medium text-[0.875rem] text-ink underline-offset-4 hover:underline`,children:[e,(0,k.jsx)(o,{"aria-hidden":!0,className:`size-3 text-ink-4`})]}):(0,k.jsx)(`span`,{className:`font-medium text-[0.875rem] text-ink`,children:e}),n?(0,k.jsx)(`span`,{className:`text-[0.75rem] text-ink-3 tabular-nums`,children:n}):null,(0,k.jsx)(`span`,{className:`text-[0.75rem] text-ink-3`,children:r})]}),i?(0,k.jsx)(`p`,{className:`mt-0.5 text-[0.8125rem] text-ink-3`,children:i}):null]})}function M({title:e,hint:t,children:n}){return(0,k.jsxs)(`section`,{className:`mt-6`,children:[(0,k.jsx)(`h3`,{className:`border-border-soft border-b pb-2 font-display font-semibold text-[1rem]`,children:e}),t?(0,k.jsx)(`p`,{className:`mt-2 text-[0.8125rem] text-ink-3`,children:t}):null,n]})}function N({credits:e}){return(0,k.jsx)(`ul`,{className:`divide-y divide-border-soft`,children:e.map(e=>(0,k.jsx)(j,{name:e.name,homepage:e.homepage,license:e.license,description:e.description[f]},e.name))})}function P({label:e,packages:t}){return(0,k.jsxs)(`div`,{className:`mt-4`,children:[(0,k.jsx)(`h4`,{className:`font-medium text-[0.75rem] text-ink-3 tracking-wide`,children:e}),(0,k.jsx)(`ul`,{className:`divide-y divide-border-soft`,children:t.map(e=>(0,k.jsx)(j,{...e},e.name))})]})}function F({active:e}){let[t,n]=(0,E.useState)(null),[i,a]=(0,E.useState)(``);(0,E.useEffect)(()=>{if(!e||t)return;let r=!1;return h(()=>import(`./oss-credits-BJrR7BR1.js`).then(e=>{r||n(e.default)}),[]),()=>{r=!0}},[e,t]),(0,E.useEffect)(()=>{e||a(``)},[e]);let o=i.trim().toLowerCase(),s=e=>o?e.filter(e=>A(o,e.name,e.license,e.description.de,e.description.en)):e,c=e=>o?e.filter(e=>A(o,e.name,e.license,e.version)):e,u=s(D),f=s(O),m=t?[{id:`shared`,label:l(`about.creditsShared`),packages:c(t.shared)},...t.groups.map(e=>({id:e.id,label:e.label,packages:c(e.packages)}))].filter(e=>e.packages.length>0):[],g=u.length===0&&f.length===0&&m.length===0;return(0,k.jsxs)(k.Fragment,{children:[(0,k.jsx)(`p`,{className:`mb-4 text-[0.875rem] text-ink-3`,children:l(`about.creditsHint`)}),(0,k.jsx)(p,{type:`search`,value:i,placeholder:l(`about.search`),onChange:e=>a(e.target.value)}),u.length>0?(0,k.jsx)(M,{title:l(`about.creditsProduct`),children:(0,k.jsx)(N,{credits:u})}):null,f.length>0?(0,k.jsx)(M,{title:l(`about.creditsBuiltWith`),children:(0,k.jsx)(N,{credits:f})}):null,t===null?(0,k.jsx)(`div`,{className:`flex justify-center py-10 text-ink-3`,children:(0,k.jsx)(d,{})}):m.length>0?(0,k.jsx)(M,{title:l(`about.creditsDeps`),hint:o?void 0:l(`about.creditsDepsHint`),children:m.map(e=>(0,k.jsx)(P,{label:e.label,packages:e.packages},e.id))}):null,t!==null&&g?(0,k.jsx)(r,{children:l(`about.noMatches`)}):null]})}var I=[`new`,`earlier`,`credits`],L=e=>l(e===`new`?`about.tab.new`:e===`earlier`?`about.tab.earlier`:`about.credits`),R=e=>e===1?l(`about.change`):l(`about.changes`,{n:e});function z({open:e,onClose:t,me:n}){let r=n?.mode===`local`,{data:o,latest:f}=v(r&&e),[p,h]=(0,E.useState)(null),[D,O]=(0,E.useState)(`new`),A=x(I.indexOf(D)),j=o?.newer&&f?f:_;(0,E.useEffect)(()=>{if(!e)return;let t=!1;return h(null),C(j===`0.5.1`?void 0:j).then(e=>{t||h(e)}),()=>{t=!0}},[e,j]);let M=p?.find(e=>e.version===`v${j}`)??p?.[0]??null,N=p?.filter(e=>e!==M)??[],P=r?o?.kind??null:`cloud`;return(0,k.jsxs)(a,{open:e,onClose:t,wide:!0,height:`tall`,children:[(0,k.jsx)(`div`,{className:`-mt-2 -mr-2 sticky top-0 z-10 flex h-0 justify-end`,children:(0,k.jsx)(c,{label:l(`common.close`),onClick:t,children:(0,k.jsx)(m,{className:`size-4`})})}),(0,k.jsxs)(`div`,{className:`flex flex-col items-center pt-4 text-center`,children:[(0,k.jsx)(y,{size:96}),(0,k.jsxs)(`div`,{className:`mt-4 font-display font-semibold text-[1.5rem] tracking-tight`,children:[`engenty`,(0,k.jsx)(`span`,{className:`text-ember`,children:`.`}),(0,k.jsx)(`span`,{className:`ml-1.5 font-normal text-ink-3`,children:`wizards`})]}),(0,k.jsxs)(`div`,{className:`mt-1 text-[0.9375rem] text-ink-3 tabular-nums`,children:[l(`about.version`,{v:_}),P?` · ${l(`about.kind.${P}`)}`:``]})]}),r?(0,k.jsx)(`div`,{className:`mt-5`,children:(0,k.jsx)(g,{enabled:e})}):null,(0,k.jsx)(`div`,{className:`mt-6 flex justify-center`,children:(0,k.jsx)(u,{value:D,onChange:O,options:I.map(e=>({id:e,label:L(e)})),label:l(`about.title`)})}),(0,k.jsxs)(`div`,{className:s(`mt-5`,b(A)),children:[D===`new`?p===null?(0,k.jsx)(`div`,{className:`flex justify-center py-6 text-ink-3`,children:(0,k.jsx)(d,{})}):M?(0,k.jsxs)(k.Fragment,{children:[(0,k.jsxs)(`h3`,{className:`flex items-baseline gap-3 border-border-soft border-b pb-2 font-display font-semibold text-[1rem]`,children:[T(M),(0,k.jsx)(`span`,{className:`font-normal font-sans text-[0.8125rem] text-ink-3 tabular-nums`,children:w(M)})]}),(0,k.jsx)(`div`,{className:`mt-3`,children:(0,k.jsx)(S,{release:M})})]}):(0,k.jsx)(`p`,{className:`text-[0.875rem] text-ink-3`,children:l(`about.changelogEmpty`)}):null,D===`earlier`?(0,k.jsx)(`div`,{className:`flex flex-col divide-y divide-border-soft`,children:N.map(e=>(0,k.jsxs)(`details`,{className:`group/r py-2`,children:[(0,k.jsxs)(`summary`,{className:`flex cursor-pointer list-none items-baseline gap-3 text-[0.875rem] [&::-webkit-details-marker]:hidden`,children:[(0,k.jsx)(i,{className:`size-3.5 shrink-0 self-center text-ink-4 transition group-open/r:rotate-90`}),(0,k.jsx)(`span`,{className:`font-medium text-ink tabular-nums`,children:T(e)}),(0,k.jsx)(`span`,{className:`text-[0.8125rem] text-ink-3 tabular-nums`,children:w(e)}),(0,k.jsx)(`span`,{className:`ml-auto text-[0.8125rem] text-ink-4`,children:R(e.commits.length)})]}),(0,k.jsx)(`div`,{className:`mt-2 pl-6`,children:(0,k.jsx)(S,{release:e})})]},e.version??`unreleased`))}):null,D===`credits`?(0,k.jsx)(F,{active:!0}):null]},D)]})}export{z as AboutDialog};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-BNakU3Ej.js";import{$t as r,Qt as i,dn as a,gn as o,on as s,tn as c}from"./ui-
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-BNakU3Ej.js";import{$t as r,Qt as i,dn as a,gn as o,on as s,tn as c}from"./ui-B6S5hYPd.js";import{t as l}from"./preload-helper-CNEI7N0N.js";var u=e(t(),1),d=e(n(),1);function f(e){switch(e.group){case`Added`:return{label:`NEW`,dot:`bg-moss`};case`Fixed`:return{label:`FIXED`,dot:`bg-amber`};case`Changed`:return{label:`CHANGED`,dot:`bg-cobalt`};case`Performance`:return{label:`PERFORMANCE`,dot:`bg-ember`};case`Deploy`:return{label:`DEPLOY`,dot:`bg-ink-4`};case`Docs`:return{label:`DOCS`,dot:`bg-ink-4`};default:return{label:`OTHER`,dot:`bg-ink-4`}}}var p=e=>e.version?e.version.replace(/^v/,``):o(`about.unreleased`),m=e=>e.timestamp?new Date(e.timestamp*1e3).toISOString().slice(0,10):``,h=e=>e.charAt(0).toUpperCase()+e.slice(1);function g(e,t){let n=t.trim().toLowerCase();if(!n)return e;let r=[];for(let t of e){if(`${p(t)} ${m(t)}`.toLowerCase().includes(n)){r.push(t);continue}let e=t.commits.filter(e=>`${f(e).label} ${e.scope??``} ${e.message}`.toLowerCase().includes(n));e.length>0&&r.push({...t,commits:e})}return r}async function _(e){if(e)try{let t=await fetch(`https://raw.githubusercontent.com/engenty/engenty-wizards/v${e}/apps/web/src/about/changelog.json`,{signal:AbortSignal.timeout(5e3)});if(t.ok)return await t.json()}catch{}return(await l(async()=>{let{default:e}=await import(`./changelog-BFdAYD28.js`);return{default:e}},[])).default}function v({release:e}){return(0,d.jsx)(`ul`,{className:`flex flex-col gap-2`,children:e.commits.map(e=>{let t=f(e);return(0,d.jsxs)(`li`,{className:`flex items-start gap-2.5 text-[0.875rem]`,children:[(0,d.jsx)(`span`,{className:a(`mt-[7px] size-1.5 shrink-0 rounded-full`,t.dot)}),(0,d.jsxs)(`span`,{className:`min-w-0 text-ink-2`,children:[(0,d.jsxs)(`span`,{className:`font-semibold text-[0.75rem] text-ink tracking-wide`,children:[t.label,e.scope?` [${e.scope}]`:``]}),` `,h(e.message),e.breaking?(0,d.jsx)(`span`,{className:`ml-1.5 rounded-full bg-rose-tint px-1.5 py-0.5 font-medium text-[0.75rem] text-rose`,children:o(`about.breaking`)}):null]})]},e.id)})})}function y({open:e,onClose:t,version:n}){let[a,l]=(0,u.useState)(null),[f,h]=(0,u.useState)(``);(0,u.useEffect)(()=>{if(!e||a)return;let t=!1;return _(n).then(e=>{t||l(e)}),()=>{t=!0}},[e,a,n]),(0,u.useEffect)(()=>{e||h(``)},[e]);let y=a?g(a,f):[];return(0,d.jsxs)(i,{open:e,onClose:t,title:o(`about.changelog`),wide:!0,height:`tall`,children:[(0,d.jsx)(`p`,{className:`-mt-3 mb-4 text-[0.875rem] text-ink-3`,children:o(`about.changelogHint`)}),a===null?(0,d.jsx)(`div`,{className:`flex justify-center py-10 text-ink-3`,children:(0,d.jsx)(s,{})}):a.length===0?(0,d.jsx)(r,{children:o(`about.changelogEmpty`)}):(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(c,{type:`search`,value:f,placeholder:o(`about.search`),onChange:e=>h(e.target.value)}),y.length===0?(0,d.jsx)(r,{children:o(`about.noMatches`)}):null,y.map(e=>(0,d.jsxs)(`section`,{className:`mt-6`,children:[(0,d.jsxs)(`h3`,{className:`flex items-baseline gap-3 border-border-soft border-b pb-2 font-display font-semibold text-[1rem]`,children:[p(e),(0,d.jsx)(`span`,{className:`font-normal font-sans text-[0.8125rem] text-ink-3 tabular-nums`,children:m(e)})]}),(0,d.jsx)(`div`,{className:`mt-3`,children:(0,d.jsx)(v,{release:e})})]},e.version??`unreleased`))]})]})}export{y as ChangelogDialog,v as ReleaseNotes,_ as loadReleases,m as releaseDate,p as releaseLabel};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-BNakU3Ej.js";import{$ as r,Bt as i,Cn as a,Ft as o,Lt as s,Mn as c,Pn as l,Rt as u,Sn as d,Tn as f,W as p,Yn as m,Zn as h,bt as g,dn as _,dt as v,en as y,fn as b,fr as x,ft as S,gn as C,kn as w,kt as T,lt as E,mt as D,nt as O,on as k,p as A,pn as j,pt as M,rn as N,rt as P,st as F,tr as I,tt as L,un as ee,ut as te,xn as R,yn as z,zt as ne}from"./ui-
|
|
1
|
+
import{r as e}from"./rolldown-runtime-hePW80VL.js";import{n as t,t as n}from"./jsx-runtime-BNakU3Ej.js";import{$ as r,Bt as i,Cn as a,Ft as o,Lt as s,Mn as c,Pn as l,Rt as u,Sn as d,Tn as f,W as p,Yn as m,Zn as h,bt as g,dn as _,dt as v,en as y,fn as b,fr as x,ft as S,gn as C,kn as w,kt as T,lt as E,mt as D,nt as O,on as k,p as A,pn as j,pt as M,rn as N,rt as P,st as F,tr as I,tt as L,un as ee,ut as te,xn as R,yn as z,zt as ne}from"./ui-B6S5hYPd.js";import{t as re}from"./phone-DtkY0NfU.js";import{Mt as ie,Q as ae,X as oe,Z as se,ft as ce,kt as le,t as ue,yt as de}from"./index-BzPid1oQ.js";import{n as fe}from"./RunnerView-BbRukEdE.js";var pe={name:`hand`,size:24,node:[[`path`,{d:`M18 11V6a2 2 0 0 0-2-2a2 2 0 0 0-2 2`,key:`1fvzgz`}],[`path`,{d:`M14 10V4a2 2 0 0 0-2-2a2 2 0 0 0-2 2v2`,key:`1kc0my`}],[`path`,{d:`M10 10.5V6a2 2 0 0 0-2-2a2 2 0 0 0-2 2v8`,key:`10h0bg`}],[`path`,{d:`M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.86-5.99-2.34l-3.6-3.6a2 2 0 0 1 2.83-2.82L7 15`,key:`1s1gnw`}]]};pe.node;var me=I(pe),he={name:`undo-2`,size:24,node:[[`path`,{d:`M9 14 4 9l5-5`,key:`102s5s`}],[`path`,{d:`M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11`,key:`f3b9sd`}]]};he.node;var ge=I(he),_e={name:`video-off`,size:24,node:[[`path`,{d:`M10.66 6H14a2 2 0 0 1 2 2v2.5l5.248-3.062A.5.5 0 0 1 22 7.87v8.196`,key:`w8jjjt`}],[`path`,{d:`M16 16a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h2`,key:`1xawa7`}],[`path`,{d:`m2 2 20 20`,key:`1ooewy`}]]};_e.node;var B=I(_e),ve={name:`volume-x`,size:24,node:[[`path`,{d:`M11 4.702a.7.7 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.7.7 0 0 0 11 19.298z`,key:`1p7khw`}],[`path`,{d:`m16.5 14.5 5-5`,key:`cul3yw`}],[`path`,{d:`m16.5 9.5 5 5`,key:`1akey5`}]]};ve.node;var ye=I(ve),be=x(),V=e(t(),1),H=e(n(),1),xe=typeof window<`u`&&window.matchMedia(`(pointer: coarse)`).matches;function Se({since:e}){let[t,n]=(0,V.useState)(Date.now());if((0,V.useEffect)(()=>{if(!e)return;let t=setInterval(()=>n(Date.now()),1e3);return()=>clearInterval(t)},[e]),!e)return null;let r=Math.max(0,Math.floor((t-e)/1e3)),i=String(Math.floor(r/60)).padStart(2,`0`),a=String(r%60).padStart(2,`0`);return(0,H.jsxs)(`span`,{className:`font-mono text-[0.8125rem] text-white/60 tabular-nums`,children:[i,`:`,a]})}function U({label:e,on:t,danger:n,busy:r,onClick:i,children:a}){return(0,H.jsx)(`button`,{type:`button`,"aria-label":e,title:e,"aria-pressed":t,disabled:r,onClick:i,className:_(`flex size-12 items-center justify-center rounded-full transition disabled:opacity-50`,n?`bg-rose text-white hover:brightness-110`:t===!1?`bg-white text-neutral-900 hover:bg-white/90`:`bg-white/15 text-white hover:bg-white/25`),children:r?(0,H.jsx)(k,{className:`size-5`}):a})}function Ce({voice:e}){let t=(0,V.useRef)(null),{captions:n}=e;return(0,V.useEffect)(()=>{n.length&&t.current?.scrollIntoView({block:`end`})},[n]),n.length?(0,H.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-4 sm:px-5`,children:(0,H.jsxs)(`ol`,{className:`mx-auto flex max-w-[720px] flex-col gap-2 py-2`,children:[n.map(e=>(0,H.jsx)(`li`,{className:_(`text-[0.9375rem] leading-snug`,e.who===`bot`?`text-white/95`:`text-right text-white/50`),children:e.text},e.id)),(0,H.jsx)(`div`,{ref:t})]})}):null}function we({voice:e,view:t,video:n,className:r}){let i=e.state===`live`,a=e.state===`connecting`,[o,s]=(0,V.useState)(null),[c,u]=(0,V.useState)(!1);(0,V.useEffect)(()=>{s(i?Date.now():null)},[i]);let d=async()=>{u(!1),await e.start(),n&&await e.startCamera()},f=()=>{e.stop(),u(!0)},p=n||e.camera,m=[...e.captions].reverse().find(e=>e.who===`bot`),h=[...e.captions].reverse().find(e=>e.who===`me`),g=e.speaking?C(`talk.speaking`):e.listening?C(`talk.listening`):i?C(`talk.live`):a?C(`talk.connecting`):c?C(`video.ended`):``;return(0,H.jsxs)(`section`,{className:_(`relative flex min-h-0 flex-col bg-neutral-950 text-white`,`safe-top`,r),children:[(0,H.jsxs)(`div`,{className:`flex h-14 shrink-0 items-center gap-3 px-4 sm:px-5`,children:[(0,H.jsx)(`div`,{className:`min-w-0 flex-1 truncate font-display font-semibold text-[1rem] tracking-tight`,children:t?.wizard.title??``}),g?(0,H.jsxs)(`span`,{className:`flex items-center gap-1.5 text-[0.8125rem] text-white/70`,children:[i?(0,H.jsx)(`span`,{className:_(`size-2 rounded-full`,e.speaking?`animate-pulse-dot bg-emerald-400`:`bg-rose`)}):null,g]}):null,(0,H.jsx)(Se,{since:o})]}),(0,H.jsxs)(`div`,{className:_(`grid min-h-0 gap-2 px-3 pb-2 sm:px-4`,p?`flex-1 grid-cols-1 sm:grid-cols-2`:`shrink-0 grid-cols-1`,!p&&i&&e.captions.length?`h-[38%]`:p?``:`flex-1`),children:[(0,H.jsxs)(`div`,{className:_(`relative min-h-0 overflow-hidden rounded-2xl bg-neutral-900`,!p&&`hidden`),children:[(0,H.jsx)(`video`,{ref:e.video,muted:!0,playsInline:!0,autoPlay:!0,className:_(`absolute inset-0 h-full w-full object-cover`,e.facing===`user`&&`-scale-x-100`,e.camera?`block`:`hidden`)}),e.camera?null:(0,H.jsxs)(`div`,{className:`absolute inset-0 flex flex-col items-center justify-center gap-2 text-white/50`,children:[(0,H.jsx)(B,{className:`size-8`}),(0,H.jsx)(`span`,{className:`text-[0.8125rem]`,children:C(`video.cameraOff`)})]}),(0,H.jsxs)(`span`,{className:`absolute bottom-2 left-3 rounded-md bg-black/50 px-2 py-0.5 text-[0.75rem]`,children:[C(`video.you`),e.muted?(0,H.jsx)(ie,{className:`ml-1.5 inline size-3`}):null]})]}),(0,H.jsxs)(`div`,{className:_(`relative flex min-h-0 items-center justify-center overflow-hidden rounded-2xl transition-shadow`,p?`bg-neutral-900`:`bg-transparent`,p&&e.speaking&&`ring-2 ring-emerald-400/70`),children:[(0,H.jsx)(`div`,{className:_(`rounded-full transition-shadow duration-500`,!p&&e.listening&&`shadow-[0_0_80px_20px_rgba(244,63,94,0.25)]`,!p&&e.speaking&&`shadow-[0_0_80px_20px_rgba(52,211,153,0.3)]`,e.speaking&&`animate-breathe`),children:(0,H.jsx)(ce,{kind:t?.wizard.avatar??`round`,size:p?140:200,fluffy:!0,interactive:!1})}),p?(0,H.jsx)(`span`,{className:`absolute bottom-2 left-3 max-w-[85%] truncate rounded-md bg-black/50 px-2 py-0.5 text-[0.75rem]`,children:t?.wizard.title??``}):null]})]}),i&&!p?(0,H.jsx)(Ce,{voice:e}):i&&(m||h)?(0,H.jsx)(`div`,{className:`shrink-0 px-4 pb-2 sm:px-5`,children:(0,H.jsxs)(`div`,{className:`mx-auto max-w-[720px] space-y-1 text-center`,children:[h?(0,H.jsx)(`p`,{className:`line-clamp-1 text-[0.8125rem] text-white/50`,children:h.text}):null,m?(0,H.jsx)(`p`,{className:`line-clamp-3 text-[0.9375rem] text-white/95 leading-snug`,children:m.text}):null]})}):null,e.error?(0,H.jsx)(`p`,{className:`shrink-0 px-5 pb-2 text-center text-[0.8125rem] text-rose`,children:e.error}):null,(0,H.jsx)(`div`,{className:`flex shrink-0 items-center justify-center gap-3 px-4 pt-1 pb-4`,children:i?(0,H.jsxs)(H.Fragment,{children:[(0,H.jsx)(U,{label:C(e.muted?`video.unmute`:`video.mute`),on:!e.muted,onClick:e.toggleMute,children:e.muted?(0,H.jsx)(ie,{className:`size-5`}):(0,H.jsx)(l,{className:`size-5`})}),(0,H.jsx)(U,{label:C(e.camera?`talk.cameraOff`:`talk.camera`),on:e.camera,onClick:()=>e.camera?e.stopCamera():void e.startCamera(),children:e.camera?(0,H.jsx)(z,{className:`size-5`}):(0,H.jsx)(B,{className:`size-5`})}),e.camera&&xe?(0,H.jsx)(U,{label:C(`video.flip`),onClick:()=>void e.flipCamera(),children:(0,H.jsx)(R,{className:`size-5`})}):null,(0,H.jsx)(U,{label:C(`video.leave`),danger:!0,onClick:f,children:(0,H.jsx)(le,{className:`size-5`})})]}):(0,H.jsxs)(`div`,{className:`flex flex-col items-center gap-2`,children:[(0,H.jsxs)(`button`,{type:`button`,disabled:a||!t?.talk,onClick:()=>void d(),className:`flex h-12 items-center gap-2 rounded-full bg-emerald-500 px-6 font-medium text-[0.9375rem] text-white transition hover:brightness-110 disabled:opacity-50`,children:[a?(0,H.jsx)(k,{className:`size-4`}):n?(0,H.jsx)(z,{className:`size-5`}):(0,H.jsx)(l,{className:`size-5`}),C(c?`video.rejoin`:n?`video.join`:`talk.start`)]}),!c&&!e.error?(0,H.jsx)(`p`,{className:`max-w-sm text-center text-[0.75rem] text-white/50`,children:C(n?`video.hint`:`talk.joinHint`)}):null]})})]})}var Te=e=>g[e.kind]!==`device`,Ee=1024,De=4e3;function W(e,t){return e?e.length>t?`${e.slice(0,t)} …`:e:``}function Oe(e,t,n=!1){let r=[`status: ${e.status}`,`camera: ${n?`on`:`off`}`];if(e.ask)return r.push(e.ask.kind===`confirm`?`question: the step wants to "${e.ask.action.summary}" in ${e.ask.service}; answer_ask allows or skips it`:`question: a sign-in at ${e.ask.site.host}; the person types it on the screen, wait`),r.join(`
|
|
2
2
|
`);if(e.status===`running`){let t=[...e.events].reverse().find(e=>e.type===`tool`||e.type===`info`||e.type===`step_started`);return r.push(`working on: ${e.step?.title??``}`),t&&r.push(`doing: ${b(t)}`),r.join(`
|
|
3
3
|
`)}if(e.status===`done`){r.push(`done. made:`);for(let{step:t,output:n}of e.shown)r.push(`- ${t.title}: ${W(n?.text,400)||`(a file, on the screen)`}`);return r.join(`
|
|
4
4
|
`)}if(e.status===`failed`)return r.push(`failed: ${e.error??``}; go_back or the person retries on the screen`),r.join(`
|