eve 0.25.3 → 0.26.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/dist/src/chunks/{use-eve-agent-Cy73lgA6.js → use-eve-agent-BkztZA0v.js} +76 -55
- package/dist/src/chunks/{use-eve-agent-CQIeqmKc.js → use-eve-agent-CruinZmd.js} +76 -55
- package/dist/src/cli/banner.d.ts +5 -0
- package/dist/src/cli/banner.js +1 -1
- package/dist/src/cli/commands/logs-events.d.ts +36 -0
- package/dist/src/cli/commands/logs-events.js +2 -0
- package/dist/src/cli/commands/logs.d.ts +64 -0
- package/dist/src/cli/commands/logs.js +4 -0
- package/dist/src/cli/dev/diagnostic-dump.d.ts +60 -0
- package/dist/src/cli/dev/diagnostic-dump.js +1 -0
- package/dist/src/cli/dev/diagnostic-sink.d.ts +37 -0
- package/dist/src/cli/dev/diagnostic-sink.js +1 -0
- package/dist/src/cli/dev/diagnostics.d.ts +42 -0
- package/dist/src/cli/dev/diagnostics.js +1 -0
- package/dist/src/cli/dev/tui/blocks.d.ts +60 -8
- package/dist/src/cli/dev/tui/blocks.js +8 -8
- package/dist/src/cli/dev/tui/command-typeahead.js +1 -1
- package/dist/src/cli/dev/tui/diagnostic-presentation.d.ts +16 -0
- package/dist/src/cli/dev/tui/diagnostic-presentation.js +3 -0
- package/dist/src/cli/dev/tui/errors.d.ts +21 -16
- package/dist/src/cli/dev/tui/errors.js +1 -1
- package/dist/src/cli/dev/tui/file-content-cache.d.ts +35 -0
- package/dist/src/cli/dev/tui/file-content-cache.js +3 -0
- package/dist/src/cli/dev/tui/line-diff.d.ts +24 -0
- package/dist/src/cli/dev/tui/line-diff.js +1 -0
- package/dist/src/cli/dev/tui/line-editor.js +1 -1
- package/dist/src/cli/dev/tui/markdown.d.ts +2 -1
- package/dist/src/cli/dev/tui/markdown.js +7 -3
- package/dist/src/cli/dev/tui/model-editor.d.ts +103 -0
- package/dist/src/cli/dev/tui/model-editor.js +1 -0
- package/dist/src/cli/dev/tui/prompt-command-handler.d.ts +1 -1
- package/dist/src/cli/dev/tui/prompt-command-handler.js +1 -1
- package/dist/src/cli/dev/tui/prompt-placeholder.d.ts +12 -0
- package/dist/src/cli/dev/tui/prompt-placeholder.js +1 -0
- package/dist/src/cli/dev/tui/question-panel.d.ts +24 -0
- package/dist/src/cli/dev/tui/question-panel.js +1 -0
- package/dist/src/cli/dev/tui/rail.d.ts +15 -0
- package/dist/src/cli/dev/tui/rail.js +1 -0
- package/dist/src/cli/dev/tui/remote-auth-command.js +1 -1
- package/dist/src/cli/dev/tui/runner.d.ts +27 -65
- package/dist/src/cli/dev/tui/runner.js +1 -1
- package/dist/src/cli/dev/tui/setup-commands.d.ts +1 -1
- package/dist/src/cli/dev/tui/setup-commands.js +2 -2
- package/dist/src/cli/dev/tui/setup-flow.d.ts +3 -0
- package/dist/src/cli/dev/tui/setup-issues.js +1 -1
- package/dist/src/cli/dev/tui/setup-panel.d.ts +33 -0
- package/dist/src/cli/dev/tui/setup-panel.js +4 -4
- package/dist/src/cli/dev/tui/status-line.d.ts +8 -6
- package/dist/src/cli/dev/tui/status-line.js +1 -1
- package/dist/src/cli/dev/tui/stream-format.d.ts +16 -3
- package/dist/src/cli/dev/tui/stream-format.js +1 -1
- package/dist/src/cli/dev/tui/subagent-pump.d.ts +127 -0
- package/dist/src/cli/dev/tui/subagent-pump.js +1 -0
- package/dist/src/cli/dev/tui/terminal-renderer.d.ts +37 -1
- package/dist/src/cli/dev/tui/terminal-renderer.js +12 -10
- package/dist/src/cli/dev/tui/test/fake-setup-flow-renderer.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 +1 -1
- package/dist/src/cli/dev/tui/theme.d.ts +30 -2
- package/dist/src/cli/dev/tui/theme.js +1 -1
- package/dist/src/cli/dev/tui/todo-panel.d.ts +44 -0
- package/dist/src/cli/dev/tui/todo-panel.js +1 -0
- package/dist/src/cli/dev/tui/tool-block-groups.d.ts +40 -0
- package/dist/src/cli/dev/tui/tool-block-groups.js +1 -0
- package/dist/src/cli/dev/tui/tool-format.js +1 -1
- package/dist/src/cli/dev/tui/tool-presentation.d.ts +67 -0
- package/dist/src/cli/dev/tui/tool-presentation.js +1 -0
- package/dist/src/cli/dev/tui/tool-rows.d.ts +15 -0
- package/dist/src/cli/dev/tui/tool-rows.js +2 -0
- package/dist/src/cli/dev/tui/tui.js +1 -1
- package/dist/src/cli/dev/tui/turn-clock.d.ts +36 -0
- package/dist/src/cli/dev/tui/turn-clock.js +1 -0
- package/dist/src/cli/dev/tui/types.d.ts +2 -2
- package/dist/src/cli/dev/ui-options.js +1 -1
- package/dist/src/cli/run.js +2 -2
- package/dist/src/cli/ui/live-row.js +1 -1
- package/dist/src/client/agent-info-schema.d.ts +9 -0
- package/dist/src/client/agent-info-schema.js +1 -1
- package/dist/src/client/client.js +1 -1
- package/dist/src/client/eve-agent-store.d.ts +1 -2
- package/dist/src/client/eve-agent-store.js +1 -1
- package/dist/src/client/index.js +1 -1
- package/dist/src/client/open-stream.d.ts +14 -10
- package/dist/src/client/open-stream.js +1 -1
- package/dist/src/client/session-utils.d.ts +2 -1
- package/dist/src/client/session-utils.js +1 -1
- package/dist/src/client/session.d.ts +3 -5
- package/dist/src/client/session.js +1 -1
- package/dist/src/client/types.d.ts +0 -6
- package/dist/src/compiled/.vendor-stamp.json +2 -1
- package/dist/src/compiled/marked/LICENSE.md +44 -0
- package/dist/src/compiled/marked/index.d.ts +24 -0
- package/dist/src/compiled/marked/index.js +59 -0
- package/dist/src/compiler/extension-compatibility.d.ts +2 -2
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/context/build-dynamic-tools.js +1 -1
- package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
- package/dist/src/evals/session.js +1 -1
- package/dist/src/execution/node-step.js +1 -1
- package/dist/src/execution/sandbox/bindings/docker-cli.d.ts +4 -0
- package/dist/src/execution/sandbox/bindings/docker-cli.js +1 -1
- package/dist/src/execution/sandbox/bindings/microsandbox-create.js +1 -1
- package/dist/src/execution/terminal-session-failure-step.js +1 -1
- package/dist/src/harness/emission.js +1 -1
- package/dist/src/harness/model-call-error.d.ts +11 -30
- package/dist/src/harness/model-call-error.js +1 -1
- package/dist/src/harness/semantic-errors/index.d.ts +9 -0
- package/dist/src/harness/semantic-errors/index.js +1 -0
- package/dist/src/harness/semantic-errors/rule.d.ts +76 -0
- package/dist/src/harness/semantic-errors/rule.js +1 -0
- package/dist/src/harness/semantic-errors/rules/gateway.d.ts +11 -0
- package/dist/src/harness/semantic-errors/rules/gateway.js +1 -0
- package/dist/src/harness/semantic-errors/rules/model-provider.d.ts +11 -0
- package/dist/src/harness/semantic-errors/rules/model-provider.js +1 -0
- package/dist/src/harness/semantic-errors/rules/sandbox.d.ts +16 -0
- package/dist/src/harness/semantic-errors/rules/sandbox.js +1 -0
- package/dist/src/harness/semantic-errors/rules/system.d.ts +2 -0
- package/dist/src/harness/semantic-errors/rules/system.js +1 -0
- package/dist/src/harness/semantic-errors/rules/workflow.d.ts +9 -0
- package/dist/src/harness/semantic-errors/rules/workflow.js +1 -0
- package/dist/src/harness/semantic-errors/signals.d.ts +28 -0
- package/dist/src/harness/semantic-errors/signals.js +1 -0
- package/dist/src/harness/tool-loop.js +2 -2
- package/dist/src/harness/workflow-sandbox.d.ts +6 -0
- package/dist/src/harness/workflow-sandbox.js +2 -2
- package/dist/src/internal/application/output-publication-lock.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/logging.d.ts +33 -1
- package/dist/src/internal/logging.js +1 -1
- package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response-from-manifest.js +1 -1
- package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.d.ts +3 -1
- package/dist/src/internal/nitro/routes/agent-info/build-agent-info-response.js +1 -1
- package/dist/src/internal/nitro/routes/info.js +1 -1
- package/dist/src/internal/resolve-model-endpoint-status.d.ts +46 -3
- package/dist/src/internal/resolve-model-endpoint-status.js +1 -1
- package/dist/src/internal/workflow/development-world-client.js +1 -1
- package/dist/src/internal/workflow/development-world-server.js +1 -1
- package/dist/src/packages/eve-catalog/src/index.js +1 -1
- package/dist/src/public/models/openai/chatgpt/model.js +3 -1
- package/dist/src/react/use-eve-agent.d.ts +0 -1
- package/dist/src/react/use-eve-agent.js +1 -1
- package/dist/src/setup/boxes/add-channels.js +1 -1
- package/dist/src/setup/boxes/deploy-project.js +1 -1
- package/dist/src/setup/boxes/model-capabilities.d.ts +24 -0
- package/dist/src/setup/boxes/model-capabilities.js +1 -0
- package/dist/src/setup/boxes/resolve-provisioning.js +1 -1
- package/dist/src/setup/boxes/select-model.d.ts +30 -8
- package/dist/src/setup/boxes/select-model.js +1 -1
- package/dist/src/setup/cli/option-row.js +1 -1
- package/dist/src/setup/cli/prompt-ui.d.ts +2 -0
- package/dist/src/setup/cli/prompt-ui.js +2 -2
- package/dist/src/setup/cli/rail-log.d.ts +4 -6
- package/dist/src/setup/cli/rail-log.js +3 -2
- package/dist/src/setup/connection-connector.js +2 -2
- package/dist/src/setup/flows/link.d.ts +13 -3
- package/dist/src/setup/flows/link.js +1 -1
- package/dist/src/setup/flows/login.js +1 -1
- package/dist/src/setup/flows/model-source-change.d.ts +38 -0
- package/dist/src/setup/flows/model-source-change.js +1 -0
- package/dist/src/setup/flows/model.d.ts +69 -65
- package/dist/src/setup/flows/model.js +1 -1
- package/dist/src/setup/flows/provider.d.ts +22 -0
- package/dist/src/setup/flows/provider.js +3 -3
- package/dist/src/setup/prompter.d.ts +2 -0
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/setup/slack-connect-lifecycle.js +1 -1
- package/dist/src/setup/slackbot.js +1 -1
- package/dist/src/setup/vercel-project.d.ts +6 -0
- package/dist/src/setup/vercel-project.js +0 -0
- package/dist/src/shared/dynamic-tool-definition.d.ts +1 -8
- package/dist/src/shared/errors.d.ts +5 -0
- package/dist/src/shared/errors.js +1 -1
- package/dist/src/shared/gateway-service-tier.d.ts +19 -0
- package/dist/src/shared/gateway-service-tier.js +1 -0
- package/dist/src/shared/model-summary.d.ts +12 -0
- package/dist/src/shared/model-summary.js +1 -0
- package/dist/src/shared/workflow-sandbox.d.ts +2 -0
- package/dist/src/shared/workflow-sandbox.js +1 -1
- package/dist/src/source-change/agent-config-ast.d.ts +54 -0
- package/dist/src/source-change/agent-config-ast.js +2 -0
- package/dist/src/source-change/agent-config-string-path.d.ts +18 -0
- package/dist/src/source-change/agent-config-string-path.js +2 -0
- package/dist/src/source-change/apply-agent-model-settings.d.ts +26 -0
- package/dist/src/source-change/apply-agent-model-settings.js +1 -0
- package/dist/src/source-change/apply-model-name.js +1 -2
- package/dist/src/source-change/static-source-change.d.ts +14 -0
- package/dist/src/source-change/static-source-change.js +1 -1
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.d.ts +0 -6
- 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.d.ts +0 -2
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/concepts/execution-model-and-durability.md +1 -1
- package/docs/concepts/sessions-runs-and-streaming.md +1 -1
- package/docs/getting-started.mdx +1 -1
- package/docs/guides/auth-and-route-protection.md +1 -1
- package/docs/guides/client/overview.mdx +1 -1
- package/docs/guides/client/streaming.mdx +1 -10
- package/docs/guides/deployment/meta.json +4 -0
- package/docs/guides/deployment/overview.md +61 -0
- package/docs/guides/deployment/self-hosting.md +88 -0
- package/docs/guides/deployment/vercel.mdx +90 -0
- package/docs/guides/dev-tui.md +8 -4
- package/docs/guides/dynamic-capabilities.md +2 -0
- package/docs/guides/frontend/nextjs.mdx +1 -1
- package/docs/guides/frontend/nuxt.mdx +1 -1
- package/docs/guides/frontend/overview.mdx +2 -5
- package/docs/guides/frontend/sveltekit.mdx +1 -1
- package/docs/guides/frontend/use-eve-agent-svelte.mdx +1 -4
- package/docs/guides/frontend/use-eve-agent-vue.mdx +1 -4
- package/docs/guides/instrumentation.md +1 -1
- package/docs/reference/cli.md +24 -2
- package/docs/tutorial/ship-it.mdx +1 -1
- package/package.json +2 -1
- package/docs/guides/deployment.md +0 -210
- /package/dist/src/cli/{dev/tui → ui}/live-region.d.ts +0 -0
- /package/dist/src/cli/{dev/tui → ui}/live-region.js +0 -0
- /package/dist/src/cli/{dev/tui → ui}/terminal-text.d.ts +0 -0
- /package/dist/src/cli/{dev/tui → ui}/terminal-text.js +0 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environment facts captured once per `eve dev` process, written into the
|
|
3
|
+
* diagnostic dump so a shared log always travels with the toolchain state
|
|
4
|
+
* that produced it.
|
|
5
|
+
*/
|
|
6
|
+
export interface DevEnvironmentInfo {
|
|
7
|
+
readonly eveVersion: string;
|
|
8
|
+
readonly nodeVersion: string;
|
|
9
|
+
readonly platform: string;
|
|
10
|
+
readonly vercelCliVersion?: string;
|
|
11
|
+
readonly vercelCliPath?: string;
|
|
12
|
+
/** Local durable session store measurements; absent when the directory does not exist yet. */
|
|
13
|
+
readonly sessionsDirectory?: {
|
|
14
|
+
readonly path: string;
|
|
15
|
+
readonly files: number;
|
|
16
|
+
readonly bytes: number;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Aggregate counters for the TUI process's session activity. Reported by
|
|
21
|
+
* the renderer at each turn boundary so the dump stays current even if
|
|
22
|
+
* the process dies mid-session.
|
|
23
|
+
*/
|
|
24
|
+
export interface DevSessionStats {
|
|
25
|
+
readonly prompts: number;
|
|
26
|
+
readonly inputTokens: number;
|
|
27
|
+
readonly outputTokens: number;
|
|
28
|
+
/** Tool invocations observed, keyed by tool name. */
|
|
29
|
+
readonly toolCalls: Readonly<Record<string, number>>;
|
|
30
|
+
/** Distinct subagent dispatches that produced observable output. */
|
|
31
|
+
readonly subagents: number;
|
|
32
|
+
}
|
|
33
|
+
export interface DevDiagnosticDump {
|
|
34
|
+
readonly path: string;
|
|
35
|
+
/** Project-relative reference, forward slashes on every platform. */
|
|
36
|
+
readonly displayPath: string;
|
|
37
|
+
updateSessionStats(stats: DevSessionStats): void;
|
|
38
|
+
close(): Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
export interface CreateDevDiagnosticDumpOptions {
|
|
41
|
+
/** Injectable environment collector; defaults to {@link collectDevEnvironmentInfo}. */
|
|
42
|
+
readonly environment?: () => Promise<DevEnvironmentInfo>;
|
|
43
|
+
readonly now?: () => Date;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Creates the environment dump paired with one dev diagnostic log: the same
|
|
47
|
+
* instance name with a `.dump` extension. The environment section is
|
|
48
|
+
* collected in the background and written as soon as it resolves; session
|
|
49
|
+
* stats rewrite the file on every update. Like the log sink, write failures
|
|
50
|
+
* disable the dump silently — never through stderr, which the TUI captures.
|
|
51
|
+
*/
|
|
52
|
+
export declare function createDevDiagnosticDump(appRoot: string, logPath: string, options?: CreateDevDiagnosticDumpOptions): DevDiagnosticDump;
|
|
53
|
+
/** Collects the real environment facts for {@link createDevDiagnosticDump}. */
|
|
54
|
+
export declare function collectDevEnvironmentInfo(appRoot: string): Promise<DevEnvironmentInfo>;
|
|
55
|
+
/**
|
|
56
|
+
* Counts files and total bytes under the app's local durable session store
|
|
57
|
+
* (`.eve/.workflow-data`). Returns `undefined` when the directory does not
|
|
58
|
+
* exist yet.
|
|
59
|
+
*/
|
|
60
|
+
export declare function measureSessionsDirectory(appRoot: string): Promise<DevEnvironmentInfo["sessionsDirectory"]>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{resolveInstalledPackageInfo}from"#internal/application/package.js";import{constants}from"node:fs";import{delimiter,join,relative,sep}from"node:path";import{access,readdir,stat,writeFile}from"node:fs/promises";import{LOCAL_WORKFLOW_WORLD_DATA_DIRECTORY_RELATIVE_PATH}from"#internal/workflow/local-world-data-directory.js";import{captureVercel,resolveVercelInvocation}from"#setup/primitives/run-vercel.js";function createDevDiagnosticDump(e,t,n={}){let r=t.replace(/\.log$/,`.dump`),o=n.now??(()=>new Date),s=o().getTime(),c,l,u=Promise.resolve(),d=!1,f=!1,write=()=>{if(f||d)return;let e=formatDump({at:o(),durationMs:o().getTime()-s,environment:c,stats:l});u=u.then(()=>writeFile(r,e,{encoding:`utf8`,mode:384})).catch(()=>{d=!0})};return write(),(n.environment??(()=>collectDevEnvironmentInfo(e)))().then(e=>{c=e,write()}).catch(()=>{}),{path:r,displayPath:relative(e,r).split(sep).join(`/`),updateSessionStats(e){l=e,write()},async close(){f||(write(),f=!0,await u)}}}function formatDump(e){let t={updatedAt:e.at.toISOString(),durationMs:e.durationMs,environment:e.environment??null,session:e.stats??null};return`${JSON.stringify(t,null,2)}\n`}async function collectDevEnvironmentInfo(t){let[n,r]=await Promise.all([detectVercelCli(t),measureSessionsDirectory(t)]),i={eveVersion:resolveInstalledPackageInfo().version,nodeVersion:process.version,platform:`${process.platform} ${process.arch}`,...n};return r!==void 0&&(i.sessionsDirectory=r),i}async function detectVercelCli(e){let t=resolveVercelInvocation(e),[n,r]=await Promise.all([captureVercel([`--version`],{cwd:e,nonInteractive:!0,timeoutMs:5e3}),t.command===`vercel`?findOnPath(`vercel`):Promise.resolve(t.command)]),i=n.ok?n.stdout:`${n.failure.stdout}\n${n.failure.stderr}`,a=/(\d+\.\d+\.\d+\S*)/.exec(i)?.[1],o={};return a!==void 0&&(o.vercelCliVersion=a),r!==void 0&&(o.vercelCliPath=r),o}async function findOnPath(e){let i=(process.env.PATH??``).split(delimiter).filter(e=>e.length>0);for(let n of i){let i=join(n,e);try{return await access(i,constants.X_OK),i}catch{}}}async function measureSessionsDirectory(e){let t=join(e,LOCAL_WORKFLOW_WORLD_DATA_DIRECTORY_RELATIVE_PATH),n;try{n=await readdir(t,{recursive:!0,withFileTypes:!0})}catch{return}let i=0,a=0;for(let e of n)if(e.isFile()){i+=1;try{a+=(await stat(join(e.parentPath,e.name))).size}catch{}}return{path:LOCAL_WORKFLOW_WORLD_DATA_DIRECTORY_RELATIVE_PATH,files:i,bytes:a}}export{collectDevEnvironmentInfo,createDevDiagnosticDump,measureSessionsDirectory};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { LogLevel } from "#internal/logging.js";
|
|
2
|
+
import type { JsonObject } from "#shared/json.js";
|
|
3
|
+
export type DevDiagnosticSource = "stderr" | "stdout" | "sandbox" | "workflow" | "tool" | "log";
|
|
4
|
+
/** Captured output or a failure summary attributed to one capture point. */
|
|
5
|
+
export interface DevDiagnosticOutputEntry {
|
|
6
|
+
readonly source: Exclude<DevDiagnosticSource, "log">;
|
|
7
|
+
readonly summary?: string;
|
|
8
|
+
readonly detail: string;
|
|
9
|
+
/** Structured remediation carried by cataloged failures. */
|
|
10
|
+
readonly hint?: string;
|
|
11
|
+
}
|
|
12
|
+
/** One structured record from eve's own logger. */
|
|
13
|
+
export interface DevDiagnosticLogRecordEntry {
|
|
14
|
+
readonly source: "log";
|
|
15
|
+
readonly level: LogLevel;
|
|
16
|
+
readonly namespace: string;
|
|
17
|
+
readonly message: string;
|
|
18
|
+
readonly fields?: JsonObject;
|
|
19
|
+
}
|
|
20
|
+
export type DevDiagnosticEntry = DevDiagnosticOutputEntry | DevDiagnosticLogRecordEntry;
|
|
21
|
+
export interface DevDiagnosticSink {
|
|
22
|
+
readonly path: string;
|
|
23
|
+
/**
|
|
24
|
+
* Project-relative reference with forward slashes on every platform:
|
|
25
|
+
* it is a display and correlation token (transcript pointers,
|
|
26
|
+
* `eve logs <ref>` input), not a filesystem path.
|
|
27
|
+
*/
|
|
28
|
+
readonly displayPath: string;
|
|
29
|
+
append(entry: DevDiagnosticEntry): void;
|
|
30
|
+
close(): Promise<void>;
|
|
31
|
+
}
|
|
32
|
+
export interface CreateDevDiagnosticSinkOptions {
|
|
33
|
+
readonly now?: () => Date;
|
|
34
|
+
readonly pid?: number;
|
|
35
|
+
}
|
|
36
|
+
/** Creates the local, process-owned diagnostics file used by `eve dev`. */
|
|
37
|
+
export declare function createDevDiagnosticSink(appRoot: string, options?: CreateDevDiagnosticSinkOptions): Promise<DevDiagnosticSink>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{join,relative,sep}from"node:path";import{chmod,mkdir,open}from"node:fs/promises";async function createDevDiagnosticSink(t,n={}){let o=join(t,`.eve`,`logs`);await mkdir(o,{recursive:!0,mode:448}),await chmod(o,448);let s=n.now?.()??new Date,c=n.pid??process.pid,l=join(o,`dev-${s.toISOString().replaceAll(`:`,`-`)}-${c}.log`);return createOpenSink(t,l,await open(l,`wx`,384),()=>n.now?.()??new Date)}function createOpenSink(e,r,i,a){let o=Promise.resolve(),s=!1,c=!1;return{path:r,displayPath:relative(e,r).split(sep).join(`/`),append(e){if(c||s)return;let t=formatDiagnosticEntry(e,a());o=o.then(()=>i.appendFile(t,`utf8`)).catch(()=>{s=!0})},async close(){c||(c=!0,await o,await i.close())}}}function formatDiagnosticEntry(e,t){return`${JSON.stringify({at:t.toISOString(),...e})}\n`}export{createDevDiagnosticSink};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type LogRecord } from "#internal/logging.js";
|
|
2
|
+
import { type CreateDevDiagnosticDumpOptions } from "./diagnostic-dump.js";
|
|
3
|
+
import { type DevDiagnosticEntry } from "./diagnostic-sink.js";
|
|
4
|
+
/**
|
|
5
|
+
* The one diagnostics recorder an `eve dev` process owns: the per-process
|
|
6
|
+
* JSONL log (sink), its environment dump, session-stats accumulation, and
|
|
7
|
+
* ownership of eve's structured log records. The TUI holds a single
|
|
8
|
+
* reference and calls in at its capture points; everything stateful about
|
|
9
|
+
* diagnostics lives here, not in the renderer.
|
|
10
|
+
*/
|
|
11
|
+
export interface DevDiagnostics {
|
|
12
|
+
/** Project-relative path of the diagnostic log, for transcript pointers. */
|
|
13
|
+
readonly displayPath: string;
|
|
14
|
+
/** Appends one captured record to the per-process diagnostic log. */
|
|
15
|
+
append(entry: DevDiagnosticEntry): void;
|
|
16
|
+
recordPrompt(): void;
|
|
17
|
+
recordStepUsage(usage: {
|
|
18
|
+
inputTokens?: number;
|
|
19
|
+
outputTokens?: number;
|
|
20
|
+
} | undefined): void;
|
|
21
|
+
recordToolCall(toolName: string): void;
|
|
22
|
+
recordSubagentDispatch(callId: string): void;
|
|
23
|
+
/** Rewrites the environment dump with the stats accumulated so far. */
|
|
24
|
+
reportStats(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Takes ownership of eve's structured log records: each record is
|
|
27
|
+
* persisted to the log with its structure intact and then handed to
|
|
28
|
+
* `onRecord` for display. While subscribed, records never reach the
|
|
29
|
+
* console, so a host that also scrapes stderr sees each record exactly
|
|
30
|
+
* once.
|
|
31
|
+
*/
|
|
32
|
+
subscribeLogRecords(onRecord: (record: LogRecord) => void): void;
|
|
33
|
+
unsubscribeLogRecords(): void;
|
|
34
|
+
close(): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Creates the diagnostics recorder for one `eve dev` process: the
|
|
38
|
+
* exclusive per-process log plus its same-instance environment dump.
|
|
39
|
+
* Rejects when the log cannot be created (callers run without
|
|
40
|
+
* diagnostics rather than crash the TUI).
|
|
41
|
+
*/
|
|
42
|
+
export declare function createDevDiagnostics(appRoot: string, options?: CreateDevDiagnosticDumpOptions): Promise<DevDiagnostics>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createDevDiagnosticDump}from"./diagnostic-dump.js";import{createDevDiagnosticSink}from"./diagnostic-sink.js";import{setLogRecordSubscriber}from"#internal/logging.js";async function createDevDiagnostics(n,r={}){let i=await createDevDiagnosticSink(n);return new DevDiagnosticsRecorder(i,createDevDiagnosticDump(n,i.path,r))}var DevDiagnosticsRecorder=class{displayPath;#e;#t;#n=0;#r=0;#i=0;#a=new Map;#o=new Set;constructor(e,t){this.displayPath=e.displayPath,this.#e=e,this.#t=t}append(e){this.#e.append(e)}recordPrompt(){this.#n+=1}recordStepUsage(e){this.#r+=e?.inputTokens??0,this.#i+=e?.outputTokens??0}recordToolCall(e){this.#a.set(e,(this.#a.get(e)??0)+1)}recordSubagentDispatch(e){this.#o.add(e)}reportStats(){let e={prompts:this.#n,inputTokens:this.#r,outputTokens:this.#i,toolCalls:Object.fromEntries(this.#a),subagents:this.#o.size};this.#t.updateSessionStats(e)}subscribeLogRecords(e){setLogRecordSubscriber(t=>{let n={source:`log`,level:t.level,namespace:t.namespace,message:t.message};this.#e.append(t.fields===void 0?n:{...n,fields:t.fields}),e(t)})}unsubscribeLogRecords(){setLogRecordSubscriber(void 0)}async close(){await this.#t.close(),await this.#e.close()}};export{createDevDiagnostics};
|
|
@@ -9,9 +9,11 @@
|
|
|
9
9
|
* boxes anywhere. Every returned row is already styled and fits within the
|
|
10
10
|
* given width, so the live region can place rows verbatim.
|
|
11
11
|
*/
|
|
12
|
+
import type { ToolDetailLine } from "./line-diff.js";
|
|
12
13
|
import type { Theme } from "./theme.js";
|
|
14
|
+
import type { ToolGroupPresentation } from "./tool-presentation.js";
|
|
13
15
|
export type ToolStatus = "running" | "done" | "error" | "denied" | "approval";
|
|
14
|
-
export type BlockKind = "user" | "assistant" | "reasoning" | "tool" | "error" | "notice" | "warning" | "result" | "flow" | "command" | "question" | "subagent" | "subagent-step" | "subagent-tool" | "connection-auth" | "sandbox" | "log" | "agent-header";
|
|
16
|
+
export type BlockKind = "user" | "assistant" | "reasoning" | "tool" | "error" | "notice" | "warning" | "result" | "flow" | "command" | "question" | "subagent" | "subagent-step" | "subagent-tool" | "subagent-close" | "connection-auth" | "sandbox" | "log" | "turn-stats" | "session-boundary" | "todo-list" | "agent-header";
|
|
15
17
|
/**
|
|
16
18
|
* One renderable transcript unit. Fields are interpreted per `kind`; unset
|
|
17
19
|
* fields are simply omitted from the rendered output.
|
|
@@ -22,10 +24,12 @@ export interface Block {
|
|
|
22
24
|
id?: string;
|
|
23
25
|
/** Nesting depth: 0 = top level, 1 = inside a subagent, etc. */
|
|
24
26
|
depth?: number;
|
|
25
|
-
/** Whether the block is still streaming / mutating (drives the
|
|
27
|
+
/** Whether the block is still streaming / mutating (drives the activity pulse). */
|
|
26
28
|
live?: boolean;
|
|
27
29
|
/** Primary label — tool name, subagent name, log source, error title. */
|
|
28
30
|
title?: string;
|
|
31
|
+
/** Past-tense tool label swapped in once the call settles successfully. */
|
|
32
|
+
doneTitle?: string;
|
|
29
33
|
/** Compact secondary text — summarized tool args. */
|
|
30
34
|
subtitle?: string;
|
|
31
35
|
/** Main multi-line content (markdown for prose, plain for logs). */
|
|
@@ -39,6 +43,8 @@ export interface Block {
|
|
|
39
43
|
* rendered dim beneath the headline, capped to a handful of lines.
|
|
40
44
|
*/
|
|
41
45
|
detail?: string;
|
|
46
|
+
/** Structured remediation shown between an error's body and its detail. */
|
|
47
|
+
hint?: string;
|
|
42
48
|
/** Tool, connection, or synthetic command lifecycle status. */
|
|
43
49
|
status?: ToolStatus;
|
|
44
50
|
/** When true, treat `body` as pre-styled and only wrap + indent it. */
|
|
@@ -47,18 +53,64 @@ export interface Block {
|
|
|
47
53
|
collapsed?: boolean;
|
|
48
54
|
/** When true, expand tool input/output instead of summarizing. */
|
|
49
55
|
expanded?: boolean;
|
|
56
|
+
/** Captured-log visibility used for concise-vs-raw diagnostic replay. */
|
|
57
|
+
logVisibility?: "stderr-only" | "all-only";
|
|
50
58
|
/** Raw tool input / output for the expanded view. */
|
|
51
59
|
toolInput?: unknown;
|
|
52
60
|
toolOutput?: unknown;
|
|
61
|
+
/** Original execution name, kept separate from a semantic display title. */
|
|
62
|
+
toolName?: string;
|
|
63
|
+
/** Optional aggregation metadata; execution state remains on this call's block. */
|
|
64
|
+
toolGroup?: ToolGroupPresentation;
|
|
65
|
+
/** Salient body lines rendered behind the `│` rail under the tool header. */
|
|
66
|
+
detailLines?: readonly ToolDetailLine[];
|
|
67
|
+
/** When true, `detailLines` stay visible after the call settles (writes). */
|
|
68
|
+
keepDetailWhenDone?: boolean;
|
|
69
|
+
/** Links a subagent section's header and children so calls can coalesce. */
|
|
70
|
+
subagentCallId?: string;
|
|
71
|
+
/**
|
|
72
|
+
* Monotonic activity stamp, bumped on every push and in-place update.
|
|
73
|
+
* Recency windows key on it so a parallel-announced call that just
|
|
74
|
+
* settled counts as newer than a later-announced one still idle.
|
|
75
|
+
*/
|
|
76
|
+
updateSeq?: number;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* What the renderers actually draw: an execution {@link Block} plus the
|
|
80
|
+
* synthesized presentation the display grouping may attach. Only the
|
|
81
|
+
* grouping layer creates these fields, so an execution block can never
|
|
82
|
+
* smuggle display state — the type boundary enforces what used to be a
|
|
83
|
+
* comment.
|
|
84
|
+
*/
|
|
85
|
+
export interface DisplayBlock extends Block {
|
|
86
|
+
/** Items listed when equivalent tool calls are coalesced into one row. */
|
|
87
|
+
toolGroupItems?: readonly ToolGroupItem[];
|
|
88
|
+
/**
|
|
89
|
+
* Stand-in for this many earlier sibling rows elided from a capped
|
|
90
|
+
* subagent run; renders as a single dim `… +N more` line.
|
|
91
|
+
*/
|
|
92
|
+
elided?: number;
|
|
93
|
+
/**
|
|
94
|
+
* This block is the last of its section, so its final row swaps the
|
|
95
|
+
* nesting rule for the closing `└` — the rail ends on the newest child
|
|
96
|
+
* instead of a bare corner row.
|
|
97
|
+
*/
|
|
98
|
+
closesRail?: boolean;
|
|
99
|
+
}
|
|
100
|
+
/** One coalesced call's row beneath an aggregated tool header. */
|
|
101
|
+
export interface ToolGroupItem {
|
|
102
|
+
readonly text: string;
|
|
103
|
+
/** Per-call failure summary, present when a failed batch is aggregated. */
|
|
104
|
+
readonly result?: string;
|
|
53
105
|
}
|
|
54
106
|
export interface RenderBlockContext {
|
|
55
|
-
/** Current
|
|
56
|
-
|
|
107
|
+
/** Current shared square-pulse frame for live activity blocks. */
|
|
108
|
+
activityPulse: string;
|
|
57
109
|
/**
|
|
58
110
|
* Kind and title of the block rendered immediately above this one. Lets a
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
111
|
+
* sandbox block detect that it continues a run (label suppressed, lines
|
|
112
|
+
* hang under the previous block's label) without any mutable run state —
|
|
113
|
+
* each captured write stays its own immediately-committed block.
|
|
62
114
|
*/
|
|
63
115
|
previous?: {
|
|
64
116
|
kind: BlockKind;
|
|
@@ -69,7 +121,7 @@ export interface RenderBlockContext {
|
|
|
69
121
|
* Renders a block to its terminal rows. Each row is fully styled and clipped
|
|
70
122
|
* to `width` visible columns.
|
|
71
123
|
*/
|
|
72
|
-
export declare function renderBlockLines(block:
|
|
124
|
+
export declare function renderBlockLines(block: DisplayBlock, width: number, theme: Theme, context: RenderBlockContext): string[];
|
|
73
125
|
/**
|
|
74
126
|
* The setup attention line (`⚠ 1 setup issue: … · /model`): yellow glyph, body
|
|
75
127
|
* at full intensity, slash commands painted blue so the fix reads as actionable
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{isPromptControlCommand}from"./prompt-commands.js";import{
|
|
2
|
-
`)}}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,
|
|
3
|
-
`).flatMap(e=>wrapVisibleLine(e,
|
|
4
|
-
`),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 renderAttentionRows(e,t,n){let r=n.colors.yellow(n.glyph.warning);return wrap(e,t-2).map((e,t)=>`${t===0?r:` `} ${paintCommands(e,n)}`)}function renderWarning(e,t,n){return renderAttentionRows(e.body??``,t,n)}function paintCommands(t,n){return t.replace(/\/[a-z:-]+/g,t=>isPromptControlCommand(t)?n.colors.blue(t):t)}function renderCommand(e,t){let n=t.colors,r=e.status===`error`?`${n.red(t.glyph.error)} `:``;return[`${n.cyan(t.glyph.user)} ${r}${n.blue(e.body??``)}`]}function renderFlow(e,t,n){let r=n.colors,i=e.title??`info`,a=i===`success`?r.green(n.glyph.success):i===`warning`?r.yellow(n.glyph.warning):i===`error`?r.red(n.glyph.error):r.dim(n.glyph.dot),o=wrap(e.body??``,t-2),paint=e=>i===`info`?r.dim(e):e;return o.map((e,t)=>`${t===0?a:` `} ${paint(e)}`)}function renderResult(e,t,n){let r=n.colors.dim(n.glyph.elbow),i=wrap(e.body??``,t-7);if(i.length===0)return[` ${r}`];let dim=e=>n.colors.dim(e.replaceAll(`\x1B[22m`,`\x1B[22m\x1B[2m`));return i.map((e,t)=>t===0?` ${r} ${dim(e)}`:` ${dim(e)}`)}function renderPreformatted(e,t,n){let
|
|
5
|
-
`))for(let e of wrapVisibleLine(n,t-
|
|
6
|
-
`),f=[];for(let e of d){let
|
|
7
|
-
`)
|
|
8
|
-
`).flatMap(e=>wrapVisibleLine(e,Math.max(1,t)))}function truncatePlain(e,
|
|
1
|
+
import{isPromptControlCommand}from"./prompt-commands.js";import{renderMarkdown}from"./markdown.js";import{elisionText}from"./rail.js";import{renderTool}from"./tool-rows.js";import{clipVisible,sliceVisible,visibleLength,wrapVisibleLine}from"#cli/ui/terminal-text.js";function renderBlockLines(e,t,n,r){let i=e.depth??0,a=nestingPrefix(i,n),s=renderBody(e,Math.max(8,t-visibleLength(a)),n,r);if(e.closesRail===!0&&i>0){let e=closingPrefix(i,n);return s.map((t,n)=>`${n===s.length-1?e:a}${t}`)}return s.map(e=>`${a}${e}`)}function nestingPrefix(e,t){return e<=0?``:` ${`${t.colors.dim(t.glyph.rule)} `.repeat(e)}`}function closingPrefix(e,t){return` ${`${t.colors.dim(t.glyph.rule)} `.repeat(e-1)}${t.colors.dim(t.glyph.corner)} `}function renderBody(e,t,a,o){if(e.elided!==void 0&&e.kind===`subagent-step`)return[` ${elisionText(e.elided,a)}`];switch(e.kind){case`user`:return renderUser(e,t,a);case`assistant`:case`subagent-step`:return renderProse(e,t,a);case`reasoning`:return renderReasoning(e,t,a);case`tool`:case`subagent-tool`:return renderTool(e,t,a,o);case`error`:return renderError(e,t,a);case`notice`:return renderNotice(e,t,a);case`warning`:return renderWarning(e,t,a);case`result`:return renderResult(e,t,a);case`flow`:return renderFlow(e,t,a);case`command`:return renderCommand(e,a);case`question`:case`connection-auth`:return renderPreformatted(e,t,a);case`sandbox`:return renderSandbox(e,t,a,o);case`log`:return renderLog(e,t,a);case`subagent`:return renderSubagentHeader(e,t,a);case`subagent-close`:{let n=` ${a.colors.dim(a.glyph.corner)}`;return e.body!==void 0&&e.body.length>0?[clipVisible(`${n} ${a.colors.dim(e.body)}`,Math.max(1,t))]:[n]}case`turn-stats`:return renderTurnStats(e,t,a);case`session-boundary`:case`todo-list`:case`agent-header`:return(e.body??``).split(`
|
|
2
|
+
`)}}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,n,r){let i=[],o=e.kind===`subagent-step`;if(o&&e.collapsed===!0){let t=firstNonEmptyLine(e.body)??(e.reasoning===void 0?void 0:firstNonEmptyLine(e.reasoning));return t===void 0?[]:[r.colors.dim(sliceVisible(t,Math.max(1,n)))]}let c=o?``:`${r.colors.bold(r.glyph.brand)} `,l=o?``:` `;e.reasoning&&e.reasoning.trim().length>0&&i.push(...renderReasoningLines(e.reasoning,n,r));let u=(e.body??``).trim();return u.length===0&&i.length===0?[`${c}${r.colors.dim(`thinking${r.glyph.ellipsis}`)}`]:(u.length>0&&renderMarkdown(u,n-l.length).split(`
|
|
3
|
+
`).flatMap(e=>wrapVisibleLine(e,n-l.length)).forEach((e,t)=>{t===0&&!o&&i.length===0?i.push(`${c}${e}`):i.push(`${l}${e}`)}),i.length>0?i:[`${c}`])}function renderReasoning(e,t,n){return e.collapsed?[`${n.colors.gray(n.glyph.reasoning)} ${n.colors.dim(e.title??`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 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)}`);if(e.hint!==void 0&&e.hint.trim().length>0)for(let[r,i]of wrap(e.hint,t-4).entries()){let e=r===0?`${n.glyph.arrow} `:` `;a.push(` ${n.colors.cyan(`${e}${i}`)}`)}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(`
|
|
4
|
+
`),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 renderAttentionRows(e,t,n){let r=n.colors.yellow(n.glyph.warning);return wrap(e,t-2).map((e,t)=>`${t===0?r:` `} ${paintCommands(e,n)}`)}function renderWarning(e,t,n){return renderAttentionRows(e.body??``,t,n)}function paintCommands(t,n){return t.replace(/\/[a-z:-]+/g,t=>isPromptControlCommand(t)?n.colors.blue(t):t)}function renderCommand(e,t){let n=t.colors,r=e.status===`error`?`${n.red(t.glyph.error)} `:``;return[`${n.cyan(t.glyph.user)} ${r}${n.blue(e.body??``)}`]}function renderFlow(e,t,n){let r=n.colors,i=e.title??`info`,a=i===`success`?r.green(n.glyph.success):i===`warning`?r.yellow(n.glyph.warning):i===`error`?r.red(n.glyph.error):r.dim(n.glyph.dot),o=wrap(e.body??``,t-2),paint=e=>i===`info`?r.dim(e):e;return o.map((e,t)=>`${t===0?a:` `} ${paint(e)}`)}function renderResult(e,t,n){let r=n.colors.dim(n.glyph.elbow),i=wrap(e.body??``,t-7);if(i.length===0)return[` ${r}`];let dim=e=>n.colors.dim(e.replaceAll(`\x1B[22m`,`\x1B[22m\x1B[2m`));return i.map((e,t)=>t===0?` ${r} ${dim(e)}`:` ${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)),i=e.kind===`question`?` `:` `,a=wrap(e.title??``,t-2),o=a.length===0?[`${r} `]:a.map((e,t)=>t===0?`${r} ${n.colors.bold(e)}`:` ${n.colors.bold(e)}`);for(let n of(e.body??``).split(`
|
|
5
|
+
`))for(let e of wrapVisibleLine(n,Math.max(1,t-i.length)))o.push(`${i}${e}`);return o}function renderSandbox(e,t,n,r){let i=n.colors.cyan(n.glyph.rule),a=n.colors.dim(`sandbox ${n.glyph.dot} `),c=visibleLength(a),l=` `.repeat(c),u=r.previous?.kind===`sandbox`,d=(e.body??``).split(`
|
|
6
|
+
`),f=[];for(let e of d){let r=wrapVisibleLine(e,Math.max(1,t-2-c));for(let e of r){let t=f.length===0&&!u?a:l;f.push(`${i} ${t}${n.colors.gray(e)}`)}}return f.length>0?f:[`${i}`]}function renderLog(e,t,r){let i=e.title===`stderr`,a=i?r.colors.red:r.colors.gray,o=r.colors.dim(r.glyph.rule),c=i?`stderr`:`stdout`,l=[`${r.colors.dim(r.glyph.reasoning)} ${r.colors.dim(c)}`];e.elided!==void 0&&e.elided>0&&l.push(`${o} ${elisionText(e.elided,r)}`);for(let n of(e.body??``).split(`
|
|
7
|
+
`))for(let e of wrapVisibleLine(n,Math.max(1,t-2)))l.push(`${o} ${r.colors.dim(a(e))}`);return l}function renderTurnStats(e,t,n){let r=`${n.glyph.corner} ${e.body??``}`;return[n.colors.dim(truncatePlain(r,Math.max(1,t)))]}function renderSubagentHeader(e,t,n){let r=truncatePlain(e.title===void 0||e.title===`agent`?`self`:e.title,Math.max(8,t-16)),i=e.subtitle!==void 0&&e.subtitle.startsWith(`#`),a=i?`:${e.subtitle.slice(1)}`:``,o=` ${e.status===`done`?n.colors.green(n.glyph.subagent):n.colors.orange(n.glyph.subagent)} ${n.colors.bold(`subagent(${r}${a})`)}`;return!i&&e.subtitle!==void 0&&e.subtitle.length>0&&(o+=` ${n.colors.dim(e.subtitle)}`),[o]}function firstNonEmptyLine(e){return e===void 0?void 0:e.split(/\r?\n/u).find(e=>e.trim().length>0)?.trim()}function wrap(e,t){return e.trim().length===0?[]:e.split(`
|
|
8
|
+
`).flatMap(e=>wrapVisibleLine(e,Math.max(1,t)))}function truncatePlain(e,t){return visibleLength(e)<=t?e:sliceVisible(e,t)}export{renderAttentionRows,renderBlockLines};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{sliceVisible,visibleLength}from"
|
|
1
|
+
import{sliceVisible,visibleLength}from"#cli/ui/terminal-text.js";import{renderCursorRow}from"#setup/cli/option-row.js";function typeaheadFor(e,t,n){let r=matchingCommands(e,t),i=n===void 0?void 0:n.matches[n.selectedIndex],a=i===void 0?-1:r.indexOf(i);return{query:t,matches:r,selectedIndex:a>=0?a:0,dismissed:n!==void 0&&n.dismissed&&n.query===t}}function matchingCommands(e,t){if(!t.startsWith(`/`)||/\s/.test(t))return[];let n=t.slice(1);return e.filter(e=>[e.name,...e.aliases].some(e=>e.startsWith(n)))}function isTypeaheadOpen(e){return e.matches.length>0&&!e.dismissed}function moveTypeaheadSelection(e,t){let n=e.matches.length;if(n===0)return e;let r=(e.selectedIndex+t+n)%n;return{...e,selectedIndex:r}}function dismissTypeahead(e){return e.dismissed?e:{...e,dismissed:!0}}function selectedTypeaheadCommand(e){return e.matches[e.selectedIndex]}function typeaheadCompletion(e){return`/${e.name}${e.takesArgument?` `:``}`}function inlineCommandHint(e){if(e.dismissed||e.matches.length!==1)return;let t=e.matches[0],n=e.query.startsWith(`/`)?e.query.slice(1):e.query;if([t.name,...t.aliases].includes(n))return t.argumentHint??``}function renderCommandSuggestions(r,i,a){let o=i.colors,s=r.matches.length,c=Math.min(s,10),l=Math.max(0,Math.min(r.selectedIndex-Math.floor(c/2),s-c)),u=Math.min(l+c,s),d=r.matches.slice(l,u),invocation=e=>{let t=e.aliases.map(e=>` (/${e})`).join(``);return`/${e.name}${t}`},f=Math.max(...d.map(e=>invocation(e).length))+2;return d.map((e,t)=>{let a=l+t===r.selectedIndex,s=`/${e.name}`,c=renderCursorRow(a?`${i.glyph.selectedPointer} ${s}`:` ${s}`,a,o),u=invocation(e).slice(`/${e.name}`.length),d=` `.repeat(f-invocation(e).length);return a&&(u.startsWith(` `)?u=u.slice(1):d=d.slice(1)),`${c}${o.dim(u)}${d}${o.dim(e.description)}`}).map(n=>visibleLength(n)>a?sliceVisible(n,a):n)}export{dismissTypeahead,inlineCommandHint,isTypeaheadOpen,moveTypeaheadSelection,renderCommandSuggestions,selectedTypeaheadCommand,typeaheadCompletion,typeaheadFor};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type DiagnosticPresentation = {
|
|
2
|
+
readonly kind: "inline";
|
|
3
|
+
readonly text: string;
|
|
4
|
+
} | {
|
|
5
|
+
readonly kind: "stored";
|
|
6
|
+
readonly summary: string;
|
|
7
|
+
/** First error-naming line of the collapsed body, when one exists. */
|
|
8
|
+
readonly headline?: string;
|
|
9
|
+
readonly omittedLines: number;
|
|
10
|
+
readonly path: string;
|
|
11
|
+
};
|
|
12
|
+
/** Chooses whether process diagnostics stay inline or collapse to the local sink. */
|
|
13
|
+
export declare function presentDiagnostic(text: string, path: string): DiagnosticPresentation;
|
|
14
|
+
export declare function formatStoredDiagnostic(presentation: Extract<DiagnosticPresentation, {
|
|
15
|
+
kind: "stored";
|
|
16
|
+
}>): string;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
const ERROR_HEADLINE_PATTERN=/^\s*(?:message|name):\s*\S|^\s*[A-Z][\w$]*Error\b/u;function presentDiagnostic(t,n){let r=t.split(`
|
|
2
|
+
`);if(r.length<=4&&t.length<=600)return{kind:`inline`,text:t};let i=r.findIndex(e=>e.trim().length>0),a=i===-1?`Diagnostic output`:r[i].trim(),o=r.slice(i+1).find(t=>ERROR_HEADLINE_PATTERN.test(t))?.trim(),s=1+(o===void 0?0:1),c={kind:`stored`,summary:clip(a),omittedLines:Math.max(0,r.length-s),path:n};return o===void 0?c:{...c,headline:clip(o)}}function formatStoredDiagnostic(e){let t=e.omittedLines,n=t===0?`diagnostic details`:`${t} diagnostic line${t===1?``:`s`}`,r=[e.summary];return e.headline!==void 0&&r.push(e.headline),r.push(`… ${n} · details: ${e.path}`),r.join(`
|
|
3
|
+
`)}function clip(e){return e.length<=240?e:`${e.slice(0,239)}…`}export{formatStoredDiagnostic,presentDiagnostic};
|
|
@@ -40,6 +40,23 @@ export declare function failureKey(event: FailureStreamEvent): string;
|
|
|
40
40
|
* which case the message stands alone instead of reading `Code: Code: …`.
|
|
41
41
|
*/
|
|
42
42
|
export declare function formatFailureMessage(event: FailureStreamEvent): string;
|
|
43
|
+
/**
|
|
44
|
+
* The structured fields the harness attaches to failure-event details:
|
|
45
|
+
* the semantic-error catalog's identity and remediation, plus the raw
|
|
46
|
+
* inspection dump for unrecognized failures. One projection so every
|
|
47
|
+
* consumer narrows the untyped `details` payload the same way.
|
|
48
|
+
*/
|
|
49
|
+
export interface FailureDetails {
|
|
50
|
+
readonly semanticErrorId?: string;
|
|
51
|
+
readonly hint?: string;
|
|
52
|
+
readonly detail?: string;
|
|
53
|
+
}
|
|
54
|
+
export declare function failureDetails(event: FailureStreamEvent): FailureDetails;
|
|
55
|
+
/**
|
|
56
|
+
* Extracts the structured remediation hint attached to a failure event's
|
|
57
|
+
* details by the semantic-error catalog, if any.
|
|
58
|
+
*/
|
|
59
|
+
export declare function formatFailureHint(event: FailureStreamEvent): string | undefined;
|
|
43
60
|
/**
|
|
44
61
|
* Extracts the diagnostic dump attached to a failure event, if any.
|
|
45
62
|
*
|
|
@@ -51,20 +68,8 @@ export declare function formatFailureMessage(event: FailureStreamEvent): string;
|
|
|
51
68
|
*/
|
|
52
69
|
export declare function formatFailureDetail(event: FailureStreamEvent): string | undefined;
|
|
53
70
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* the diagnostic detail along with it. The variant is picked off the summary
|
|
58
|
-
* message the harness wrote, so a stale key, an expired OIDC token, and
|
|
59
|
-
* missing credentials each get the fix that actually applies.
|
|
60
|
-
*/
|
|
61
|
-
export declare function formatGatewayAuthFailureNotice(event: FailureStreamEvent): string;
|
|
62
|
-
/**
|
|
63
|
-
* Recognizes a model-call failure caused by AI Gateway authentication. The
|
|
64
|
-
* primary signal is the machine-readable `gatewayName` the harness merges
|
|
65
|
-
* into every model-call failure's details (`extractModelCallErrorDetails`);
|
|
66
|
-
* the summary name is the fallback for payloads whose gateway error was not
|
|
67
|
-
* preserved on the cause chain. Both identifiers are imported from the
|
|
68
|
-
* harness module that writes them, so the two sides cannot drift.
|
|
71
|
+
* The surface-local hint for a failure, when the TUI can offer a better
|
|
72
|
+
* fix than the catalog's (currently: gateway credential failures resolve
|
|
73
|
+
* in-session via `/model`). Returns `undefined` to keep the harness hint.
|
|
69
74
|
*/
|
|
70
|
-
export declare function
|
|
75
|
+
export declare function localFailureHint(event: FailureStreamEvent): string | undefined;
|
|
@@ -1 +1 @@
|
|
|
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 failureDetails(e){let t=e.data.details;if(typeof t!=`object`||!t)return{};let n=t,r={};return typeof n.semanticErrorId==`string`&&(r.semanticErrorId=n.semanticErrorId),typeof n.hint==`string`&&n.hint.trim().length>0&&(r.hint=n.hint.trim()),typeof n.detail==`string`&&(r.detail=n.detail),r}function formatFailureHint(e){return failureDetails(e).hint}function formatFailureDetail(e){let t=failureDetails(e).detail;if(t===void 0)return;let n=t.trim();if(!(n.length===0||n===e.data.message.trim()))return n}const LOCAL_HINT_OVERRIDES={"gateway-auth-invalid-api-key":`Run /model to refresh credentials, or update AI_GATEWAY_API_KEY in .env.local (a stale shell export can shadow it).`,"gateway-auth-invalid-oidc-token":`Run /model to refresh the OIDC token, or set AI_GATEWAY_API_KEY in .env.local.`,"gateway-auth-missing-credentials":`Run /model to connect this to a project and refresh AI Gateway credentials, or set AI_GATEWAY_API_KEY manually in .env.local.`};function localFailureHint(t){let n=failureDetails(t).semanticErrorId;return n===void 0?void 0:LOCAL_HINT_OVERRIDES[n]}export{InterruptedError,failureDetails,failureKey,formatFailureDetail,formatFailureHint,formatFailureMessage,interruptedError,isAbortLikeError,isInterruptedError,localFailureHint};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session-local knowledge of file contents, so the write block can show a
|
|
3
|
+
* real diff without any protocol addition. Two feeds keep it current: every
|
|
4
|
+
* `write_file` input is a full replacement (exact), and every full-file
|
|
5
|
+
* `read_file` result reconstructs to the file's exact lines. Files touched
|
|
6
|
+
* outside these two paths (e.g. by `bash`) are invisible here — a write over
|
|
7
|
+
* unknown prior content renders plain rather than pretending to be a diff.
|
|
8
|
+
*/
|
|
9
|
+
export declare class FileContentCache {
|
|
10
|
+
#private;
|
|
11
|
+
/**
|
|
12
|
+
* Records one write and returns the content it replaced. Tool blocks
|
|
13
|
+
* re-render on every lifecycle event of the same call, so a repeated
|
|
14
|
+
* observation of `callId` keeps returning the original previous content
|
|
15
|
+
* instead of diffing the write against itself.
|
|
16
|
+
*/
|
|
17
|
+
observeWrite(input: {
|
|
18
|
+
path: string;
|
|
19
|
+
content: string;
|
|
20
|
+
callId: string;
|
|
21
|
+
}): string | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Forgets everything. A new conversation runs against a fresh session —
|
|
24
|
+
* possibly a fresh sandbox — so stale bases would produce confidently
|
|
25
|
+
* wrong diffs.
|
|
26
|
+
*/
|
|
27
|
+
clear(): void;
|
|
28
|
+
/**
|
|
29
|
+
* Records a read result when it provably covers the whole file: not
|
|
30
|
+
* truncated, starting at line 1, with exactly `totalLines` numbered lines.
|
|
31
|
+
* Partial or truncated reads are ignored — caching them would produce
|
|
32
|
+
* confidently wrong diffs later.
|
|
33
|
+
*/
|
|
34
|
+
observeRead(output: unknown): void;
|
|
35
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
const MAX_CACHED_CONTENT_CHARS=2e5;var FileContentCache=class{#e=new Map;observeWrite(t){let n=this.#e.get(t.path);if(n?.writerCallId===t.callId)return n.previous;if(t.content.length>MAX_CACHED_CONTENT_CHARS){this.#e.delete(t.path);return}let r=n?.content,i={content:t.content,writerCallId:t.callId};return r!==void 0&&(i.previous=r),this.#e.set(t.path,i),r}clear(){this.#e.clear()}observeRead(t){let n=readFileResultShape(t);if(n===void 0||n.truncated||n.content.length>MAX_CACHED_CONTENT_CHARS)return;let r=reconstructNumberedLines(n.content);r===void 0||r.length!==n.totalLines||this.#e.set(n.path,{content:r.join(`
|
|
2
|
+
`)})}};function readFileResultShape(e){if(typeof e!=`object`||!e||Array.isArray(e))return;let{content:t,path:n,totalLines:r,truncated:i}=e;if(!(typeof t!=`string`||typeof n!=`string`)&&!(typeof r!=`number`||typeof i!=`boolean`))return{content:t,path:n,totalLines:r,truncated:i}}function reconstructNumberedLines(e){if(e===``)return[];let t=[];for(let[n,r]of e.split(`
|
|
3
|
+
`).entries()){let e=/^(\d+): (.*)$/su.exec(r);if(e===null||Number(e[1])!==n+1)return;t.push(e[2])}return t}export{FileContentCache};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure line diffing for the write block's rail. The TUI computes diffs
|
|
3
|
+
* client-side from content it has already seen (write inputs, full-file read
|
|
4
|
+
* results) — putting prior content into the tool's output would feed it
|
|
5
|
+
* straight back into model context, paying tokens for something only the
|
|
6
|
+
* terminal needs.
|
|
7
|
+
*/
|
|
8
|
+
/** One rail row under a tool header. `kind` is unset for plain/context text. */
|
|
9
|
+
export interface ToolDetailLine {
|
|
10
|
+
readonly text: string;
|
|
11
|
+
readonly kind?: "added" | "removed" | "gap";
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Builds the write rail for `content` against what it replaced.
|
|
15
|
+
*
|
|
16
|
+
* - `previous` known → a windowed line diff (changes with two context lines,
|
|
17
|
+
* unchanged stretches collapsed behind `gap` rows); identical content
|
|
18
|
+
* yields no rows.
|
|
19
|
+
* - `previous` unknown but the file provably did not exist → every line is
|
|
20
|
+
* an addition.
|
|
21
|
+
* - otherwise → plain content rows, because inventing `+` markers for an
|
|
22
|
+
* overwrite would misread as "everything changed".
|
|
23
|
+
*/
|
|
24
|
+
export declare function diffWriteDetail(previous: string | undefined, content: string, existed?: boolean): ToolDetailLine[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function diffWriteDetail(e,t,n){let r=splitContentLines(t);if(e===void 0)return n===!1?r.map(e=>({text:e,kind:`added`})):r.map(e=>({text:e}));let i=splitContentLines(e);return(i.length+1)*(r.length+1)>25e4?r.map(e=>({text:e})):windowHunks(lcsDiff(i,r))}function splitContentLines(e){let t=e.split(/\r?\n/u);for(;t.length>0&&t.at(-1)?.trim()===``;)t.pop();return t}function lcsDiff(e,t){let n=t.length+1,r=new Uint32Array((e.length+1)*n);for(let i=e.length-1;i>=0;--i)for(let a=t.length-1;a>=0;--a)r[i*n+a]=e[i]===t[a]?r[(i+1)*n+a+1]+1:Math.max(r[(i+1)*n+a],r[i*n+a+1]);let i=[],a=0,o=0;for(;a<e.length&&o<t.length;)e[a]===t[o]?(i.push({text:e[a]}),a+=1,o+=1):r[(a+1)*n+o]>=r[a*n+o+1]?(i.push({text:e[a],kind:`removed`}),a+=1):(i.push({text:t[o],kind:`added`}),o+=1);for(;a<e.length;a+=1)i.push({text:e[a],kind:`removed`});for(;o<t.length;o+=1)i.push({text:t[o],kind:`added`});return i}function windowHunks(e){let t=e.map(e=>e.kind===`added`||e.kind===`removed`);if(!t.includes(!0))return[];let n=e.map((n,r)=>{for(let n=Math.max(0,r-2);n<=Math.min(e.length-1,r+2);n+=1)if(t[n])return!0;return!1}),r=[];for(let[t,i]of e.entries())n[t]?r.push(i):r.at(-1)?.kind!==`gap`&&r.push({text:``,kind:`gap`});return r}export{diffWriteDetail};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{inputTextWidth,offsetAtVisibleColumn}from"
|
|
1
|
+
import{inputTextWidth,offsetAtVisibleColumn}from"#cli/ui/terminal-text.js";import{graphemeBoundaryAtOrAfter,graphemes,nextGraphemeBoundary,previousGraphemeBoundary}from"#shared/text-boundaries.js";const EMPTY_LINE={text:``,cursor:0};function lineOf(e){return{text:e,cursor:e.length}}function maskLine(e){return{text:`•`.repeat(graphemes(e.text).length),cursor:graphemes(e.text.slice(0,e.cursor)).length}}function insert(e,t){if(t.length===0)return e;let r=e.text.slice(0,e.cursor)+t+e.text.slice(e.cursor);return{text:r,cursor:graphemeBoundaryAtOrAfter(r,e.cursor+t.length)}}function backspace(e){if(e.cursor===0)return e;let t=previousGraphemeBoundary(e.text,e.cursor),r=e.text.slice(0,t)+e.text.slice(e.cursor);return{text:r,cursor:graphemeBoundaryAtOrAfter(r,t)}}function deleteForward(e){if(e.cursor>=e.text.length)return e;let t=nextGraphemeBoundary(e.text,e.cursor),r=e.text.slice(0,e.cursor)+e.text.slice(t);return{text:r,cursor:graphemeBoundaryAtOrAfter(r,e.cursor)}}function moveLeft(e){return e.cursor===0?e:{text:e.text,cursor:previousGraphemeBoundary(e.text,e.cursor)}}function moveRight(e){return e.cursor>=e.text.length?e:{text:e.text,cursor:nextGraphemeBoundary(e.text,e.cursor)}}function moveHome(e){let t=logicalLineStart(e.text,e.cursor);return e.cursor===t?e:{text:e.text,cursor:t}}function moveEnd(e){let t=logicalLineEnd(e.text,e.cursor);return e.cursor===t?e:{text:e.text,cursor:t}}function killToEnd(e){let t=logicalLineEnd(e.text,e.cursor);return e.cursor>=t?e:{text:e.text.slice(0,e.cursor)+e.text.slice(t),cursor:e.cursor}}function killToStart(e){let t=logicalLineStart(e.text,e.cursor);return e.cursor<=t?e:{text:e.text.slice(0,t)+e.text.slice(e.cursor),cursor:t}}function deleteWord(e){if(e.cursor===0)return e;let t=logicalLineStart(e.text,e.cursor),r=e.cursor;for(;r>t;){let t=previousGraphemeBoundary(e.text,r);if(!isWhitespace(e.text.slice(t,r)))break;r=t}for(;r>t;){let t=previousGraphemeBoundary(e.text,r);if(isWhitespace(e.text.slice(t,r)))break;r=t}let i=e.text.slice(0,r)+e.text.slice(e.cursor);return{text:i,cursor:graphemeBoundaryAtOrAfter(i,r)}}function logicalLineStart(e,t){return t===0?0:e.lastIndexOf(`
|
|
2
2
|
`,t-1)+1}function logicalLineEnd(e,t){let n=e.indexOf(`
|
|
3
3
|
`,t);return n===-1?e.length:n}function applyLineEditorKey(e,t,n){let r=n?.multiline??!1;switch(t.type){case`text`:return insert(e,r?t.value:t.value.replaceAll(`
|
|
4
4
|
`,` `));case`newline`:return r?insert(e,`
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
/** Renders parsed GFM blocks to terminal text, fitting tables to `width`. */
|
|
2
|
+
export declare function renderMarkdown(input: string, width?: number): string;
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
import{visibleLength}from"
|
|
2
|
-
`),n=[];for(let e
|
|
3
|
-
`)
|
|
1
|
+
import{sliceVisible,visibleLength}from"#cli/ui/terminal-text.js";import{lexer}from"#compiled/marked/index.js";const ansi={bold:`\x1B[1m`,boldOff:`\x1B[22m`,cyan:`\x1B[36m`,cyanOff:`\x1B[39m`,dim:`\x1B[2m`,dimOff:`\x1B[22m`,italic:`\x1B[3m`,italicOff:`\x1B[23m`,strike:`\x1B[9m`,strikeOff:`\x1B[29m`};function renderMarkdown(e,t=1/0){return trimTrailingBlankRows(renderBlocks(lexer(e),t)).join(`
|
|
2
|
+
`)}function renderBlocks(e,t){let n=[];for(let i of e)switch(i.type){case`space`:pushBlankRow(n);break;case`heading`:{let e=i.depth===1?`█`:i.depth===2?`■`:`▶`;n.push(`${e} ${ansi.bold}${renderInline(i.tokens)}${ansi.boldOff}`);break}case`paragraph`:case`text`:n.push(...renderInline(i.tokens,i.text).split(`
|
|
3
|
+
`));break;case`code`:n.push(...renderCodeBlock(i));break;case`blockquote`:n.push(...renderBlocks(i.tokens??[],Math.max(8,t-2)).map(e=>`${ansi.dim}│${ansi.dimOff} ${e}`));break;case`list`:n.push(...renderList(i,t));break;case`table`:n.push(...renderTable(i,t));break;case`hr`:n.push(ansi.dim+`─`.repeat(horizontalRuleWidth(t))+ansi.dimOff);break;case`html`:n.push(...(i.text??i.raw??``).split(`
|
|
4
|
+
`));break;case`def`:break;default:i.tokens===void 0?i.text!==void 0&&n.push(i.text):n.push(...renderBlocks(i.tokens,t));break}return n}function renderCodeBlock(e){let t=[];e.lang?.trim()&&t.push(` ${ansi.dim}${e.lang.trim()}${ansi.dimOff}`);let n=(e.text??``).replace(/\n$/u,``).split(`
|
|
5
|
+
`);for(let e of n)t.push(`${ansi.dim}│${ansi.dimOff} ${ansi.cyan}${e}${ansi.cyanOff}`);return t}function renderList(e,t){let n=[],r=typeof e.start==`number`?e.start:1;for(let i of e.items??[]){let a=e.ordered?`${r}.`:`•`,o=i.checked===!0?`☑ `:i.checked===!1?`☐ `:``,s=renderBlocks(i.tokens??[],Math.max(8,t-a.length-1));(s.length===0?[``]:s).forEach((e,t)=>{n.push(t===0?`${a} ${o}${e}`:`${` `.repeat(a.length+1)}${e}`)}),r+=1}return n}function renderInline(e,t=``){return e===void 0?t:e.map(renderInlineToken).join(``)}function renderInlineToken(e){switch(e.type){case`text`:return renderInline(e.tokens,e.text??``);case`strong`:return`${ansi.bold}${renderInline(e.tokens,e.text)}${ansi.boldOff}`;case`em`:return`${ansi.italic}${renderInline(e.tokens,e.text)}${ansi.italicOff}`;case`del`:return`${ansi.strike}${renderInline(e.tokens,e.text)}${ansi.strikeOff}`;case`codespan`:return`${ansi.cyan}${e.text??``}${ansi.cyanOff}`;case`link`:{let t=renderInline(e.tokens,e.text),n=e.href??``;return n.length===0||t===n?`${ansi.cyan}${t}${ansi.cyanOff}`:`${t} (${ansi.cyan}${n}${ansi.cyanOff})`}case`image`:{let t=e.text?.trim()||`image`,n=e.href??``;return n.length===0?`[${t}]`:`[${t}] (${ansi.cyan}${n}${ansi.cyanOff})`}case`br`:return`
|
|
6
|
+
`;case`checkbox`:return e.checked?`☑ `:`☐ `;case`escape`:return e.text??``;case`html`:return e.text??e.raw??``;default:return renderInline(e.tokens,e.text??e.raw??``)}}function renderTable(e,n){let i=e.header??[];if(i.length===0)return[];let a=i.map((t,n)=>normalizeAlignment(e.align?.[n])),o=i.map(renderTableCell),s=(e.rows??[]).map(e=>normalizeTableRow(e,i.length).map(renderTableCell)),c=[o,...s],l=a.map((e,n)=>Math.max(3,...c.map(e=>visibleLength(e[n]??``))));return fitTableWidths(l,n),[formatTableRow(o.map(e=>`${ansi.bold}${e}${ansi.boldOff}`),l,a),l.map(e=>`─`.repeat(e)).join(` `),...s.map(e=>formatTableRow(e,l,a))]}function renderTableCell(e){return renderInline(e.tokens,e.text).replaceAll(`
|
|
7
|
+
`,` `)}function normalizeTableRow(e,t){return Array.from({length:t},(t,n)=>e[n]??{text:``,tokens:[]})}function normalizeAlignment(e){return e??`left`}function fitTableWidths(e,t){if(!Number.isFinite(t))return;let n=Math.max(0,e.length-1)*2,r=Math.max(e.length*3,Math.floor(t)-n);for(;e.reduce((e,t)=>e+t,0)>r;){let t=Math.max(...e),n=e.findIndex(e=>e===t&&e>3);if(n===-1)return;e[n]=t-1}}function formatTableRow(e,t,n){return e.map((e,r)=>alignTableCell(fitTableCell(e,t[r]??3),t[r]??3,n[r]??`left`)).join(` `)}function fitTableCell(n,r){return visibleLength(n)<=r?n:`${sliceVisible(n,Math.max(1,r-1))}…`}function alignTableCell(e,n,r){let i=Math.max(0,n-visibleLength(e));if(r===`right`)return`${` `.repeat(i)}${e}`;if(r===`center`){let t=Math.floor(i/2);return`${` `.repeat(t)}${e}${` `.repeat(i-t)}`}return`${e}${` `.repeat(i)}`}function horizontalRuleWidth(e){return Number.isFinite(e)?Math.max(3,Math.min(40,Math.floor(e))):40}function pushBlankRow(e){e.length>0&&e.at(-1)!==``&&e.push(``)}function trimTrailingBlankRows(e){for(;e.at(-1)===``;)e.pop();return e}export{renderMarkdown};
|