wizards 0.1.9
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/LICENSE +110 -0
- package/README.md +170 -0
- package/apps/runtime/dist/agents/architect.js +453 -0
- package/apps/runtime/dist/agents/project-assistant.js +354 -0
- package/apps/runtime/dist/agents/subscription.js +206 -0
- package/apps/runtime/dist/agents/thought.js +21 -0
- package/apps/runtime/dist/agents/website.js +197 -0
- package/apps/runtime/dist/app.js +153 -0
- package/apps/runtime/dist/auth/account.js +121 -0
- package/apps/runtime/dist/auth/index.js +329 -0
- package/apps/runtime/dist/auth/keys.js +55 -0
- package/apps/runtime/dist/auth/local-ticket.js +23 -0
- package/apps/runtime/dist/authoring/example.js +73 -0
- package/apps/runtime/dist/authoring/guide.js +259 -0
- package/apps/runtime/dist/authoring/ops.js +117 -0
- package/apps/runtime/dist/cli/autostart.js +134 -0
- package/apps/runtime/dist/cli/clients.js +44 -0
- package/apps/runtime/dist/cli/environment.js +81 -0
- package/apps/runtime/dist/cli/exec.js +45 -0
- package/apps/runtime/dist/cli/home.js +74 -0
- package/apps/runtime/dist/cli/machine.js +145 -0
- package/apps/runtime/dist/cli/main.js +125 -0
- package/apps/runtime/dist/cli/setup.js +273 -0
- package/apps/runtime/dist/cli/start.js +190 -0
- package/apps/runtime/dist/cli/status.js +120 -0
- package/apps/runtime/dist/cli/ui.js +12 -0
- package/apps/runtime/dist/cli/update.js +58 -0
- package/apps/runtime/dist/connectors/builtin.js +70 -0
- package/apps/runtime/dist/connectors/external.js +400 -0
- package/apps/runtime/dist/connectors/gmail.js +107 -0
- package/apps/runtime/dist/connectors/imap.js +217 -0
- package/apps/runtime/dist/connectors/index.js +266 -0
- package/apps/runtime/dist/connectors/mail.js +72 -0
- package/apps/runtime/dist/connectors/outlook.js +90 -0
- package/apps/runtime/dist/credits/credits.js +103 -0
- package/apps/runtime/dist/credits/estimate.js +132 -0
- package/apps/runtime/dist/db/adopt.js +149 -0
- package/apps/runtime/dist/db/client.js +146 -0
- package/apps/runtime/dist/db/control-schema.js +70 -0
- package/apps/runtime/dist/db/migrations/control/0000_last_absorbing_man.sql +47 -0
- package/apps/runtime/dist/db/migrations/control/0001_gorgeous_nicolaos.sql +41 -0
- package/apps/runtime/dist/db/migrations/control/0002_secret_penance.sql +1 -0
- package/apps/runtime/dist/db/migrations/control/0003_nasty_mordo.sql +3 -0
- package/apps/runtime/dist/db/migrations/control/0004_breezy_eddie_brock.sql +6 -0
- package/apps/runtime/dist/db/migrations/control/meta/0000_snapshot.json +311 -0
- package/apps/runtime/dist/db/migrations/control/meta/0001_snapshot.json +599 -0
- package/apps/runtime/dist/db/migrations/control/meta/0002_snapshot.json +607 -0
- package/apps/runtime/dist/db/migrations/control/meta/0003_snapshot.json +311 -0
- package/apps/runtime/dist/db/migrations/control/meta/0004_snapshot.json +350 -0
- package/apps/runtime/dist/db/migrations/control/meta/_journal.json +41 -0
- package/apps/runtime/dist/db/migrations/tenant/0000_eminent_freak.sql +188 -0
- package/apps/runtime/dist/db/migrations/tenant/0001_salty_master_chief.sql +1 -0
- package/apps/runtime/dist/db/migrations/tenant/0002_cloudy_firebird.sql +1 -0
- package/apps/runtime/dist/db/migrations/tenant/0003_brown_warbound.sql +52 -0
- package/apps/runtime/dist/db/migrations/tenant/0004_romantic_nocturne.sql +6 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0000_snapshot.json +1323 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0001_snapshot.json +1330 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0002_snapshot.json +1337 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0003_snapshot.json +1605 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0004_snapshot.json +1645 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/_journal.json +41 -0
- package/apps/runtime/dist/db/schema.js +278 -0
- package/apps/runtime/dist/documents/parse.js +230 -0
- package/apps/runtime/dist/engenty/connections-external/build-connector.js +193 -0
- package/apps/runtime/dist/engenty/connections-external/errors.js +11 -0
- package/apps/runtime/dist/engenty/connections-external/import-service.js +270 -0
- package/apps/runtime/dist/engenty/connections-external/importer/classify.js +34 -0
- package/apps/runtime/dist/engenty/connections-external/importer/map-auth.js +185 -0
- package/apps/runtime/dist/engenty/connections-external/importer/normalize-mcp.js +63 -0
- package/apps/runtime/dist/engenty/connections-external/importer/normalize-openapi.js +130 -0
- package/apps/runtime/dist/engenty/connections-external/invoke/http-invoker.js +143 -0
- package/apps/runtime/dist/engenty/connections-external/invoke/mcp-client.js +143 -0
- package/apps/runtime/dist/engenty/connections-external/net/guarded-fetch.js +119 -0
- package/apps/runtime/dist/engenty/connections-external/oauth-dcr.js +88 -0
- package/apps/runtime/dist/engenty/connections-external/registry-client.js +336 -0
- package/apps/runtime/dist/engenty/connections-external/registry-source.js +82 -0
- package/apps/runtime/dist/engenty/connections-external/types.js +7 -0
- package/apps/runtime/dist/engenty/connections-github/connector.js +209 -0
- package/apps/runtime/dist/engenty/connections-google/connectors/calendar.js +359 -0
- package/apps/runtime/dist/engenty/connections-google/connectors/contacts.js +94 -0
- package/apps/runtime/dist/engenty/connections-google/connectors/drive.js +290 -0
- package/apps/runtime/dist/engenty/connections-google/connectors/gmail.js +567 -0
- package/apps/runtime/dist/engenty/connections-google/definitions.js +11 -0
- package/apps/runtime/dist/engenty/connections-google/shared.js +73 -0
- package/apps/runtime/dist/engenty/connections-hubspot/connector.js +140 -0
- package/apps/runtime/dist/engenty/connections-microsoft/action.js +17 -0
- package/apps/runtime/dist/engenty/connections-microsoft/graph.js +114 -0
- package/apps/runtime/dist/engenty/connections-microsoft/onedrive.js +286 -0
- package/apps/runtime/dist/engenty/connections-microsoft/outlook.js +464 -0
- package/apps/runtime/dist/engenty/connections-s3/s3.js +328 -0
- package/apps/runtime/dist/engenty/connections-sdk/files-capability.js +86 -0
- package/apps/runtime/dist/engenty/connections-sdk/oauth2.js +150 -0
- package/apps/runtime/dist/engenty/connections-sdk/registry.js +89 -0
- package/apps/runtime/dist/engenty/connections-sdk/storage-capability.js +84 -0
- package/apps/runtime/dist/engenty/connections-sdk/types.js +30 -0
- package/apps/runtime/dist/engenty/connections-slack/connector.js +360 -0
- package/apps/runtime/dist/engenty/csv-import/csv-matrix.js +178 -0
- package/apps/runtime/dist/engenty/csv-import/import-sources.js +87 -0
- package/apps/runtime/dist/engenty/csv-import/parse-csv.js +129 -0
- package/apps/runtime/dist/engenty/csv-import/serialize-csv.js +20 -0
- package/apps/runtime/dist/engenty/csv-import/types.js +1 -0
- package/apps/runtime/dist/engenty/csv-import/xlsx-workbook.js +159 -0
- package/apps/runtime/dist/engenty/doc-converter/interface.js +9 -0
- package/apps/runtime/dist/engenty/doc-converter/page-break.js +92 -0
- package/apps/runtime/dist/engenty/doc-converter/providers/local/index.js +72 -0
- package/apps/runtime/dist/engenty/document-scanner/schemas/classifier.js +30 -0
- package/apps/runtime/dist/engenty/document-scanner/schemas/index.js +4 -0
- package/apps/runtime/dist/engenty/document-scanner/schemas/invoice.js +73 -0
- package/apps/runtime/dist/engenty/document-scanner/schemas/receipt.js +63 -0
- package/apps/runtime/dist/engenty/document-scanner/schemas/shared.js +40 -0
- package/apps/runtime/dist/engenty/search-index/chunks.js +164 -0
- package/apps/runtime/dist/engenty/search-index/contracts.js +9 -0
- package/apps/runtime/dist/engenty/shims/connections-sdk.js +39 -0
- package/apps/runtime/dist/engenty/shims/plugin-sdk.js +1 -0
- package/apps/runtime/dist/engenty/shims/web-ingest.js +3 -0
- package/apps/runtime/dist/engenty/web-ingest/ssrf.js +277 -0
- package/apps/runtime/dist/engine/asks.js +60 -0
- package/apps/runtime/dist/engine/events.js +46 -0
- package/apps/runtime/dist/engine/input.js +170 -0
- package/apps/runtime/dist/engine/prepare.js +51 -0
- package/apps/runtime/dist/engine/requirements.js +124 -0
- package/apps/runtime/dist/engine/resources.js +89 -0
- package/apps/runtime/dist/engine/runner.js +560 -0
- package/apps/runtime/dist/engine/steps.js +598 -0
- package/apps/runtime/dist/engine/template.js +183 -0
- package/apps/runtime/dist/engine/types.js +3 -0
- package/apps/runtime/dist/env.js +224 -0
- package/apps/runtime/dist/files/blobs.js +22 -0
- package/apps/runtime/dist/files/objects.js +86 -0
- package/apps/runtime/dist/files/storage.js +95 -0
- package/apps/runtime/dist/geocode.js +58 -0
- package/apps/runtime/dist/harness/claude.js +138 -0
- package/apps/runtime/dist/harness/codex.js +228 -0
- package/apps/runtime/dist/harness/cursor.js +93 -0
- package/apps/runtime/dist/harness/env.js +124 -0
- package/apps/runtime/dist/harness/gemini.js +126 -0
- package/apps/runtime/dist/harness/index.js +99 -0
- package/apps/runtime/dist/harness/model.js +267 -0
- package/apps/runtime/dist/harness/prompt.js +121 -0
- package/apps/runtime/dist/harness/terminal.js +193 -0
- package/apps/runtime/dist/harness/types.js +7 -0
- package/apps/runtime/dist/index.js +76 -0
- package/apps/runtime/dist/limits.js +57 -0
- package/apps/runtime/dist/link-preview.js +59 -0
- package/apps/runtime/dist/manage.js +151 -0
- package/apps/runtime/dist/mcp/auth.js +102 -0
- package/apps/runtime/dist/mcp/bridge.js +59 -0
- package/apps/runtime/dist/mcp/handler.js +42 -0
- package/apps/runtime/dist/mcp/scopes.js +5 -0
- package/apps/runtime/dist/mcp/tools.js +401 -0
- package/apps/runtime/dist/media/ffmpeg.js +121 -0
- package/apps/runtime/dist/media/generate.js +120 -0
- package/apps/runtime/dist/media/marking.js +121 -0
- package/apps/runtime/dist/media/transcribe.js +30 -0
- package/apps/runtime/dist/model-errors.js +3 -0
- package/apps/runtime/dist/models.js +489 -0
- package/apps/runtime/dist/plugin.js +61 -0
- package/apps/runtime/dist/render/chromium.js +85 -0
- package/apps/runtime/dist/render/convert.js +161 -0
- package/apps/runtime/dist/render/downloads.js +277 -0
- package/apps/runtime/dist/render/guard.js +25 -0
- package/apps/runtime/dist/routes/api.js +74 -0
- package/apps/runtime/dist/routes/delivery.js +52 -0
- package/apps/runtime/dist/routes/internal.js +49 -0
- package/apps/runtime/dist/routes/marketplace.js +36 -0
- package/apps/runtime/dist/routes/runs.js +805 -0
- package/apps/runtime/dist/routes/studio.js +702 -0
- package/apps/runtime/dist/routes/wizard-stream.js +30 -0
- package/apps/runtime/dist/running.js +39 -0
- package/apps/runtime/dist/sandbox/agentos.js +191 -0
- package/apps/runtime/dist/sandbox/docker.js +77 -0
- package/apps/runtime/dist/sandbox/index.js +30 -0
- package/apps/runtime/dist/sandbox/types.js +1 -0
- package/apps/runtime/dist/secrets/crypto.js +28 -0
- package/apps/runtime/dist/secrets/signing.js +34 -0
- package/apps/runtime/dist/secrets/vault.js +59 -0
- package/apps/runtime/dist/services/architect.js +92 -0
- package/apps/runtime/dist/services/brand.js +20 -0
- package/apps/runtime/dist/services/cloud.js +52 -0
- package/apps/runtime/dist/services/draft-events.js +27 -0
- package/apps/runtime/dist/services/errors.js +24 -0
- package/apps/runtime/dist/services/files.js +129 -0
- package/apps/runtime/dist/services/links.js +16 -0
- package/apps/runtime/dist/services/marketplace.js +292 -0
- package/apps/runtime/dist/services/package.js +202 -0
- package/apps/runtime/dist/services/profile.js +23 -0
- package/apps/runtime/dist/services/project-files.js +266 -0
- package/apps/runtime/dist/services/project-index.js +109 -0
- package/apps/runtime/dist/services/projects.js +181 -0
- package/apps/runtime/dist/services/runs.js +224 -0
- package/apps/runtime/dist/services/shares.js +129 -0
- package/apps/runtime/dist/services/widgets.js +34 -0
- package/apps/runtime/dist/services/wizards.js +342 -0
- package/apps/runtime/dist/settings.js +16 -0
- package/apps/runtime/dist/store/index.js +279 -0
- package/apps/runtime/dist/tenants/control.js +106 -0
- package/apps/runtime/dist/tenants/tenant.js +26 -0
- package/apps/runtime/dist/tools/browser.js +380 -0
- package/apps/runtime/dist/tools/connector.js +204 -0
- package/apps/runtime/dist/tools/index.js +234 -0
- package/apps/runtime/dist/tools/mail.js +104 -0
- package/apps/runtime/dist/tools/net-guard.js +59 -0
- package/apps/runtime/dist/tools/project.js +53 -0
- package/apps/runtime/dist/tools/shared.js +42 -0
- package/apps/runtime/dist/tools/store.js +238 -0
- package/apps/runtime/dist/update.js +118 -0
- package/apps/runtime/dist/widgets/bundle.js +99 -0
- package/apps/runtime/dist/widgets/render.js +312 -0
- package/apps/runtime/dist/widgets/runtime.js +84 -0
- package/apps/runtime/dist/widgets/script.js +30 -0
- package/apps/runtime/dist/widgets/step.js +192 -0
- package/apps/web/dist/ai-labels/ai-black.svg +20 -0
- package/apps/web/dist/ai-labels/ai-generated-black.svg +31 -0
- package/apps/web/dist/ai-labels/ai-generated-white.svg +32 -0
- package/apps/web/dist/ai-labels/ai-modified-black.svg +30 -0
- package/apps/web/dist/ai-labels/ai-modified-white.svg +31 -0
- package/apps/web/dist/ai-labels/ai-white.svg +21 -0
- package/apps/web/dist/assets/ChangelogDialog-O00vEnbm.js +1 -0
- package/apps/web/dist/assets/ChatPanel-CH9ry0Hp.js +1 -0
- package/apps/web/dist/assets/CreditsDialog-DRzecwUw.js +1 -0
- package/apps/web/dist/assets/EditorPage-BRnBf02Q.js +2 -0
- package/apps/web/dist/assets/FlowPreview-DDOj8IAH.js +1 -0
- package/apps/web/dist/assets/HomePage-CAGTTG3N.js +1 -0
- package/apps/web/dist/assets/ImportWizard-0RRrAnX3.js +1 -0
- package/apps/web/dist/assets/LocalRuntime-BrP-ENHg.css +1 -0
- package/apps/web/dist/assets/LocalRuntime-C-TBYrzs.js +16 -0
- package/apps/web/dist/assets/NewWizardPage-kI90h3_9.js +2 -0
- package/apps/web/dist/assets/PublicRunner-CKRDeIVd.js +1 -0
- package/apps/web/dist/assets/RunnerView-Rc4H8wYH.js +2 -0
- package/apps/web/dist/assets/SettingsPage-CESMuZxq.js +2 -0
- package/apps/web/dist/assets/SetupPage-D1rrYU14.js +1 -0
- package/apps/web/dist/assets/SharePage-COTAmOgh.js +1 -0
- package/apps/web/dist/assets/api-BY28cjGY.js +10 -0
- package/apps/web/dist/assets/arrow-left-UpjOBfQp.js +1 -0
- package/apps/web/dist/assets/arrow-right-CucQycEy.js +1 -0
- package/apps/web/dist/assets/changelog-p3wsaDDS.js +1 -0
- package/apps/web/dist/assets/check-Bjx41xbB.js +1 -0
- package/apps/web/dist/assets/createLucideIcon-DBu2Ovxj.js +1 -0
- package/apps/web/dist/assets/definition-cy7uvY5L.js +55 -0
- package/apps/web/dist/assets/engenty-CWIFpgKq.js +1 -0
- package/apps/web/dist/assets/esm-D1OEhjTK.js +7 -0
- package/apps/web/dist/assets/external-link-CRg6DVdO.js +1 -0
- package/apps/web/dist/assets/fluffy-engenty-CJ3wCQgT.js +456 -0
- package/apps/web/dist/assets/index-CQ_q9iMO.css +1 -0
- package/apps/web/dist/assets/index-D0gxh90t.js +10 -0
- package/apps/web/dist/assets/jsx-runtime-Dk72oS4N.js +1 -0
- package/apps/web/dist/assets/meta-BbSdtTUa.js +1 -0
- package/apps/web/dist/assets/mic-CeqQ89Dj.js +1 -0
- package/apps/web/dist/assets/oss-credits-cPuZUFHD.js +1 -0
- package/apps/web/dist/assets/outputs-D6pxH6ve.js +69 -0
- package/apps/web/dist/assets/plus-HA210wXA.js +1 -0
- package/apps/web/dist/assets/preload-helper-CNEI7N0N.js +1 -0
- package/apps/web/dist/assets/qr-scanner-worker.min-CJaXo3yu.js +98 -0
- package/apps/web/dist/assets/qr-scanner.min-C_UI0gH-.js +1 -0
- package/apps/web/dist/assets/type-BzYgVWKL.js +1 -0
- package/apps/web/dist/assets/ui-Ddwl35A6.js +1 -0
- package/apps/web/dist/assets/upload-DsgLfQ3U.js +1 -0
- package/apps/web/dist/assets/video-Dk1fuTDl.js +1 -0
- package/apps/web/dist/assets/wand-sparkles-Bf97fs8T.js +1 -0
- package/apps/web/dist/embed.js +102 -0
- package/apps/web/dist/favicon.svg +1 -0
- package/apps/web/dist/icons/apple-touch-icon.png +0 -0
- package/apps/web/dist/icons/icon-192.png +0 -0
- package/apps/web/dist/icons/icon-512.png +0 -0
- package/apps/web/dist/icons/icon-maskable-512.png +0 -0
- package/apps/web/dist/index.html +46 -0
- package/apps/web/dist/install.sh +532 -0
- package/apps/web/dist/manifest.webmanifest +20 -0
- package/apps/web/dist/sw.js +15 -0
- package/bin/wizards.mjs +13 -0
- package/node_modules/@engenty-wizards/shared/dist/connectors.d.ts +77 -0
- package/node_modules/@engenty-wizards/shared/dist/connectors.js +2 -0
- package/node_modules/@engenty-wizards/shared/dist/definition.d.ts +1415 -0
- package/node_modules/@engenty-wizards/shared/dist/definition.js +762 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-format.d.ts +5 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-format.js +132 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-value.d.ts +11 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-value.js +209 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns.d.ts +532 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns.js +216 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/index.d.ts +3 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/index.js +3 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-lexical.d.ts +14 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-lexical.js +166 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-rank.d.ts +33 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-rank.js +99 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace-entry.d.ts +35 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace-entry.js +86 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace-search.d.ts +20 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace-search.js +133 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace.d.ts +298 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace.js +211 -0
- package/node_modules/@engenty-wizards/shared/dist/merge.d.ts +7 -0
- package/node_modules/@engenty-wizards/shared/dist/merge.js +40 -0
- package/node_modules/@engenty-wizards/shared/dist/projects.d.ts +74 -0
- package/node_modules/@engenty-wizards/shared/dist/projects.js +96 -0
- package/node_modules/@engenty-wizards/shared/dist/run.d.ts +219 -0
- package/node_modules/@engenty-wizards/shared/dist/run.js +1 -0
- package/node_modules/@engenty-wizards/shared/dist/store.d.ts +100 -0
- package/node_modules/@engenty-wizards/shared/dist/store.js +44 -0
- package/node_modules/@engenty-wizards/shared/dist/workspace.d.ts +16 -0
- package/node_modules/@engenty-wizards/shared/dist/workspace.js +51 -0
- package/node_modules/@engenty-wizards/shared/package.json +10 -0
- package/package.json +62 -0
- package/plugin/.claude-plugin/plugin.json +9 -0
- package/plugin/.mcp.json +8 -0
- package/plugin/commands/wizard.md +8 -0
- package/plugin/skills/build-wizard/SKILL.md +27 -0
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
import { anthropic } from "@ai-sdk/anthropic";
|
|
2
|
+
import { isTextMime } from "@engenty-wizards/shared/workspace";
|
|
3
|
+
import { Agent } from "@mastra/core/agent";
|
|
4
|
+
import { createTool } from "@mastra/core/tools";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { connectorsLine, exampleWizard, mcpServersLine, PRINCIPLES, SCHEMA_DOC, WIDGET_GUIDE, } from "../authoring/guide.js";
|
|
7
|
+
import { wizardOpSchema } from "../authoring/ops.js";
|
|
8
|
+
import { importFromRegistry, listConnectors, searchRegistry } from "../connectors/external.js";
|
|
9
|
+
import { attachTools, costOf, gatewayTools, textModel } from "../models.js";
|
|
10
|
+
import { htmlToMarkdown } from "../render/convert.js";
|
|
11
|
+
import { ServiceError } from "../services/errors.js";
|
|
12
|
+
import { deleteFile, listFiles, readFileText, writeFile } from "../services/files.js";
|
|
13
|
+
import { checkDraftWidget } from "../services/widgets.js";
|
|
14
|
+
import { editWizard, ownedWizard, writeDraft } from "../services/wizards.js";
|
|
15
|
+
import { assertPublicUrl, safeFetch } from "../tools/net-guard.js";
|
|
16
|
+
import { runScript } from "../widgets/script.js";
|
|
17
|
+
import { thoughtLine } from "./thought.js";
|
|
18
|
+
const MAX_STEPS = 45;
|
|
19
|
+
function systemPrompt(mcp, connectors) {
|
|
20
|
+
return `You design wizards for "engenty wizards": a page-by-page flow an end user walks through, where AI steps research, write, draw images, render video, build documents, dashboards and interactive widgets, or write into other systems.
|
|
21
|
+
|
|
22
|
+
You talk to the ADMIN who builds the wizard. Answer in the admin's language, briefly and warmly. Never mention JSON, ids, schemas, files or templates to them — talk about pages, questions, steps, the widget and results.
|
|
23
|
+
|
|
24
|
+
${SCHEMA_DOC}
|
|
25
|
+
${PRINCIPLES}
|
|
26
|
+
${WIDGET_GUIDE}
|
|
27
|
+
|
|
28
|
+
${mcpServersLine(mcp)}
|
|
29
|
+
|
|
30
|
+
${connectorsLine(connectors)}
|
|
31
|
+
|
|
32
|
+
Example of a complete wizard:
|
|
33
|
+
\`\`\`json
|
|
34
|
+
${exampleWizard()}
|
|
35
|
+
\`\`\`
|
|
36
|
+
|
|
37
|
+
HOW YOU WORK
|
|
38
|
+
- You change the wizard ONLY through tools: edit_wizard (small ops) or replace_wizard (new or mostly rewritten). Every write returns the validator's issues — fix them before you finish.
|
|
39
|
+
- Widgets and their data live in the workspace: list_files, read_file, write_file, delete_file, download_files. Then check_widget, look at the screenshot, fix, check again.
|
|
40
|
+
- Order: 1. write the wizard's steps, 2. fetch only the reference data the widget truly needs (one download_files call for all of it), 3. write the widget and its sample.json, 4. check_widget and fix, 5. answer. You have about 30 tool calls — never spend them on exploring.
|
|
41
|
+
- Call independent tools in the same step (they run together).
|
|
42
|
+
- Never retype data you downloaded. Reshape it with run_script (output to a file), or let the widget read the raw files with wizard.json() and transform them when it starts.
|
|
43
|
+
- Work in few, purposeful steps: every tool call costs the admin time and credits.
|
|
44
|
+
- Services the wizard should work in for the person: find_connectors, import_connector (it returns the actions), then a connection for it in the wizard. list_connectors shows what the project has.
|
|
45
|
+
- Research what you need to prepare (web_search, web_fetch) — e.g. which lakes, their outlines, a chart library.
|
|
46
|
+
- Finish with one to three sentences to the admin: what you built or changed, and at most one suggestion. If they only asked a question, just answer it.`;
|
|
47
|
+
}
|
|
48
|
+
/** Turns a tool call into the line the admin sees while it runs. */
|
|
49
|
+
function activity(tool, args) {
|
|
50
|
+
const host = (u) => {
|
|
51
|
+
try {
|
|
52
|
+
return new URL(String(u)).hostname;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return "";
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
switch (tool) {
|
|
59
|
+
case "replace_wizard":
|
|
60
|
+
case "edit_wizard":
|
|
61
|
+
return "Baut den Ablauf …";
|
|
62
|
+
case "write_file":
|
|
63
|
+
return args.path ? `Schreibt ${String(args.path)} …` : "Schreibt eine Datei …";
|
|
64
|
+
case "download_files":
|
|
65
|
+
return "Lädt Daten herunter …";
|
|
66
|
+
case "web_fetch":
|
|
67
|
+
return args.url ? `Liest ${host(args.url)} …` : "Liest im Web …";
|
|
68
|
+
case "web_search":
|
|
69
|
+
return "Sucht im Web …";
|
|
70
|
+
case "check_widget":
|
|
71
|
+
return "Testet das Widget …";
|
|
72
|
+
case "run_script":
|
|
73
|
+
return args.output ? `Bereitet ${String(args.output)} vor …` : "Rechnet …";
|
|
74
|
+
case "list_files":
|
|
75
|
+
case "read_file":
|
|
76
|
+
return "Sieht sich die Dateien an …";
|
|
77
|
+
case "delete_file":
|
|
78
|
+
return "Räumt Dateien auf …";
|
|
79
|
+
default:
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/** A tool failure the model can read and fix, instead of a crashed turn. */
|
|
84
|
+
async function attempt(run) {
|
|
85
|
+
try {
|
|
86
|
+
return await run();
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
if (err instanceof ServiceError) {
|
|
90
|
+
return { error: err.message, ...err.data };
|
|
91
|
+
}
|
|
92
|
+
return { error: err.message };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function buildTools(input, resolved, wrote) {
|
|
96
|
+
const { userId, wizardId } = input;
|
|
97
|
+
const signal = input.signal;
|
|
98
|
+
const projectId = async () => (await ownedWizard(userId, wizardId)).projectId;
|
|
99
|
+
const tools = {
|
|
100
|
+
find_connectors: createTool({
|
|
101
|
+
id: "find_connectors",
|
|
102
|
+
description: "Search the integrations registry for a service that can be imported as a connector (from its OpenAPI spec or MCP server). Returns domains with a short description.",
|
|
103
|
+
inputSchema: z.object({ query: z.string().describe("Service name, e.g. Notion") }),
|
|
104
|
+
execute: async ({ query }) => attempt(async () => ({ services: await searchRegistry(query) })),
|
|
105
|
+
}),
|
|
106
|
+
import_connector: createTool({
|
|
107
|
+
id: "import_connector",
|
|
108
|
+
description: "Import a service from the registry into this project as a connector. Returns its id, tool prefix, how people connect (OAuth, API key, none) and its actions with their marks (read / write / destructive). Importing again returns the existing one.",
|
|
109
|
+
inputSchema: z.object({
|
|
110
|
+
domain: z.string().describe("A domain from find_connectors, e.g. notion.com"),
|
|
111
|
+
kind: z
|
|
112
|
+
.enum(["mcp", "openapi"])
|
|
113
|
+
.optional()
|
|
114
|
+
.describe("Default: the service's MCP server if it has one, else its OpenAPI spec."),
|
|
115
|
+
}),
|
|
116
|
+
execute: async ({ domain, kind }) => attempt(async () => {
|
|
117
|
+
const result = await importFromRegistry(userId, await projectId(), { domain, kind });
|
|
118
|
+
wrote();
|
|
119
|
+
return result;
|
|
120
|
+
}),
|
|
121
|
+
}),
|
|
122
|
+
list_connectors: createTool({
|
|
123
|
+
id: "list_connectors",
|
|
124
|
+
description: "The connectors this project has imported, with every action.",
|
|
125
|
+
inputSchema: z.object({}),
|
|
126
|
+
execute: async () => attempt(async () => ({ connectors: await listConnectors(await projectId()) })),
|
|
127
|
+
}),
|
|
128
|
+
replace_wizard: createTool({
|
|
129
|
+
id: "replace_wizard",
|
|
130
|
+
description: "Replace the whole wizard. Use for a new wizard or a rewrite. Returns the validator's issues.",
|
|
131
|
+
inputSchema: z.object({ wizard: z.record(z.string(), z.unknown()) }),
|
|
132
|
+
execute: async ({ wizard }) => attempt(async () => {
|
|
133
|
+
const w = await ownedWizard(userId, wizardId);
|
|
134
|
+
const { issues } = await writeDraft(userId, wizardId, {
|
|
135
|
+
definition: wizard,
|
|
136
|
+
baseRevision: w.revision,
|
|
137
|
+
});
|
|
138
|
+
wrote();
|
|
139
|
+
return { ok: true, issues };
|
|
140
|
+
}),
|
|
141
|
+
}),
|
|
142
|
+
edit_wizard: createTool({
|
|
143
|
+
id: "edit_wizard",
|
|
144
|
+
description: "Change the wizard with ops, applied in order: set_meta, set_lists {lists} and set_connections {connections} (each replaces the whole array), upsert_step (the complete step; replaces the step with that id or inserts it before/after another), remove_step, move_step. Returns the validator's issues.",
|
|
145
|
+
inputSchema: z.object({ ops: z.array(wizardOpSchema).min(1) }),
|
|
146
|
+
execute: async ({ ops }) => attempt(async () => {
|
|
147
|
+
const w = await ownedWizard(userId, wizardId);
|
|
148
|
+
const { issues } = await editWizard(userId, wizardId, { ops, baseRevision: w.revision }, { source: "studio" });
|
|
149
|
+
wrote();
|
|
150
|
+
return { ok: true, issues };
|
|
151
|
+
}),
|
|
152
|
+
}),
|
|
153
|
+
list_files: createTool({
|
|
154
|
+
id: "list_files",
|
|
155
|
+
description: "The files in the wizard's workspace (path, mime, size).",
|
|
156
|
+
inputSchema: z.object({}),
|
|
157
|
+
execute: async () => attempt(async () => (await listFiles(userId, wizardId)).map(({ path, mime, size }) => ({ path, mime, size }))),
|
|
158
|
+
}),
|
|
159
|
+
read_file: createTool({
|
|
160
|
+
id: "read_file",
|
|
161
|
+
description: "Read a workspace file as text.",
|
|
162
|
+
inputSchema: z.object({ path: z.string() }),
|
|
163
|
+
execute: async ({ path }) => attempt(async () => {
|
|
164
|
+
const f = await readFileText(userId, wizardId, path);
|
|
165
|
+
return f.text === null
|
|
166
|
+
? { path: f.path, mime: f.mime, size: f.size, note: "binary file" }
|
|
167
|
+
: {
|
|
168
|
+
path: f.path,
|
|
169
|
+
text: f.text.length > 60_000
|
|
170
|
+
? `${f.text.slice(0, 60_000)}\n…[${f.text.length - 60_000} more characters]`
|
|
171
|
+
: f.text,
|
|
172
|
+
};
|
|
173
|
+
}),
|
|
174
|
+
}),
|
|
175
|
+
write_file: createTool({
|
|
176
|
+
id: "write_file",
|
|
177
|
+
description: "Create or overwrite a text file in the workspace (HTML, JS, CSS, JSON, CSV, SVG). Max 5 MB.",
|
|
178
|
+
inputSchema: z.object({ path: z.string(), content: z.string() }),
|
|
179
|
+
execute: async ({ path, content }) => attempt(async () => {
|
|
180
|
+
const f = await writeFile(userId, wizardId, path, content);
|
|
181
|
+
wrote();
|
|
182
|
+
return { ok: true, path: f.path, size: f.size };
|
|
183
|
+
}),
|
|
184
|
+
}),
|
|
185
|
+
delete_file: createTool({
|
|
186
|
+
id: "delete_file",
|
|
187
|
+
description: "Delete a workspace file.",
|
|
188
|
+
inputSchema: z.object({ path: z.string() }),
|
|
189
|
+
execute: async ({ path }) => attempt(async () => {
|
|
190
|
+
await deleteFile(userId, wizardId, path);
|
|
191
|
+
wrote();
|
|
192
|
+
return { ok: true };
|
|
193
|
+
}),
|
|
194
|
+
}),
|
|
195
|
+
download_files: createTool({
|
|
196
|
+
id: "download_files",
|
|
197
|
+
description: "Download public URLs straight into the workspace — all at once (libraries from cdnjs/jsdelivr, GeoJSON outlines, CSV, images). The content does not pass through you; you get each file's size and first characters. Requests to the same host are spaced one second apart (fair use of OpenStreetMap and others).",
|
|
198
|
+
inputSchema: z.object({
|
|
199
|
+
files: z
|
|
200
|
+
.array(z.object({ url: z.string(), path: z.string() }))
|
|
201
|
+
.min(1)
|
|
202
|
+
.max(40),
|
|
203
|
+
}),
|
|
204
|
+
execute: async ({ files }) => {
|
|
205
|
+
const results = [];
|
|
206
|
+
const lastHit = new Map();
|
|
207
|
+
for (const { url, path } of files) {
|
|
208
|
+
const host = (() => {
|
|
209
|
+
try {
|
|
210
|
+
return new URL(url).hostname;
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
return "";
|
|
214
|
+
}
|
|
215
|
+
})();
|
|
216
|
+
const wait = (lastHit.get(host) ?? 0) + 1000 - Date.now();
|
|
217
|
+
if (wait > 0) {
|
|
218
|
+
await new Promise((r) => setTimeout(r, wait));
|
|
219
|
+
}
|
|
220
|
+
lastHit.set(host, Date.now());
|
|
221
|
+
results.push(await attempt(async () => {
|
|
222
|
+
const res = await safeFetch(url, {
|
|
223
|
+
signal: AbortSignal.any([...(signal ? [signal] : []), AbortSignal.timeout(30_000)]),
|
|
224
|
+
headers: { "user-agent": "engenty-wizards/0.1 (widget builder)" },
|
|
225
|
+
});
|
|
226
|
+
if (!res.ok) {
|
|
227
|
+
return { path, error: `HTTP ${res.status}` };
|
|
228
|
+
}
|
|
229
|
+
const data = new Uint8Array(await res.arrayBuffer());
|
|
230
|
+
const mime = res.headers.get("content-type")?.split(";")[0];
|
|
231
|
+
const f = await writeFile(userId, wizardId, path, data, mime);
|
|
232
|
+
wrote();
|
|
233
|
+
return {
|
|
234
|
+
path: f.path,
|
|
235
|
+
size: f.size,
|
|
236
|
+
start: isTextMime(f.mime) ? Buffer.from(data.slice(0, 160)).toString("utf8") : null,
|
|
237
|
+
};
|
|
238
|
+
}));
|
|
239
|
+
}
|
|
240
|
+
return { results };
|
|
241
|
+
},
|
|
242
|
+
}),
|
|
243
|
+
run_script: createTool({
|
|
244
|
+
id: "run_script",
|
|
245
|
+
description: "Run JavaScript over workspace files in a browser without network — to reshape downloaded data (simplify outlines, merge files, compute bounds or SVG paths) instead of retyping it. The body of an async function: `files` maps each input path to its text; return a string or a JSON value. With `output`, the result is saved as that workspace file.",
|
|
246
|
+
inputSchema: z.object({
|
|
247
|
+
script: z.string(),
|
|
248
|
+
inputs: z.array(z.string()).describe("Workspace paths to pass in `files`."),
|
|
249
|
+
output: z.string().optional(),
|
|
250
|
+
}),
|
|
251
|
+
execute: async ({ script, inputs, output }) => attempt(async () => {
|
|
252
|
+
const files = {};
|
|
253
|
+
for (const path of inputs) {
|
|
254
|
+
const f = await readFileText(userId, wizardId, path);
|
|
255
|
+
if (f.text !== null) {
|
|
256
|
+
files[f.path] = f.text;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
const result = await runScript(script, files);
|
|
260
|
+
const text = typeof result === "string" ? result : JSON.stringify(result);
|
|
261
|
+
if (output) {
|
|
262
|
+
const f = await writeFile(userId, wizardId, output, text ?? "");
|
|
263
|
+
wrote();
|
|
264
|
+
return { ok: true, path: f.path, size: f.size, start: (text ?? "").slice(0, 400) };
|
|
265
|
+
}
|
|
266
|
+
return {
|
|
267
|
+
result: (text ?? "").length > 8000 ? `${text.slice(0, 8000)} …[truncated]` : text,
|
|
268
|
+
};
|
|
269
|
+
}),
|
|
270
|
+
}),
|
|
271
|
+
web_fetch: createTool({
|
|
272
|
+
id: "web_fetch",
|
|
273
|
+
description: "Read a public web page or API response (Markdown/text, first 6000 chars).",
|
|
274
|
+
inputSchema: z.object({ url: z.string() }),
|
|
275
|
+
execute: async ({ url }) => attempt(async () => {
|
|
276
|
+
const safe = await assertPublicUrl(url);
|
|
277
|
+
const res = await safeFetch(safe.toString(), {
|
|
278
|
+
signal: AbortSignal.any([...(signal ? [signal] : []), AbortSignal.timeout(20_000)]),
|
|
279
|
+
headers: { "user-agent": "Mozilla/5.0 (compatible; engenty-wizards/0.1)" },
|
|
280
|
+
});
|
|
281
|
+
const type = res.headers.get("content-type") ?? "";
|
|
282
|
+
const body = await res.text();
|
|
283
|
+
const text = type.includes("html") ? htmlToMarkdown(body) : body;
|
|
284
|
+
return { status: res.status, content: text.slice(0, 6000) };
|
|
285
|
+
}),
|
|
286
|
+
}),
|
|
287
|
+
check_widget: createTool({
|
|
288
|
+
id: "check_widget",
|
|
289
|
+
description: "Load a widget step in a real browser with its sample data (or the data you pass): returns script errors, whether it registered a timeline, and a screenshot you can look at.",
|
|
290
|
+
inputSchema: z.object({
|
|
291
|
+
stepId: z.string(),
|
|
292
|
+
data: z.record(z.string(), z.unknown()).optional(),
|
|
293
|
+
}),
|
|
294
|
+
execute: async ({ stepId, data }) => attempt(async () => {
|
|
295
|
+
const r = await checkDraftWidget(userId, wizardId, stepId, data);
|
|
296
|
+
return {
|
|
297
|
+
errors: r.errors,
|
|
298
|
+
timelineSeconds: r.duration,
|
|
299
|
+
size: r.size,
|
|
300
|
+
bundleBytes: r.bytes,
|
|
301
|
+
screenshot: Buffer.from(r.png).toString("base64"),
|
|
302
|
+
};
|
|
303
|
+
}),
|
|
304
|
+
toModelOutput: (out) => {
|
|
305
|
+
if (!out || out.error || !out.screenshot) {
|
|
306
|
+
return { type: "json", value: out };
|
|
307
|
+
}
|
|
308
|
+
const { screenshot, ...rest } = out;
|
|
309
|
+
return {
|
|
310
|
+
type: "content",
|
|
311
|
+
value: [
|
|
312
|
+
{ type: "text", text: JSON.stringify(rest) },
|
|
313
|
+
{ type: "image-data", data: screenshot, mediaType: "image/png" },
|
|
314
|
+
],
|
|
315
|
+
};
|
|
316
|
+
},
|
|
317
|
+
}),
|
|
318
|
+
};
|
|
319
|
+
if (resolved.vendor === "anthropic") {
|
|
320
|
+
tools.web_search = anthropic.tools.webSearch_20250305({ maxUses: 5 });
|
|
321
|
+
}
|
|
322
|
+
else if (resolved.gateway) {
|
|
323
|
+
tools.web_search = gatewayTools.perplexitySearch({ maxResults: 6 });
|
|
324
|
+
}
|
|
325
|
+
return tools;
|
|
326
|
+
}
|
|
327
|
+
/** One studio turn: the architect reads the draft and its workspace and changes them with tools. */
|
|
328
|
+
export async function runArchitect(input) {
|
|
329
|
+
const w = await ownedWizard(input.userId, input.wizardId);
|
|
330
|
+
const files = await listFiles(input.userId, input.wizardId);
|
|
331
|
+
let changed = false;
|
|
332
|
+
// Building a wizard is the hardest job here: widgets are code.
|
|
333
|
+
const resolved = await textModel("highest");
|
|
334
|
+
const tools = buildTools(input, resolved, () => {
|
|
335
|
+
changed = true;
|
|
336
|
+
});
|
|
337
|
+
attachTools(resolved, tools);
|
|
338
|
+
const agent = new Agent({
|
|
339
|
+
id: "architect",
|
|
340
|
+
name: "Architect",
|
|
341
|
+
// The system prompt is long and identical on every turn: cache it.
|
|
342
|
+
instructions: {
|
|
343
|
+
role: "system",
|
|
344
|
+
content: systemPrompt(input.mcpServers, input.connectors),
|
|
345
|
+
providerOptions: { anthropic: { cacheControl: { type: "ephemeral" } } },
|
|
346
|
+
},
|
|
347
|
+
model: resolved.model,
|
|
348
|
+
tools,
|
|
349
|
+
});
|
|
350
|
+
const context = [
|
|
351
|
+
`Current wizard (revision ${w.revision}):\n\`\`\`json\n${JSON.stringify(w.draft)}\n\`\`\``,
|
|
352
|
+
`Workspace files: ${files.length ? files.map((f) => `${f.path} (${f.size} B)`).join(", ") : "none"}`,
|
|
353
|
+
input.message,
|
|
354
|
+
].join("\n\n");
|
|
355
|
+
const stream = await agent.stream([
|
|
356
|
+
...input.history
|
|
357
|
+
.slice(-10)
|
|
358
|
+
.map((m) => m.role === "user"
|
|
359
|
+
? { role: "user", content: m.content }
|
|
360
|
+
: { role: "assistant", content: m.content }),
|
|
361
|
+
{
|
|
362
|
+
role: "user",
|
|
363
|
+
content: input.images?.length
|
|
364
|
+
? [
|
|
365
|
+
{ type: "text", text: context },
|
|
366
|
+
...input.images.map((i) => ({
|
|
367
|
+
type: "file",
|
|
368
|
+
data: i.data,
|
|
369
|
+
mediaType: i.mime,
|
|
370
|
+
filename: i.path,
|
|
371
|
+
})),
|
|
372
|
+
]
|
|
373
|
+
: context,
|
|
374
|
+
},
|
|
375
|
+
], {
|
|
376
|
+
maxSteps: MAX_STEPS,
|
|
377
|
+
abortSignal: input.signal,
|
|
378
|
+
modelSettings: { maxOutputTokens: 32_000 },
|
|
379
|
+
});
|
|
380
|
+
let reply = "";
|
|
381
|
+
let steps = 0;
|
|
382
|
+
// A big write_file streams its arguments for minutes; name the file as soon as its path arrives.
|
|
383
|
+
const streaming = new Map();
|
|
384
|
+
let reasoning = "";
|
|
385
|
+
let thought = null;
|
|
386
|
+
for await (const chunk of stream.fullStream) {
|
|
387
|
+
const payload = chunk.payload ?? chunk;
|
|
388
|
+
if (chunk.type === "reasoning-start") {
|
|
389
|
+
reasoning = "";
|
|
390
|
+
}
|
|
391
|
+
else if (chunk.type === "reasoning-delta") {
|
|
392
|
+
reasoning += payload.text ?? "";
|
|
393
|
+
const line = thoughtLine(reasoning);
|
|
394
|
+
if (line && line !== thought) {
|
|
395
|
+
thought = line;
|
|
396
|
+
input.onThought?.(line);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
else if (chunk.type === "text-delta") {
|
|
400
|
+
const text = payload.text ?? payload.delta ?? "";
|
|
401
|
+
reply += text;
|
|
402
|
+
input.onText?.(text);
|
|
403
|
+
}
|
|
404
|
+
else if (chunk.type === "tool-call-input-streaming-start") {
|
|
405
|
+
streaming.set(payload.toolCallId, { tool: payload.toolName, args: "", named: false });
|
|
406
|
+
const label = activity(payload.toolName, {});
|
|
407
|
+
if (label) {
|
|
408
|
+
input.onActivity?.(label);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
else if (chunk.type === "tool-call-delta") {
|
|
412
|
+
const s = streaming.get(payload.toolCallId);
|
|
413
|
+
if (s && !s.named) {
|
|
414
|
+
s.args += payload.argsTextDelta ?? "";
|
|
415
|
+
const path = s.args.match(/"path"\s*:\s*"([^"]+)"/)?.[1];
|
|
416
|
+
if (path) {
|
|
417
|
+
s.named = true;
|
|
418
|
+
const label = activity(s.tool, { path });
|
|
419
|
+
if (label) {
|
|
420
|
+
input.onActivity?.(label);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
else if (chunk.type === "tool-call") {
|
|
426
|
+
const label = activity(payload.toolName, (payload.args ?? payload.input ?? {}));
|
|
427
|
+
if (label) {
|
|
428
|
+
input.onActivity?.(label);
|
|
429
|
+
}
|
|
430
|
+
if (payload.toolName === "replace_wizard" || payload.toolName === "edit_wizard") {
|
|
431
|
+
input.onBuilding?.();
|
|
432
|
+
}
|
|
433
|
+
// Keep what it says before and after a tool call apart.
|
|
434
|
+
if (reply.trim() && !reply.endsWith("\n\n")) {
|
|
435
|
+
input.onText?.("\n\n");
|
|
436
|
+
reply += "\n\n";
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
else if (chunk.type === "step-finish") {
|
|
440
|
+
steps += 1;
|
|
441
|
+
}
|
|
442
|
+
else if (chunk.type === "error") {
|
|
443
|
+
throw payload.error ?? new Error("architect stream error");
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
const usage = (await stream.totalUsage) ?? (await stream.usage);
|
|
447
|
+
return {
|
|
448
|
+
reply: reply.trim(),
|
|
449
|
+
changed,
|
|
450
|
+
unfinished: steps >= MAX_STEPS,
|
|
451
|
+
costUsd: costOf(resolved, usage),
|
|
452
|
+
};
|
|
453
|
+
}
|