@bastani/atomic 0.9.25 → 0.9.26-alpha.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 +34 -0
- package/dist/builtin/intercom/package.json +2 -2
- package/dist/builtin/mcp/OAUTH.md +1 -1
- package/dist/builtin/mcp/native-client-licenses/NOTICE +2 -2
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/package.json +3 -3
- package/dist/builtin/web-access/package.json +2 -2
- package/dist/builtin/workflows/CHANGELOG.md +6 -0
- package/dist/builtin/workflows/package.json +2 -2
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +17 -0
- package/dist/builtin/workflows/src/index.js +15 -0
- package/dist/cli/args.js +1 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
- package/dist/core/agent-session-extension-bindings.js +4 -0
- package/dist/core/agent-session-extension-bindings.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +5 -1
- package/dist/core/agent-session-methods.d.ts.map +1 -1
- package/dist/core/agent-session-methods.js.map +1 -1
- package/dist/core/agent-session-prompt.d.ts.map +1 -1
- package/dist/core/agent-session-prompt.js +1 -0
- package/dist/core/agent-session-prompt.js.map +1 -1
- package/dist/core/agent-session-state.d.ts +14 -2
- package/dist/core/agent-session-state.d.ts.map +1 -1
- package/dist/core/agent-session-state.js +31 -6
- package/dist/core/agent-session-state.js.map +1 -1
- package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
- package/dist/core/agent-session-tool-registry.js +5 -1
- package/dist/core/agent-session-tool-registry.js.map +1 -1
- package/dist/core/agent-session.d.ts +1 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +2 -2
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +4 -3
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-registry.d.ts +2 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +3 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/oauth-login.d.ts +1 -0
- package/dist/core/oauth-login.d.ts.map +1 -1
- package/dist/core/oauth-login.js.map +1 -1
- package/dist/core/oauth-provider-metadata.d.ts.map +1 -1
- package/dist/core/oauth-provider-metadata.js +1 -0
- package/dist/core/oauth-provider-metadata.js.map +1 -1
- package/dist/core/settings-manager-resource-accessors.d.ts +3 -3
- package/dist/core/settings-manager-resource-accessors.d.ts.map +1 -1
- package/dist/core/settings-manager-resource-accessors.js +2 -1
- package/dist/core/settings-manager-resource-accessors.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/settings-types.d.ts +2 -1
- package/dist/core/settings-types.d.ts.map +1 -1
- package/dist/core/settings-types.js.map +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/extensions/codemode/execute.d.ts.map +1 -1
- package/dist/extensions/codemode/execute.js +133 -31
- package/dist/extensions/codemode/execute.js.map +1 -1
- package/dist/extensions/codemode/tool.d.ts +2 -1
- package/dist/extensions/codemode/tool.d.ts.map +1 -1
- package/dist/extensions/codemode/tool.js +25 -4
- package/dist/extensions/codemode/tool.js.map +1 -1
- package/dist/extensions/mcp/cli.js +2 -2
- package/dist/extensions/mcp/cli.js.map +1 -1
- package/dist/extensions/mcp/client/oauth/flow.d.ts +6 -0
- package/dist/extensions/mcp/client/oauth/flow.d.ts.map +1 -1
- package/dist/extensions/mcp/client/oauth/flow.js +23 -5
- package/dist/extensions/mcp/client/oauth/flow.js.map +1 -1
- package/dist/extensions/mcp/client/oauth/index.d.ts +1 -1
- package/dist/extensions/mcp/client/oauth/index.d.ts.map +1 -1
- package/dist/extensions/mcp/client/oauth/index.js +1 -1
- package/dist/extensions/mcp/client/oauth/index.js.map +1 -1
- package/dist/extensions/mcp/index.d.ts.map +1 -1
- package/dist/extensions/mcp/index.js +22 -12
- package/dist/extensions/mcp/index.js.map +1 -1
- package/dist/extensions/mcp/oauth.d.ts +12 -7
- package/dist/extensions/mcp/oauth.d.ts.map +1 -1
- package/dist/extensions/mcp/oauth.js +58 -24
- package/dist/extensions/mcp/oauth.js.map +1 -1
- package/dist/extensions/mcp/runtime.js +1 -1
- package/dist/extensions/mcp/runtime.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main-session-options.d.ts.map +1 -1
- package/dist/main-session-options.js +6 -0
- package/dist/main-session-options.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/atomic-banner.d.ts +2 -0
- package/dist/modes/interactive/components/atomic-banner.d.ts.map +1 -1
- package/dist/modes/interactive/components/atomic-banner.js +9 -1
- package/dist/modes/interactive/components/atomic-banner.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts +2 -0
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +9 -4
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector-handlers.js +1 -1
- package/dist/modes/interactive/components/settings-selector-handlers.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector-items.js +3 -3
- package/dist/modes/interactive/components/settings-selector-items.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector-types.d.ts +3 -3
- package/dist/modes/interactive/components/settings-selector-types.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector-types.js.map +1 -1
- package/dist/modes/interactive/components/startup-identity.js +2 -2
- package/dist/modes/interactive/components/startup-identity.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +3 -4
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/interactive-auth-login.js +14 -5
- package/dist/modes/interactive/interactive-auth-login.js.map +1 -1
- package/dist/modes/interactive/interactive-auth-routing.js +38 -17
- package/dist/modes/interactive/interactive-auth-routing.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.d.ts +6 -4
- package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
- package/dist/modes/interactive/interactive-resource-rendering.js +1 -1
- package/dist/modes/interactive/interactive-resource-rendering.js.map +1 -1
- package/dist/modes/interactive/interactive-selectors.js +2 -2
- package/dist/modes/interactive/interactive-selectors.js.map +1 -1
- package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-startup.js +12 -4
- package/dist/modes/interactive/interactive-startup.js.map +1 -1
- package/dist/modes/interactive/login-provider-options.d.ts +2 -1
- package/dist/modes/interactive/login-provider-options.d.ts.map +1 -1
- package/dist/modes/interactive/login-provider-options.js +11 -6
- package/dist/modes/interactive/login-provider-options.js.map +1 -1
- package/dist/modes/interactive/theme/system-theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/system-theme.js +10 -4
- package/dist/modes/interactive/theme/system-theme.js.map +1 -1
- package/docs/codemode.md +214 -0
- package/docs/docs.json +1 -0
- package/docs/extensions/api-reference.md +2 -0
- package/docs/getting-started/authentication.md +2 -2
- package/docs/guides.md +1 -1
- package/docs/mcp-servers.md +2 -0
- package/docs/providers.md +5 -3
- package/docs/reference/cli.md +1 -1
- package/docs/settings.md +1 -1
- package/docs/terminal-setup.md +2 -0
- package/docs/tools.md +1 -3
- package/docs/usage.md +1 -1
- package/npm-shrinkwrap.json +68 -73
- package/package.json +8 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings-types.js","sourceRoot":"","sources":["../../src/core/settings-types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,CAAU,CAAC","sourcesContent":["export const CACHE_WARMING_MODES = [\"off\", \"streaming\", \"idle\"] as const;\nexport type CacheWarmingMode = (typeof CACHE_WARMING_MODES)[number];\n\nimport type { Transport } from \"@bastani/pi-ai/compat\";\nimport type { ScrollViewScrollbar, WheelScrollLines } from \"@earendil-works/pi-tui\";\n\nexport interface CompactionModelOverride {\n\treserveTokens?: number;\n\tpreserve_recent?: number;\n}\n\nexport interface CompactionSettings {\n\tenabled?: boolean; // default: true\n\treserveTokens?: number; // default: 16384\n\tcompression_ratio?: number; // default: 0.5 (fraction of compactable context to keep)\n\tpreserve_recent?: number; // default: 2 (recent context-eligible messages to keep)\n\tquery?: string; // default: auto-detected from session context\n\tmodelOverrides?: Record<string, CompactionModelOverride>; // exact \"provider/modelId\" keys\n}\n\nexport interface BranchSummarySettings {\n\treserveTokens?: number; // default: 16384 (tokens reserved for prompt + LLM response)\n\tskipPrompt?: boolean; // default: false - when true, skips \"Summarize branch?\" prompt and defaults to no summary\n}\n\nexport interface SessionSummarySettings {\n\tenabled?: boolean; // default: true - generate a one-line resume-picker summary once the agent goes idle\n}\n\nexport interface ProviderRetrySettings {\n\ttimeoutMs?: number; // SDK/provider request timeout in milliseconds\n\tmaxRetries?: number; // SDK/provider retry attempts\n\tmaxRetryDelayMs?: number; // default: 60000 (max server-requested delay before failing)\n}\n\nexport interface RetrySettings {\n\tenabled?: boolean; // default: true\n\tmaxRetries?: number; // default: 3\n\tbaseDelayMs?: number; // default: 2000 (exponential backoff: 2s, 4s, 8s)\n\tmaxAgentDelayMs?: number; // default: 60000\n\tprovider?: ProviderRetrySettings;\n}\n\nexport interface TerminalSettings {\n\tshowImages?: boolean; // default: true (only relevant if terminal supports images)\n\timageWidthCells?: number; // default: 60 (preferred inline image width in terminal cells)\n\tclearOnShrink?: boolean; // default: false (clear empty rows when content shrinks)\n\tshowTerminalProgress?: boolean; // default: false (OSC 9;4 terminal progress indicators)\n\thyperlinks?: boolean | \"auto\";\n\timages?: \"kitty\" | \"iterm2\" | \"auto\" | false;\n\ttrueColor?: boolean | \"auto\";\n}\n\nexport interface ImageSettings {\n\tautoResize?: boolean; // default: true (resize images to 2000x2000 max for better model compatibility)\n\tblockImages?: boolean; // default: false - when true, prevents all images from being sent to LLM providers\n}\n\nexport interface SearchSettings {\n\tcontextBefore?: number;\n\tcontextAfter?: number;\n}\nexport interface ThinkingBudgetsSettings {\n\tminimal?: number;\n\tlow?: number;\n\tmedium?: number;\n\thigh?: number;\n}\n\nexport type MermaidRenderingMode = \"off\" | \"final\" | \"streaming\";\n\nexport interface MarkdownSettings {\n\tcodeBlockIndent?: string; // default: \" \"\n\tmermaid?: MermaidRenderingMode; // default: \"streaming\"\n\tlatex?: boolean; // default: true\n}\n\nexport interface WarningSettings {\n\tanthropicExtraUsage?: boolean; // default: true\n}\n\nexport type DefaultProjectTrust = \"ask\" | \"always\" | \"never\";\n\nexport type TransportSetting = Transport;\n\n/** What the terminal keeps when Atomic's fullscreen session exits. */\nexport type FullscreenExitOutput = \"transcript\" | \"resume-hint\";\n\nexport type CodemodeMode = \"on\" | \"only\";\n\n/**\n * Package source for npm/git packages.\n * - String form: load all resources from the package\n * - Object form: filter which resources to load\n * - autoload=false: start empty and apply only explicit resource patterns\n */\nexport type PackageSource =\n\t| string\n\t| {\n\t\t\tsource: string;\n\t\t\tautoload?: boolean;\n\t\t\textensions?: string[];\n\t\t\tskills?: string[];\n\t\t\tprompts?: string[];\n\t\t\tthemes?: string[];\n\t\t\tworkflows?: string[];\n\t\t\tmcpServers?: string[];\n\t };\n\nexport interface BashInterceptorSettings {\n\tenabled?: boolean; // default: false\n}\n\n/** Provider filters for the candidates `model: \"auto\"` may route to. Does not affect `routerModel`. */\nexport interface ModelRoutingSettings {\n\t/** When nonempty, only these provider IDs are routing candidates. */\n\tallowedProviders?: string[];\n\t/** Provider IDs that are never routing candidates; applied after `allowedProviders`. */\n\texcludedProviders?: string[];\n}\n\nexport interface Settings {\n\tlastChangelogVersion?: string;\n\tfirstRunOnboardingStartedVersion?: string;\n\tonboardedVersion?: string;\n\tdefaultProvider?: string;\n\tdefaultModel?: string;\n\trouterModel?: string; // default: \"\"; workflow-stage/subagent auto-model router inference only, never \"auto\"\n\tmodelRouting?: ModelRoutingSettings;\n\tdefaultThinkingLevel?: \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\";\n\tmodelThinkingLevels?: Record<string, \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\">;\n\tfallbackModels?: string[]; // Ordered main-chat fallback models, optionally suffixed with :thinkingLevel\n\ttransport?: TransportSetting; // default: \"auto\"\n\tsteeringMode?: \"all\" | \"one-at-a-time\";\n\tfollowUpMode?: \"all\" | \"one-at-a-time\";\n\ttheme?: string;\n\tenableAnalytics?: boolean; // storage only; no analytics transmission is performed\n\ttrackingId?: string; // stable UUID generated on first analytics opt-in\n\tdeviceId?: string; // global installation ID, created only when a login needs it\n\tshowCacheMissNotices?: boolean; // default: false - show cache costs and provider recovery diagnostics\n\tcompaction?: CompactionSettings;\n\tbranchSummary?: BranchSummarySettings;\n\tsessionSummary?: SessionSummarySettings;\n\tretry?: RetrySettings;\n\thideThinkingBlock?: boolean;\n\texternalEditor?: string; // Command for Ctrl+G external editor; takes precedence over VISUAL/EDITOR\n\tshellPath?: string; // Custom shell path (e.g., for Cygwin users on Windows)\n\tquietStartup?: boolean;\n\tdefaultProjectTrust?: DefaultProjectTrust; // default: \"ask\"; global setting only\n\tshellCommandPrefix?: string; // Prefix prepended to every bash command (e.g., \"shopt -s expand_aliases\" for alias support)\n\tbashInterceptor?: BashInterceptorSettings; // default: disabled; when enabled, user_bash handlers can intercept bash tool execution\n\tsearch?: SearchSettings; // Context lines for search results; defaults: before=1, after=3\n\tnpmCommand?: string[]; // Command used for npm package lookup/install operations, argv-style (e.g., [\"mise\", \"exec\", \"node@20\", \"--\", \"npm\"])\n\tcollapseChangelog?: boolean; // Show condensed changelog after update (use /changelog for full)\n\tenableInstallTelemetry?: boolean; // default: true - version-adoption ping on first interactive launch with fresh settings or after an update with changelog entries\n\tpackages?: PackageSource[]; // Array of npm/git package sources (string or object with filtering)\n\textensions?: string[]; // Array of local extension file paths or directories\n\tskills?: string[]; // Array of local skill file paths or directories\n\tprompts?: string[]; // Array of local prompt template paths or directories\n\tthemes?: string[]; // Array of local theme file paths or directories\n\tworkflows?: string[]; // Array of local workflow file paths or directories\n\tenableSkillCommands?: boolean; // default: true - register skills as /skill:name commands\n\tterminal?: TerminalSettings;\n\therdr?: { enabled?: boolean }; // default: true, only inside an interactive Herdr pane\n\timages?: ImageSettings;\n\tenabledModels?: string[]; // Model patterns for cycling (same format as --models CLI flag)\n\tdefaultTools?: string[]; // Initial tool selection; +name/-name modify inherited selection\n\tdoubleEscapeAction?: \"fork\" | \"tree\" | \"none\"; // Action for double-escape with empty editor (default: \"tree\")\n\ttreeFilterMode?: \"default\" | \"no-tools\" | \"user-only\" | \"labeled-only\" | \"all\"; // Default filter when opening /tree\n\tthinkingBudgets?: ThinkingBudgetsSettings; // Custom token budgets for thinking levels\n\teditorPaddingX?: number; // Horizontal padding for input editor (default: 0)\n\toutputPad?: 0 | 1; // Horizontal padding for chat message output (default: 1)\n\tautocompleteMaxVisible?: number; // Max visible items in autocomplete dropdown (default: 5)\n\tshowHardwareCursor?: boolean; // Show terminal cursor while still positioning it for IME\n\tfullscreenScrollbar?: ScrollViewScrollbar; // default: \"auto\"\n\tfullscreenExitOutput?: FullscreenExitOutput; // default: \"transcript\"\n\tfullscreenCopyOnSelect?: boolean; // default: true\n\tfullscreenWheelScrollLines?: WheelScrollLines; // default: \"auto\", numeric values 1-100\n\tcodemode?: { mode?: CodemodeMode; inlineBudget?: number };\n\tmarkdown?: MarkdownSettings;\n\twarnings?: WarningSettings;\n\tsessionDir?: string; // Custom session storage directory (same format as --session-dir CLI flag)\n\thttpProxy?: string; // Proxy URL applied as HTTP_PROXY and HTTPS_PROXY; global setting only\n\thttpIdleTimeoutMs?: number | string; // HTTP idle timeout; 0 or \"disabled\" disables it\n\tcacheWarming?: CacheWarmingMode; // Global only; each refresh costs money. Default: streaming.\n\twebsocketConnectTimeoutMs?: number | string; // WebSocket connect timeout; 0 or \"disabled\" disables it\n\tstreamDeadlineMs?: number | string; // Max idle gap between provider stream events; 0 or \"disabled\" disables it\n}\n\nexport type SettingsScope = \"global\" | \"project\";\n\nexport interface SettingsManagerCreateOptions {\n\tprojectTrusted?: boolean;\n}\n\nexport type SettingsFieldOrigin = \"primary\" | \"legacy\";\n\nexport interface SettingsStorage {\n\twithLock(scope: SettingsScope, fn: (current: string | undefined) => string | undefined): void;\n\t/**\n\t * Optional write-specific lock whose callback receives the current primary\n\t * document rather than a layered effective view. Storage implementations\n\t * without a distinct primary document can omit this method; layered storage\n\t * implementations must provide it to keep fallback fields out of the primary\n\t * document.\n\t */\n\twithPrimaryWriteLock?(scope: SettingsScope, fn: (currentPrimary: string | undefined) => string | undefined): void;\n\tgetFieldOrigin?(scope: SettingsScope, field: keyof Settings): SettingsFieldOrigin | undefined;\n}\n\nexport interface SettingsError {\n\tscope: SettingsScope;\n\tpath?: string;\n\terror: Error;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"settings-types.js","sourceRoot":"","sources":["../../src/core/settings-types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,CAAU,CAAC","sourcesContent":["export const CACHE_WARMING_MODES = [\"off\", \"streaming\", \"idle\"] as const;\nexport type CacheWarmingMode = (typeof CACHE_WARMING_MODES)[number];\n\nimport type { Transport } from \"@bastani/pi-ai/compat\";\nimport type { ScrollViewScrollbar, WheelScrollLines } from \"@earendil-works/pi-tui\";\n\nexport interface CompactionModelOverride {\n\treserveTokens?: number;\n\tpreserve_recent?: number;\n}\n\nexport interface CompactionSettings {\n\tenabled?: boolean; // default: true\n\treserveTokens?: number; // default: 16384\n\tcompression_ratio?: number; // default: 0.5 (fraction of compactable context to keep)\n\tpreserve_recent?: number; // default: 2 (recent context-eligible messages to keep)\n\tquery?: string; // default: auto-detected from session context\n\tmodelOverrides?: Record<string, CompactionModelOverride>; // exact \"provider/modelId\" keys\n}\n\nexport interface BranchSummarySettings {\n\treserveTokens?: number; // default: 16384 (tokens reserved for prompt + LLM response)\n\tskipPrompt?: boolean; // default: false - when true, skips \"Summarize branch?\" prompt and defaults to no summary\n}\n\nexport interface SessionSummarySettings {\n\tenabled?: boolean; // default: true - generate a one-line resume-picker summary once the agent goes idle\n}\n\nexport interface ProviderRetrySettings {\n\ttimeoutMs?: number; // SDK/provider request timeout in milliseconds\n\tmaxRetries?: number; // SDK/provider retry attempts\n\tmaxRetryDelayMs?: number; // default: 60000 (max server-requested delay before failing)\n}\n\nexport interface RetrySettings {\n\tenabled?: boolean; // default: true\n\tmaxRetries?: number; // default: 3\n\tbaseDelayMs?: number; // default: 2000 (exponential backoff: 2s, 4s, 8s)\n\tmaxAgentDelayMs?: number; // default: 60000\n\tprovider?: ProviderRetrySettings;\n}\n\nexport interface TerminalSettings {\n\tshowImages?: boolean; // default: true (only relevant if terminal supports images)\n\timageWidthCells?: number; // default: 60 (preferred inline image width in terminal cells)\n\tclearOnShrink?: boolean; // default: false (clear empty rows when content shrinks)\n\tshowTerminalProgress?: boolean; // default: false (OSC 9;4 terminal progress indicators)\n\thyperlinks?: boolean | \"auto\";\n\timages?: \"kitty\" | \"iterm2\" | \"auto\" | false;\n\ttrueColor?: boolean | \"auto\";\n}\n\nexport interface ImageSettings {\n\tautoResize?: boolean; // default: true (resize images to 2000x2000 max for better model compatibility)\n\tblockImages?: boolean; // default: false - when true, prevents all images from being sent to LLM providers\n}\n\nexport interface SearchSettings {\n\tcontextBefore?: number;\n\tcontextAfter?: number;\n}\nexport interface ThinkingBudgetsSettings {\n\tminimal?: number;\n\tlow?: number;\n\tmedium?: number;\n\thigh?: number;\n}\n\nexport type MermaidRenderingMode = \"off\" | \"final\" | \"streaming\";\n\nexport interface MarkdownSettings {\n\tcodeBlockIndent?: string; // default: \" \"\n\tmermaid?: MermaidRenderingMode; // default: \"streaming\"\n\tlatex?: boolean; // default: true\n}\n\nexport interface WarningSettings {\n\tanthropicExtraUsage?: boolean; // default: true\n}\n\nexport type DefaultProjectTrust = \"ask\" | \"always\" | \"never\";\nexport type QuietStartup = boolean | \"header\";\n\nexport type TransportSetting = Transport;\n\n/** What the terminal keeps when Atomic's fullscreen session exits. */\nexport type FullscreenExitOutput = \"transcript\" | \"resume-hint\";\n\nexport type CodemodeMode = \"on\" | \"only\";\n\n/**\n * Package source for npm/git packages.\n * - String form: load all resources from the package\n * - Object form: filter which resources to load\n * - autoload=false: start empty and apply only explicit resource patterns\n */\nexport type PackageSource =\n\t| string\n\t| {\n\t\t\tsource: string;\n\t\t\tautoload?: boolean;\n\t\t\textensions?: string[];\n\t\t\tskills?: string[];\n\t\t\tprompts?: string[];\n\t\t\tthemes?: string[];\n\t\t\tworkflows?: string[];\n\t\t\tmcpServers?: string[];\n\t };\n\nexport interface BashInterceptorSettings {\n\tenabled?: boolean; // default: false\n}\n\n/** Provider filters for the candidates `model: \"auto\"` may route to. Does not affect `routerModel`. */\nexport interface ModelRoutingSettings {\n\t/** When nonempty, only these provider IDs are routing candidates. */\n\tallowedProviders?: string[];\n\t/** Provider IDs that are never routing candidates; applied after `allowedProviders`. */\n\texcludedProviders?: string[];\n}\n\nexport interface Settings {\n\tlastChangelogVersion?: string;\n\tfirstRunOnboardingStartedVersion?: string;\n\tonboardedVersion?: string;\n\tdefaultProvider?: string;\n\tdefaultModel?: string;\n\trouterModel?: string; // default: \"\"; workflow-stage/subagent auto-model router inference only, never \"auto\"\n\tmodelRouting?: ModelRoutingSettings;\n\tdefaultThinkingLevel?: \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\";\n\tmodelThinkingLevels?: Record<string, \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\" | \"max\">;\n\tfallbackModels?: string[]; // Ordered main-chat fallback models, optionally suffixed with :thinkingLevel\n\ttransport?: TransportSetting; // default: \"auto\"\n\tsteeringMode?: \"all\" | \"one-at-a-time\";\n\tfollowUpMode?: \"all\" | \"one-at-a-time\";\n\ttheme?: string;\n\tenableAnalytics?: boolean; // storage only; no analytics transmission is performed\n\ttrackingId?: string; // stable UUID generated on first analytics opt-in\n\tdeviceId?: string; // global installation ID, created only when a login needs it\n\tshowCacheMissNotices?: boolean; // default: false - show cache costs and provider recovery diagnostics\n\tcompaction?: CompactionSettings;\n\tbranchSummary?: BranchSummarySettings;\n\tsessionSummary?: SessionSummarySettings;\n\tretry?: RetrySettings;\n\thideThinkingBlock?: boolean;\n\texternalEditor?: string; // Command for Ctrl+G external editor; takes precedence over VISUAL/EDITOR\n\tshellPath?: string; // Custom shell path (e.g., for Cygwin users on Windows)\n\tquietStartup?: QuietStartup; // default: false; true hides all startup output, \"header\" keeps only the startup header\n\tdefaultProjectTrust?: DefaultProjectTrust; // default: \"ask\"; global setting only\n\tshellCommandPrefix?: string; // Prefix prepended to every bash command (e.g., \"shopt -s expand_aliases\" for alias support)\n\tbashInterceptor?: BashInterceptorSettings; // default: disabled; when enabled, user_bash handlers can intercept bash tool execution\n\tsearch?: SearchSettings; // Context lines for search results; defaults: before=1, after=3\n\tnpmCommand?: string[]; // Command used for npm package lookup/install operations, argv-style (e.g., [\"mise\", \"exec\", \"node@20\", \"--\", \"npm\"])\n\tcollapseChangelog?: boolean; // Show condensed changelog after update (use /changelog for full)\n\tenableInstallTelemetry?: boolean; // default: true - version-adoption ping on first interactive launch with fresh settings or after an update with changelog entries\n\tpackages?: PackageSource[]; // Array of npm/git package sources (string or object with filtering)\n\textensions?: string[]; // Array of local extension file paths or directories\n\tskills?: string[]; // Array of local skill file paths or directories\n\tprompts?: string[]; // Array of local prompt template paths or directories\n\tthemes?: string[]; // Array of local theme file paths or directories\n\tworkflows?: string[]; // Array of local workflow file paths or directories\n\tenableSkillCommands?: boolean; // default: true - register skills as /skill:name commands\n\tterminal?: TerminalSettings;\n\therdr?: { enabled?: boolean }; // default: true, only inside an interactive Herdr pane\n\timages?: ImageSettings;\n\tenabledModels?: string[]; // Model patterns for cycling (same format as --models CLI flag)\n\tdefaultTools?: string[]; // Initial tool selection; +name/-name modify inherited selection\n\tdoubleEscapeAction?: \"fork\" | \"tree\" | \"none\"; // Action for double-escape with empty editor (default: \"tree\")\n\ttreeFilterMode?: \"default\" | \"no-tools\" | \"user-only\" | \"labeled-only\" | \"all\"; // Default filter when opening /tree\n\tthinkingBudgets?: ThinkingBudgetsSettings; // Custom token budgets for thinking levels\n\teditorPaddingX?: number; // Horizontal padding for input editor (default: 0)\n\toutputPad?: 0 | 1; // Horizontal padding for chat message output (default: 1)\n\tautocompleteMaxVisible?: number; // Max visible items in autocomplete dropdown (default: 5)\n\tshowHardwareCursor?: boolean; // Show terminal cursor while still positioning it for IME\n\tfullscreenScrollbar?: ScrollViewScrollbar; // default: \"auto\"\n\tfullscreenExitOutput?: FullscreenExitOutput; // default: \"transcript\"\n\tfullscreenCopyOnSelect?: boolean; // default: true\n\tfullscreenWheelScrollLines?: WheelScrollLines; // default: \"auto\", numeric values 1-100\n\tcodemode?: { mode?: CodemodeMode; inlineBudget?: number };\n\tmarkdown?: MarkdownSettings;\n\twarnings?: WarningSettings;\n\tsessionDir?: string; // Custom session storage directory (same format as --session-dir CLI flag)\n\thttpProxy?: string; // Proxy URL applied as HTTP_PROXY and HTTPS_PROXY; global setting only\n\thttpIdleTimeoutMs?: number | string; // HTTP idle timeout; 0 or \"disabled\" disables it\n\tcacheWarming?: CacheWarmingMode; // Global only; each refresh costs money. Default: streaming.\n\twebsocketConnectTimeoutMs?: number | string; // WebSocket connect timeout; 0 or \"disabled\" disables it\n\tstreamDeadlineMs?: number | string; // Max idle gap between provider stream events; 0 or \"disabled\" disables it\n}\n\nexport type SettingsScope = \"global\" | \"project\";\n\nexport interface SettingsManagerCreateOptions {\n\tprojectTrusted?: boolean;\n}\n\nexport type SettingsFieldOrigin = \"primary\" | \"legacy\";\n\nexport interface SettingsStorage {\n\twithLock(scope: SettingsScope, fn: (current: string | undefined) => string | undefined): void;\n\t/**\n\t * Optional write-specific lock whose callback receives the current primary\n\t * document rather than a layered effective view. Storage implementations\n\t * without a distinct primary document can omit this method; layered storage\n\t * implementations must provide it to keep fallback fields out of the primary\n\t * document.\n\t */\n\twithPrimaryWriteLock?(scope: SettingsScope, fn: (currentPrimary: string | undefined) => string | undefined): void;\n\tgetFieldOrigin?(scope: SettingsScope, field: keyof Settings): SettingsFieldOrigin | undefined;\n}\n\nexport interface SettingsError {\n\tscope: SettingsScope;\n\tpath?: string;\n\terror: Error;\n}\n"]}
|
|
@@ -118,7 +118,7 @@ Atomic documentation (read when the user asks about model choice, computer use o
|
|
|
118
118
|
- Additional docs: ${docsPath}
|
|
119
119
|
- Examples: ${examplesPath} (extensions, custom tools, SDK)
|
|
120
120
|
- Docs/examples references above must be resolved against these absolute roots; e.g. docs/foo.md means ${docsPath}/foo.md and examples/bar means ${examplesPath}/bar.
|
|
121
|
-
- When asked about: atomic workflows (docs/workflows.md), extensions (docs/extensions.md, examples/extensions/), themes (docs/themes.md), skills (docs/skills.md), prompt templates (docs/prompt-templates.md), TUI components (docs/tui.md), keybindings (docs/keybindings.md), SDK integrations (docs/sdk.md), custom providers (docs/custom-provider.md), adding models (docs/models.md), atomic packages (docs/packages.md)
|
|
121
|
+
- When asked about: atomic workflows (docs/workflows.md), extensions (docs/extensions.md, examples/extensions/), themes (docs/themes.md), skills (docs/skills.md), prompt templates (docs/prompt-templates.md), TUI components (docs/tui.md), keybindings (docs/keybindings.md), SDK integrations (docs/sdk.md), custom providers (docs/custom-provider.md), adding models (docs/models.md), atomic packages (docs/packages.md), codemode scripts and non-LLM models such as classifiers and image models (docs/codemode.md)
|
|
122
122
|
- Bundled integrations use the same docs root in npm and binary installations: MCP servers (docs/mcp-servers.md), web access (docs/web-access.md), intercom (docs/intercom.md), subagents (docs/subagents.md), workflows (docs/workflows.md). Read these guides rather than guessing paths inside builtin packages.
|
|
123
123
|
- When the user asks which model to choose for a task, read ${docsPath}/models/model-selection.md and ${docsPath}/models/evals.md, then consult https://artificialanalysis.ai/ for the relevant benchmark charts and methodology. Match the task to individual evaluations rather than an aggregate winner. Cite the benchmark, source date, exact model/effort and cost or latency tradeoff; distinguish measured results from recommendations. If live evidence is unavailable, label the dated docs snapshot instead of claiming a refresh. Check the configured catalog before giving an exact provider/model or thinking setting; catalog presence is not proof of live access.
|
|
124
124
|
- For computer use (CUA) on desktop apps, simulators and emulators, use Cua Driver through the bundled cua-driver skill and one-shot \`cua-driver call <tool>\` commands: when a model chooses the next action (interactive sessions or any workflow stage acting outside ctx.tool), use the CLI; when workflow TypeScript code owns the sequence and postcondition, use the @trycua/cua-driver TypeScript SDK inside ctx.tool. If \`cua-driver --version\` fails, make one bounded attempt with upstream's one-line executable installer and report its side effects. The executable installer does not install an agent skill; ignore upstream README's optional skill-install steps, never run \`cua-driver skills install\` or \`clawhub install @cua/driver\`, and do not link or copy a skill into \`~/.agents/skills/cua-driver\`. Atomic already bundles it; leave any existing user-level skill alone. Run every cua-driver command with CUA_DRIVER_RS_TELEMETRY_ENABLED=false and follow ${docsPath}/computer-use.md for install, readiness and permissions. Prefer the agent-browser skill for what it covers, because its text snapshots cost far fewer tokens than screenshot-driven CUA: websites and web apps in Chrome/Chromium, Mobile Safari in the iOS Simulator or on a connected iPhone/iPad (\`agent-browser -p ios\`, macOS with Xcode and Appium), Electron desktop apps such as VS Code, Slack, Discord, Figma, Notion and Spotify and other apps exposing a CDP port, Slack workspaces, and cloud browsers. Use cua-driver for everything else (native desktop apps, native iOS apps in the iOS Simulator, Android emulators, OS dialogs and permission prompts, desktop Safari and other non-Chromium browsers) and whenever agent-browser hits a limitation. For terminal automation/testing, prefer herdr on macOS, Linux and Windows; install it if missing when network access and permissions permit, and fall back to tmux or native Windows psmux if installation or use is not possible. Load the matching skill and ${docsPath}/workflows/verification.md. Preserve the pinned herdr skill's explicit-request and HERDR_ENV=1 requirements; never control a focused session from outside Herdr. Check installed capabilities, use dedicated sessions, respect desktop permissions, and stop before destructive actions. These CLIs are not interchangeable, and skills do not grant tools or authorization.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport { getSystemMessageText } from \"@bastani/pi-ai\";\nimport { getDocsPath, getExamplesPath, getReadmePath } from \"../config.js\";\nimport { formatSkillsForPrompt, type Skill } from \"./skills.ts\";\n\nconst DEFAULT_PROMPT_TOOLS = [\"read\", \"bash\", \"edit\", \"write\", \"find\", \"search\", \"ask_user_question\", \"todo\"] as const;\n\nexport interface SystemPromptModel {\n\t/** Provider identifier for the selected model. */\n\tprovider: string;\n\t/** Stable provider-specific model identifier. */\n\tid: string;\n\t/** Human-readable model name, when available. */\n\tname?: string;\n}\n\nexport interface BuildSystemPromptOptions {\n\t/** Custom system prompt (replaces the default prefix). */\n\tcustomPrompt?: string;\n\t/** Exact full prompt replacement set by a before_agent_start handler. */\n\tforceSystemPrompt?: string;\n\t/** Tools to include in prompt. Default: [read, bash, edit, write, find, search, ask_user_question, todo] */\n\tselectedTools?: string[];\n\t/** Tool names explicitly excluded by the caller and omitted from generated guidance. */\n\texcludedTools?: string[];\n\t/** Optional one-line tool snippets keyed by tool name. */\n\ttoolSnippets?: Record<string, string>;\n\t/** Guideline bullets contributed by each tool, keyed by tool name. */\n\ttoolGuidelines?: Record<string, string[]>;\n\t/** Additional guideline bullets appended to the default system prompt rules. */\n\tpromptGuidelines?: string[];\n\t/** Text appended from user configuration before project context, skills, and cwd. */\n\tappendSystemPrompt?: string;\n\t/** Additional XML-wrapped prompt sections keyed by tag name. */\n\tsections?: Record<string, string>;\n\t/** Working directory. */\n\tcwd: string;\n\t/** Currently selected model, used for model-aware prompt metadata. */\n\tselectedModel?: SystemPromptModel;\n\t/** Current reasoning/thinking level for the selected model. */\n\tselectedThinkingLevel?: string;\n\t/** Pre-loaded context files. */\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\t/** Pre-loaded skills. */\n\tskills?: Skill[];\n}\n\nexport type NormalizedBuildSystemPromptOptions = BuildSystemPromptOptions & {\n\tselectedTools: string[];\n\ttoolSnippets: Record<string, string>;\n\ttoolGuidelines: Record<string, string[]>;\n\tpromptGuidelines: string[];\n\tappendSystemPrompt: string;\n\tsections: Record<string, string>;\n\tcontextFiles: Array<{ path: string; content: string }>;\n\tskills: Skill[];\n};\n\n/**\n * Ordered system prompt sections, keyed by name. `preamble` is untagged text; every other\n * section is wrapped in a tag of the same name so the model can match later updates to it.\n * These become `SystemMessage.sections` in the transcript.\n */\nexport type SystemPromptSections = Record<string, string>;\n\nconst SYSTEM_PROMPT_SECTION_NAME = /^[a-z][a-z0-9_-]*$/;\n/** Normalize prompt input into the mutable, collection-complete shape exposed to extensions. */\nexport function normalizeBuildSystemPromptOptions(input: BuildSystemPromptOptions): NormalizedBuildSystemPromptOptions {\n\treturn {\n\t\tcustomPrompt: input.customPrompt,\n\t\tforceSystemPrompt: input.forceSystemPrompt,\n\t\tselectedTools: [...(input.selectedTools ?? DEFAULT_PROMPT_TOOLS)],\n\t\ttoolSnippets: { ...(input.toolSnippets ?? {}) },\n\t\ttoolGuidelines: Object.fromEntries(\n\t\t\tObject.entries(input.toolGuidelines ?? {}).map(([name, guidelines]) => [name, [...guidelines]]),\n\t\t),\n\t\tpromptGuidelines: [...(input.promptGuidelines ?? [])],\n\t\tappendSystemPrompt: input.appendSystemPrompt ?? \"\",\n\t\tsections: { ...(input.sections ?? {}) },\n\t\tcwd: input.cwd,\n\t\t...(input.excludedTools === undefined ? {} : { excludedTools: [...input.excludedTools] }),\n\t\t...(input.selectedModel === undefined ? {} : { selectedModel: { ...input.selectedModel } }),\n\t\t...(input.selectedThinkingLevel === undefined ? {} : { selectedThinkingLevel: input.selectedThinkingLevel }),\n\t\tcontextFiles: (input.contextFiles ?? []).map((file) => ({ ...file })),\n\t\tskills: (input.skills ?? []).map((skill) => ({ ...skill })),\n\t};\n}\n\nfunction renderProjectContext(contextFiles: Array<{ path: string; content: string }>): string {\n\treturn [\n\t\t\"Project-specific instructions and guidelines:\",\n\t\t...contextFiles.map(\n\t\t\t({ path, content }) => `<project_instructions path=\"${path}\">\\n${content}\\n</project_instructions>`,\n\t\t),\n\t].join(\"\\n\\n\");\n}\n\nfunction buildRules(\n\tselectedTools: string[],\n\ttoolGuidelines: Record<string, string[]>,\n\tpromptGuidelines: string[],\n): string {\n\tconst rules: string[] = [];\n\tconst seen = new Set<string>();\n\tconst addRule = (rule: string): void => {\n\t\tconst normalized = rule.trim();\n\t\tif (!normalized || seen.has(normalized)) return;\n\t\tseen.add(normalized);\n\t\trules.push(normalized);\n\t};\n\n\tconst tools = selectedTools;\n\tconst hasBash = tools.includes(\"bash\");\n\tconst hasPowerShell = tools.includes(\"powershell\");\n\tconst hasFind = tools.includes(\"find\");\n\tconst hasLs = tools.includes(\"ls\");\n\tconst shouldIncludeAskUserFallbackGuidance = tools.length > 0 && !tools.includes(\"ask_user_question\");\n\tconst addGuideline = addRule;\n\tif ((hasBash || hasPowerShell) && !hasFind && !hasLs) {\n\t\tif (hasBash && hasPowerShell) {\n\t\t\taddRule(\"Use bash or PowerShell for file operations like listing, searching, and finding files\");\n\t\t} else if (hasPowerShell) {\n\t\t\taddRule(\"Use PowerShell for file operations like listing, searching, and finding files\");\n\t\t} else {\n\t\t\taddRule(\"Use bash for file operations like ls, rg, find\");\n\t\t}\n\t}\n\tif (shouldIncludeAskUserFallbackGuidance) {\n\t\taddGuideline(\n\t\t\t\"If an equivalent user-question tool is available, use it for all questions to the user instead of plain text, including confirmations and approvals, following its supported schema. When no usable question tool or human-input channel exists, do not stall on a question: choose the interpretation best supported by the repository and the stated objective, state the assumption in your response, and continue fully autonomously on best judgment. Tool unavailability alone is not a blocker. Preserve safety and authorization constraints.\",\n\t\t);\n\t}\n\tif (hasBash || hasPowerShell) {\n\t\taddGuideline(\n\t\t\t\"**Repository intent**: When working in a repository, infer how its maintainers actually work before imposing defaults: review recent commits, open and merged PRs, issues and their comments, and project/board status when tooling allows (for example `git log` and the `gh` CLI) to learn conventions, priorities, and scope norms. Better, identify the requesting user (`git config user.name`/`user.email`, `gh api user`) and study their own commits, PRs, reviews, and issue comments so you interpret ambiguous requests the way they would, aligning style, scope, and process with their patterns.\",\n\t\t);\n\t\taddGuideline(\n\t\t\t[\n\t\t\t\t\"**Execution history**: Leave a mineable record of how each task was executed and what the user prefers, and mine those records to calibrate later work. The records only accumulate value if every task writes them. If the user, a context file, or `APPEND_SYSTEM.md` asks you not to record some or all of these records, skip those records.\",\n\t\t\t\t\" - When you author a commit, PR, issue, or issue/review comment for a task, record how it ran: `Assistant-workflow: <workflow name> (run <runId>)` for a registered or custom workflow, or `Assistant-workflow: inline` when no workflow was used; and `Assistant-duration: <elapsed> <converged|blocked|abandoned>, estimated <estimate>` (for example `Assistant-duration: 42m converged, estimated 30m`), measuring wall-clock time from launch or task start until acceptance was proven or work stopped, including resumes and repair rounds. Take elapsed time from workflow status timing or timestamps you recorded (for example `date` at task start); write `unmeasured` rather than guess. Put these as trailers alongside `Assistant-model` in commits (git trailers, or the equivalent commit-message metadata in the repository's version control system) and as the same `Key: value` lines in PR/merge request, issue, and comment bodies. For multi-commit work, record the workflow on each commit and the final duration once, in the last commit or the PR body.\",\n\t\t\t\t\" - In the same artifacts, record how the result was verified with one `Assistant-verification: <method> <passed|failed|unavailable>: <what it proved or why>` line per method that actually ran or was attempted (for example `Assistant-verification: herdr terminal E2E passed: /tasks lists running tasks first at 80x24`, `Assistant-verification: vitest unit passed: npm run test:unit`, or `Assistant-verification: cua-driver unavailable: Accessibility permission not granted`). Name the concrete mechanism, such as unit, integration, or E2E tests, agent-browser, Cua Driver, herdr or tmux terminal automation, the qlty CLI, typecheck or lint, or a manual scenario, and the command or scenario it exercised. Record only checks that ran and their observed outcome; never record a skipped, mocked, or planned check as passed.\",\n\t\t\t\t\" - When the user states or reveals a durable preference about how they work (a correction, a rejected approach, scope, review, tooling, or communication style), record it in the same artifacts as `User-preference: <one line, in the user's terms>`, and tie it to the requesting user with a `Co-authored-by: <name> <email>` trailer taken from their version control identity (for example `git config user.name`/`user.email`) unless that line is already present; in PR, issue, and comment bodies, add the same line or their hosting account (for example from `gh api user`). Record only what the user expressed or their own edits show; never record secrets, credentials, or personal details unrelated to the work. If repository rules restrict commit or PR formats, fit the records into what they allow.\",\n\t\t\t\t\" - Before choosing between a workflow and inline work, choosing how to verify a change, estimating a duration, or interpreting an ambiguous request, mine these records with the rest of the history using the repository's version control system and its hosting CLI, for example `git log --format='%h %an <%ae> %s%n%(trailers:key=Assistant-workflow,key=Assistant-duration,key=Assistant-verification,key=User-preference,key=Co-authored-by)'` with `gh pr list --state all --search 'Assistant-workflow in:body'` on GitHub, or the equivalent commands for other systems and hosts (for example `glab` on GitLab). Compare tasks of similar kind and size, and state the sample size with the median and range. Treat fewer than five comparable records as anecdotal, and prefer the more recent record when two conflict. When choosing verification, start from the methods that proved comparable changes (the same files, subsystem, or kind of change), reuse their commands and scenarios, and do not retry a setup recorded as `unavailable` without a reason to expect a different result; past records never replace the project's required checks. Prioritize preferences tied to the requesting user by their co-author line, commit author, or hosting account. When the user has none that cover the situation, fall back to other contributors' relevant preferences as repository conventions; the user's own records and current request override them, so users can always encode their own preference. This history is a guide, not the decision: the current request, the task itself, and explicit user instructions decide between a workflow and inline work. Missing, sparse, or mostly inline workflow history is not evidence that the user prefers inline work: records exist only for tasks that wrote them, and past inline runs may reflect an earlier default rather than a choice. Without a recorded or stated preference that covers the situation, judge the task's shape yourself and choose a workflow when it would help, then let comparable records and the user's preferences refine that call.\",\n\t\t\t].join(\"\\n\"),\n\t\t);\n\t}\n\n\tfor (const name of selectedTools) {\n\t\tfor (const rule of toolGuidelines[name] ?? []) addRule(rule);\n\t}\n\tfor (const rule of promptGuidelines) addRule(rule);\n\taddRule(\n\t\t\"Write self-describing code and do not add comments unless the user explicitly asks for them or the task instructions call for them. Code that needs a comment to be understood is a smell: restructure it with clearer names, smaller units, or explicit types instead\",\n\t);\n\taddRule(\"Be concise in your responses\");\n\taddRule(\"Show file paths clearly when working with files\");\n\treturn rules.map((rule) => `- ${rule}`).join(\"\\n\");\n}\n\n/** Build the ordered, independently replaceable sections of the structured system prompt. */\nexport function buildSystemPromptSections(input: BuildSystemPromptOptions): SystemPromptSections {\n\tconst options = normalizeBuildSystemPromptOptions(input);\n\tconst {\n\t\tcustomPrompt,\n\t\tselectedTools,\n\t\ttoolSnippets,\n\t\ttoolGuidelines,\n\t\tpromptGuidelines,\n\t\tappendSystemPrompt,\n\t\tsections: customSections,\n\t\tcwd,\n\t\tcontextFiles,\n\t\tskills,\n\t} = options;\n\tconst explicitlyExcludedTools = new Set(options.excludedTools ?? []);\n\tconst tools = selectedTools.filter((name) => !explicitlyExcludedTools.has(name));\n\tconst readmePath = getReadmePath();\n\tconst docsPath = getDocsPath();\n\tconst examplesPath = getExamplesPath();\n\tconst modelName = options.selectedModel?.name?.trim() || options.selectedModel?.id || \"unknown\";\n\tconst modelReasoningLevel = options.selectedThinkingLevel?.trim() || \"off\";\n\tconst now = new Date();\n\tconst date = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, \"0\")}-${String(now.getDate()).padStart(2, \"0\")}`;\n\n\tfor (const name of Object.keys(customSections)) {\n\t\tif (!SYSTEM_PROMPT_SECTION_NAME.test(name) || name === \"preamble\") {\n\t\t\tthrow new Error(`Invalid system prompt section name: ${name}`);\n\t\t}\n\t}\n\n\tconst promptSections: Record<string, string> = {};\n\tif (customPrompt) {\n\t\tpromptSections.preamble = customPrompt;\n\t} else {\n\t\tpromptSections.preamble =\n\t\t\t\"You are an expert coding assistant operating named Atomic, a coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.\";\n\t\tconst visibleTools = tools.filter((name) => !!toolSnippets[name]);\n\t\tconst toolsList =\n\t\t\tvisibleTools.length > 0 ? visibleTools.map((name) => `- ${name}: ${toolSnippets[name]}`).join(\"\\n\") : \"(none)\";\n\t\tpromptSections.tools = `Available tools:\\n${toolsList}\\n\\nIn addition to the tools above, you may have access to other custom tools depending on the project.`;\n\t\tpromptSections.rules = `Guidelines:\\n${buildRules(tools, toolGuidelines, promptGuidelines)}`;\n\t\tpromptSections.docs = `\nAtomic documentation (read when the user asks about model choice, computer use or automation, MCP, web access, intercom, subagents, or customizing Atomic itself, its SDK, creating workflows, packages, extensions, themes, skills, or TUI):\n- Main documentation: ${readmePath}\n- Additional docs: ${docsPath}\n- Examples: ${examplesPath} (extensions, custom tools, SDK)\n- Docs/examples references above must be resolved against these absolute roots; e.g. docs/foo.md means ${docsPath}/foo.md and examples/bar means ${examplesPath}/bar.\n- When asked about: atomic workflows (docs/workflows.md), extensions (docs/extensions.md, examples/extensions/), themes (docs/themes.md), skills (docs/skills.md), prompt templates (docs/prompt-templates.md), TUI components (docs/tui.md), keybindings (docs/keybindings.md), SDK integrations (docs/sdk.md), custom providers (docs/custom-provider.md), adding models (docs/models.md), atomic packages (docs/packages.md)\n- Bundled integrations use the same docs root in npm and binary installations: MCP servers (docs/mcp-servers.md), web access (docs/web-access.md), intercom (docs/intercom.md), subagents (docs/subagents.md), workflows (docs/workflows.md). Read these guides rather than guessing paths inside builtin packages.\n- When the user asks which model to choose for a task, read ${docsPath}/models/model-selection.md and ${docsPath}/models/evals.md, then consult https://artificialanalysis.ai/ for the relevant benchmark charts and methodology. Match the task to individual evaluations rather than an aggregate winner. Cite the benchmark, source date, exact model/effort and cost or latency tradeoff; distinguish measured results from recommendations. If live evidence is unavailable, label the dated docs snapshot instead of claiming a refresh. Check the configured catalog before giving an exact provider/model or thinking setting; catalog presence is not proof of live access.\n- For computer use (CUA) on desktop apps, simulators and emulators, use Cua Driver through the bundled cua-driver skill and one-shot \\`cua-driver call <tool>\\` commands: when a model chooses the next action (interactive sessions or any workflow stage acting outside ctx.tool), use the CLI; when workflow TypeScript code owns the sequence and postcondition, use the @trycua/cua-driver TypeScript SDK inside ctx.tool. If \\`cua-driver --version\\` fails, make one bounded attempt with upstream's one-line executable installer and report its side effects. The executable installer does not install an agent skill; ignore upstream README's optional skill-install steps, never run \\`cua-driver skills install\\` or \\`clawhub install @cua/driver\\`, and do not link or copy a skill into \\`~/.agents/skills/cua-driver\\`. Atomic already bundles it; leave any existing user-level skill alone. Run every cua-driver command with CUA_DRIVER_RS_TELEMETRY_ENABLED=false and follow ${docsPath}/computer-use.md for install, readiness and permissions. Prefer the agent-browser skill for what it covers, because its text snapshots cost far fewer tokens than screenshot-driven CUA: websites and web apps in Chrome/Chromium, Mobile Safari in the iOS Simulator or on a connected iPhone/iPad (\\`agent-browser -p ios\\`, macOS with Xcode and Appium), Electron desktop apps such as VS Code, Slack, Discord, Figma, Notion and Spotify and other apps exposing a CDP port, Slack workspaces, and cloud browsers. Use cua-driver for everything else (native desktop apps, native iOS apps in the iOS Simulator, Android emulators, OS dialogs and permission prompts, desktop Safari and other non-Chromium browsers) and whenever agent-browser hits a limitation. For terminal automation/testing, prefer herdr on macOS, Linux and Windows; install it if missing when network access and permissions permit, and fall back to tmux or native Windows psmux if installation or use is not possible. Load the matching skill and ${docsPath}/workflows/verification.md. Preserve the pinned herdr skill's explicit-request and HERDR_ENV=1 requirements; never control a focused session from outside Herdr. Check installed capabilities, use dedicated sessions, respect desktop permissions, and stop before destructive actions. These CLIs are not interchangeable, and skills do not grant tools or authorization.\n- Also skip \\`cua-driver skills update\\` and any skill installation into other agent directories such as \\`~/.claude/skills\\`; updating the executable is separate from installing or updating a skill.\n- When working on Atomic topics, read the docs and examples, and follow .md cross-references before implementing\n- Always read Atomic .md files completely and follow links to related docs (e.g., tui.md for TUI API details)`;\n\t}\n\n\tif (appendSystemPrompt) promptSections.addendum = appendSystemPrompt;\n\tif (contextFiles.length > 0) promptSections.project_context = renderProjectContext(contextFiles);\n\tconst skillFileReadTool = ([\"read\", \"bash\"] as const).find((tool) => tools.includes(tool));\n\tif (skillFileReadTool && skills.length > 0) {\n\t\tconst skillsPrompt = formatSkillsForPrompt(skills, skillFileReadTool).trim();\n\t\tif (skillsPrompt) promptSections.skills = skillsPrompt;\n\t}\n\tpromptSections.model = `Model name (used for commit attribution): ${modelName}\\nModel reasoning level: ${modelReasoningLevel}`;\n\tpromptSections.date = `Current date: ${date}`;\n\tpromptSections.cwd = `Current working directory: ${cwd.replace(/\\\\/g, \"/\")}`;\n\tfor (const [name, content] of Object.entries(customSections)) {\n\t\tif (content) promptSections[name] = content;\n\t}\n\n\tconst sections: SystemPromptSections = { preamble: promptSections.preamble };\n\tfor (const [name, content] of Object.entries(promptSections)) {\n\t\tif (name !== \"preamble\") sections[name] = `<${name}>\\n${content}\\n</${name}>`;\n\t}\n\treturn sections;\n}\n\n/**\n * The complete prompt state for `input`. A forced prompt is opaque and lives in `content`\n * with no sections; otherwise `content` is empty and the structured sections carry the prompt.\n */\nexport function buildSystemPromptState(input: BuildSystemPromptOptions): {\n\tcontent: string;\n\tsections?: SystemPromptSections;\n} {\n\tif (input.forceSystemPrompt !== undefined) return { content: input.forceSystemPrompt };\n\treturn { content: \"\", sections: buildSystemPromptSections(input) };\n}\n\n/** Build the system prompt text, rendered exactly as the transcript's system message replays it. */\nexport function buildSystemPrompt(input: BuildSystemPromptOptions): string {\n\treturn getSystemMessageText({ role: \"system\", ...buildSystemPromptState(input), timestamp: 0 });\n}\n\n/**\n * Diff the sections the model currently has (replayed from the transcript, so never null)\n * against the desired ones. Returns a `SystemMessage.sections` patch, or undefined when\n * nothing changed.\n */\nexport function diffSystemPromptSections(\n\tprevious: Record<string, string | null>,\n\tcurrent: SystemPromptSections,\n): Record<string, string | null> | undefined {\n\tconst patch: Record<string, string | null> = {};\n\tfor (const [name, text] of Object.entries(current)) {\n\t\tif (previous[name] !== text) patch[name] = text;\n\t}\n\tfor (const name of Object.keys(previous)) {\n\t\tif (current[name] === undefined) patch[name] = null;\n\t}\n\treturn Object.keys(patch).length > 0 ? patch : undefined;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport { getSystemMessageText } from \"@bastani/pi-ai\";\nimport { getDocsPath, getExamplesPath, getReadmePath } from \"../config.js\";\nimport { formatSkillsForPrompt, type Skill } from \"./skills.ts\";\n\nconst DEFAULT_PROMPT_TOOLS = [\"read\", \"bash\", \"edit\", \"write\", \"find\", \"search\", \"ask_user_question\", \"todo\"] as const;\n\nexport interface SystemPromptModel {\n\t/** Provider identifier for the selected model. */\n\tprovider: string;\n\t/** Stable provider-specific model identifier. */\n\tid: string;\n\t/** Human-readable model name, when available. */\n\tname?: string;\n}\n\nexport interface BuildSystemPromptOptions {\n\t/** Custom system prompt (replaces the default prefix). */\n\tcustomPrompt?: string;\n\t/** Exact full prompt replacement set by a before_agent_start handler. */\n\tforceSystemPrompt?: string;\n\t/** Tools to include in prompt. Default: [read, bash, edit, write, find, search, ask_user_question, todo] */\n\tselectedTools?: string[];\n\t/** Tool names explicitly excluded by the caller and omitted from generated guidance. */\n\texcludedTools?: string[];\n\t/** Optional one-line tool snippets keyed by tool name. */\n\ttoolSnippets?: Record<string, string>;\n\t/** Guideline bullets contributed by each tool, keyed by tool name. */\n\ttoolGuidelines?: Record<string, string[]>;\n\t/** Additional guideline bullets appended to the default system prompt rules. */\n\tpromptGuidelines?: string[];\n\t/** Text appended from user configuration before project context, skills, and cwd. */\n\tappendSystemPrompt?: string;\n\t/** Additional XML-wrapped prompt sections keyed by tag name. */\n\tsections?: Record<string, string>;\n\t/** Working directory. */\n\tcwd: string;\n\t/** Currently selected model, used for model-aware prompt metadata. */\n\tselectedModel?: SystemPromptModel;\n\t/** Current reasoning/thinking level for the selected model. */\n\tselectedThinkingLevel?: string;\n\t/** Pre-loaded context files. */\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\t/** Pre-loaded skills. */\n\tskills?: Skill[];\n}\n\nexport type NormalizedBuildSystemPromptOptions = BuildSystemPromptOptions & {\n\tselectedTools: string[];\n\ttoolSnippets: Record<string, string>;\n\ttoolGuidelines: Record<string, string[]>;\n\tpromptGuidelines: string[];\n\tappendSystemPrompt: string;\n\tsections: Record<string, string>;\n\tcontextFiles: Array<{ path: string; content: string }>;\n\tskills: Skill[];\n};\n\n/**\n * Ordered system prompt sections, keyed by name. `preamble` is untagged text; every other\n * section is wrapped in a tag of the same name so the model can match later updates to it.\n * These become `SystemMessage.sections` in the transcript.\n */\nexport type SystemPromptSections = Record<string, string>;\n\nconst SYSTEM_PROMPT_SECTION_NAME = /^[a-z][a-z0-9_-]*$/;\n/** Normalize prompt input into the mutable, collection-complete shape exposed to extensions. */\nexport function normalizeBuildSystemPromptOptions(input: BuildSystemPromptOptions): NormalizedBuildSystemPromptOptions {\n\treturn {\n\t\tcustomPrompt: input.customPrompt,\n\t\tforceSystemPrompt: input.forceSystemPrompt,\n\t\tselectedTools: [...(input.selectedTools ?? DEFAULT_PROMPT_TOOLS)],\n\t\ttoolSnippets: { ...(input.toolSnippets ?? {}) },\n\t\ttoolGuidelines: Object.fromEntries(\n\t\t\tObject.entries(input.toolGuidelines ?? {}).map(([name, guidelines]) => [name, [...guidelines]]),\n\t\t),\n\t\tpromptGuidelines: [...(input.promptGuidelines ?? [])],\n\t\tappendSystemPrompt: input.appendSystemPrompt ?? \"\",\n\t\tsections: { ...(input.sections ?? {}) },\n\t\tcwd: input.cwd,\n\t\t...(input.excludedTools === undefined ? {} : { excludedTools: [...input.excludedTools] }),\n\t\t...(input.selectedModel === undefined ? {} : { selectedModel: { ...input.selectedModel } }),\n\t\t...(input.selectedThinkingLevel === undefined ? {} : { selectedThinkingLevel: input.selectedThinkingLevel }),\n\t\tcontextFiles: (input.contextFiles ?? []).map((file) => ({ ...file })),\n\t\tskills: (input.skills ?? []).map((skill) => ({ ...skill })),\n\t};\n}\n\nfunction renderProjectContext(contextFiles: Array<{ path: string; content: string }>): string {\n\treturn [\n\t\t\"Project-specific instructions and guidelines:\",\n\t\t...contextFiles.map(\n\t\t\t({ path, content }) => `<project_instructions path=\"${path}\">\\n${content}\\n</project_instructions>`,\n\t\t),\n\t].join(\"\\n\\n\");\n}\n\nfunction buildRules(\n\tselectedTools: string[],\n\ttoolGuidelines: Record<string, string[]>,\n\tpromptGuidelines: string[],\n): string {\n\tconst rules: string[] = [];\n\tconst seen = new Set<string>();\n\tconst addRule = (rule: string): void => {\n\t\tconst normalized = rule.trim();\n\t\tif (!normalized || seen.has(normalized)) return;\n\t\tseen.add(normalized);\n\t\trules.push(normalized);\n\t};\n\n\tconst tools = selectedTools;\n\tconst hasBash = tools.includes(\"bash\");\n\tconst hasPowerShell = tools.includes(\"powershell\");\n\tconst hasFind = tools.includes(\"find\");\n\tconst hasLs = tools.includes(\"ls\");\n\tconst shouldIncludeAskUserFallbackGuidance = tools.length > 0 && !tools.includes(\"ask_user_question\");\n\tconst addGuideline = addRule;\n\tif ((hasBash || hasPowerShell) && !hasFind && !hasLs) {\n\t\tif (hasBash && hasPowerShell) {\n\t\t\taddRule(\"Use bash or PowerShell for file operations like listing, searching, and finding files\");\n\t\t} else if (hasPowerShell) {\n\t\t\taddRule(\"Use PowerShell for file operations like listing, searching, and finding files\");\n\t\t} else {\n\t\t\taddRule(\"Use bash for file operations like ls, rg, find\");\n\t\t}\n\t}\n\tif (shouldIncludeAskUserFallbackGuidance) {\n\t\taddGuideline(\n\t\t\t\"If an equivalent user-question tool is available, use it for all questions to the user instead of plain text, including confirmations and approvals, following its supported schema. When no usable question tool or human-input channel exists, do not stall on a question: choose the interpretation best supported by the repository and the stated objective, state the assumption in your response, and continue fully autonomously on best judgment. Tool unavailability alone is not a blocker. Preserve safety and authorization constraints.\",\n\t\t);\n\t}\n\tif (hasBash || hasPowerShell) {\n\t\taddGuideline(\n\t\t\t\"**Repository intent**: When working in a repository, infer how its maintainers actually work before imposing defaults: review recent commits, open and merged PRs, issues and their comments, and project/board status when tooling allows (for example `git log` and the `gh` CLI) to learn conventions, priorities, and scope norms. Better, identify the requesting user (`git config user.name`/`user.email`, `gh api user`) and study their own commits, PRs, reviews, and issue comments so you interpret ambiguous requests the way they would, aligning style, scope, and process with their patterns.\",\n\t\t);\n\t\taddGuideline(\n\t\t\t[\n\t\t\t\t\"**Execution history**: Leave a mineable record of how each task was executed and what the user prefers, and mine those records to calibrate later work. The records only accumulate value if every task writes them. If the user, a context file, or `APPEND_SYSTEM.md` asks you not to record some or all of these records, skip those records.\",\n\t\t\t\t\" - When you author a commit, PR, issue, or issue/review comment for a task, record how it ran: `Assistant-workflow: <workflow name> (run <runId>)` for a registered or custom workflow, or `Assistant-workflow: inline` when no workflow was used; and `Assistant-duration: <elapsed> <converged|blocked|abandoned>, estimated <estimate>` (for example `Assistant-duration: 42m converged, estimated 30m`), measuring wall-clock time from launch or task start until acceptance was proven or work stopped, including resumes and repair rounds. Take elapsed time from workflow status timing or timestamps you recorded (for example `date` at task start); write `unmeasured` rather than guess. Put these as trailers alongside `Assistant-model` in commits (git trailers, or the equivalent commit-message metadata in the repository's version control system) and as the same `Key: value` lines in PR/merge request, issue, and comment bodies. For multi-commit work, record the workflow on each commit and the final duration once, in the last commit or the PR body.\",\n\t\t\t\t\" - In the same artifacts, record how the result was verified with one `Assistant-verification: <method> <passed|failed|unavailable>: <what it proved or why>` line per method that actually ran or was attempted (for example `Assistant-verification: herdr terminal E2E passed: /tasks lists running tasks first at 80x24`, `Assistant-verification: vitest unit passed: npm run test:unit`, or `Assistant-verification: cua-driver unavailable: Accessibility permission not granted`). Name the concrete mechanism, such as unit, integration, or E2E tests, agent-browser, Cua Driver, herdr or tmux terminal automation, the qlty CLI, typecheck or lint, or a manual scenario, and the command or scenario it exercised. Record only checks that ran and their observed outcome; never record a skipped, mocked, or planned check as passed.\",\n\t\t\t\t\" - When the user states or reveals a durable preference about how they work (a correction, a rejected approach, scope, review, tooling, or communication style), record it in the same artifacts as `User-preference: <one line, in the user's terms>`, and tie it to the requesting user with a `Co-authored-by: <name> <email>` trailer taken from their version control identity (for example `git config user.name`/`user.email`) unless that line is already present; in PR, issue, and comment bodies, add the same line or their hosting account (for example from `gh api user`). Record only what the user expressed or their own edits show; never record secrets, credentials, or personal details unrelated to the work. If repository rules restrict commit or PR formats, fit the records into what they allow.\",\n\t\t\t\t\" - Before choosing between a workflow and inline work, choosing how to verify a change, estimating a duration, or interpreting an ambiguous request, mine these records with the rest of the history using the repository's version control system and its hosting CLI, for example `git log --format='%h %an <%ae> %s%n%(trailers:key=Assistant-workflow,key=Assistant-duration,key=Assistant-verification,key=User-preference,key=Co-authored-by)'` with `gh pr list --state all --search 'Assistant-workflow in:body'` on GitHub, or the equivalent commands for other systems and hosts (for example `glab` on GitLab). Compare tasks of similar kind and size, and state the sample size with the median and range. Treat fewer than five comparable records as anecdotal, and prefer the more recent record when two conflict. When choosing verification, start from the methods that proved comparable changes (the same files, subsystem, or kind of change), reuse their commands and scenarios, and do not retry a setup recorded as `unavailable` without a reason to expect a different result; past records never replace the project's required checks. Prioritize preferences tied to the requesting user by their co-author line, commit author, or hosting account. When the user has none that cover the situation, fall back to other contributors' relevant preferences as repository conventions; the user's own records and current request override them, so users can always encode their own preference. This history is a guide, not the decision: the current request, the task itself, and explicit user instructions decide between a workflow and inline work. Missing, sparse, or mostly inline workflow history is not evidence that the user prefers inline work: records exist only for tasks that wrote them, and past inline runs may reflect an earlier default rather than a choice. Without a recorded or stated preference that covers the situation, judge the task's shape yourself and choose a workflow when it would help, then let comparable records and the user's preferences refine that call.\",\n\t\t\t].join(\"\\n\"),\n\t\t);\n\t}\n\n\tfor (const name of selectedTools) {\n\t\tfor (const rule of toolGuidelines[name] ?? []) addRule(rule);\n\t}\n\tfor (const rule of promptGuidelines) addRule(rule);\n\taddRule(\n\t\t\"Write self-describing code and do not add comments unless the user explicitly asks for them or the task instructions call for them. Code that needs a comment to be understood is a smell: restructure it with clearer names, smaller units, or explicit types instead\",\n\t);\n\taddRule(\"Be concise in your responses\");\n\taddRule(\"Show file paths clearly when working with files\");\n\treturn rules.map((rule) => `- ${rule}`).join(\"\\n\");\n}\n\n/** Build the ordered, independently replaceable sections of the structured system prompt. */\nexport function buildSystemPromptSections(input: BuildSystemPromptOptions): SystemPromptSections {\n\tconst options = normalizeBuildSystemPromptOptions(input);\n\tconst {\n\t\tcustomPrompt,\n\t\tselectedTools,\n\t\ttoolSnippets,\n\t\ttoolGuidelines,\n\t\tpromptGuidelines,\n\t\tappendSystemPrompt,\n\t\tsections: customSections,\n\t\tcwd,\n\t\tcontextFiles,\n\t\tskills,\n\t} = options;\n\tconst explicitlyExcludedTools = new Set(options.excludedTools ?? []);\n\tconst tools = selectedTools.filter((name) => !explicitlyExcludedTools.has(name));\n\tconst readmePath = getReadmePath();\n\tconst docsPath = getDocsPath();\n\tconst examplesPath = getExamplesPath();\n\tconst modelName = options.selectedModel?.name?.trim() || options.selectedModel?.id || \"unknown\";\n\tconst modelReasoningLevel = options.selectedThinkingLevel?.trim() || \"off\";\n\tconst now = new Date();\n\tconst date = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, \"0\")}-${String(now.getDate()).padStart(2, \"0\")}`;\n\n\tfor (const name of Object.keys(customSections)) {\n\t\tif (!SYSTEM_PROMPT_SECTION_NAME.test(name) || name === \"preamble\") {\n\t\t\tthrow new Error(`Invalid system prompt section name: ${name}`);\n\t\t}\n\t}\n\n\tconst promptSections: Record<string, string> = {};\n\tif (customPrompt) {\n\t\tpromptSections.preamble = customPrompt;\n\t} else {\n\t\tpromptSections.preamble =\n\t\t\t\"You are an expert coding assistant operating named Atomic, a coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.\";\n\t\tconst visibleTools = tools.filter((name) => !!toolSnippets[name]);\n\t\tconst toolsList =\n\t\t\tvisibleTools.length > 0 ? visibleTools.map((name) => `- ${name}: ${toolSnippets[name]}`).join(\"\\n\") : \"(none)\";\n\t\tpromptSections.tools = `Available tools:\\n${toolsList}\\n\\nIn addition to the tools above, you may have access to other custom tools depending on the project.`;\n\t\tpromptSections.rules = `Guidelines:\\n${buildRules(tools, toolGuidelines, promptGuidelines)}`;\n\t\tpromptSections.docs = `\nAtomic documentation (read when the user asks about model choice, computer use or automation, MCP, web access, intercom, subagents, or customizing Atomic itself, its SDK, creating workflows, packages, extensions, themes, skills, or TUI):\n- Main documentation: ${readmePath}\n- Additional docs: ${docsPath}\n- Examples: ${examplesPath} (extensions, custom tools, SDK)\n- Docs/examples references above must be resolved against these absolute roots; e.g. docs/foo.md means ${docsPath}/foo.md and examples/bar means ${examplesPath}/bar.\n- When asked about: atomic workflows (docs/workflows.md), extensions (docs/extensions.md, examples/extensions/), themes (docs/themes.md), skills (docs/skills.md), prompt templates (docs/prompt-templates.md), TUI components (docs/tui.md), keybindings (docs/keybindings.md), SDK integrations (docs/sdk.md), custom providers (docs/custom-provider.md), adding models (docs/models.md), atomic packages (docs/packages.md), codemode scripts and non-LLM models such as classifiers and image models (docs/codemode.md)\n- Bundled integrations use the same docs root in npm and binary installations: MCP servers (docs/mcp-servers.md), web access (docs/web-access.md), intercom (docs/intercom.md), subagents (docs/subagents.md), workflows (docs/workflows.md). Read these guides rather than guessing paths inside builtin packages.\n- When the user asks which model to choose for a task, read ${docsPath}/models/model-selection.md and ${docsPath}/models/evals.md, then consult https://artificialanalysis.ai/ for the relevant benchmark charts and methodology. Match the task to individual evaluations rather than an aggregate winner. Cite the benchmark, source date, exact model/effort and cost or latency tradeoff; distinguish measured results from recommendations. If live evidence is unavailable, label the dated docs snapshot instead of claiming a refresh. Check the configured catalog before giving an exact provider/model or thinking setting; catalog presence is not proof of live access.\n- For computer use (CUA) on desktop apps, simulators and emulators, use Cua Driver through the bundled cua-driver skill and one-shot \\`cua-driver call <tool>\\` commands: when a model chooses the next action (interactive sessions or any workflow stage acting outside ctx.tool), use the CLI; when workflow TypeScript code owns the sequence and postcondition, use the @trycua/cua-driver TypeScript SDK inside ctx.tool. If \\`cua-driver --version\\` fails, make one bounded attempt with upstream's one-line executable installer and report its side effects. The executable installer does not install an agent skill; ignore upstream README's optional skill-install steps, never run \\`cua-driver skills install\\` or \\`clawhub install @cua/driver\\`, and do not link or copy a skill into \\`~/.agents/skills/cua-driver\\`. Atomic already bundles it; leave any existing user-level skill alone. Run every cua-driver command with CUA_DRIVER_RS_TELEMETRY_ENABLED=false and follow ${docsPath}/computer-use.md for install, readiness and permissions. Prefer the agent-browser skill for what it covers, because its text snapshots cost far fewer tokens than screenshot-driven CUA: websites and web apps in Chrome/Chromium, Mobile Safari in the iOS Simulator or on a connected iPhone/iPad (\\`agent-browser -p ios\\`, macOS with Xcode and Appium), Electron desktop apps such as VS Code, Slack, Discord, Figma, Notion and Spotify and other apps exposing a CDP port, Slack workspaces, and cloud browsers. Use cua-driver for everything else (native desktop apps, native iOS apps in the iOS Simulator, Android emulators, OS dialogs and permission prompts, desktop Safari and other non-Chromium browsers) and whenever agent-browser hits a limitation. For terminal automation/testing, prefer herdr on macOS, Linux and Windows; install it if missing when network access and permissions permit, and fall back to tmux or native Windows psmux if installation or use is not possible. Load the matching skill and ${docsPath}/workflows/verification.md. Preserve the pinned herdr skill's explicit-request and HERDR_ENV=1 requirements; never control a focused session from outside Herdr. Check installed capabilities, use dedicated sessions, respect desktop permissions, and stop before destructive actions. These CLIs are not interchangeable, and skills do not grant tools or authorization.\n- Also skip \\`cua-driver skills update\\` and any skill installation into other agent directories such as \\`~/.claude/skills\\`; updating the executable is separate from installing or updating a skill.\n- When working on Atomic topics, read the docs and examples, and follow .md cross-references before implementing\n- Always read Atomic .md files completely and follow links to related docs (e.g., tui.md for TUI API details)`;\n\t}\n\n\tif (appendSystemPrompt) promptSections.addendum = appendSystemPrompt;\n\tif (contextFiles.length > 0) promptSections.project_context = renderProjectContext(contextFiles);\n\tconst skillFileReadTool = ([\"read\", \"bash\"] as const).find((tool) => tools.includes(tool));\n\tif (skillFileReadTool && skills.length > 0) {\n\t\tconst skillsPrompt = formatSkillsForPrompt(skills, skillFileReadTool).trim();\n\t\tif (skillsPrompt) promptSections.skills = skillsPrompt;\n\t}\n\tpromptSections.model = `Model name (used for commit attribution): ${modelName}\\nModel reasoning level: ${modelReasoningLevel}`;\n\tpromptSections.date = `Current date: ${date}`;\n\tpromptSections.cwd = `Current working directory: ${cwd.replace(/\\\\/g, \"/\")}`;\n\tfor (const [name, content] of Object.entries(customSections)) {\n\t\tif (content) promptSections[name] = content;\n\t}\n\n\tconst sections: SystemPromptSections = { preamble: promptSections.preamble };\n\tfor (const [name, content] of Object.entries(promptSections)) {\n\t\tif (name !== \"preamble\") sections[name] = `<${name}>\\n${content}\\n</${name}>`;\n\t}\n\treturn sections;\n}\n\n/**\n * The complete prompt state for `input`. A forced prompt is opaque and lives in `content`\n * with no sections; otherwise `content` is empty and the structured sections carry the prompt.\n */\nexport function buildSystemPromptState(input: BuildSystemPromptOptions): {\n\tcontent: string;\n\tsections?: SystemPromptSections;\n} {\n\tif (input.forceSystemPrompt !== undefined) return { content: input.forceSystemPrompt };\n\treturn { content: \"\", sections: buildSystemPromptSections(input) };\n}\n\n/** Build the system prompt text, rendered exactly as the transcript's system message replays it. */\nexport function buildSystemPrompt(input: BuildSystemPromptOptions): string {\n\treturn getSystemMessageText({ role: \"system\", ...buildSystemPromptState(input), timestamp: 0 });\n}\n\n/**\n * Diff the sections the model currently has (replayed from the transcript, so never null)\n * against the desired ones. Returns a `SystemMessage.sections` patch, or undefined when\n * nothing changed.\n */\nexport function diffSystemPromptSections(\n\tprevious: Record<string, string | null>,\n\tcurrent: SystemPromptSections,\n): Record<string, string | null> | undefined {\n\tconst patch: Record<string, string | null> = {};\n\tfor (const [name, text] of Object.entries(current)) {\n\t\tif (previous[name] !== text) patch[name] = text;\n\t}\n\tfor (const name of Object.keys(previous)) {\n\t\tif (current[name] === undefined) patch[name] = null;\n\t}\n\treturn Object.keys(patch).length > 0 ? patch : undefined;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../../src/extensions/codemode/execute.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../../src/extensions/codemode/execute.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACX,QAAQ,EAQR,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAa,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAWhF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAEnF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAGlE,OAAO,EAIN,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EAGxB,MAAM,WAAW,CAAC;AAEnB,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAsB1F;AAOD,kHAAkH;AAClH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAa5E;AAkSD,wBAAsB,eAAe,CACpC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,iBAAiB,EACxB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,mBAAmB,CAAC,KAAK,IAAI,CAAC,GAAG,SAAS,EAC5E,GAAG,EAAE,oBAAoB,GAAG,SAAS,EACrC,OAAO,GAAE,mBAAwB,GAC/B,OAAO,CAAC,eAAe,CAAC,mBAAmB,CAAC,CAAC,CAgI/C"}
|
|
@@ -6,7 +6,7 @@ import { CodemodeSandbox, loadQuickJSWasm, parseCodemodeSource, renderToolSample
|
|
|
6
6
|
import { getCodemodeWorkerUrl, getQuickJSWasmPath } from "../../config.js";
|
|
7
7
|
import { combineUsage } from "../../core/usage-totals.js";
|
|
8
8
|
import { Bm25Ranker, createToolSearchDocument, DEFAULT_TOOL_SEARCH_LIMIT } from "../tool-search/tool.js";
|
|
9
|
-
import { CODEMODE_STORE_ENTRY_TYPE, getCodemodeCallableTools, toCodemodeDeclaration, } from "./tool.js";
|
|
9
|
+
import { CODEMODE_DOCS_PATH, CODEMODE_STORE_ENTRY_TYPE, getCodemodeCallableTools, toCodemodeDeclaration, } from "./tool.js";
|
|
10
10
|
export function readCodemodeStore(branch) {
|
|
11
11
|
const store = new Map();
|
|
12
12
|
for (const entry of branch) {
|
|
@@ -49,11 +49,86 @@ export function toCodemodeModelInfo(model) {
|
|
|
49
49
|
cost: model.cost,
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
|
+
const MODEL_TYPES = ["chat", "image", "classifier"];
|
|
52
53
|
function modelType(value) {
|
|
53
54
|
if (value === "chat" || value === "image" || value === "classifier")
|
|
54
55
|
return value;
|
|
55
56
|
throw new Error('Model type must be "chat", "image", or "classifier"');
|
|
56
57
|
}
|
|
58
|
+
function withArticle(word) {
|
|
59
|
+
return `${/^[aeiou]/.test(word) ? "an" : "a"} ${word}`;
|
|
60
|
+
}
|
|
61
|
+
function isRecord(value) {
|
|
62
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
63
|
+
}
|
|
64
|
+
function describeValue(value) {
|
|
65
|
+
if (value === undefined || value === null)
|
|
66
|
+
return String(value);
|
|
67
|
+
if (Array.isArray(value))
|
|
68
|
+
return value.length === 0 ? "an empty array" : "an array";
|
|
69
|
+
if (typeof value === "object") {
|
|
70
|
+
const keys = Object.keys(value);
|
|
71
|
+
if (keys.length === 0)
|
|
72
|
+
return "{}";
|
|
73
|
+
return `{ ${keys.slice(0, 6).join(", ")}${keys.length > 6 ? ", ..." : ""} }`;
|
|
74
|
+
}
|
|
75
|
+
return typeof value === "string" ? "a string" : `a ${typeof value}`;
|
|
76
|
+
}
|
|
77
|
+
const CLASSIFIER_CONTEXT_SHAPE = '{ state: { ... }, questions: { <id>: { type: "choice", instructions, criteria: { <label>: <meaning> } } | { type: "score", instructions, criteria: [<lowest level>, ..., <highest level>] } | { type: "bool", instructions, criteria: { true: <meaning>, false: <meaning> } } } }';
|
|
78
|
+
function checkClassifierContext(context) {
|
|
79
|
+
const fail = (problem) => new Error(`models.classify() ${problem}. Expected context: ${CLASSIFIER_CONTEXT_SHAPE}. See "Classify" in ${CODEMODE_DOCS_PATH}.`);
|
|
80
|
+
if (!isRecord(context))
|
|
81
|
+
throw fail(`expects a context object as its second argument, got ${describeValue(context)}`);
|
|
82
|
+
if (!isRecord(context.state))
|
|
83
|
+
throw fail(`context.state must be an object, got ${describeValue(context.state)}`);
|
|
84
|
+
const { questions } = context;
|
|
85
|
+
if (!isRecord(questions) || Object.keys(questions).length === 0)
|
|
86
|
+
throw fail(`context.questions must map question IDs to questions, got ${describeValue(questions)}`);
|
|
87
|
+
const isStrings = (values) => values.length > 0 && values.every((value) => typeof value === "string");
|
|
88
|
+
for (const [questionId, question] of Object.entries(questions)) {
|
|
89
|
+
const at = `context.questions.${questionId}`;
|
|
90
|
+
if (!isRecord(question))
|
|
91
|
+
throw fail(`${at} must be a question object, got ${describeValue(question)}`);
|
|
92
|
+
if (typeof question.instructions !== "string")
|
|
93
|
+
throw fail(`${at}.instructions must be a string`);
|
|
94
|
+
const { criteria } = question;
|
|
95
|
+
if (question.type === "choice") {
|
|
96
|
+
if (!isRecord(criteria) || !isStrings(Object.values(criteria)))
|
|
97
|
+
throw fail(`${at} is a "choice" question, so criteria must map each label to its meaning`);
|
|
98
|
+
}
|
|
99
|
+
else if (question.type === "score") {
|
|
100
|
+
if (!Array.isArray(criteria) || !isStrings(criteria))
|
|
101
|
+
throw fail(`${at} is a "score" question, so criteria must list the levels as strings, lowest first`);
|
|
102
|
+
}
|
|
103
|
+
else if (question.type === "bool") {
|
|
104
|
+
if (!isRecord(criteria) || typeof criteria.true !== "string" || typeof criteria.false !== "string")
|
|
105
|
+
throw fail(`${at} is a "bool" question, so criteria must be { true: string, false: string }`);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
throw fail(`${at}.type must be "choice", "score", or "bool", got ${JSON.stringify(question.type)}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return context;
|
|
112
|
+
}
|
|
113
|
+
function checkImagesContext(context) {
|
|
114
|
+
const fail = (problem) => new Error(`models.generateImages() ${problem}. Expected context: { input: [{ type: "text", text: <prompt> }, ...optional { type: "image", data: <base64>, mimeType } references] }. See "Generate images" in ${CODEMODE_DOCS_PATH}.`);
|
|
115
|
+
if (!isRecord(context))
|
|
116
|
+
throw fail(`expects a context object as its second argument, got ${describeValue(context)}`);
|
|
117
|
+
const { input } = context;
|
|
118
|
+
if (!Array.isArray(input) || input.length === 0)
|
|
119
|
+
throw fail(`context.input must be a non-empty array of blocks, got ${describeValue(input)}`);
|
|
120
|
+
input.forEach((block, index) => {
|
|
121
|
+
if (isRecord(block) && block.type === "text" && typeof block.text === "string")
|
|
122
|
+
return;
|
|
123
|
+
if (isRecord(block) &&
|
|
124
|
+
block.type === "image" &&
|
|
125
|
+
typeof block.data === "string" &&
|
|
126
|
+
typeof block.mimeType === "string")
|
|
127
|
+
return;
|
|
128
|
+
throw fail(`context.input[${index}] must be a text or image block, got ${describeValue(block)}`);
|
|
129
|
+
});
|
|
130
|
+
return context;
|
|
131
|
+
}
|
|
57
132
|
function provider(value) {
|
|
58
133
|
if (value === undefined || value === null)
|
|
59
134
|
return undefined;
|
|
@@ -148,10 +223,48 @@ function discoveryGlobals(tools, samples, options) {
|
|
|
148
223
|
},
|
|
149
224
|
];
|
|
150
225
|
}
|
|
151
|
-
function modelGlobals(ctx, id, calls, publish, addUsage) {
|
|
226
|
+
function modelGlobals(ctx, id, calls, publish, addUsage, addGeneratedImages) {
|
|
152
227
|
const models = ctx.modelRegistry;
|
|
153
228
|
const limit = createLimiter(4);
|
|
154
229
|
let count = 0;
|
|
230
|
+
const runModelCall = async (name, type, [ref, context], checkContext, run) => {
|
|
231
|
+
const listHint = `List the ${type} models you can use with models.getAvailableOfType("${type}").`;
|
|
232
|
+
if (!isRecord(ref) || typeof ref.provider !== "string" || typeof ref.id !== "string") {
|
|
233
|
+
const undefinedHint = ref === undefined || ref === null
|
|
234
|
+
? " models.getModelOfType() returns undefined for an unknown provider or id."
|
|
235
|
+
: "";
|
|
236
|
+
throw new Error(`${name}() expects ${withArticle(type)} model as its first argument, got ${describeValue(ref)}.${undefinedHint} ${listHint}`);
|
|
237
|
+
}
|
|
238
|
+
const { provider: providerId, id: modelId } = ref;
|
|
239
|
+
const model = models.getModelOfType(type, providerId, modelId);
|
|
240
|
+
if (!model) {
|
|
241
|
+
const actualType = MODEL_TYPES.find((other) => other !== type && models.getModelOfType(other, providerId, modelId) !== undefined);
|
|
242
|
+
throw new Error(actualType
|
|
243
|
+
? `"${providerId}/${modelId}" is ${withArticle(actualType)} model, not ${withArticle(type)} model. ${listHint}`
|
|
244
|
+
: `Unknown ${type} model "${providerId}/${modelId}". ${listHint}`);
|
|
245
|
+
}
|
|
246
|
+
const checked = checkContext(context);
|
|
247
|
+
const record = {
|
|
248
|
+
id: `${id}/${name}/${++count}`,
|
|
249
|
+
name,
|
|
250
|
+
args: `${model.provider}/${model.id}`,
|
|
251
|
+
status: "running",
|
|
252
|
+
};
|
|
253
|
+
calls.push(record);
|
|
254
|
+
publish();
|
|
255
|
+
const start = performance.now();
|
|
256
|
+
const result = await limit(() => run(model, checked));
|
|
257
|
+
record.durationMs = performance.now() - start;
|
|
258
|
+
record.status = result.stopReason === "stop" ? "ok" : result.stopReason === "aborted" ? "cancelled" : "error";
|
|
259
|
+
if (result.errorMessage)
|
|
260
|
+
record.error = result.errorMessage.slice(0, 500);
|
|
261
|
+
if (result.usage) {
|
|
262
|
+
record.cost = result.usage.cost.total;
|
|
263
|
+
addUsage(result.usage);
|
|
264
|
+
}
|
|
265
|
+
publish();
|
|
266
|
+
return result;
|
|
267
|
+
};
|
|
155
268
|
return [
|
|
156
269
|
{
|
|
157
270
|
name: "models.getModelsOfType",
|
|
@@ -175,7 +288,7 @@ function modelGlobals(ctx, id, calls, publish, addUsage) {
|
|
|
175
288
|
execute: (args) => {
|
|
176
289
|
const [type, source, modelId] = args;
|
|
177
290
|
if (typeof source !== "string" || typeof modelId !== "string")
|
|
178
|
-
throw new Error(
|
|
291
|
+
throw new Error(`models.getModelOfType(type, provider, id) expects three strings, got (${args.map(describeValue).join(", ")}). The provider and the id are separate arguments, for example models.getModelOfType("classifier", "typesafe", "jev-latest").`);
|
|
179
292
|
const model = models.getModelOfType(modelType(type), source, modelId);
|
|
180
293
|
return model ? toCodemodeModelInfo(model) : undefined;
|
|
181
294
|
},
|
|
@@ -183,35 +296,16 @@ function modelGlobals(ctx, id, calls, publish, addUsage) {
|
|
|
183
296
|
{
|
|
184
297
|
name: "models.classify",
|
|
185
298
|
spread: true,
|
|
186
|
-
execute:
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
id: `${id}/models.classify/${++count}`,
|
|
195
|
-
name: "models.classify",
|
|
196
|
-
args: `${model.provider}/${model.id}`,
|
|
197
|
-
status: "running",
|
|
198
|
-
};
|
|
199
|
-
calls.push(record);
|
|
200
|
-
publish();
|
|
201
|
-
const start = performance.now();
|
|
202
|
-
const result = await limit(() => models.classify(model, context, { signal }));
|
|
203
|
-
record.durationMs = performance.now() - start;
|
|
204
|
-
record.status =
|
|
205
|
-
result.stopReason === "stop" ? "ok" : result.stopReason === "aborted" ? "cancelled" : "error";
|
|
206
|
-
if (result.errorMessage)
|
|
207
|
-
record.error = result.errorMessage.slice(0, 500);
|
|
208
|
-
if (result.usage) {
|
|
209
|
-
record.cost = result.usage.cost.total;
|
|
210
|
-
addUsage(result.usage);
|
|
211
|
-
}
|
|
212
|
-
publish();
|
|
299
|
+
execute: (args, { signal }) => runModelCall("models.classify", "classifier", args, checkClassifierContext, (model, context) => models.classify(model, context, { signal })),
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
name: "models.generateImages",
|
|
303
|
+
spread: true,
|
|
304
|
+
execute: (args, { signal }) => runModelCall("models.generateImages", "image", args, checkImagesContext, async (model, context) => {
|
|
305
|
+
const result = await models.generateImages(model, context, { signal });
|
|
306
|
+
addGeneratedImages(result.output.filter((block) => block.type === "image").length);
|
|
213
307
|
return result;
|
|
214
|
-
},
|
|
308
|
+
}),
|
|
215
309
|
},
|
|
216
310
|
];
|
|
217
311
|
}
|
|
@@ -220,6 +314,7 @@ export async function executeCodemode(id, input, signal, update, ctx, options =
|
|
|
220
314
|
const { code, options: source } = parseCodemodeSource(input.code);
|
|
221
315
|
const calls = [];
|
|
222
316
|
let usage;
|
|
317
|
+
let generatedImages = 0;
|
|
223
318
|
const snapshot = () => ({ calls: calls.map((call) => ({ ...call })) });
|
|
224
319
|
const publish = () => update?.({ content: [], details: snapshot() });
|
|
225
320
|
const callable = ctx ? getCodemodeCallableTools(ctx.tools) : [];
|
|
@@ -260,6 +355,8 @@ export async function executeCodemode(id, input, signal, update, ctx, options =
|
|
|
260
355
|
...(options.models && ctx
|
|
261
356
|
? modelGlobals(ctx, id, calls, publish, (extra) => {
|
|
262
357
|
usage = usage ? combineUsage(usage, extra) : extra;
|
|
358
|
+
}, (count) => {
|
|
359
|
+
generatedImages += count;
|
|
263
360
|
})
|
|
264
361
|
: []),
|
|
265
362
|
],
|
|
@@ -296,6 +393,11 @@ export async function executeCodemode(id, input, signal, update, ctx, options =
|
|
|
296
393
|
type: "text",
|
|
297
394
|
text: `Script error:\n${result.error.stack ?? result.error.message}\n\nTool calls made before the failure (they are not undone): ${calls.map((call) => `${call.name} (${call.status})`).join(", ") || "none"}`,
|
|
298
395
|
});
|
|
396
|
+
if (generatedImages > 0 && !content.some((block) => block.type === "image"))
|
|
397
|
+
content.push({
|
|
398
|
+
type: "text",
|
|
399
|
+
text: `Note: models.generateImages() returned ${generatedImages} image${generatedImages === 1 ? "" : "s"} that the script did not show. Show each image block of result.output with image(block).`,
|
|
400
|
+
});
|
|
299
401
|
const text = content
|
|
300
402
|
.filter((block) => block.type === "text")
|
|
301
403
|
.map((block) => block.text)
|