eve 0.6.0-beta.5 → 0.6.0-beta.7
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/CHANGELOG.md +33 -0
- package/dist/docs/public/advanced/dev-tui.md +16 -1
- package/dist/docs/public/advanced/sessions-runs-and-streaming.md +1 -1
- package/dist/docs/public/connections.mdx +4 -0
- package/dist/docs/public/getting-started.mdx +3 -3
- package/dist/src/chunks/{use-eve-agent-9vL56Fjy.js → use-eve-agent-DCZbkLG7.js} +10 -0
- package/dist/src/chunks/{use-eve-agent-DTWI5Lji.js → use-eve-agent-DoheC4_o.js} +10 -0
- package/dist/src/cli/commands/channel-add-conflicts.d.ts +2 -2
- package/dist/src/cli/commands/channels.d.ts +3 -3
- package/dist/src/cli/commands/channels.js +1 -1
- package/dist/src/cli/commands/setup.d.ts +55 -0
- package/dist/src/cli/commands/setup.js +1 -0
- package/dist/src/cli/dev/repl/repl.js +1 -1
- package/dist/src/cli/dev/tui/agent-header.d.ts +26 -0
- package/dist/src/cli/dev/tui/agent-header.js +1 -0
- package/dist/src/cli/dev/tui/blocks.d.ts +72 -0
- package/dist/src/cli/dev/tui/blocks.js +6 -0
- package/dist/src/cli/dev/tui/errors.d.ts +52 -0
- package/dist/src/cli/dev/tui/errors.js +1 -0
- package/dist/src/cli/dev/tui/line-editor.d.ts +68 -0
- package/dist/src/cli/dev/tui/line-editor.js +1 -0
- package/dist/src/cli/dev/tui/live-region.d.ts +60 -0
- package/dist/src/cli/dev/tui/live-region.js +3 -0
- package/dist/src/cli/dev/tui/markdown.d.ts +0 -13
- package/dist/src/cli/dev/tui/runner.d.ts +77 -22
- package/dist/src/cli/dev/tui/runner.js +1 -1
- package/dist/src/cli/dev/tui/stream-format.d.ts +76 -0
- package/dist/src/cli/dev/tui/stream-format.js +2 -0
- package/dist/src/cli/dev/tui/terminal-renderer.d.ts +21 -69
- package/dist/src/cli/dev/tui/terminal-renderer.js +4 -12
- package/dist/src/cli/dev/tui/terminal-text.d.ts +6 -0
- package/dist/src/cli/dev/tui/terminal-text.js +1 -1
- package/dist/src/cli/dev/tui/test/mock-terminal.d.ts +7 -0
- package/dist/src/cli/dev/tui/test/mock-terminal.js +2 -2
- package/dist/src/cli/dev/tui/theme.d.ts +95 -0
- package/dist/src/cli/dev/tui/theme.js +1 -0
- package/dist/src/cli/dev/tui/tool-format.d.ts +31 -0
- package/dist/src/cli/dev/tui/tool-format.js +2 -0
- package/dist/src/cli/dev/tui/tui.d.ts +9 -12
- package/dist/src/cli/run.js +1 -1
- package/dist/src/client/client.d.ts +11 -1
- package/dist/src/client/client.js +1 -1
- package/dist/src/client/index.d.ts +1 -1
- package/dist/src/client/types.d.ts +161 -0
- package/dist/src/compiler/artifacts.js +1 -1
- package/dist/src/compiler/normalize-sandbox.js +1 -1
- package/dist/src/compiler/workspace-resources.js +1 -1
- package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
- package/dist/src/evals/scorers/autoevals.js +1 -1
- package/dist/src/execution/node-step.js +1 -1
- package/dist/src/execution/sandbox/bindings/local.js +1 -1
- package/dist/src/execution/tool-auth.d.ts +7 -4
- package/dist/src/execution/tool-auth.js +1 -1
- package/dist/src/harness/code-mode.js +1 -1
- package/dist/src/harness/tool-loop.js +1 -1
- package/dist/src/harness/tools.js +1 -1
- package/dist/src/internal/application/cache-metadata.js +1 -1
- package/dist/src/internal/application/compiled-artifacts.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/application/tsconfig-dependencies.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-artifacts.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-source-snapshot-copy.js +1 -1
- package/dist/src/internal/nitro/dev-runtime-source-snapshot.js +1 -1
- package/dist/src/internal/nitro/host/build-application.js +1 -1
- package/dist/src/internal/nitro/host/build-vercel-agent-summary.js +1 -1
- package/dist/src/internal/nitro/host/configure-nitro-routes.js +3 -3
- package/dist/src/internal/nitro/host/create-application-nitro.js +1 -1
- package/dist/src/internal/nitro/host/dev-authored-source-watcher.js +1 -1
- package/dist/src/internal/nitro/host/prepare-application-host.js +1 -1
- package/dist/src/internal/nitro/host/start-production-server.js +1 -1
- package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.d.ts +153 -73
- package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.js +1 -6
- package/dist/src/internal/nitro/routes/info.d.ts +11 -13
- package/dist/src/internal/nitro/routes/info.js +1 -1
- package/dist/src/internal/workflow-bundle/builder-support.js +1 -1
- package/dist/src/internal/workflow-bundle/builder.js +2 -2
- package/dist/src/internal/workflow-bundle/workflow-builders.js +1 -1
- package/dist/src/node_modules/.pnpm/@clack_core@1.3.1/node_modules/@clack/core/dist/index.js +5 -5
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/index.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/checks.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/coerce.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/compat.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/errors.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/external.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/from-json-schema.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/iso.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/parse.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/schemas.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/api.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/checks.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/core.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/doc.js +3 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/errors.js +2 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/index.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/json-schema-generator.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/json-schema-processors.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/json-schema.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/parse.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/regexes.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/registries.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/schemas.js +60 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/to-json-schema.js +3 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/util.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/versions.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/ar.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/az.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/be.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/bg.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/ca.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/cs.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/da.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/de.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/el.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/en.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/eo.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/es.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/fa.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/fi.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/fr-CA.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/fr.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/he.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/hr.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/hu.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/hy.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/id.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/index.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/is.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/it.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/ja.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/ka.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/kh.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/km.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/ko.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/lt.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/mk.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/ms.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/nl.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/no.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/ota.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/pl.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/ps.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/pt.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/ro.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/ru.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/sl.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/sv.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/ta.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/th.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/tr.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/ua.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/uk.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/ur.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/uz.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/vi.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/yo.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/zh-CN.js +1 -0
- package/dist/src/node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/locales/zh-TW.js +1 -0
- package/dist/src/protocol/routes.d.ts +4 -8
- package/dist/src/public/channels/eve.js +1 -1
- package/dist/src/public/next/server.js +1 -1
- package/dist/src/public/nuxt/dev-server.js +1 -1
- package/dist/src/public/sveltekit/dev-server.js +1 -1
- package/dist/src/runtime/connections/scoped-authorization.js +1 -1
- package/dist/src/runtime/framework-channels/index.d.ts +1 -1
- package/dist/src/runtime/framework-tools/connection-search-dynamic.js +1 -1
- package/dist/src/runtime/resolve-agent-graph.js +1 -1
- package/dist/src/runtime/sandbox/keys.js +1 -1
- package/dist/src/setup/append-env.d.ts +21 -0
- package/dist/src/setup/append-env.js +3 -0
- package/dist/src/setup/boxes/add-channels.d.ts +33 -0
- package/dist/src/setup/boxes/add-channels.js +1 -0
- package/dist/src/setup/boxes/add-connections.d.ts +34 -0
- package/dist/src/setup/boxes/add-connections.js +1 -0
- package/dist/src/setup/boxes/apply-ai-gateway-credential.d.ts +28 -0
- package/dist/src/setup/boxes/apply-ai-gateway-credential.js +1 -0
- package/dist/src/setup/boxes/deploy-project.d.ts +30 -0
- package/dist/src/setup/boxes/deploy-project.js +1 -0
- package/dist/src/setup/boxes/detect-ai-gateway.d.ts +10 -0
- package/dist/src/setup/boxes/detect-ai-gateway.js +2 -0
- package/dist/src/setup/boxes/link-project.d.ts +33 -0
- package/dist/src/setup/boxes/link-project.js +1 -0
- package/dist/src/setup/boxes/preflight.d.ts +29 -0
- package/dist/src/setup/boxes/preflight.js +1 -0
- package/dist/src/setup/boxes/resolve-provisioning.d.ts +37 -0
- package/dist/src/setup/boxes/resolve-provisioning.js +1 -0
- package/dist/src/setup/boxes/resolve-target.d.ts +41 -0
- package/dist/src/setup/boxes/resolve-target.js +1 -0
- package/dist/src/setup/boxes/scaffold.d.ts +34 -0
- package/dist/src/setup/boxes/scaffold.js +1 -0
- package/dist/src/setup/boxes/select-channels.d.ts +21 -0
- package/dist/src/setup/boxes/select-channels.js +1 -0
- package/dist/src/setup/boxes/select-chat.d.ts +34 -0
- package/dist/src/setup/boxes/select-chat.js +1 -0
- package/dist/src/setup/boxes/select-model.d.ts +41 -0
- package/dist/src/setup/boxes/select-model.js +1 -0
- package/dist/src/setup/channel-setup-prompter.d.ts +8 -0
- package/dist/src/setup/channel-setup-prompter.js +1 -0
- package/dist/src/setup/gateway-models.d.ts +10 -0
- package/dist/src/setup/gateway-models.js +1 -0
- package/dist/src/setup/headless.d.ts +46 -0
- package/dist/src/setup/headless.js +1 -0
- package/dist/src/setup/index.d.ts +8 -0
- package/dist/src/setup/index.js +1 -0
- package/dist/src/setup/onboarding.d.ts +56 -0
- package/dist/src/setup/onboarding.js +1 -0
- package/dist/src/setup/path-exists.d.ts +1 -0
- package/dist/src/setup/path-exists.js +1 -0
- package/dist/src/setup/prompter.d.ts +107 -0
- package/dist/src/setup/prompter.js +1 -0
- package/dist/src/setup/quit-guard.d.ts +47 -0
- package/dist/src/setup/quit-guard.js +1 -0
- package/dist/src/setup/run-vercel-link.d.ts +10 -0
- package/dist/src/setup/run-vercel-link.js +1 -0
- package/dist/src/setup/runner.d.ts +49 -0
- package/dist/src/setup/runner.js +1 -0
- package/dist/src/setup/scaffold/channels-catalog.d.ts +29 -0
- package/dist/src/setup/scaffold/channels-catalog.js +1 -0
- package/dist/src/setup/scaffold/channels.d.ts +80 -0
- package/dist/src/setup/scaffold/channels.js +7 -0
- package/dist/src/setup/scaffold/cli/channel-add-prompter.d.ts +12 -0
- package/dist/src/setup/scaffold/cli/channel-add-prompter.js +1 -0
- package/dist/src/setup/scaffold/cli/channel-setup-prompter.d.ts +56 -0
- package/dist/src/setup/scaffold/cli/command-output.d.ts +12 -0
- package/dist/src/setup/scaffold/cli/connection-add-prompter.d.ts +44 -0
- package/dist/src/setup/scaffold/cli/connection-add-prompter.js +1 -0
- package/dist/src/setup/scaffold/cli/index.d.ts +7 -0
- package/dist/src/setup/scaffold/cli/index.js +1 -0
- package/dist/src/setup/scaffold/cli/prompt-ui.d.ts +151 -0
- package/dist/src/{packages/eve-scaffold/src → setup/scaffold}/cli/prompt-ui.js +2 -2
- package/dist/src/setup/scaffold/cli/rail-log.d.ts +53 -0
- package/dist/src/{packages/eve-scaffold/src → setup/scaffold}/cli/rail-log.js +1 -1
- package/dist/src/setup/scaffold/cli/select-component.d.ts +67 -0
- package/dist/src/setup/scaffold/cli/select-component.js +1 -0
- package/dist/src/setup/scaffold/cli/select-state.d.ts +60 -0
- package/dist/src/setup/scaffold/connections/catalog.d.ts +118 -0
- package/dist/src/setup/scaffold/connections/catalog.js +1 -0
- package/dist/src/setup/scaffold/connections.d.ts +38 -0
- package/dist/src/setup/scaffold/connections.js +21 -0
- package/dist/src/setup/scaffold/files.d.ts +9 -0
- package/dist/src/setup/scaffold/human-action.d.ts +23 -0
- package/dist/src/setup/scaffold/index.d.ts +7 -0
- package/dist/src/setup/scaffold/index.js +1 -0
- package/dist/src/setup/scaffold/module-files.d.ts +3 -0
- package/dist/src/setup/scaffold/package-json.d.ts +6 -0
- package/dist/src/setup/scaffold/pnpm-workspace.d.ts +3 -0
- package/dist/src/setup/scaffold/primitives/detect-deployment.d.ts +13 -0
- package/dist/src/setup/scaffold/primitives/index.d.ts +3 -0
- package/dist/src/setup/scaffold/primitives/index.js +1 -0
- package/dist/src/setup/scaffold/primitives/pnpm-invocation.d.ts +12 -0
- package/dist/src/setup/scaffold/primitives/process-output.d.ts +19 -0
- package/dist/src/setup/scaffold/primitives/run-pnpm.d.ts +17 -0
- package/dist/src/{packages/eve-scaffold/src → setup/scaffold}/primitives/run-pnpm.js +1 -1
- package/dist/src/setup/scaffold/primitives/run-vercel.d.ts +66 -0
- package/dist/src/setup/scaffold/primitives/run-vercel.js +1 -0
- package/dist/src/setup/scaffold/primitives/update-connection-connector.d.ts +8 -0
- package/dist/src/setup/scaffold/primitives/update-slack-channel.d.ts +6 -0
- package/dist/src/setup/scaffold/project.d.ts +21 -0
- package/dist/src/setup/scaffold/project.js +80 -0
- package/dist/src/setup/scaffold/steps/deploy-to-vercel.d.ts +17 -0
- package/dist/src/setup/scaffold/steps/index.d.ts +4 -0
- package/dist/src/setup/scaffold/steps/index.js +1 -0
- package/dist/src/setup/scaffold/steps/project-resolution.d.ts +19 -0
- package/dist/src/{packages/eve-scaffold/src → setup/scaffold}/steps/project-resolution.js +1 -1
- package/dist/src/setup/scaffold/steps/run-add-connection.d.ts +40 -0
- package/dist/src/setup/scaffold/steps/run-add-connection.js +1 -0
- package/dist/src/setup/scaffold/steps/run-add-to-agent.d.ts +81 -0
- package/dist/src/setup/scaffold/steps/run-add-to-agent.js +2 -0
- package/dist/src/setup/scaffold/steps/setup-connection.d.ts +65 -0
- package/dist/src/{packages/eve-scaffold/src → setup/scaffold}/steps/setup-connection.js +1 -1
- package/dist/src/setup/scaffold/steps/setup-slackbot.d.ts +63 -0
- package/dist/src/{packages/eve-scaffold/src → setup/scaffold}/steps/setup-slackbot.js +1 -1
- package/dist/src/setup/scaffold/web-template.d.ts +80 -0
- package/dist/src/setup/state.d.ts +142 -0
- package/dist/src/setup/state.js +1 -0
- package/dist/src/setup/step.d.ts +54 -0
- package/dist/src/setup/step.js +1 -0
- package/dist/src/setup/vercel-project.d.ts +95 -0
- package/dist/src/setup/vercel-project.js +1 -0
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.js +1 -1
- package/dist/src/vue/index.js +1 -1
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/package.json +37 -4
- package/dist/src/cli/dev/tui/layout.d.ts +0 -24
- package/dist/src/cli/dev/tui/layout.js +0 -3
- package/dist/src/cli/dev/tui/terminal-frame-buffer.d.ts +0 -21
- package/dist/src/cli/dev/tui/terminal-frame-buffer.js +0 -2
- package/dist/src/packages/eve-scaffold/src/channels-catalog.js +0 -1
- package/dist/src/packages/eve-scaffold/src/channels.js +0 -7
- package/dist/src/packages/eve-scaffold/src/cli/channel-add-prompter.js +0 -1
- package/dist/src/packages/eve-scaffold/src/cli/connection-add-prompter.js +0 -1
- package/dist/src/packages/eve-scaffold/src/cli/index.js +0 -1
- package/dist/src/packages/eve-scaffold/src/cli/select-component.js +0 -1
- package/dist/src/packages/eve-scaffold/src/connections/catalog.js +0 -1
- package/dist/src/packages/eve-scaffold/src/connections.js +0 -21
- package/dist/src/packages/eve-scaffold/src/index.js +0 -1
- package/dist/src/packages/eve-scaffold/src/primitives/index.js +0 -1
- package/dist/src/packages/eve-scaffold/src/primitives/run-vercel.js +0 -1
- package/dist/src/packages/eve-scaffold/src/project.js +0 -1
- package/dist/src/packages/eve-scaffold/src/steps/index.js +0 -1
- package/dist/src/packages/eve-scaffold/src/steps/run-add-connection.js +0 -1
- package/dist/src/packages/eve-scaffold/src/steps/run-add-to-agent.js +0 -2
- /package/dist/src/{packages/eve-scaffold/src → setup/scaffold}/cli/channel-setup-prompter.js +0 -0
- /package/dist/src/{packages/eve-scaffold/src → setup/scaffold}/cli/command-output.js +0 -0
- /package/dist/src/{packages/eve-scaffold/src → setup/scaffold}/cli/select-state.js +0 -0
- /package/dist/src/{packages/eve-scaffold/src → setup/scaffold}/files.js +0 -0
- /package/dist/src/{packages/eve-scaffold/src → setup/scaffold}/human-action.js +0 -0
- /package/dist/src/{packages/eve-scaffold/src → setup/scaffold}/module-files.js +0 -0
- /package/dist/src/{packages/eve-scaffold/src → setup/scaffold}/package-json.js +0 -0
- /package/dist/src/{packages/eve-scaffold/src → setup/scaffold}/pnpm-workspace.js +0 -0
- /package/dist/src/{packages/eve-scaffold/src → setup/scaffold}/primitives/detect-deployment.js +0 -0
- /package/dist/src/{packages/eve-scaffold/src → setup/scaffold}/primitives/pnpm-invocation.js +0 -0
- /package/dist/src/{packages/eve-scaffold/src → setup/scaffold}/primitives/process-output.js +0 -0
- /package/dist/src/{packages/eve-scaffold/src → setup/scaffold}/primitives/update-connection-connector.js +0 -0
- /package/dist/src/{packages/eve-scaffold/src → setup/scaffold}/primitives/update-slack-channel.js +0 -0
- /package/dist/src/{packages/eve-scaffold/src → setup/scaffold}/steps/deploy-to-vercel.js +0 -0
- /package/dist/src/{packages/eve-scaffold/src → setup/scaffold}/web-template.js +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# eve
|
|
2
2
|
|
|
3
|
+
## 0.6.0-beta.7
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- edf9f1a: Redesign the `eve dev` terminal UI and add `Client.info()`.
|
|
8
|
+
|
|
9
|
+
The TUI now streams its transcript into the terminal's native scrollback instead of a bordered alt-screen, so scrolling, copy/paste, and the transcript all survive after you exit. The visual language follows the Vercel / Next.js CLI: a monochrome base with the `▲` brand mark, colored gutter glyphs per speaker, the `dots` spinner, and status icons (`✓` done, `⨯` error). Tool calls collapse to a one-line summary (`✓ get_weather city="SF" → 73°F`) that expands under `--tools full`, subagent work is indented beneath a `◆` header, and a startup header prints the connected agent's model, instructions, tools, skills, and subagents. Subagents now default to `auto-collapsed`.
|
|
10
|
+
|
|
11
|
+
The prompt input gains shell-style editing: `↑`/`↓` cycle through your previously sent messages, `←`/`→`/Home/End/`Ctrl+A`/`Ctrl+E` move the caret, and `Ctrl+U`/`Ctrl+K`/`Ctrl+W` kill the line/word. Escape sequences that arrive split across reads (common with PTYs) are reassembled, and pasted text is sanitized of stray control bytes.
|
|
12
|
+
|
|
13
|
+
Failures read more cleanly: a terminal `session.failed` (or a dead-socket transport error) no longer leaves you stuck — the TUI starts a fresh session before the next prompt and notes it inline, so you can keep going. A failure cascade (`step.failed` → `turn.failed` → `session.failed`) renders one error block instead of three, and code bugs escaping user code show their stack trace dim beneath the headline (capped to a dozen lines; recognized provider/config failures keep their curated one-line summary). Error blocks no longer double-print a `Code: Code:` prefix and render docs links in cyan, and denied tool approvals settle to a `→ denied` line instead of a frozen `?`.
|
|
14
|
+
|
|
15
|
+
Captured server `stdout`/`stderr` renders as quiet, indented log runs: consecutive lines from the same source coalesce behind one `stdout ·` / `stderr ·` label with a hanging indent, runs get a blank line of breathing room on both sides, and nothing is ever truncated — a transcript can't be clicked open, so the full output is always shown.
|
|
16
|
+
|
|
17
|
+
`Client.info()` fetches the agent inspection payload (`GET /eve/v1/info`) — model id, instructions source, tools, skills, subagents, schedules, and sandbox — for both local and remote targets, returning the new `AgentInfoResult` type.
|
|
18
|
+
|
|
19
|
+
## 0.6.0-beta.6
|
|
20
|
+
|
|
21
|
+
### Minor Changes
|
|
22
|
+
|
|
23
|
+
- ed176f9: Adds `eve setup`: in a fresh directory it runs the same guided onboarding as `create-eve` (name, Vercel project, model, channels, deploy); inside an existing agent it runs in-project setup. The onboarding flow now lives in the eve package as reusable setup boxes with split interactive/headless faces, and `create-eve` drives that shared flow, so the wizard behaves identically from either entry point.
|
|
24
|
+
|
|
25
|
+
### Patch Changes
|
|
26
|
+
|
|
27
|
+
- 5e87d70: Per-tool interactive authorization never leaks a raw `Required` error into
|
|
28
|
+
the model. When a tool's `auth` strategy is interactive but no callback URL
|
|
29
|
+
can be minted for the run, the tool now fails with a classified
|
|
30
|
+
`ConnectionAuthorizationFailedError` (`reason: "authorization_callback_unavailable"`,
|
|
31
|
+
non-retryable) instead of rethrowing the raw authorization error — which the
|
|
32
|
+
model would otherwise surface as a sign-in URL and loop on. Non-interactive
|
|
33
|
+
strategies still rethrow their original error, since they have no consent
|
|
34
|
+
flow to park on.
|
|
35
|
+
|
|
3
36
|
## 0.6.0-beta.5
|
|
4
37
|
|
|
5
38
|
### Patch Changes
|
|
@@ -9,7 +9,22 @@ description: "Drive an Eve agent locally in an interactive terminal UI: chat, st
|
|
|
9
9
|
eve dev
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
On startup the TUI prints a header for the connected agent — the model, instructions prompt, and the tools, skills, and subagents it has available:
|
|
13
|
+
|
|
14
|
+
```text
|
|
15
|
+
▲ Weather Agent
|
|
16
|
+
· Model openai/gpt-5
|
|
17
|
+
· Instructions agent/instructions.md
|
|
18
|
+
· Tools get_weather, get_forecast, geocode
|
|
19
|
+
· Subagents researcher
|
|
20
|
+
· Server http://localhost:3000
|
|
21
|
+
|
|
22
|
+
Type to chat · ↑ history · /new reset session · /exit quit · Ctrl+C interrupt
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
From there the conversation streams straight into your terminal's normal scrollback — your prompts, the agent's replies, reasoning, tool calls, nested subagents, connection-authorization prompts, and any captured `stdout`/`stderr` — so you keep native scrolling, copy/paste, and a transcript that persists after you exit. Each turn is rendered without boxes: a colored gutter glyph marks who's speaking, tool calls collapse to a one-line summary (`✓ get_weather city="SF" → 73°F`), and a subagent's work is indented beneath its `◆` header. A sticky line at the bottom shows the input prompt or the live status (spinner, token usage). Press `Enter` to send; `Ctrl+C` interrupts a running turn or quits at the prompt. Two slash commands: `/new` starts a fresh session and `/exit` quits.
|
|
26
|
+
|
|
27
|
+
The prompt input behaves like a shell line editor: `↑`/`↓` cycle through the messages you've sent this session, `←`/`→`, Home/End, and `Ctrl+A`/`Ctrl+E` move the caret, and `Ctrl+U`/`Ctrl+K`/`Ctrl+W` kill the line, the rest of the line, or the previous word. If a turn fails terminally — the server session dies or the connection drops — the TUI starts a fresh session and notes it inline so you can keep going (server-side context resets with the old session). Errors render compactly, with docs links highlighted, and a code bug escaping your agent's own code shows its stack trace dim beneath the error headline. Captured server `stdout`/`stderr` renders as dim, indented log runs behind a `│` rule — consecutive lines from the same source share one label, and nothing is ever hidden.
|
|
13
28
|
|
|
14
29
|
The agent will sometimes need something from you, and the TUI asks inline. Tool approvals are a `y`/`n`. Option questions let you pick with `↑`/`↓` and `Enter`, or you can type a freeform answer. If a tool needs an authorized [connection](../connections), the URL shows up right in the transcript, and the turn picks back up once you've finished the flow.
|
|
15
30
|
|
|
@@ -100,7 +100,7 @@ Start with the [TypeScript Client](../client/overview) guide. It covers basic us
|
|
|
100
100
|
|
|
101
101
|
## Inspect the agent over HTTP
|
|
102
102
|
|
|
103
|
-
`GET /eve/v1/info` returns a JSON inspection
|
|
103
|
+
`GET /eve/v1/info` returns a JSON inspection snapshot for the running agent: model, instructions, authored and framework tools, skills, channels, schedules, subagents, sandbox, connections, hooks, workflow, and workspace metadata. Local development accepts loopback requests; deployed Vercel targets require the route's OIDC auth.
|
|
104
104
|
|
|
105
105
|
```bash
|
|
106
106
|
curl http://127.0.0.1:3000/eve/v1/info
|
|
@@ -205,6 +205,10 @@ async execute(_input, ctx) {
|
|
|
205
205
|
}
|
|
206
206
|
```
|
|
207
207
|
|
|
208
|
+
### Authorization and approval together
|
|
209
|
+
|
|
210
|
+
A tool can require both sign-in (`auth`) and a human approval. Today the model's approval gate runs before the tool's `execute`, so the order the user sees is **approve, then sign in**. Eve records the approval on session state the moment it's granted, and that record survives the sign-in park — so when the turn resumes after authorization, the tool is not put through approval a second time. You get one approval and one sign-in, never a double prompt.
|
|
211
|
+
|
|
208
212
|
## What to read next
|
|
209
213
|
|
|
210
214
|
- [Integrations](/integrations): browse every channel and connection Eve ships, in one gallery.
|
|
@@ -155,9 +155,9 @@ If a coding agent (Claude Code, Cursor, and the like) is doing the setup, hand i
|
|
|
155
155
|
|
|
156
156
|
<CopyPrompt text="Set up an Eve agent for the user. Eve is a filesystem-first TypeScript framework for durable agents, published as the npm package eve. Read its docs: once eve is installed they are bundled in the package at node_modules/eve/dist/docs/public; before eve is installed, read the published Introduction and Getting Started pages. If the project has no Eve app, scaffold one with `pnpm create eve@beta`; to add Eve to an existing app, run `pnpm add eve@beta`. Make sure agent/agent.ts (which sets the model) and agent/instructions.md exist, then add a first typed tool at agent/tools/get_weather.ts using defineTool from eve/tools with a Zod inputSchema and an inline execute. Run it locally with `pnpm dev` (or `eve dev`), then exercise the HTTP API: create a session with POST /eve/v1/session, attach to GET /eve/v1/session/:id/stream, and send a follow-up with the returned continuationToken. Verify with the project's typecheck, adapt model and provider choices to the project, and do not commit unless the user asks.">
|
|
157
157
|
Set up an Eve agent: read the Eve docs (bundled at node_modules/eve/dist/docs/public once eve is
|
|
158
|
-
installed), scaffold with `pnpm create eve@beta` (or `pnpm add eve@beta` in an existing app), add
|
|
159
|
-
tool at agent/tools/get_weather.ts, run it with `pnpm dev`, then create a session, stream
|
|
160
|
-
send a follow-up.
|
|
158
|
+
installed), scaffold with `pnpm create eve@beta` (or `pnpm add eve@beta` in an existing app), add
|
|
159
|
+
a typed tool at agent/tools/get_weather.ts, run it with `pnpm dev`, then create a session, stream
|
|
160
|
+
it, and send a follow-up.
|
|
161
161
|
</CopyPrompt>
|
|
162
162
|
|
|
163
163
|
Once `eve` is a dependency, the full docs are bundled in the package, so the agent can read them locally without fetching anything:
|
|
@@ -434,6 +434,16 @@ var Client = class {
|
|
|
434
434
|
}
|
|
435
435
|
return await response.json();
|
|
436
436
|
}
|
|
437
|
+
async info() {
|
|
438
|
+
const url = createClientUrl(this.#host, EVE_INFO_ROUTE_PATH);
|
|
439
|
+
const headers = await this.#resolveHeaders();
|
|
440
|
+
const response = await fetch(url, { headers });
|
|
441
|
+
if (!response.ok) {
|
|
442
|
+
const body = await response.text();
|
|
443
|
+
throw new ClientError(response.status, body);
|
|
444
|
+
}
|
|
445
|
+
return await response.json();
|
|
446
|
+
}
|
|
437
447
|
session(state) {
|
|
438
448
|
let resolved;
|
|
439
449
|
if (typeof state === "string") resolved = {
|
|
@@ -434,6 +434,16 @@ var Client = class {
|
|
|
434
434
|
}
|
|
435
435
|
return await response.json();
|
|
436
436
|
}
|
|
437
|
+
async info() {
|
|
438
|
+
const url = createClientUrl(this.#host, EVE_INFO_ROUTE_PATH);
|
|
439
|
+
const headers = await this.#resolveHeaders();
|
|
440
|
+
const response = await fetch(url, { headers });
|
|
441
|
+
if (!response.ok) {
|
|
442
|
+
const body = await response.text();
|
|
443
|
+
throw new ClientError(response.status, body);
|
|
444
|
+
}
|
|
445
|
+
return await response.json();
|
|
446
|
+
}
|
|
437
447
|
session(state) {
|
|
438
448
|
let resolved;
|
|
439
449
|
if (typeof state === "string") resolved = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ChannelKind } from "
|
|
2
|
-
import type { DisabledChannelReasons } from "
|
|
1
|
+
import type { ChannelKind } from "#setup/scaffold/index.js";
|
|
2
|
+
import type { DisabledChannelReasons } from "#setup/scaffold/cli/index.js";
|
|
3
3
|
/**
|
|
4
4
|
* Existing authored registrations that affect the scaffolded channel picker
|
|
5
5
|
* or would conflict with a generated channel module.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type AddToAgentState, type DeployProjectOptions, type RunAddToAgentOptions } from "
|
|
2
|
-
import { type ChannelAddPrompter } from "
|
|
3
|
-
import { type DeploymentInfo } from "
|
|
1
|
+
import { type AddToAgentState, type DeployProjectOptions, type RunAddToAgentOptions } from "#setup/scaffold/steps/index.js";
|
|
2
|
+
import { type ChannelAddPrompter } from "#setup/scaffold/cli/index.js";
|
|
3
|
+
import { type DeploymentInfo } from "#setup/scaffold/primitives/index.js";
|
|
4
4
|
export interface CliLogger {
|
|
5
5
|
error(message: string): void;
|
|
6
6
|
log(message: string): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{assertCanAddSelectedChannels,inspectExistingChannelRegistrations}from"./channel-add-conflicts.js";import{isEveProject
|
|
1
|
+
import{assertCanAddSelectedChannels,inspectExistingChannelRegistrations}from"./channel-add-conflicts.js";import{isEveProject,listAuthoredChannels}from"#setup/scaffold/index.js";import{createAddToAgentState,deployProject,runAddToAgent}from"#setup/scaffold/steps/index.js";import{ChannelAddCancelledError,createChannelAddPrompter}from"#setup/scaffold/cli/index.js";import{detectDeployment}from"#setup/scaffold/primitives/index.js";const NOT_AN_AGENT_MESSAGE="No Eve agent in this directory. Run `pnpm create eve@beta`, then run this command from inside the new project.",KNOWN_CHANNEL_KINDS=[`slack`,`web`];function isChannelKind(e){return KNOWN_CHANNEL_KINDS.includes(e)}function parseChannelKind(e){if(!isChannelKind(e))throw Error(`Unknown channel kind "${e}". Known: ${KNOWN_CHANNEL_KINDS.join(`, `)}.`);return e}const defaultChannelsAddDependencies={detectDeployment,deployProject,runAddToAgent};async function runAddChannelsFlow(n,r,a,o){if(r===void 0&&(a.yes||!process.stdin.isTTY||!process.stdout.isTTY))throw Error(`Pass a channel kind: \`eve channels add <${KNOWN_CHANNEL_KINDS.join(`|`)}>\`.`);let s=o.createPrompter?.()??createChannelAddPrompter();s.intro(`Add channels to your Eve agent`),s.log.message(`Checking the current Vercel project...`);let c=createAddToAgentState(await o.detectDeployment(n)),l;function inspectRegistrations(){return l===void 0&&(s.log.message(`Inspecting existing channel registrations...`),l=inspectExistingChannelRegistrations(n)),l}let u=r===void 0?(await inspectRegistrations()).disabledChannelReasons:void 0;c=await o.runAddToAgent({prompter:s,projectPath:n,state:c,presetChannels:r===void 0?void 0:[r],presetCreateSlackbot:a.yes?!0:void 0,disabledChannelReasons:u,force:a.force,validateSelectedChannels:async t=>{!t.includes(`web`)&&!t.includes(`slack`)||assertCanAddSelectedChannels(t,await inspectRegistrations())}}),c=await o.deployProject({prompter:s,projectPath:n,state:c}),s.outro(c.channels.length===0?`No channels added.`:`Channels added.`)}async function runChannelsAddCommand(e,t,r,i=defaultChannelsAddDependencies){if(!await isEveProject(t)){e.error(NOT_AN_AGENT_MESSAGE),process.exitCode=1;return}try{await runAddChannelsFlow(t,r.kind===void 0?void 0:parseChannelKind(r.kind),r.options,i)}catch(t){if(t instanceof ChannelAddCancelledError)return;e.error(t instanceof Error?t.message:String(t)),process.exitCode=1}}async function runChannelsListCommand(e,t,i){if(!await isEveProject(t)){e.error(NOT_AN_AGENT_MESSAGE),process.exitCode=1;return}let a=await listAuthoredChannels(t);if(i.json){e.log(JSON.stringify({channels:a},null,2));return}if(a.length===0){e.log("No channels defined. Run `eve channels add` to add one.");return}for(let t of a)e.log(t)}export{runChannelsAddCommand,runChannelsListCommand};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type DeploymentInfo } from "#setup/scaffold/primitives/index.js";
|
|
2
|
+
import { type Prompter } from "#setup/prompter.js";
|
|
3
|
+
import { type ArgsHeadlessAiGateway, type ArgsHeadlessProject, type ChannelKind, type ChatPreference } from "#setup/state.js";
|
|
4
|
+
export interface SetupCliLogger {
|
|
5
|
+
error(message: string): void;
|
|
6
|
+
log(message: string): void;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Preset answers for a headless `eve setup` run. They mirror the create flow's
|
|
10
|
+
* preset options so a headless onboarding run is fully determined by its
|
|
11
|
+
* inputs; each field is threaded into the matching onboarding box option.
|
|
12
|
+
*/
|
|
13
|
+
export interface SetupCommandPresets {
|
|
14
|
+
presetName?: string;
|
|
15
|
+
presetModel?: string;
|
|
16
|
+
presetChannels?: ChannelKind[];
|
|
17
|
+
presetCreateSlackbot?: boolean;
|
|
18
|
+
presetNoDeploy?: boolean;
|
|
19
|
+
overwriteExisting?: boolean;
|
|
20
|
+
presetConnections?: string[];
|
|
21
|
+
presetChatPreference?: ChatPreference;
|
|
22
|
+
}
|
|
23
|
+
export interface SetupCommandOptions {
|
|
24
|
+
/**
|
|
25
|
+
* Programmatic-only for now: the `eve setup` CLI registers no headless flags,
|
|
26
|
+
* so a headless run is only reachable through this API with presets that
|
|
27
|
+
* answer every decision. The CLI fails fast on a non-interactive terminal
|
|
28
|
+
* instead of silently entering a headless run that cannot succeed.
|
|
29
|
+
*/
|
|
30
|
+
headless?: boolean;
|
|
31
|
+
/** Override for the scaffolded `eve` dependency version. Defaults to "beta",
|
|
32
|
+
* matching the create flow; ai/zod/tsgo come from build-stamped defaults. */
|
|
33
|
+
evePackageVersion?: string;
|
|
34
|
+
presets?: SetupCommandPresets;
|
|
35
|
+
/** Headless-only Vercel provisioning flags, mirroring the create flow. */
|
|
36
|
+
provisioning?: {
|
|
37
|
+
project: ArgsHeadlessProject;
|
|
38
|
+
aiGateway: ArgsHeadlessAiGateway;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export interface SetupCommandDependencies {
|
|
42
|
+
createPrompter: () => Prompter;
|
|
43
|
+
detectDeployment(projectPath: string): Promise<DeploymentInfo>;
|
|
44
|
+
isEveProject(projectPath: string): Promise<boolean>;
|
|
45
|
+
hasInteractiveTerminal(): boolean;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The unified `eve setup` entry. In a directory that is not yet an Eve project
|
|
49
|
+
* it runs the SAME onboarding composition as `pnpm create eve`, scaffolding in
|
|
50
|
+
* place; inside an existing project it runs in-project setup: the channel
|
|
51
|
+
* interview, then channel scaffolding, then deploy, against the detected
|
|
52
|
+
* on-disk project link. Both compose the shared boxes through the shared
|
|
53
|
+
* runner.
|
|
54
|
+
*/
|
|
55
|
+
export declare function runSetupCommand(logger: SetupCliLogger, appRoot: string, options: SetupCommandOptions, dependencies?: SetupCommandDependencies): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{basename}from"node:path";import{isEveProject}from"#setup/scaffold/index.js";import{createAddToAgentState}from"#setup/scaffold/steps/index.js";import{detectDeployment}from"#setup/scaffold/primitives/index.js";import{addChannels}from"#setup/boxes/add-channels.js";import{deployProject as deployProject$1}from"#setup/boxes/deploy-project.js";import{selectChannels}from"#setup/boxes/select-channels.js";import{composeOnboardingBoxes}from"#setup/onboarding.js";import{createPrompter}from"#setup/prompter.js";import{runHeadless,runInteractive}from"#setup/runner.js";import{createDefaultSetupState,snapshotSetupState}from"#setup/state.js";const defaultDependencies={createPrompter,detectDeployment,isEveProject,hasInteractiveTerminal:()=>!!(process.stdin.isTTY&&process.stdout.isTTY)};async function runSetupCommand(t,n,r,i=defaultDependencies){let a=!await i.isEveProject(n),o=r.evePackageVersion??`beta`,s=r.presets??{},c=r.headless!==!0;if(c&&!i.hasInteractiveTerminal()){t.error("eve setup is interactive and needs a terminal. For automation, use `create-eve --headless` to scaffold a new agent or `eve channels add` inside an existing project."),process.exitCode=1;return}let l=i.createPrompter(),u={write:e=>l.log.message(e)};l.intro(a?`Create a new Eve agent`:`Set up your Eve agent`);let d=a?`Agent created.`:`Setup complete.`,f,p;a?(f=createDefaultSetupState(),p=composeOnboardingBoxes({prompter:l,presetName:s.presetName,presetModel:s.presetModel,presetChannels:s.presetChannels,presetConnections:s.presetConnections,presetCreateSlackbot:s.presetCreateSlackbot,provisioning:r.provisioning,presetChatPreference:s.presetChatPreference??`skip`,targetDirectory:n,inPlace:!0,overwriteExisting:s.overwriteExisting,presetNoDeploy:s.presetNoDeploy,headless:!c,evePackageVersion:o})):(l.log.message(`Checking the current Vercel project...`),f={...createDefaultSetupState(),...createAddToAgentState(await i.detectDeployment(n)),agentName:basename(n),projectPath:{kind:`resolved`,inPlace:!0,path:n}},p=[selectChannels({prompter:l,presetChannels:s.presetChannels}),addChannels({prompter:l,evePackageVersion:o,presetCreateSlackbot:s.presetCreateSlackbot}),deployProject$1({prompter:l,skip:s.presetNoDeploy})]);try{if(c){let e=await runInteractive(p,f,u,{snapshot:snapshotSetupState});l.outro(e.kind===`cancelled`?`Cancelled.`:d);return}await runHeadless(p,f,u,{snapshot:snapshotSetupState}),l.outro(d)}catch(e){t.error(e instanceof Error?e.message:String(e)),process.exitCode=1}}export{runSetupCommand};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{EVE_CONTINUE_SESSION_ROUTE_PATTERN,EVE_CREATE_SESSION_ROUTE_PATH,EVE_MESSAGE_STREAM_ROUTE_PATTERN,createEveMessageStreamRoutePath}from"#protocol/routes.js";import{
|
|
1
|
+
import{EVE_CONTINUE_SESSION_ROUTE_PATTERN,EVE_CREATE_SESSION_ROUTE_PATH,EVE_MESSAGE_STREAM_ROUTE_PATTERN,createEveMessageStreamRoutePath}from"#protocol/routes.js";import{createCliTheme,renderCliBanner,renderCliSection,renderCliSpeakerLine,renderCliTaggedLine}from"#cli/ui/output.js";import{createInterface,emitKeypressEvents}from"node:readline";import{openStreamIterable}from"#client/open-stream.js";import{isCurrentTurnBoundaryEvent}from"#protocol/message.js";import{toErrorMessage}from"#shared/errors.js";import{createDevelopmentRequestHeadersAsync}from"#services/dev-client/request-headers.js";import{extractCurrentTurnBoundaryEvent}from"#services/dev-client/stream.js";import{resolveDevelopmentServerResourceUrl}from"#services/dev-client/url.js";import{formatVercelAuthChallengeMessage,isVercelAuthChallenge}from"#services/dev-client/vercel-auth-error.js";import{createDevClient}from"#services/dev-client.js";import{parseDevReplInput}from"#cli/dev/repl/input.js";import{ESCAPED_RUNTIME_INPUT_PROMPT,extractPendingRuntimeInputRequests,promptForRuntimeInputRequests}from"#cli/dev/repl/input-requests.js";import{createDevelopmentTerminal}from"#cli/dev/repl/terminal.js";function renderConnectionRows(r){let i=[{label:`Server`,tone:`info`,value:r.serverUrl},{label:`Create`,tone:`info`,value:`POST ${EVE_CREATE_SESSION_ROUTE_PATH}`},{label:`Continue`,tone:`info`,value:`POST ${EVE_CONTINUE_SESSION_ROUTE_PATTERN}`},{label:`Stream`,tone:`info`,value:`GET ${EVE_MESSAGE_STREAM_ROUTE_PATTERN}`}];return i.push({label:`Session`,value:`Follow-up messages reuse the active continuation token.`}),i}function renderCommandRows(){return[{label:`/help`,value:`Print the connection contract and available commands.`},{label:`/new`,value:`Clear the current durable session cursor.`},{label:`/exit`,value:`Exit the REPL.`}]}function renderIntro(e,t){return[renderCliBanner(e,{subtitle:`Interactive development REPL for the active Eve server.`,title:`Eve Dev`}),``,renderCliSection(e,{rows:renderConnectionRows(t),title:`Connection`}),``,renderCliSection(e,{rows:renderCommandRows(),title:`Commands`})].join(`
|
|
2
2
|
`)}function normalizeStepMessage(e){let t=e.trim();return t.length>0?t:null}function getRenderTag(e){return e.options?.isSubagent===!0?`subagent`:e.fallback}function getRenderTone(e){return e.options?.isSubagent===!0?`subagent`:e.fallback}function prefixSourceLabel(e){return e.options?.sourceLabel===void 0?e.message:`${e.options.sourceLabel}${e.separator??` `}${e.message}`}function formatContentEvent(e,t,n){switch(t.type){case`message.appended`:return{finalized:!1,kind:`message`,line:renderCliSpeakerLine(e,{message:t.data.messageSoFar,speaker:n?.sourceLabel??`agent`,tone:getRenderTone({fallback:`accent`,options:n})})};case`message.completed`:if(t.data.message===null)return;if(t.data.finishReason===`tool-calls`){let r=normalizeStepMessage(t.data.message);return r===null?void 0:{finalized:!0,kind:`message`,line:renderCliTaggedLine(e,{message:prefixSourceLabel({message:r,options:n,separator:`: `}),tag:getRenderTag({fallback:`step`,options:n}),tone:getRenderTone({fallback:`accent`,options:n})})}}return{finalized:!0,kind:`message`,line:renderCliSpeakerLine(e,{message:t.data.message,speaker:n?.sourceLabel??`agent`,tone:getRenderTone({fallback:`accent`,options:n})})};case`reasoning.appended`:return{finalized:!1,kind:`reasoning`,line:renderCliTaggedLine(e,{message:prefixSourceLabel({message:t.data.reasoningSoFar,options:n,separator:`: `}),tag:getRenderTag({fallback:`reasoning`,options:n}),tone:getRenderTone({fallback:`info`,options:n})})};case`reasoning.completed`:return{finalized:!0,kind:`reasoning`,line:renderCliTaggedLine(e,{message:prefixSourceLabel({message:t.data.reasoning,options:n,separator:`: `}),tag:getRenderTag({fallback:`reasoning`,options:n}),tone:getRenderTone({fallback:`info`,options:n})})};default:return}}function formatEvent(e,t,n){let r=formatContentEvent(e,t,n);if(r!==void 0)return r.line;switch(t.type){case`message.received`:return;case`actions.requested`:return renderCliTaggedLine(e,{message:prefixSourceLabel({message:`${t.type} (${t.data.actions.length} action${t.data.actions.length===1?``:`s`})`,options:n}),tag:getRenderTag({fallback:`event`,options:n}),tone:getRenderTone({fallback:`muted`,options:n})});case`input.requested`:return renderCliTaggedLine(e,{message:prefixSourceLabel({message:`${t.type} (${t.data.requests.length} request${t.data.requests.length===1?``:`s`})`,options:n}),tag:getRenderTag({fallback:`event`,options:n}),tone:getRenderTone({fallback:`info`,options:n})});case`action.result`:return renderCliTaggedLine(e,{message:prefixSourceLabel({message:`${t.type} (${formatActionResultLabel(t.data.result)})`,options:n}),tag:getRenderTag({fallback:`event`,options:n}),tone:getRenderTone({fallback:`muted`,options:n})});case`session.waiting`:case`session.completed`:return;case`authorization.required`:return renderCliTaggedLine(e,{message:prefixSourceLabel({message:`${t.type} (${t.data.name}: ${t.data.description}${formatAuthorizationChallengeSuffix(t.data.authorization)})`,options:n}),tag:getRenderTag({fallback:`event`,options:n}),tone:getRenderTone({fallback:`warning`,options:n})});case`compaction.requested`:return renderCliTaggedLine(e,{message:prefixSourceLabel({message:`compacting conversation history`,options:n}),tag:getRenderTag({fallback:`event`,options:n}),tone:getRenderTone({fallback:`muted`,options:n})});case`compaction.completed`:return renderCliTaggedLine(e,{message:prefixSourceLabel({message:`conversation history compacted`,options:n}),tag:getRenderTag({fallback:`event`,options:n}),tone:getRenderTone({fallback:`muted`,options:n})});case`step.failed`:case`turn.failed`:case`session.failed`:return;case`subagent.called`:return renderCliTaggedLine(e,{message:prefixSourceLabel({message:`${t.type} (${t.data.name} -> ${t.data.childSessionId})`,options:n}),tag:getRenderTag({fallback:`event`,options:n}),tone:getRenderTone({fallback:`info`,options:n})});case`subagent.started`:return renderCliTaggedLine(e,{message:prefixSourceLabel({message:`${t.type} (${t.data.subagentName})`,options:n}),tag:getRenderTag({fallback:`event`,options:n}),tone:getRenderTone({fallback:`info`,options:n})});case`subagent.event`:return renderCliTaggedLine(e,{message:prefixSourceLabel({message:`${t.type} (${t.data.subagentName}: ${formatNestedSubagentEventLabel(t.data.event)})`,options:n}),tag:getRenderTag({fallback:`event`,options:n}),tone:getRenderTone({fallback:`muted`,options:n})});case`subagent.completed`:return renderCliTaggedLine(e,{message:prefixSourceLabel({message:`${t.type} (${t.data.subagentName})`,options:n}),tag:getRenderTag({fallback:`event`,options:n}),tone:getRenderTone({fallback:`info`,options:n})});default:return}}function getEventDisplayBlockKind(e){switch(e.type){case`message.appended`:case`message.completed`:case`reasoning.appended`:case`reasoning.completed`:return`content`;default:return`meta`}}function createTurnDisplayState(){return{activeLiveContentKind:null,lastPrintedBlockKind:null}}function printDisplayLine(e){let t=e.state;return t.activeLiveContentKind!==null&&(e.terminal.commitLive(),t={activeLiveContentKind:null,lastPrintedBlockKind:`content`}),t.lastPrintedBlockKind!==null&&t.lastPrintedBlockKind!==e.kind&&e.terminal.print(``),e.terminal.print(e.line),{activeLiveContentKind:null,lastPrintedBlockKind:e.kind}}function renderTurnEvent(e){let t=formatContentEvent(e.theme,e.event,e.options);if(t!==void 0){let n=e.state;return n.activeLiveContentKind!==null&&n.activeLiveContentKind!==t.kind&&(e.terminal.commitLive(),n={activeLiveContentKind:null,lastPrintedBlockKind:`content`}),n.lastPrintedBlockKind!==null&&n.lastPrintedBlockKind!==`content`&&e.terminal.print(``),e.terminal.updateLive(t.line),t.finalized?(e.terminal.commitLive(),{activeLiveContentKind:null,lastPrintedBlockKind:`content`}):{activeLiveContentKind:t.kind,lastPrintedBlockKind:`content`}}let n=formatEvent(e.theme,e.event,e.options);return n===void 0?e.state:printDisplayLine({kind:getEventDisplayBlockKind(e.event),line:n,state:e.state,terminal:e.terminal})}function isAbortLikeError(e){return(e instanceof DOMException||e instanceof Error)&&e.name===`AbortError`}function shouldDrainSubagentStreamsOnBoundary(e){return e.length===0}var ReplSubagentStreamManager=class{#e=new Map;#t;#n;#r;#i;constructor(e){this.#t=e.displayStateRef,this.#n=e.serverUrl,this.#r=e.terminal,this.#i=e.theme}subscribe(e){if(this.#e.has(e.sessionId))return;let t=new AbortController,n=this.#a({controller:t,sessionId:e.sessionId,subagentName:e.subagentName}).finally(()=>{this.#e.delete(e.sessionId)});this.#e.set(e.sessionId,{controller:t,done:n,label:e.subagentName})}async waitForIdle(){for(;this.#e.size>0;)await Promise.all([...this.#e.values()].map(e=>e.done))}async close(){let e=[...this.#e.values()];for(let t of e)t.controller.abort();await Promise.allSettled(e.map(e=>e.done))}async#a(e){let t=resolveDevelopmentServerResourceUrl({resource:createEveMessageStreamRoutePath(e.sessionId),serverUrl:this.#n});try{for await(let n of openStreamIterable({host:this.#n,maxReconnectAttempts:3,resolveHeaders:async()=>await createDevelopmentRequestHeadersAsync({resourceUrl:t}),sessionId:e.sessionId,signal:e.controller.signal,startIndex:0}))if(this.#t.current=renderTurnEvent({event:n,options:{isSubagent:!0,sourceLabel:e.subagentName},state:this.#t.current,terminal:this.#r,theme:this.#i}),n.type===`subagent.called`&&this.subscribe({sessionId:n.data.childSessionId,subagentName:n.data.name}),isCurrentTurnBoundaryEvent(n))return}catch(t){if(isAbortLikeError(t))return;let n=toErrorMessage(t);this.#t.current=printDisplayLine({kind:`meta`,line:renderCliTaggedLine(this.#i,{message:`${e.subagentName} stream failed: ${n}`,tag:`subagent`,tone:`danger`}),state:this.#t.current,terminal:this.#r})}finally{e.controller.abort()}}};function formatActionResultLabel(e){switch(e.kind){case`load-skill-result`:return e.kind;case`subagent-result`:return`${e.kind}:${e.subagentName}`;case`tool-result`:return`${e.kind}:${e.toolName}`}}function formatAuthorizationChallengeSuffix(e){if(e===void 0)return``;let t=[];return e.url!==void 0&&t.push(e.url),e.userCode!==void 0&&t.push(`code ${e.userCode}`),e.instructions!==void 0&&t.push(e.instructions),t.length===0?``:` — ${t.join(`, `)}`}function formatNestedSubagentEventLabel(e){switch(e.type){case`actions.requested`:{let t=e.data.actions,n=t.map(e=>e.kind===`tool-call`?e.toolName:e.kind).join(`,`);return`${e.type} (${t.length} action${t.length===1?``:`s`}${n.length>0?`: ${n}`:``})`}case`action.result`:return`${e.type} (${formatActionResultLabel(e.data.result)})`;case`input.requested`:return`${e.type} (${e.data.requests.length} request${e.data.requests.length===1?``:`s`})`;default:return e.type}}function formatDispatch(e,t){return t.continuationToken?renderCliTaggedLine(e,{message:`resuming session ${t.continuationToken}`,tag:`session`,tone:`info`}):renderCliTaggedLine(e,{message:`starting a new session`,tag:`session`,tone:`info`})}function formatTurnDispatch(e,t){return t.turn.inputResponses!==void 0&&t.turn.message===void 0?renderCliTaggedLine(e,{message:`responding to pending input request${t.turn.inputResponses.length===1?``:`s`}`,tag:`session`,tone:`info`}):formatDispatch(e,t.session)}function formatSessionBoundary(e,t){let n=extractCurrentTurnBoundaryEvent(t),r=extractPendingRuntimeInputRequests(t);switch(n?.type){case`session.waiting`:return[renderCliTaggedLine(e,{message:r.length>0?`waiting for input approval/answer or the next message`:`waiting for the next message`,tag:`session`,tone:`success`})];case`session.completed`:return[renderCliTaggedLine(e,{message:`session completed; the next input starts a new session`,tag:`session`,tone:`success`})];case`session.failed`:{let t=n.data.details&&typeof n.data.details.name==`string`?n.data.details.name:void 0;return[renderCliTaggedLine(e,{message:t?`session failed (${t}): ${n.data.message}`:`session failed: ${n.data.message}`,tag:`session`,tone:`danger`}),renderCliTaggedLine(e,{message:`cleared; the next input starts a new session`,tag:`session`,tone:`warning`})]}default:return[]}}async function waitForInputLine(e,t,n={}){return await new Promise(r=>{let i=e.input,cleanup=()=>{e.off(`close`,handleClose),e.off(`line`,handleLine),i.off(`keypress`,handleKeypress)},handleClose=()=>{cleanup(),r(void 0)},handleLine=e=>{cleanup(),r(e)},handleKeypress=(t,i)=>{n.allowEscape!==!0||i.name!==`escape`||(cleanup(),e.write(null,{ctrl:!0,name:`u`}),r(ESCAPED_RUNTIME_INPUT_PROMPT))};e.setPrompt(t),e.once(`close`,handleClose),e.once(`line`,handleLine),n.allowEscape&&(emitKeypressEvents(i,e),i.on(`keypress`,handleKeypress)),e.prompt()})}async function runTurn(e){let t=e.turn,n={current:createTurnDisplayState()},i=new ReplSubagentStreamManager({displayStateRef:n,serverUrl:e.serverUrl,terminal:e.terminal,theme:e.theme}),ask=async t=>{e.terminal.startPrompt(e.rl,t);let n=await waitForInputLine(e.rl,t,{allowEscape:!0});return e.terminal.stopPrompt(),n};try{for(;;){let a=e.client.getSession();n.current=printDisplayLine({kind:`meta`,line:formatTurnDispatch(e.theme,{session:a,turn:t}),state:n.current,terminal:e.terminal});let o=await e.client.send({inputResponses:t.inputResponses,message:t.message,onEvent(t){n.current=renderTurnEvent({event:t,state:n.current,terminal:e.terminal,theme:e.theme}),t.type===`subagent.called`&&i.subscribe({sessionId:t.data.childSessionId,subagentName:t.data.name})},onResponseStart(t){t.sessionId&&a.sessionId!==t.sessionId&&(n.current=printDisplayLine({kind:`meta`,line:renderCliTaggedLine(e.theme,{message:t.sessionId,tag:`session`,tone:`accent`}),state:n.current,terminal:e.terminal}),n.current=printDisplayLine({kind:`meta`,line:renderCliTaggedLine(e.theme,{message:resolveDevelopmentServerResourceUrl({resource:createEveMessageStreamRoutePath(t.sessionId),serverUrl:e.serverUrl}).toString(),tag:`stream`,tone:`info`}),state:n.current,terminal:e.terminal}))}}),s=extractPendingRuntimeInputRequests(o.events);if(shouldDrainSubagentStreamsOnBoundary(s)){await i.waitForIdle();for(let t of formatSessionBoundary(e.theme,o.events))n.current=printDisplayLine({kind:`meta`,line:t,state:n.current,terminal:e.terminal});return`continue`}let c=await promptForRuntimeInputRequests({ask,print(t){n.current=printDisplayLine({kind:`meta`,line:t,state:n.current,terminal:e.terminal})},requests:s,theme:e.theme});if(c.kind===`aborted`)return`exit`;if(c.kind===`deferred`)return n.current=printDisplayLine({kind:`meta`,line:renderCliTaggedLine(e.theme,{message:`left pending input requests unresolved; send a new message to ignore them`,tag:`session`,tone:`warning`}),state:n.current,terminal:e.terminal}),`continue`;t={inputResponses:c.inputResponses}}}finally{await i.close()}}async function runDevelopmentRepl(e){let t=createDevelopmentTerminal(),n=createCliTheme({color:!0}),r=createInterface({input:process.stdin,output:t.output,terminal:!0});r.on(`SIGINT`,()=>{r.close()});let a=createDevClient({serverUrl:e.serverUrl});try{for(t.print(renderIntro(n,e)),t.print(``);;){t.print(``),t.startPrompt(r,`you> `);let i=await waitForInputLine(r,`you> `);if(t.stopPrompt(),i===void 0)return;let o=parseDevReplInput(i);switch(o.kind!==`empty`&&o.kind!==`exit`&&t.print(``),o.kind){case`empty`:continue;case`help`:t.print(renderIntro(n,e)),t.print(``);continue;case`exit`:return;case`new`:await a.clear(),t.print(renderCliTaggedLine(n,{message:`cleared; the next input starts a new session`,tag:`session`,tone:`warning`})),t.print(``);continue;case`message`:try{if(await runTurn({client:a,rl:r,serverUrl:e.serverUrl,terminal:t,theme:n,turn:{message:o.message}})===`exit`)return}catch(r){isVercelAuthChallenge(r)?t.printError(renderCliTaggedLine(n,{message:formatVercelAuthChallengeMessage({serverUrl:e.serverUrl}),tag:`auth`,tone:`warning`})):t.printError(renderCliTaggedLine(n,{message:toErrorMessage(r),tag:`error`,tone:`danger`}))}t.print(``)}}}finally{await a.close(),r.close(),t.dispose()}}export{createTurnDisplayState,formatContentEvent,formatEvent,renderTurnEvent,runDevelopmentRepl,shouldDrainSubagentStreamsOnBoundary};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the startup header the dev TUI commits to scrollback before the first
|
|
3
|
+
* prompt. Styled after the Next.js dev banner: a leading `▲` brand mark, then
|
|
4
|
+
* an aligned `·` list of the agent's resolved configuration (model,
|
|
5
|
+
* instructions, authored tools, skills, subagents, server). When the
|
|
6
|
+
* `/eve/v1/info` payload is unavailable it degrades to a minimal name +
|
|
7
|
+
* server banner.
|
|
8
|
+
*/
|
|
9
|
+
import type { AgentInfoResult } from "#client/index.js";
|
|
10
|
+
import type { Theme } from "./theme.js";
|
|
11
|
+
export interface AgentHeaderInput {
|
|
12
|
+
/** Resolved display name (e.g. "Weather Agent"). */
|
|
13
|
+
name: string;
|
|
14
|
+
/** Server URL the TUI is connected to. */
|
|
15
|
+
serverUrl: string;
|
|
16
|
+
/** Agent inspection payload, or `undefined` when it could not be fetched. */
|
|
17
|
+
info?: AgentInfoResult;
|
|
18
|
+
theme: Theme;
|
|
19
|
+
/** Available terminal width. */
|
|
20
|
+
width: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Returns the styled rows of the startup header (no trailing blank line is
|
|
24
|
+
* added by callers other than the one separating it from the transcript).
|
|
25
|
+
*/
|
|
26
|
+
export declare function buildAgentHeader(input: AgentHeaderInput): string[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{truncate}from"./tool-format.js";function buildAgentHeader(t){let{theme:n,info:r,name:i,serverUrl:a,width:o}=t,s=n.colors,c=[];if(r){c.push({label:`Model`,value:r.agent.model.id}),r.instructions.static&&c.push({label:`Instructions`,value:r.instructions.static.logicalPath});let e=[...r.tools.authored,...r.tools.dynamic.filter(e=>e.origin===`authored`).map(e=>({name:e.slug}))];e.length>0&&c.push({label:`Tools`,value:joinNames(e)});let t=[...r.skills.static,...r.skills.dynamic.filter(e=>e.origin===`authored`).map(e=>({name:e.slug}))];t.length>0&&c.push({label:`Skills`,value:joinNames(t)}),r.subagents.local.length>0&&c.push({label:`Subagents`,value:joinNames(r.subagents.local)}),r.schedules.length>0&&c.push({label:`Schedules`,value:joinNames(r.schedules)}),r.sandbox&&c.push({label:`Sandbox`,value:r.sandbox.logicalPath})}c.push({label:`Server`,value:a,link:!0});let l=c.reduce((e,t)=>Math.max(e,t.label.length),0),u=Math.max(8,o-l-6),d=[];if(d.push(` ${s.bold(`${n.glyph.brand} ${i}`)}`),r&&(r.diagnostics.discoveryErrors>0||r.diagnostics.discoveryWarnings>0)){let e=[];r.diagnostics.discoveryErrors>0&&e.push(s.red(`${r.diagnostics.discoveryErrors} error${plural(r.diagnostics.discoveryErrors)}`)),r.diagnostics.discoveryWarnings>0&&e.push(s.yellow(`${r.diagnostics.discoveryWarnings} warning${plural(r.diagnostics.discoveryWarnings)}`)),d.push(` ${s.dim(n.glyph.warning)} ${e.join(s.dim(` · `))}`)}for(let t of c){let r=s.dim(n.glyph.dot)+` `+s.gray(t.label.padEnd(l)),i=truncate(t.value,u);d.push(` ${r} ${t.link?s.cyan(i):i}`)}return d.push(``),d.push(` ${s.dim(`Type to chat ${n.glyph.dot} ↑ history ${n.glyph.dot} /new reset session ${n.glyph.dot} /exit quit ${n.glyph.dot} Ctrl+C interrupt`)}`),d}function joinNames(e){return e.map(e=>e.name).join(`, `)}function plural(e){return e===1?``:`s`}export{buildAgentHeader};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The transcript block model and its renderer.
|
|
3
|
+
*
|
|
4
|
+
* A {@link Block} is one logical unit of the conversation — a user message, a
|
|
5
|
+
* streamed assistant reply, a reasoning trace, a tool call, a nested subagent
|
|
6
|
+
* step, a log line, and so on. {@link renderBlockLines} turns a block into the
|
|
7
|
+
* exact terminal rows it occupies: a colored gutter glyph, brand-aligned
|
|
8
|
+
* indentation, nesting rules for subagents, and word-wrapped content — with no
|
|
9
|
+
* boxes anywhere. Every returned row is already styled and fits within the
|
|
10
|
+
* given width, so the live region can place rows verbatim.
|
|
11
|
+
*/
|
|
12
|
+
import type { Theme } from "./theme.js";
|
|
13
|
+
export type ToolStatus = "running" | "done" | "error" | "denied" | "approval";
|
|
14
|
+
export type BlockKind = "user" | "assistant" | "reasoning" | "tool" | "error" | "notice" | "question" | "subagent" | "subagent-step" | "subagent-tool" | "connection-auth" | "log";
|
|
15
|
+
/**
|
|
16
|
+
* One renderable transcript unit. Fields are interpreted per `kind`; unset
|
|
17
|
+
* fields are simply omitted from the rendered output.
|
|
18
|
+
*/
|
|
19
|
+
export interface Block {
|
|
20
|
+
kind: BlockKind;
|
|
21
|
+
/** Stable id for in-place updates while the block is live. */
|
|
22
|
+
id?: string;
|
|
23
|
+
/** Nesting depth: 0 = top level, 1 = inside a subagent, etc. */
|
|
24
|
+
depth?: number;
|
|
25
|
+
/** Whether the block is still streaming / mutating (drives the spinner). */
|
|
26
|
+
live?: boolean;
|
|
27
|
+
/** Primary label — tool name, subagent name, log source, error title. */
|
|
28
|
+
title?: string;
|
|
29
|
+
/** Compact secondary text — summarized tool args. */
|
|
30
|
+
subtitle?: string;
|
|
31
|
+
/** Main multi-line content (markdown for prose, plain for logs). */
|
|
32
|
+
body?: string;
|
|
33
|
+
/** Reasoning trace shown above `body` (subagent steps). */
|
|
34
|
+
reasoning?: string;
|
|
35
|
+
/** One-line summarized result shown after a tool resolves. */
|
|
36
|
+
result?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Errors only: multi-line diagnostic dump (stack trace, cause chain)
|
|
39
|
+
* rendered dim beneath the headline, capped to a handful of lines.
|
|
40
|
+
*/
|
|
41
|
+
detail?: string;
|
|
42
|
+
/** Tool / connection lifecycle status. */
|
|
43
|
+
status?: ToolStatus;
|
|
44
|
+
/** When true, treat `body` as pre-styled and only wrap + indent it. */
|
|
45
|
+
preformatted?: boolean;
|
|
46
|
+
/** Reasoning only: collapse the trace to a single "thinking" line. */
|
|
47
|
+
collapsed?: boolean;
|
|
48
|
+
/** When true, expand tool input/output instead of summarizing. */
|
|
49
|
+
expanded?: boolean;
|
|
50
|
+
/** Raw tool input / output for the expanded view. */
|
|
51
|
+
toolInput?: unknown;
|
|
52
|
+
toolOutput?: unknown;
|
|
53
|
+
}
|
|
54
|
+
export interface RenderBlockContext {
|
|
55
|
+
/** Current spinner frame for live blocks. */
|
|
56
|
+
spinner: string;
|
|
57
|
+
/**
|
|
58
|
+
* Kind and title of the block rendered immediately above this one. Lets a
|
|
59
|
+
* log block detect that it continues a same-source run (label suppressed,
|
|
60
|
+
* lines hang under the previous block's label) without any mutable run
|
|
61
|
+
* state — each captured write stays its own immediately-committed block.
|
|
62
|
+
*/
|
|
63
|
+
previous?: {
|
|
64
|
+
kind: BlockKind;
|
|
65
|
+
title?: string;
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Renders a block to its terminal rows. Each row is fully styled and clipped
|
|
70
|
+
* to `width` visible columns.
|
|
71
|
+
*/
|
|
72
|
+
export declare function renderBlockLines(block: Block, width: number, theme: Theme, context: RenderBlockContext): string[];
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{formatValuePretty,truncate}from"./tool-format.js";import{sliceVisible,visibleLength,wrapVisibleLine}from"./terminal-text.js";import{renderMarkdown}from"./markdown.js";function renderBlockLines(e,t,n,i){let a=nestingPrefix(e.depth??0,n);return renderBody(e,Math.max(8,t-visibleLength(a)),n,i).map(e=>`${a}${e}`)}function nestingPrefix(e,t){return e<=0?``:`${t.colors.orange(t.glyph.rule)} `.repeat(e)}function renderBody(e,t,n,r){switch(e.kind){case`user`:return renderUser(e,t,n);case`assistant`:case`subagent-step`:return renderProse(e,t,n);case`reasoning`:return renderReasoning(e,t,n);case`tool`:case`subagent-tool`:return renderTool(e,t,n,r);case`error`:return renderError(e,t,n);case`notice`:return renderNotice(e,t,n);case`question`:case`connection-auth`:return renderPreformatted(e,t,n);case`log`:return renderLog(e,t,n,r);case`subagent`:return renderSubagentHeader(e,t,n)}}function renderUser(e,t,n){let r=n.colors.cyan(n.glyph.user);return wrap(e.body??``,t-2).map(e=>`${r} ${e}`)}function renderProse(e,t,n){let r=[],o=e.kind===`subagent-step`,s=o?``:`${n.colors.bold(n.colors.white(n.glyph.brand))} `,c=o?``:` `;e.reasoning&&e.reasoning.trim().length>0&&r.push(...renderReasoningLines(e.reasoning,t,n));let l=(e.body??``).trim();return l.length===0&&r.length===0?[`${s}${n.colors.dim(`thinking${n.glyph.ellipsis}`)}`]:(l.length>0&&renderMarkdown(l).split(`
|
|
2
|
+
`).flatMap(e=>wrapVisibleLine(e,t-c.length)).forEach((e,t)=>{t===0&&!o&&r.length===0?r.push(`${s}${e}`):r.push(`${c}${e}`)}),r.length>0?r:[`${s}`])}function renderReasoning(e,t,n){return e.collapsed?[`${n.colors.gray(n.glyph.reasoning)} ${n.colors.dim(`thinking`)}`]:renderReasoningLines(e.body??``,t,n,n.glyph.reasoning)}function renderReasoningLines(e,t,n,r){let i=r?2:0,a=wrap(e.trim(),t-i);return a.length===0?[]:a.map((e,t)=>`${r?t===0?`${n.colors.gray(r)} `:` `:``}${n.colors.dim(n.colors.italic(e))}`)}function renderTool(e,n,r,i){let{icon:a,accent:o}=toolGlyph(e.status??`running`,r,i),s=e.title??`tool`,c=n-2,l=truncatePlain(s,c),u=`${a} ${r.colors.bold(l)}`,d=c-l.length-2,f=e.subtitle??``;f.length>0&&d>=6&&(u+=` ${r.colors.gray(truncate(f,d))}`);let p=[u];return e.expanded?p.push(...renderToolExpanded(e,n,r)):e.status===`done`&&e.result&&e.result.length>0?p.push(resultLine(r.glyph.arrow,e.result,n,r,o)):e.status===`error`&&e.result?p.push(resultLine(r.glyph.arrow,e.result,n,r,r.colors.red)):e.status===`denied`&&p.push(resultLine(r.glyph.arrow,`denied`,n,r,r.colors.yellow)),p}function renderToolExpanded(t,n,r){let i=[],push=(t,a,o)=>{if(a!==void 0){i.push(` ${r.colors.dim(t)}`);for(let t of wrap(formatValuePretty(a),n-4))i.push(` ${o(t)}`)}};return push(`input`,t.toolInput,r.colors.gray),t.status===`error`&&t.result?push(`error`,t.result,r.colors.red):push(`output`,t.toolOutput,r.colors.gray),i}function resultLine(e,n,r,i,a){let o=r-4;return` ${i.colors.dim(e)} ${a(truncate(n,o))}`}function toolGlyph(e,t,n){switch(e){case`done`:return{icon:t.colors.green(t.glyph.success),accent:t.colors.gray};case`error`:return{icon:t.colors.red(t.glyph.error),accent:t.colors.red};case`denied`:return{icon:t.colors.yellow(t.glyph.warning),accent:t.colors.yellow};case`approval`:return{icon:t.colors.yellow(t.glyph.question),accent:t.colors.yellow};default:return{icon:t.colors.yellow(n.spinner),accent:t.colors.gray}}}function renderError(e,t,n){let r=n.colors.red(n.colors.bold(n.glyph.error)),i=e.title??`Error`,a=[`${r} ${n.colors.red(n.colors.bold(i))}`];for(let r of wrap(e.body??``,t-2))a.push(` ${colorizeError(r,n)}`);return a.push(...renderErrorDetail(e.detail,t,n)),a}function renderErrorDetail(e,t,n){if(e===void 0||e.trim().length===0)return[];let r=e.split(`
|
|
3
|
+
`),i=r.slice(0,12),a=i.map(e=>` ${n.colors.dim(truncatePlain(e,Math.max(1,t-2)))}`),o=r.length-i.length;return o>0&&a.push(` ${n.colors.dim(`${n.glyph.ellipsis} +${o} more line${o===1?``:`s`}`)}`),a}const URL_PATTERN=/(https?:\/\/\S+)/u;function colorizeError(e,t){return URL_PATTERN.test(e)?e.split(URL_PATTERN).map((e,n)=>n%2==1?t.colors.cyan(e):t.colors.red(e)).join(``):t.colors.red(e)}function renderNotice(e,t,n){let r=n.colors.dim(n.glyph.dot),i=wrap(e.body??``,t-2);return i.length===0?[r]:i.map(e=>`${r} ${n.colors.dim(e)}`)}function renderPreformatted(e,t,n){let r=e.kind===`connection-auth`?n.colors.yellow(n.glyph.connection):n.colors.yellow(n.colors.bold(n.glyph.question)),a=e.title??``,o=[`${r} ${n.colors.bold(a)}`];for(let n of(e.body??``).split(`
|
|
4
|
+
`))for(let e of wrapVisibleLine(n,t-2))o.push(` ${e}`);return o}function renderLog(e,t,n,a){let o=e.title===`stderr`,s=o?n.colors.red:n.colors.gray,c=n.colors.dim(n.glyph.rule),l=o?`stderr`:`stdout`,u=n.colors.dim(`${l} ${n.glyph.dot} `),d=visibleLength(u),f=` `.repeat(d),p=a.previous?.kind===`log`&&a.previous.title===e.title,m=(e.body??``).split(`
|
|
5
|
+
`),h=[];for(let e of m){let r=wrapVisibleLine(e,Math.max(1,t-2-d));for(let e of r){let t=h.length===0&&!p?u:f;h.push(`${c} ${t}${n.colors.dim(s(e))}`)}}return h.length>0?h:[`${c}`]}function renderSubagentHeader(e,t,n){let r=truncatePlain(e.title??`subagent`,Math.max(8,t-14));return[`${n.colors.orange(n.glyph.subagent)} ${n.colors.bold(r)} ${n.colors.dim(`subagent`)}`]}function wrap(e,t){return e.trim().length===0?[]:e.split(`
|
|
6
|
+
`).flatMap(e=>wrapVisibleLine(e,Math.max(1,t)))}function truncatePlain(e,t){return visibleLength(e)<=t?e:sliceVisible(e,t)}export{renderBlockLines};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error classification and display formatting shared by the TUI runner and
|
|
3
|
+
* terminal renderer. One module owns the interrupt sentinel and the
|
|
4
|
+
* failure-event projections so the two sides cannot drift apart.
|
|
5
|
+
*/
|
|
6
|
+
import type { SessionFailedStreamEvent, StepFailedStreamEvent, TurnFailedStreamEvent } from "#client/index.js";
|
|
7
|
+
/**
|
|
8
|
+
* One of the failure events a session stream can carry. All three share the
|
|
9
|
+
* same `{ code, message, details? }` payload shape — the harness emits them
|
|
10
|
+
* as a cascade (`step.failed` → `turn.failed` → `session.failed` /
|
|
11
|
+
* `session.waiting`) describing a single underlying failure.
|
|
12
|
+
*/
|
|
13
|
+
export type FailureStreamEvent = StepFailedStreamEvent | TurnFailedStreamEvent | SessionFailedStreamEvent;
|
|
14
|
+
/**
|
|
15
|
+
* Thrown when the user interrupts the TUI (Ctrl+C, or Ctrl+D on an empty
|
|
16
|
+
* prompt). The runner treats it as a clean exit, never as a failure.
|
|
17
|
+
*/
|
|
18
|
+
export declare class InterruptedError extends Error {
|
|
19
|
+
constructor();
|
|
20
|
+
}
|
|
21
|
+
export declare function interruptedError(): InterruptedError;
|
|
22
|
+
export declare function isInterruptedError(error: unknown): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Recognizes errors raised by aborting an in-flight fetch/stream (e.g. the
|
|
25
|
+
* subagent child-session pump being cancelled). These are expected shutdown
|
|
26
|
+
* noise, not failures to surface.
|
|
27
|
+
*/
|
|
28
|
+
export declare function isAbortLikeError(error: unknown): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Stable identity for one failure cascade entry. The harness emits the same
|
|
31
|
+
* `{ code, message }` payload on `step.failed`, `turn.failed`, and (for
|
|
32
|
+
* terminal failures) `session.failed`; keying on both lets the stream
|
|
33
|
+
* translator render the underlying failure exactly once.
|
|
34
|
+
*/
|
|
35
|
+
export declare function failureKey(event: FailureStreamEvent): string;
|
|
36
|
+
/**
|
|
37
|
+
* One-line headline for a failure event: `code: message`, except when the
|
|
38
|
+
* message already carries its own class-name prefix (e.g. a
|
|
39
|
+
* `HookConflictError` whose message starts with `HookConflictError:`), in
|
|
40
|
+
* which case the message stands alone instead of reading `Code: Code: …`.
|
|
41
|
+
*/
|
|
42
|
+
export declare function formatFailureMessage(event: FailureStreamEvent): string;
|
|
43
|
+
/**
|
|
44
|
+
* Extracts the diagnostic dump attached to a failure event, if any.
|
|
45
|
+
*
|
|
46
|
+
* `details.detail` is the `util.inspect` rendering (stack trace and cause
|
|
47
|
+
* chain included) that `formatError` attaches to *unrecognized* failures —
|
|
48
|
+
* i.e. code bugs escaping user code. Recognized provider/config failures
|
|
49
|
+
* deliberately ship a curated summary without the dump, so this returns
|
|
50
|
+
* `undefined` for them and the headline stands alone.
|
|
51
|
+
*/
|
|
52
|
+
export declare function formatFailureDetail(event: FailureStreamEvent): string | undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var InterruptedError=class extends Error{constructor(){super(`Interrupted`),this.name=`InterruptedError`}};function interruptedError(){return new InterruptedError}function isInterruptedError(e){return e instanceof InterruptedError}function isAbortLikeError(e){return e instanceof Error?e.name===`AbortError`||/\babort(?:ed)?\b/iu.test(e.message):!1}function failureKey(e){return`${e.data.code}:${e.data.message}`}function formatFailureMessage(e){let{code:t,message:n}=e.data;return!t||n===t||n.startsWith(`${t}:`)||n.startsWith(`${t} `)?n:`${t}: ${n}`}function formatFailureDetail(e){let t=e.data.details;if(typeof t!=`object`||!t)return;let n=t.detail;if(typeof n!=`string`)return;let r=n.trim();if(!(r.length===0||r===e.data.message.trim()))return r}export{InterruptedError,failureKey,formatFailureDetail,formatFailureMessage,interruptedError,isAbortLikeError,isInterruptedError};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A tiny, dependency-free line-editing model for the prompt input.
|
|
3
|
+
*
|
|
4
|
+
* The renderer owns the terminal; this module owns the *text* — a single
|
|
5
|
+
* logical line plus a caret position — and exposes pure transforms for the
|
|
6
|
+
* common readline-style edits (insert, delete, word/line kill, cursor moves)
|
|
7
|
+
* and a {@link visibleLine} helper that windows a long line around the caret
|
|
8
|
+
* so it stays on screen. Keeping it pure makes the editing rules trivial to
|
|
9
|
+
* unit test without a TTY.
|
|
10
|
+
*/
|
|
11
|
+
/** One logical input line: its text and the caret's index within it. */
|
|
12
|
+
export interface LineState {
|
|
13
|
+
readonly text: string;
|
|
14
|
+
readonly cursor: number;
|
|
15
|
+
}
|
|
16
|
+
/** The empty line with the caret at column 0. */
|
|
17
|
+
export declare const EMPTY_LINE: LineState;
|
|
18
|
+
/** Builds a line from `text` with the caret placed at the end. */
|
|
19
|
+
export declare function lineOf(text: string): LineState;
|
|
20
|
+
/** Inserts `value` at the caret and advances the caret past it. */
|
|
21
|
+
export declare function insert(state: LineState, value: string): LineState;
|
|
22
|
+
/** Deletes the character before the caret (Backspace). */
|
|
23
|
+
export declare function backspace(state: LineState): LineState;
|
|
24
|
+
/** Deletes the character at the caret (Delete / Ctrl+D mid-line). */
|
|
25
|
+
export declare function deleteForward(state: LineState): LineState;
|
|
26
|
+
/** Moves the caret one column left. */
|
|
27
|
+
export declare function moveLeft(state: LineState): LineState;
|
|
28
|
+
/** Moves the caret one column right. */
|
|
29
|
+
export declare function moveRight(state: LineState): LineState;
|
|
30
|
+
/** Moves the caret to the start of the line (Home / Ctrl+A). */
|
|
31
|
+
export declare function moveHome(state: LineState): LineState;
|
|
32
|
+
/** Moves the caret to the end of the line (End / Ctrl+E). */
|
|
33
|
+
export declare function moveEnd(state: LineState): LineState;
|
|
34
|
+
/** Deletes from the caret to the end of the line (Ctrl+K). */
|
|
35
|
+
export declare function killToEnd(state: LineState): LineState;
|
|
36
|
+
/** Deletes from the start of the line to the caret (Ctrl+U). */
|
|
37
|
+
export declare function killToStart(state: LineState): LineState;
|
|
38
|
+
/** Deletes the whitespace-delimited word before the caret (Ctrl+W). */
|
|
39
|
+
export declare function deleteWord(state: LineState): LineState;
|
|
40
|
+
/**
|
|
41
|
+
* The portion of `state.text` to draw within `budget` columns, split at the
|
|
42
|
+
* caret so the renderer can place its caret glyph between `before` and
|
|
43
|
+
* `after`. When the line is wider than `budget` it is windowed around the
|
|
44
|
+
* caret, marking truncated ends with `…` so the caret is always visible.
|
|
45
|
+
*/
|
|
46
|
+
export interface VisibleLine {
|
|
47
|
+
readonly before: string;
|
|
48
|
+
readonly after: string;
|
|
49
|
+
}
|
|
50
|
+
export declare function visibleLine(state: LineState, budget: number, ellipsis?: string): VisibleLine;
|
|
51
|
+
/**
|
|
52
|
+
* In-memory, append-only prompt history with shell-style up/down navigation.
|
|
53
|
+
*
|
|
54
|
+
* Navigation is non-destructive: stepping back from the live line stashes the
|
|
55
|
+
* in-progress draft and restores it when the user steps forward past the
|
|
56
|
+
* newest entry. Consecutive duplicate submissions are collapsed.
|
|
57
|
+
*/
|
|
58
|
+
export declare class PromptHistory {
|
|
59
|
+
#private;
|
|
60
|
+
/** Records a submitted prompt (skips blanks and consecutive duplicates). */
|
|
61
|
+
add(entry: string): void;
|
|
62
|
+
/** Resets navigation to the live line, stashing `draft` as the in-progress text. */
|
|
63
|
+
begin(draft: string): void;
|
|
64
|
+
/** The previous (older) entry, or `undefined` at the oldest entry. */
|
|
65
|
+
previous(currentDraft: string): string | undefined;
|
|
66
|
+
/** The next (newer) entry, or the stashed draft once past the newest entry. */
|
|
67
|
+
next(): string | undefined;
|
|
68
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const EMPTY_LINE={text:``,cursor:0};function lineOf(e){return{text:e,cursor:e.length}}function insert(e,t){return t.length===0?e:{text:e.text.slice(0,e.cursor)+t+e.text.slice(e.cursor),cursor:e.cursor+t.length}}function backspace(e){return e.cursor===0?e:{text:e.text.slice(0,e.cursor-1)+e.text.slice(e.cursor),cursor:e.cursor-1}}function deleteForward(e){return e.cursor>=e.text.length?e:{text:e.text.slice(0,e.cursor)+e.text.slice(e.cursor+1),cursor:e.cursor}}function moveLeft(e){return e.cursor===0?e:{text:e.text,cursor:e.cursor-1}}function moveRight(e){return e.cursor>=e.text.length?e:{text:e.text,cursor:e.cursor+1}}function moveHome(e){return e.cursor===0?e:{text:e.text,cursor:0}}function moveEnd(e){return e.cursor===e.text.length?e:{text:e.text,cursor:e.text.length}}function killToEnd(e){return e.cursor>=e.text.length?e:{text:e.text.slice(0,e.cursor),cursor:e.cursor}}function killToStart(e){return e.cursor===0?e:{text:e.text.slice(e.cursor),cursor:0}}function deleteWord(e){if(e.cursor===0)return e;let t=e.cursor;for(;t>0&&isWhitespace(e.text[t-1]);)--t;for(;t>0&&!isWhitespace(e.text[t-1]);)--t;return{text:e.text.slice(0,t)+e.text.slice(e.cursor),cursor:t}}function isWhitespace(e){return e!==void 0&&/\s/u.test(e)}function visibleLine(e,t,n=`…`){let r=Math.max(1,t),{text:i,cursor:a}=e;if(i.length<=r)return{before:i.slice(0,a),after:i.slice(a)};let o=a<r?0:a-r+1;o=Math.min(o,i.length-r),o=Math.max(0,o);let s=o+r,c=i.slice(o,s),l=a-o;return o>0&&l>0&&(c=n+c.slice(n.length)),s<i.length&&l<c.length&&(c=c.slice(0,c.length-n.length)+n),{before:c.slice(0,l),after:c.slice(l)}}var PromptHistory=class{#e=[];#t=0;#n=``;add(e){if(e.trim().length!==0){if(this.#e.at(-1)===e){this.#r();return}this.#e.push(e),this.#r()}}begin(e){this.#t=this.#e.length,this.#n=e}previous(e){if(this.#e.length!==0&&(this.#t===this.#e.length&&(this.#n=e),this.#t!==0))return--this.#t,this.#e[this.#t]}next(){if(!(this.#t>=this.#e.length))return this.#t+=1,this.#t===this.#e.length?this.#n:this.#e[this.#t]}#r(){this.#t=this.#e.length,this.#n=``}};export{EMPTY_LINE,PromptHistory,backspace,deleteForward,deleteWord,insert,killToEnd,killToStart,lineOf,moveEnd,moveHome,moveLeft,moveRight,visibleLine};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The inline scrollback engine.
|
|
3
|
+
*
|
|
4
|
+
* Unlike a full-screen alt-buffer UI, the dev TUI streams its transcript into
|
|
5
|
+
* the terminal's *native* scrollback so the user keeps real scrolling, copy /
|
|
6
|
+
* paste, and a persistent transcript after exit. Two regions are maintained:
|
|
7
|
+
*
|
|
8
|
+
* - **Committed scrollback** — finalized rows printed once and owned by the
|
|
9
|
+
* terminal thereafter (never repainted).
|
|
10
|
+
* - **Live region** — the still-streaming rows plus the sticky footer, redrawn
|
|
11
|
+
* in place on every update.
|
|
12
|
+
*
|
|
13
|
+
* Redrawing moves the cursor to the top of the previous live region, clears to
|
|
14
|
+
* the end of the screen, and reprints. {@link flush} additionally writes a run
|
|
15
|
+
* of newly-finalized rows above the live region so they scroll away for good.
|
|
16
|
+
*
|
|
17
|
+
* Writes go through the terminal's original `write` captured at construction,
|
|
18
|
+
* so the renderer's foreign-output capture (which monkeypatches
|
|
19
|
+
* `process.stdout.write`) never mistakes the engine's own paint for agent log
|
|
20
|
+
* output.
|
|
21
|
+
*/
|
|
22
|
+
export interface LiveRegionOutput {
|
|
23
|
+
write(chunk: string): boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface LiveRegionOptions {
|
|
26
|
+
/** Wrap each paint in synchronized-update markers to avoid flicker. */
|
|
27
|
+
synchronized?: boolean;
|
|
28
|
+
}
|
|
29
|
+
export declare class LiveRegion {
|
|
30
|
+
#private;
|
|
31
|
+
constructor(output: LiveRegionOutput, options?: LiveRegionOptions);
|
|
32
|
+
/** Hides the hardware cursor; the renderer draws its own caret. */
|
|
33
|
+
hideCursor(): void;
|
|
34
|
+
showCursor(): void;
|
|
35
|
+
/** Writes a newline through the bound (original) write. */
|
|
36
|
+
newline(): void;
|
|
37
|
+
/**
|
|
38
|
+
* Repaints the live region in place from `liveRows`. Each row must already
|
|
39
|
+
* be styled and fit within the terminal width (one row == one screen line).
|
|
40
|
+
*/
|
|
41
|
+
update(liveRows: readonly string[]): void;
|
|
42
|
+
/**
|
|
43
|
+
* Commits `committedRows` to scrollback above the live region, then repaints
|
|
44
|
+
* `liveRows`. Committed rows are permanent and scroll with the terminal.
|
|
45
|
+
*/
|
|
46
|
+
flush(committedRows: readonly string[], liveRows: readonly string[]): void;
|
|
47
|
+
/**
|
|
48
|
+
* Erases the live region, leaving the cursor at its former top. Committed
|
|
49
|
+
* scrollback is untouched. Used on teardown before restoring the cursor.
|
|
50
|
+
*/
|
|
51
|
+
clear(): void;
|
|
52
|
+
/** Clears the visible transcript and, where supported, terminal scrollback. */
|
|
53
|
+
clearAll(): void;
|
|
54
|
+
/**
|
|
55
|
+
* Forgets the live-region row count without moving the cursor. Call after
|
|
56
|
+
* the cursor position is known to be a fresh column-0 line that the engine
|
|
57
|
+
* did not itself paint (e.g. immediately after teardown).
|
|
58
|
+
*/
|
|
59
|
+
reset(): void;
|
|
60
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
const CLEAR_TO_END=`\x1B[0J`;var LiveRegion=class{#e;#t;#n=0;constructor(e,t){this.#e=e.write.bind(e),this.#t=t?.synchronized??!0}hideCursor(){this.#e(`\x1B[?25l`)}showCursor(){this.#e(`\x1B[?25h`)}newline(){this.#e(`
|
|
2
|
+
`)}update(e){this.#r([],e)}flush(e,t){this.#r(e,t)}clear(){if(this.#n===0){this.#e(`\r`),this.#e(CLEAR_TO_END);return}this.#e(`${this.#i()}${CLEAR_TO_END}`),this.#n=0}clearAll(){this.#e(`\x1B[3J\x1B[2J\x1B[H`),this.#n=0}reset(){this.#n=0}#r(t,n){let r=this.#i()+CLEAR_TO_END+t.map(e=>`${e}\n`).join(``)+n.join(`
|
|
3
|
+
`);this.#e(this.#t?`[?2026h${r}[?2026l`:r),this.#n=n.length}#i(){return this.#n<=1?`\r`:`[${this.#n-1}F`}};export{LiveRegion};
|