@oxbit/cli 0.8.0 → 0.9.0
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/package.json +1 -1
- package/runtime/dist/index.js +441 -28
- package/runtime/package.json +1 -1
- package/web/dist/assets/{index-DoZNi2PS.css → index-BG8qkqOX.css} +1 -1
- package/web/dist/assets/{index-O78N-E-Z.js → index-MUHvcYc7.js} +171 -139
- package/web/dist/assets/{typescript-BDEBNDpD.js → typescript-Du4_Siji.js} +2 -2
- package/web/dist/index.html +2 -2
- package/web/dist/schemas/settings.v1.schema.json +32 -0
- package/web/dist/sdk/index.js +52 -0
package/runtime/dist/index.js
CHANGED
|
@@ -933,11 +933,11 @@ const $id$1 = "https://oxbit.dev/schemas/settings.v1.schema.json";
|
|
|
933
933
|
const title$2 = "Oxbit Settings";
|
|
934
934
|
const description$2 = "User, private workspace and repository settings. Literal dotted IDs; objects merge recursively, arrays and scalar values replace. Unrecognized extension settings are preserved. Null is a value, not a reset, and must be valid for its setting.";
|
|
935
935
|
const type$2 = "object";
|
|
936
|
-
const properties$2 = /* @__PURE__ */ JSON.parse(`{"$schema":{"type":"string","description":"JSON Schema URI. Ignored when merging effective preferences."},"agentACP.provider":{"title":"Default agent","description":"A built-in agent ID, an ACP Registry agent ID, or custom.","type":"string","default":"codex"},"agentACP.useModifierToSend":{"title":"Send with Ctrl/Cmd+Enter only","description":"Enter inserts a new line and Ctrl/Cmd+Enter sends the message.","type":"boolean","default":false},"agentACP.notifications":{"title":"Agent desktop notifications","description":"Show a system notification when the agent needs input or finishes while Oxbit is in the background.","type":"string","default":"whenHidden","enum":["whenHidden","never"]},"agentACP.codex.command":{"title":"Codex ACP executable","type":"string","default":"npx"},"agentACP.codex.args":{"title":"Codex ACP arguments (JSON array)","type":"string","default":"[\\"-y\\",\\"@agentclientprotocol/codex-acp@2.2.2\\"]"},"agentACP.claude.command":{"title":"Claude Agent executable","type":"string","default":"npx"},"agentACP.claude.args":{"title":"Claude Agent arguments (JSON array)","type":"string","default":"[\\"-y\\",\\"@agentclientprotocol/claude-agent-acp@0.89.1\\"]"},"agentACP.gemini.command":{"title":"Gemini CLI executable","type":"string","default":"npx"},"agentACP.gemini.args":{"title":"Gemini CLI arguments (JSON array)","type":"string","default":"[\\"-y\\",\\"@google/gemini-cli@0.63.0\\",\\"--acp\\"]"},"agentACP.copilot.command":{"title":"GitHub Copilot executable","type":"string","default":"npx"},"agentACP.copilot.args":{"title":"GitHub Copilot arguments (JSON array)","type":"string","default":"[\\"-y\\",\\"@github/copilot@1.0.95\\",\\"--acp\\"]"},"agentACP.cursor.command":{"title":"Cursor ACP executable","type":"string","default":"agent"},"agentACP.cursor.args":{"title":"Cursor ACP arguments (JSON array)","type":"string","default":"[\\"acp\\"]"},"agentACP.amp.command":{"title":"Amp Agent ACP executable","type":"string","default":"npx"},"agentACP.amp.args":{"title":"Amp Agent ACP arguments (JSON array)","type":"string","default":"[\\"-y\\",\\"amp-acp@0.10.0\\"]"},"agentACP.custom.name":{"title":"Custom agent name","type":"string","default":""},"agentACP.custom.command":{"title":"Custom agent executable","type":"string","default":""},"agentACP.custom.args":{"title":"Custom agent arguments (JSON array)","type":"string","default":"[]"},"workbench.keymap":{"title":"Keymap","description":"Keyboard layout applied on top of the Oxbit defaults. User keybindings always win.","type":"string","default":"default","enum":["default","vscode","jetbrains","macos","sublime","atom","visual-studio","emacs"]},"runtime.keepAlive":{"title":"Keep Runtime Alive","description":"How long a runtime Oxbit started keeps running after the last client disconnects or its connection heartbeats stop. Terminals and tasks continue while it runs.","type":"string","default":"75s","enum":["75s","15m","1h","8h","untilStopped"]},"runtime.autoReconnect":{"title":"Reconnect Automatically","description":"Reconnect to the runtime after the connection drops, including when the iOS app returns to the foreground.","type":"boolean","default":true},"workbench.tooltipDelay":{"title":"Tooltip Delay","description":"Delay in milliseconds before showing a tooltip on hover. Keyboard focus shows tooltips immediately.","type":"number","default":400,"minimum":0,"maximum":5000},"workbench.colorTheme":{"title":"Color Theme","description":"Specifies the color theme used in the workbench.","type":"string","default":"Graphite (dark)"},"workbench.density":{"title":"Layout Density","description":"Controls row heights, padding and label sizes across the workbench.","type":"string","default":"compact","enum":["compact","comfortable"]},"workbench.sidebarLocation":{"title":"Sidebar Location","description":"Where the primary sidebar is docked.","type":"string","default":"left","enum":["left","right"]},"editor.fontFamily":{"title":"Font Family","description":"Controls the font family of the editor.","type":"string","default":"'JetBrains Mono', ui-monospace, monospace"},"editor.fontSize":{"title":"Font Size","description":"Font size in pixels.","type":"number","default":13,"minimum":8,"maximum":32},"editor.lineHeight":{"title":"Line Height","description":"Line height in pixels. 0 uses 1.55 × font size.","type":"number","default":20,"minimum":0,"maximum":60},"editor.fontLigatures":{"title":"Font Ligatures","description":"Enables font ligatures when the font supports them.","type":"boolean","default":false},"editor.tabSize":{"title":"Tab Size","description":"The number of spaces a tab is equal to.","type":"number","default":2,"minimum":1,"maximum":8},"editor.insertSpaces":{"title":"Insert Spaces","description":"Insert spaces when pressing Tab.","type":"boolean","default":true},"editor.detectIndentation":{"title":"Detect Indentation","description":"Detect Tab Size and Insert Spaces from file contents on open.","type":"boolean","default":true},"editor.renderIndentGuides":{"title":"Indentation Guides","description":"Render vertical guides for each indent level.","type":"boolean","default":true},"editor.wordWrap":{"title":"Word Wrap","description":"Controls how lines should wrap.","type":"string","default":"off","enum":["off","on","bounded"]},"editor.renderWhitespace":{"title":"Render Whitespace","description":"Controls how the editor renders whitespace characters.","type":"string","default":"selection","enum":["none","boundary","selection","all"]},"editor.cursorBlinking":{"title":"Cursor Blinking","description":"Cursor animation style.","type":"string","default":"blink","enum":["blink","smooth","phase","solid"]},"editor.minimap":{"title":"Minimap","description":"Show a minimap of the document.","type":"boolean","default":false},"files.autoSave":{"title":"Auto Save","description":"Controls auto save of editors that have unsaved changes.","type":"string","default":"off","enum":["off","afterDelay","onFocusChange","onWindowChange"]},"files.autoSaveDelay":{"title":"Auto Save Delay","description":"Delay in milliseconds after which an editor is saved automatically. Applies when Auto Save is afterDelay.","type":"number","default":1000,"minimum":100,"maximum":60000},"files.trimTrailingWhitespace":{"title":"Trim Trailing Whitespace","description":"Remove trailing whitespace when saving.","type":"boolean","default":true},"editor.formatOnSave":{"title":"Format On Save","description":"Format a file on save. A formatter must be available.","type":"boolean","default":false},"editor.defaultFormatter":{"title":"Default Formatter","description":"Formatter used when several are available.","type":"string","default":"oxbit.prettier","anyOf":[{"enum":["oxbit.prettier","oxbit.builtin-ts"]},{"type":"string"}]},"terminal.fontSize":{"title":"Terminal Font Size","description":"Font size in pixels for the terminal.","type":"number","default":12,"minimum":8,"maximum":32},"terminal.scrollback":{"title":"Scrollback","description":"Maximum number of lines kept in the terminal buffer.","type":"number","default":5000,"minimum":100,"maximum":100000},"terminal.confirmOnKill":{"title":"Confirm On Kill","description":"Ask before killing a terminal with a running process.","type":"boolean","default":true},"scm.autoFetch":{"title":"Auto Fetch","description":"Periodically fetch from the default remote.","type":"boolean","default":true},"scm.diffLayout":{"title":"Diff Layout","description":"Default layout for diff editors.","type":"string","default":"side-by-side","enum":["side-by-side","inline"]},"files.associations":{"title":"File Associations","description":"Map filename or workspace-relative glob patterns to language IDs. Explicit associations take precedence over built-in detection.","type":"object","default":{},"propertyNames":{"minLength":1,"maxLength":1024},"additionalProperties":{"type":"string","pattern":"^[\\\\w+-]+$"}},"languageServers":{"title":"Language Servers","description":"Configure enabled state, selectors, rootMarkers, executable, args, env, initializationOptions, settings, and priority by server ID. Servers install on first use in a trusted runtime. License keys belong in the runtime-local credential file.","type":"object","default":{},"propertyNames":{"pattern":"^[a-zA-Z0-9._-]+$"},"additionalProperties":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Enable this language server."},"selectors":{"type":"array","items":{"type":"object","properties":{"language":{"type":"string"},"pattern":{"type":"string"},"scheme":{"const":"file"}},"additionalProperties":false,"minProperties":1}},"rootMarkers":{"type":"array","items":{"type":"string","pattern":"^(?!/)(?!.*\\\\\\\\)(?!.*(?:^|/)\\\\.\\\\.(?:/|$))[^\\\\u0000]+$","minLength":1}},"executable":{"type":"string","pattern":"^[^\\\\u0000]*$","minLength":1},"args":{"type":"array","items":{"type":"string","pattern":"^[^\\\\u0000]*$"}},"env":{"type":"object","propertyNames":{"pattern":"^[A-Za-z_][A-Za-z0-9_]*$"},"additionalProperties":{"type":"string","pattern":"^[^\\\\u0000]*$"}},"initializationOptions":{"type":"object","additionalProperties":true,"description":"Server-specific initialization options. Store license credentials in the runtime credential file."},"settings":{"type":"object","additionalProperties":true,"description":"Server-specific configuration; nested objects merge across files."},"priority":{"type":"number"}},"additionalProperties":false}},"ui.fontFamily":{"title":"UI Font Family","description":"Overrides theme typography. Reset restores the theme value.","type":"string","default":""},"ui.fontSize":{"title":"UI Font Size","description":"Overrides theme typography. Reset restores the theme value.","type":"number","default":12,"minimum":8,"maximum":72},"ui.fontWeight":{"title":"UI Font Weight","description":"Overrides theme typography. Reset restores the theme value.","type":"number","default":400,"minimum":100,"maximum":900},"ui.fontStyle":{"title":"UI Font Style","description":"Overrides theme typography. Reset restores the theme value.","type":"string","default":"normal","enum":["normal","italic","oblique"]},"ui.lineHeight":{"title":"UI Line Height","description":"Overrides theme typography. Reset restores the theme value.","type":"number","default":1.4,"minimum":1,"maximum":3},"ui.letterSpacing":{"title":"UI Letter Spacing","description":"Overrides theme typography. Reset restores the theme value.","type":"number","default":0,"minimum":-3,"maximum":10},"ui.fontLigatures":{"title":"UI Font Ligatures","description":"Overrides theme typography. Reset restores the theme value.","type":"boolean","default":false},"terminal.fontFamily":{"title":"Terminal Font Family","description":"Overrides theme typography. Reset restores the theme value.","type":"string","default":""},"terminal.fontWeight":{"title":"Terminal Font Weight","description":"Overrides theme typography. Reset restores the theme value.","type":"number","default":400,"minimum":100,"maximum":900},"terminal.fontStyle":{"title":"Terminal Font Style","description":"Overrides theme typography. Reset restores the theme value.","type":"string","default":"normal","enum":["normal","italic","oblique"]},"terminal.lineHeight":{"title":"Terminal Line Height","description":"Overrides theme typography. Reset restores the theme value.","type":"number","default":1,"minimum":1,"maximum":3},"terminal.letterSpacing":{"title":"Terminal Letter Spacing","description":"Overrides theme typography. Reset restores the theme value.","type":"number","default":0,"minimum":-3,"maximum":10},"terminal.fontLigatures":{"title":"Terminal Font Ligatures","description":"Overrides theme typography. Reset restores the theme value.","type":"boolean","default":false},"workbench.iconTheme":{"title":"File Icon Theme","description":"Select a locally installed icon theme. Unavailable selections use Oxbit defaults until restored.","type":"string","default":"oxbit.default"},"workbench.productIconTheme":{"title":"Product Icon Theme","description":"Select a locally installed icon theme. Unavailable selections use Oxbit defaults until restored.","type":"string","default":"oxbit.default"},"editor.semanticHighlighting":{"title":"Semantic Highlighting","description":"Color symbols using language server information.","type":"boolean","default":true},"editor.inlayHints.types":{"title":"Type Inlay Hints","description":"Show supported type hints in the visible editor.","type":"boolean","default":true},"editor.inlayHints.parameters":{"title":"Parameter Inlay Hints","description":"Show supported parameter hints in the visible editor.","type":"boolean","default":true},"editor.largeFileIntelligence":{"title":"Large File Intelligence","description":"Allow full semantic highlighting and inlay hints for files larger than 1 MiB.","type":"boolean","default":false},"workbench.locale":{"title":"Display Language","type":"string","default":"en","enum":["en","de","es","ja","zh"]},"workbench.reducedMotion":{"title":"Reduced Motion","type":"boolean","default":false},"desktop.projects.openBehavior":{"title":"Open projects","type":"string","default":"currentWindow","enum":["currentWindow","newWindow"]},"desktop.tools.gitPath":{"title":"git executable path","type":"string","default":""},"desktop.tools.ghPath":{"title":"gh executable path","type":"string","default":""},"project.intelligence":{"type":"object","properties":{"enabled":{"type":"boolean","default":true,"description":"Index project dependencies, imports and related files."},"exclude":{"type":"array","items":{"type":"string","maxLength":1024},"default":[]},"maxFiles":{"type":"integer","minimum":1,"maximum":100000,"default":20000},"maxFileBytes":{"type":"integer","minimum":1,"maximum":5242880,"default":1048576}},"additionalProperties":false,"title":"Project Intelligence","description":"Partial overrides of project.json intelligence. Objects merge across files."},"project.schemas":{"type":"object","properties":{"catalog":{"type":"boolean","default":true,"description":"Discover file schemas through SchemaStore. Bundled Oxbit settings support remains available."},"download":{"type":"boolean","default":true,"description":"Allow remote schema downloads; cached and bundled schemas work offline."},"associations":{"type":"array","maxItems":1000,"default":[],"items":{"type":"object","properties":{"url":{"type":"string","minLength":1,"description":"Schema URL or workspace file URI."},"fileMatch":{"type":"array","items":{"type":"string","maxLength":1024}},"schema":{"type":["object","boolean"],"description":"An inline JSON Schema."}},"additionalProperties":false,"anyOf":[{"required":["url"]},{"required":["schema"]}]}}},"additionalProperties":false,"title":"JSON Schemas","description":"Partial overrides of project.json schemas. Association arrays replace lower arrays."}}`);
|
|
936
|
+
const properties$2 = /* @__PURE__ */ JSON.parse(`{"$schema":{"type":"string","description":"JSON Schema URI. Ignored when merging effective preferences."},"agentACP.provider":{"title":"Default agent","description":"A built-in agent ID, an ACP Registry agent ID, or custom.","type":"string","default":"codex"},"agentACP.useModifierToSend":{"title":"Send with Ctrl/Cmd+Enter only","description":"Enter inserts a new line and Ctrl/Cmd+Enter sends the message.","type":"boolean","default":false},"agentACP.notifications":{"title":"Agent desktop notifications","description":"Show a system notification when the agent needs input or finishes while Oxbit is in the background.","type":"string","default":"whenHidden","enum":["whenHidden","never"]},"agentACP.codex.command":{"title":"Codex ACP executable","type":"string","default":"npx"},"agentACP.codex.args":{"title":"Codex ACP arguments (JSON array)","type":"string","default":"[\\"-y\\",\\"@agentclientprotocol/codex-acp@2.2.2\\"]"},"agentACP.claude.command":{"title":"Claude Agent executable","type":"string","default":"npx"},"agentACP.claude.args":{"title":"Claude Agent arguments (JSON array)","type":"string","default":"[\\"-y\\",\\"@agentclientprotocol/claude-agent-acp@0.89.1\\"]"},"agentACP.gemini.command":{"title":"Gemini CLI executable","type":"string","default":"npx"},"agentACP.gemini.args":{"title":"Gemini CLI arguments (JSON array)","type":"string","default":"[\\"-y\\",\\"@google/gemini-cli@0.63.0\\",\\"--acp\\"]"},"agentACP.copilot.command":{"title":"GitHub Copilot executable","type":"string","default":"npx"},"agentACP.copilot.args":{"title":"GitHub Copilot arguments (JSON array)","type":"string","default":"[\\"-y\\",\\"@github/copilot@1.0.95\\",\\"--acp\\"]"},"agentACP.cursor.command":{"title":"Cursor ACP executable","type":"string","default":"agent"},"agentACP.cursor.args":{"title":"Cursor ACP arguments (JSON array)","type":"string","default":"[\\"acp\\"]"},"agentACP.amp.command":{"title":"Amp Agent ACP executable","type":"string","default":"npx"},"agentACP.amp.args":{"title":"Amp Agent ACP arguments (JSON array)","type":"string","default":"[\\"-y\\",\\"amp-acp@0.10.0\\"]"},"agentACP.custom.name":{"title":"Custom agent name","type":"string","default":""},"agentACP.custom.command":{"title":"Custom agent executable","type":"string","default":""},"agentACP.custom.args":{"title":"Custom agent arguments (JSON array)","type":"string","default":"[]"},"agentACP.oxbit.api":{"title":"Oxbit Agent API","description":"openai uses the Responses API, anthropic the Messages API, and openai-compatible Chat Completions at the base URL.","type":"string","default":"openai","enum":["openai","anthropic","openai-compatible"]},"agentACP.oxbit.baseUrl":{"title":"Oxbit Agent base URL","description":"Origin and path prefix for openai-compatible, for example https://openrouter.ai/api.","type":"string","default":""},"agentACP.oxbit.model":{"title":"Oxbit Agent model","description":"Model ID for new conversations.","type":"string","default":""},"workbench.keymap":{"title":"Keymap","description":"Keyboard layout applied on top of the Oxbit defaults. User keybindings always win.","type":"string","default":"default","enum":["default","vscode","jetbrains","macos","sublime","atom","visual-studio","emacs"]},"runtime.keepAlive":{"title":"Keep Runtime Alive","description":"How long a runtime Oxbit started keeps running after the last client disconnects or its connection heartbeats stop. Terminals and tasks continue while it runs.","type":"string","default":"75s","enum":["75s","15m","1h","8h","untilStopped"]},"runtime.autoReconnect":{"title":"Reconnect Automatically","description":"Reconnect to the runtime after the connection drops, including when the iOS app returns to the foreground.","type":"boolean","default":true},"workbench.tooltipDelay":{"title":"Tooltip Delay","description":"Delay in milliseconds before showing a tooltip on hover. Keyboard focus shows tooltips immediately.","type":"number","default":400,"minimum":0,"maximum":5000},"workbench.colorTheme":{"title":"Color Theme","description":"Specifies the color theme used in the workbench.","type":"string","default":"Graphite (dark)"},"workbench.density":{"title":"Layout Density","description":"Controls row heights, padding and label sizes across the workbench.","type":"string","default":"compact","enum":["compact","comfortable"]},"workbench.sidebarLocation":{"title":"Sidebar Location","description":"Where the primary sidebar is docked.","type":"string","default":"left","enum":["left","right"]},"editor.fontFamily":{"title":"Font Family","description":"Controls the font family of the editor.","type":"string","default":"'JetBrains Mono', ui-monospace, monospace"},"editor.fontSize":{"title":"Font Size","description":"Font size in pixels.","type":"number","default":13,"minimum":8,"maximum":32},"editor.lineHeight":{"title":"Line Height","description":"Line height in pixels. 0 uses 1.55 × font size.","type":"number","default":20,"minimum":0,"maximum":60},"editor.fontLigatures":{"title":"Font Ligatures","description":"Enables font ligatures when the font supports them.","type":"boolean","default":false},"editor.tabSize":{"title":"Tab Size","description":"The number of spaces a tab is equal to.","type":"number","default":2,"minimum":1,"maximum":8},"editor.insertSpaces":{"title":"Insert Spaces","description":"Insert spaces when pressing Tab.","type":"boolean","default":true},"editor.detectIndentation":{"title":"Detect Indentation","description":"Detect Tab Size and Insert Spaces from file contents on open.","type":"boolean","default":true},"editor.renderIndentGuides":{"title":"Indentation Guides","description":"Render vertical guides for each indent level.","type":"boolean","default":true},"editor.wordWrap":{"title":"Word Wrap","description":"Controls how lines should wrap.","type":"string","default":"off","enum":["off","on","bounded"]},"editor.renderWhitespace":{"title":"Render Whitespace","description":"Controls how the editor renders whitespace characters.","type":"string","default":"selection","enum":["none","boundary","selection","all"]},"editor.cursorBlinking":{"title":"Cursor Blinking","description":"Cursor animation style.","type":"string","default":"blink","enum":["blink","smooth","phase","solid"]},"editor.minimap":{"title":"Minimap","description":"Show a minimap of the document.","type":"boolean","default":false},"files.autoSave":{"title":"Auto Save","description":"Controls auto save of editors that have unsaved changes.","type":"string","default":"off","enum":["off","afterDelay","onFocusChange","onWindowChange"]},"files.autoSaveDelay":{"title":"Auto Save Delay","description":"Delay in milliseconds after which an editor is saved automatically. Applies when Auto Save is afterDelay.","type":"number","default":1000,"minimum":100,"maximum":60000},"files.trimTrailingWhitespace":{"title":"Trim Trailing Whitespace","description":"Remove trailing whitespace when saving.","type":"boolean","default":true},"editor.formatOnSave":{"title":"Format On Save","description":"Format a file on save. A formatter must be available.","type":"boolean","default":false},"editor.defaultFormatter":{"title":"Default Formatter","description":"Formatter used when several are available.","type":"string","default":"oxbit.prettier","anyOf":[{"enum":["oxbit.prettier","oxbit.builtin-ts"]},{"type":"string"}]},"terminal.fontSize":{"title":"Terminal Font Size","description":"Font size in pixels for the terminal.","type":"number","default":12,"minimum":8,"maximum":32},"terminal.scrollback":{"title":"Scrollback","description":"Maximum number of lines kept in the terminal buffer.","type":"number","default":5000,"minimum":100,"maximum":100000},"terminal.confirmOnKill":{"title":"Confirm On Kill","description":"Ask before killing a terminal with a running process.","type":"boolean","default":true},"scm.autoFetch":{"title":"Auto Fetch","description":"Periodically fetch from the default remote.","type":"boolean","default":true},"scm.diffLayout":{"title":"Diff Layout","description":"Default layout for diff editors.","type":"string","default":"side-by-side","enum":["side-by-side","inline"]},"files.associations":{"title":"File Associations","description":"Map filename or workspace-relative glob patterns to language IDs. Explicit associations take precedence over built-in detection.","type":"object","default":{},"propertyNames":{"minLength":1,"maxLength":1024},"additionalProperties":{"type":"string","pattern":"^[\\\\w+-]+$"}},"languageServers":{"title":"Language Servers","description":"Configure enabled state, selectors, rootMarkers, executable, args, env, initializationOptions, settings, and priority by server ID. Servers install on first use in a trusted runtime. License keys belong in the runtime-local credential file.","type":"object","default":{},"propertyNames":{"pattern":"^[a-zA-Z0-9._-]+$"},"additionalProperties":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Enable this language server."},"selectors":{"type":"array","items":{"type":"object","properties":{"language":{"type":"string"},"pattern":{"type":"string"},"scheme":{"const":"file"}},"additionalProperties":false,"minProperties":1}},"rootMarkers":{"type":"array","items":{"type":"string","pattern":"^(?!/)(?!.*\\\\\\\\)(?!.*(?:^|/)\\\\.\\\\.(?:/|$))[^\\\\u0000]+$","minLength":1}},"executable":{"type":"string","pattern":"^[^\\\\u0000]*$","minLength":1},"args":{"type":"array","items":{"type":"string","pattern":"^[^\\\\u0000]*$"}},"env":{"type":"object","propertyNames":{"pattern":"^[A-Za-z_][A-Za-z0-9_]*$"},"additionalProperties":{"type":"string","pattern":"^[^\\\\u0000]*$"}},"initializationOptions":{"type":"object","additionalProperties":true,"description":"Server-specific initialization options. Store license credentials in the runtime credential file."},"settings":{"type":"object","additionalProperties":true,"description":"Server-specific configuration; nested objects merge across files."},"priority":{"type":"number"}},"additionalProperties":false}},"ui.fontFamily":{"title":"UI Font Family","description":"Overrides theme typography. Reset restores the theme value.","type":"string","default":""},"ui.fontSize":{"title":"UI Font Size","description":"Overrides theme typography. Reset restores the theme value.","type":"number","default":12,"minimum":8,"maximum":72},"ui.fontWeight":{"title":"UI Font Weight","description":"Overrides theme typography. Reset restores the theme value.","type":"number","default":400,"minimum":100,"maximum":900},"ui.fontStyle":{"title":"UI Font Style","description":"Overrides theme typography. Reset restores the theme value.","type":"string","default":"normal","enum":["normal","italic","oblique"]},"ui.lineHeight":{"title":"UI Line Height","description":"Overrides theme typography. Reset restores the theme value.","type":"number","default":1.4,"minimum":1,"maximum":3},"ui.letterSpacing":{"title":"UI Letter Spacing","description":"Overrides theme typography. Reset restores the theme value.","type":"number","default":0,"minimum":-3,"maximum":10},"ui.fontLigatures":{"title":"UI Font Ligatures","description":"Overrides theme typography. Reset restores the theme value.","type":"boolean","default":false},"terminal.fontFamily":{"title":"Terminal Font Family","description":"Overrides theme typography. Reset restores the theme value.","type":"string","default":""},"terminal.fontWeight":{"title":"Terminal Font Weight","description":"Overrides theme typography. Reset restores the theme value.","type":"number","default":400,"minimum":100,"maximum":900},"terminal.fontStyle":{"title":"Terminal Font Style","description":"Overrides theme typography. Reset restores the theme value.","type":"string","default":"normal","enum":["normal","italic","oblique"]},"terminal.lineHeight":{"title":"Terminal Line Height","description":"Overrides theme typography. Reset restores the theme value.","type":"number","default":1,"minimum":1,"maximum":3},"terminal.letterSpacing":{"title":"Terminal Letter Spacing","description":"Overrides theme typography. Reset restores the theme value.","type":"number","default":0,"minimum":-3,"maximum":10},"terminal.fontLigatures":{"title":"Terminal Font Ligatures","description":"Overrides theme typography. Reset restores the theme value.","type":"boolean","default":false},"workbench.iconTheme":{"title":"File Icon Theme","description":"Select a locally installed icon theme. Unavailable selections use Oxbit defaults until restored.","type":"string","default":"oxbit.default"},"workbench.productIconTheme":{"title":"Product Icon Theme","description":"Select a locally installed icon theme. Unavailable selections use Oxbit defaults until restored.","type":"string","default":"oxbit.default"},"editor.semanticHighlighting":{"title":"Semantic Highlighting","description":"Color symbols using language server information.","type":"boolean","default":true},"editor.inlayHints.types":{"title":"Type Inlay Hints","description":"Show supported type hints in the visible editor.","type":"boolean","default":true},"editor.inlayHints.parameters":{"title":"Parameter Inlay Hints","description":"Show supported parameter hints in the visible editor.","type":"boolean","default":true},"editor.largeFileIntelligence":{"title":"Large File Intelligence","description":"Allow full semantic highlighting and inlay hints for files larger than 1 MiB.","type":"boolean","default":false},"workbench.locale":{"title":"Display Language","type":"string","default":"en","enum":["en","de","es","ja","zh"]},"workbench.reducedMotion":{"title":"Reduced Motion","type":"boolean","default":false},"desktop.projects.openBehavior":{"title":"Open projects","type":"string","default":"currentWindow","enum":["currentWindow","newWindow"]},"desktop.tools.gitPath":{"title":"git executable path","type":"string","default":""},"desktop.tools.ghPath":{"title":"gh executable path","type":"string","default":""},"project.intelligence":{"type":"object","properties":{"enabled":{"type":"boolean","default":true,"description":"Index project dependencies, imports and related files."},"exclude":{"type":"array","items":{"type":"string","maxLength":1024},"default":[]},"maxFiles":{"type":"integer","minimum":1,"maximum":100000,"default":20000},"maxFileBytes":{"type":"integer","minimum":1,"maximum":5242880,"default":1048576}},"additionalProperties":false,"title":"Project Intelligence","description":"Partial overrides of project.json intelligence. Objects merge across files."},"project.schemas":{"type":"object","properties":{"catalog":{"type":"boolean","default":true,"description":"Discover file schemas through SchemaStore. Bundled Oxbit settings support remains available."},"download":{"type":"boolean","default":true,"description":"Allow remote schema downloads; cached and bundled schemas work offline."},"associations":{"type":"array","maxItems":1000,"default":[],"items":{"type":"object","properties":{"url":{"type":"string","minLength":1,"description":"Schema URL or workspace file URI."},"fileMatch":{"type":"array","items":{"type":"string","maxLength":1024}},"schema":{"type":["object","boolean"],"description":"An inline JSON Schema."}},"additionalProperties":false,"anyOf":[{"required":["url"]},{"required":["schema"]}]}}},"additionalProperties":false,"title":"JSON Schemas","description":"Partial overrides of project.json schemas. Association arrays replace lower arrays."}}`);
|
|
937
937
|
const propertyNames = { "anyOf": [{ "not": { "pattern": "^\\[.*\\]$" } }, { "pattern": "^\\[[^\\[\\]]+\\]$" }] };
|
|
938
938
|
const patternProperties = { "^\\[[^\\[\\]]+\\]$": { "$ref": "#/definitions/languageOverrides" } };
|
|
939
939
|
const additionalProperties$1 = true;
|
|
940
|
-
const definitions$1 = { "languageOverrides": { "type": "object", "properties": { "agentACP.provider": { "$ref": "#/properties/agentACP.provider" }, "agentACP.useModifierToSend": { "$ref": "#/properties/agentACP.useModifierToSend" }, "agentACP.notifications": { "$ref": "#/properties/agentACP.notifications" }, "agentACP.codex.command": { "$ref": "#/properties/agentACP.codex.command" }, "agentACP.codex.args": { "$ref": "#/properties/agentACP.codex.args" }, "agentACP.claude.command": { "$ref": "#/properties/agentACP.claude.command" }, "agentACP.claude.args": { "$ref": "#/properties/agentACP.claude.args" }, "agentACP.gemini.command": { "$ref": "#/properties/agentACP.gemini.command" }, "agentACP.gemini.args": { "$ref": "#/properties/agentACP.gemini.args" }, "agentACP.copilot.command": { "$ref": "#/properties/agentACP.copilot.command" }, "agentACP.copilot.args": { "$ref": "#/properties/agentACP.copilot.args" }, "agentACP.cursor.command": { "$ref": "#/properties/agentACP.cursor.command" }, "agentACP.cursor.args": { "$ref": "#/properties/agentACP.cursor.args" }, "agentACP.amp.command": { "$ref": "#/properties/agentACP.amp.command" }, "agentACP.amp.args": { "$ref": "#/properties/agentACP.amp.args" }, "agentACP.custom.name": { "$ref": "#/properties/agentACP.custom.name" }, "agentACP.custom.command": { "$ref": "#/properties/agentACP.custom.command" }, "agentACP.custom.args": { "$ref": "#/properties/agentACP.custom.args" }, "workbench.keymap": { "$ref": "#/properties/workbench.keymap" }, "runtime.keepAlive": { "$ref": "#/properties/runtime.keepAlive" }, "runtime.autoReconnect": { "$ref": "#/properties/runtime.autoReconnect" }, "workbench.tooltipDelay": { "$ref": "#/properties/workbench.tooltipDelay" }, "workbench.colorTheme": { "$ref": "#/properties/workbench.colorTheme" }, "workbench.density": { "$ref": "#/properties/workbench.density" }, "workbench.sidebarLocation": { "$ref": "#/properties/workbench.sidebarLocation" }, "editor.fontFamily": { "$ref": "#/properties/editor.fontFamily" }, "editor.fontSize": { "$ref": "#/properties/editor.fontSize" }, "editor.lineHeight": { "$ref": "#/properties/editor.lineHeight" }, "editor.fontLigatures": { "$ref": "#/properties/editor.fontLigatures" }, "editor.tabSize": { "$ref": "#/properties/editor.tabSize" }, "editor.insertSpaces": { "$ref": "#/properties/editor.insertSpaces" }, "editor.detectIndentation": { "$ref": "#/properties/editor.detectIndentation" }, "editor.renderIndentGuides": { "$ref": "#/properties/editor.renderIndentGuides" }, "editor.wordWrap": { "$ref": "#/properties/editor.wordWrap" }, "editor.renderWhitespace": { "$ref": "#/properties/editor.renderWhitespace" }, "editor.cursorBlinking": { "$ref": "#/properties/editor.cursorBlinking" }, "editor.minimap": { "$ref": "#/properties/editor.minimap" }, "files.autoSave": { "$ref": "#/properties/files.autoSave" }, "files.autoSaveDelay": { "$ref": "#/properties/files.autoSaveDelay" }, "files.trimTrailingWhitespace": { "$ref": "#/properties/files.trimTrailingWhitespace" }, "editor.formatOnSave": { "$ref": "#/properties/editor.formatOnSave" }, "editor.defaultFormatter": { "$ref": "#/properties/editor.defaultFormatter" }, "terminal.fontSize": { "$ref": "#/properties/terminal.fontSize" }, "terminal.scrollback": { "$ref": "#/properties/terminal.scrollback" }, "terminal.confirmOnKill": { "$ref": "#/properties/terminal.confirmOnKill" }, "scm.autoFetch": { "$ref": "#/properties/scm.autoFetch" }, "scm.diffLayout": { "$ref": "#/properties/scm.diffLayout" }, "files.associations": { "$ref": "#/properties/files.associations" }, "languageServers": { "$ref": "#/properties/languageServers" }, "ui.fontFamily": { "$ref": "#/properties/ui.fontFamily" }, "ui.fontSize": { "$ref": "#/properties/ui.fontSize" }, "ui.fontWeight": { "$ref": "#/properties/ui.fontWeight" }, "ui.fontStyle": { "$ref": "#/properties/ui.fontStyle" }, "ui.lineHeight": { "$ref": "#/properties/ui.lineHeight" }, "ui.letterSpacing": { "$ref": "#/properties/ui.letterSpacing" }, "ui.fontLigatures": { "$ref": "#/properties/ui.fontLigatures" }, "terminal.fontFamily": { "$ref": "#/properties/terminal.fontFamily" }, "terminal.fontWeight": { "$ref": "#/properties/terminal.fontWeight" }, "terminal.fontStyle": { "$ref": "#/properties/terminal.fontStyle" }, "terminal.lineHeight": { "$ref": "#/properties/terminal.lineHeight" }, "terminal.letterSpacing": { "$ref": "#/properties/terminal.letterSpacing" }, "terminal.fontLigatures": { "$ref": "#/properties/terminal.fontLigatures" }, "workbench.iconTheme": { "$ref": "#/properties/workbench.iconTheme" }, "workbench.productIconTheme": { "$ref": "#/properties/workbench.productIconTheme" }, "editor.semanticHighlighting": { "$ref": "#/properties/editor.semanticHighlighting" }, "editor.inlayHints.types": { "$ref": "#/properties/editor.inlayHints.types" }, "editor.inlayHints.parameters": { "$ref": "#/properties/editor.inlayHints.parameters" }, "editor.largeFileIntelligence": { "$ref": "#/properties/editor.largeFileIntelligence" }, "workbench.locale": { "$ref": "#/properties/workbench.locale" }, "workbench.reducedMotion": { "$ref": "#/properties/workbench.reducedMotion" }, "desktop.projects.openBehavior": { "$ref": "#/properties/desktop.projects.openBehavior" }, "desktop.tools.gitPath": { "$ref": "#/properties/desktop.tools.gitPath" }, "desktop.tools.ghPath": { "$ref": "#/properties/desktop.tools.ghPath" }, "project.intelligence": false, "project.schemas": false }, "additionalProperties": true, "description": "Settings for a language ID, such as [mdx] or [php]. Runtime project options belong at the top level.", "propertyNames": { "not": { "pattern": "^\\[.*\\]$" } } } };
|
|
940
|
+
const definitions$1 = { "languageOverrides": { "type": "object", "properties": { "agentACP.provider": { "$ref": "#/properties/agentACP.provider" }, "agentACP.useModifierToSend": { "$ref": "#/properties/agentACP.useModifierToSend" }, "agentACP.notifications": { "$ref": "#/properties/agentACP.notifications" }, "agentACP.codex.command": { "$ref": "#/properties/agentACP.codex.command" }, "agentACP.codex.args": { "$ref": "#/properties/agentACP.codex.args" }, "agentACP.claude.command": { "$ref": "#/properties/agentACP.claude.command" }, "agentACP.claude.args": { "$ref": "#/properties/agentACP.claude.args" }, "agentACP.gemini.command": { "$ref": "#/properties/agentACP.gemini.command" }, "agentACP.gemini.args": { "$ref": "#/properties/agentACP.gemini.args" }, "agentACP.copilot.command": { "$ref": "#/properties/agentACP.copilot.command" }, "agentACP.copilot.args": { "$ref": "#/properties/agentACP.copilot.args" }, "agentACP.cursor.command": { "$ref": "#/properties/agentACP.cursor.command" }, "agentACP.cursor.args": { "$ref": "#/properties/agentACP.cursor.args" }, "agentACP.amp.command": { "$ref": "#/properties/agentACP.amp.command" }, "agentACP.amp.args": { "$ref": "#/properties/agentACP.amp.args" }, "agentACP.custom.name": { "$ref": "#/properties/agentACP.custom.name" }, "agentACP.custom.command": { "$ref": "#/properties/agentACP.custom.command" }, "agentACP.custom.args": { "$ref": "#/properties/agentACP.custom.args" }, "agentACP.oxbit.api": { "$ref": "#/properties/agentACP.oxbit.api" }, "agentACP.oxbit.baseUrl": { "$ref": "#/properties/agentACP.oxbit.baseUrl" }, "agentACP.oxbit.model": { "$ref": "#/properties/agentACP.oxbit.model" }, "workbench.keymap": { "$ref": "#/properties/workbench.keymap" }, "runtime.keepAlive": { "$ref": "#/properties/runtime.keepAlive" }, "runtime.autoReconnect": { "$ref": "#/properties/runtime.autoReconnect" }, "workbench.tooltipDelay": { "$ref": "#/properties/workbench.tooltipDelay" }, "workbench.colorTheme": { "$ref": "#/properties/workbench.colorTheme" }, "workbench.density": { "$ref": "#/properties/workbench.density" }, "workbench.sidebarLocation": { "$ref": "#/properties/workbench.sidebarLocation" }, "editor.fontFamily": { "$ref": "#/properties/editor.fontFamily" }, "editor.fontSize": { "$ref": "#/properties/editor.fontSize" }, "editor.lineHeight": { "$ref": "#/properties/editor.lineHeight" }, "editor.fontLigatures": { "$ref": "#/properties/editor.fontLigatures" }, "editor.tabSize": { "$ref": "#/properties/editor.tabSize" }, "editor.insertSpaces": { "$ref": "#/properties/editor.insertSpaces" }, "editor.detectIndentation": { "$ref": "#/properties/editor.detectIndentation" }, "editor.renderIndentGuides": { "$ref": "#/properties/editor.renderIndentGuides" }, "editor.wordWrap": { "$ref": "#/properties/editor.wordWrap" }, "editor.renderWhitespace": { "$ref": "#/properties/editor.renderWhitespace" }, "editor.cursorBlinking": { "$ref": "#/properties/editor.cursorBlinking" }, "editor.minimap": { "$ref": "#/properties/editor.minimap" }, "files.autoSave": { "$ref": "#/properties/files.autoSave" }, "files.autoSaveDelay": { "$ref": "#/properties/files.autoSaveDelay" }, "files.trimTrailingWhitespace": { "$ref": "#/properties/files.trimTrailingWhitespace" }, "editor.formatOnSave": { "$ref": "#/properties/editor.formatOnSave" }, "editor.defaultFormatter": { "$ref": "#/properties/editor.defaultFormatter" }, "terminal.fontSize": { "$ref": "#/properties/terminal.fontSize" }, "terminal.scrollback": { "$ref": "#/properties/terminal.scrollback" }, "terminal.confirmOnKill": { "$ref": "#/properties/terminal.confirmOnKill" }, "scm.autoFetch": { "$ref": "#/properties/scm.autoFetch" }, "scm.diffLayout": { "$ref": "#/properties/scm.diffLayout" }, "files.associations": { "$ref": "#/properties/files.associations" }, "languageServers": { "$ref": "#/properties/languageServers" }, "ui.fontFamily": { "$ref": "#/properties/ui.fontFamily" }, "ui.fontSize": { "$ref": "#/properties/ui.fontSize" }, "ui.fontWeight": { "$ref": "#/properties/ui.fontWeight" }, "ui.fontStyle": { "$ref": "#/properties/ui.fontStyle" }, "ui.lineHeight": { "$ref": "#/properties/ui.lineHeight" }, "ui.letterSpacing": { "$ref": "#/properties/ui.letterSpacing" }, "ui.fontLigatures": { "$ref": "#/properties/ui.fontLigatures" }, "terminal.fontFamily": { "$ref": "#/properties/terminal.fontFamily" }, "terminal.fontWeight": { "$ref": "#/properties/terminal.fontWeight" }, "terminal.fontStyle": { "$ref": "#/properties/terminal.fontStyle" }, "terminal.lineHeight": { "$ref": "#/properties/terminal.lineHeight" }, "terminal.letterSpacing": { "$ref": "#/properties/terminal.letterSpacing" }, "terminal.fontLigatures": { "$ref": "#/properties/terminal.fontLigatures" }, "workbench.iconTheme": { "$ref": "#/properties/workbench.iconTheme" }, "workbench.productIconTheme": { "$ref": "#/properties/workbench.productIconTheme" }, "editor.semanticHighlighting": { "$ref": "#/properties/editor.semanticHighlighting" }, "editor.inlayHints.types": { "$ref": "#/properties/editor.inlayHints.types" }, "editor.inlayHints.parameters": { "$ref": "#/properties/editor.inlayHints.parameters" }, "editor.largeFileIntelligence": { "$ref": "#/properties/editor.largeFileIntelligence" }, "workbench.locale": { "$ref": "#/properties/workbench.locale" }, "workbench.reducedMotion": { "$ref": "#/properties/workbench.reducedMotion" }, "desktop.projects.openBehavior": { "$ref": "#/properties/desktop.projects.openBehavior" }, "desktop.tools.gitPath": { "$ref": "#/properties/desktop.tools.gitPath" }, "desktop.tools.ghPath": { "$ref": "#/properties/desktop.tools.ghPath" }, "project.intelligence": false, "project.schemas": false }, "additionalProperties": true, "description": "Settings for a language ID, such as [mdx] or [php]. Runtime project options belong at the top level.", "propertyNames": { "not": { "pattern": "^\\[.*\\]$" } } } };
|
|
941
941
|
const schema = {
|
|
942
942
|
$schema: $schema$2,
|
|
943
943
|
$id: $id$1,
|
|
@@ -1166,6 +1166,7 @@ const ACP_CUSTOM_PROVIDER = "custom";
|
|
|
1166
1166
|
const ACP_REGISTRY_URL = "https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json";
|
|
1167
1167
|
const acpPreset = (id) => ACP_PROVIDERS.find((provider) => provider.id === id);
|
|
1168
1168
|
const acpBuiltinForRegistry = (registryId) => ACP_PROVIDERS.find((provider) => provider.registryId === registryId);
|
|
1169
|
+
const PUSH_RELAY_URL = "https://oxbit-push.ryanyannelli.workers.dev";
|
|
1169
1170
|
const taskPhases = [
|
|
1170
1171
|
"preinit",
|
|
1171
1172
|
"init",
|
|
@@ -3456,6 +3457,8 @@ function bounded(value) {
|
|
|
3456
3457
|
);
|
|
3457
3458
|
return value;
|
|
3458
3459
|
}
|
|
3460
|
+
const BRANCH_DIFF_FILES = 50;
|
|
3461
|
+
const BRANCH_DIFF_TEXT = 2e5;
|
|
3459
3462
|
const conflicted = (index, working) => ["DD", "AU", "UD", "UA", "DU", "AA", "UU"].includes(index + working);
|
|
3460
3463
|
const digest$1 = (value) => createHash("sha256").update(value).digest("hex");
|
|
3461
3464
|
class Git {
|
|
@@ -3786,18 +3789,18 @@ class Git {
|
|
|
3786
3789
|
if (typeof params.path !== "string")
|
|
3787
3790
|
throw new RpcError("INVALID_PARAMS", "A file path is required");
|
|
3788
3791
|
await this.files.resolve(params.path, true);
|
|
3789
|
-
const
|
|
3792
|
+
const detail2 = await this.show(params.ref, signal), file = detail2.files.find((file2) => file2.path === params.path);
|
|
3790
3793
|
if (!file)
|
|
3791
3794
|
throw new RpcError("NOT_FOUND", "File is not part of this commit");
|
|
3792
|
-
const before =
|
|
3795
|
+
const before = detail2.commit.parents[0] ? await this.optional(
|
|
3793
3796
|
[
|
|
3794
3797
|
"show",
|
|
3795
|
-
`${
|
|
3798
|
+
`${detail2.commit.parents[0]}:${file.originalPath ?? file.path}`
|
|
3796
3799
|
],
|
|
3797
3800
|
signal
|
|
3798
3801
|
) : void 0;
|
|
3799
3802
|
const after = await this.optional(
|
|
3800
|
-
["show", `${
|
|
3803
|
+
["show", `${detail2.commit.id}:${file.path}`],
|
|
3801
3804
|
signal
|
|
3802
3805
|
);
|
|
3803
3806
|
const diff = await this.run(
|
|
@@ -3808,7 +3811,7 @@ class Git {
|
|
|
3808
3811
|
"--no-ext-diff",
|
|
3809
3812
|
"--no-textconv",
|
|
3810
3813
|
"--no-color",
|
|
3811
|
-
|
|
3814
|
+
detail2.commit.id,
|
|
3812
3815
|
"--",
|
|
3813
3816
|
file.path,
|
|
3814
3817
|
...file.originalPath ? [file.originalPath] : []
|
|
@@ -3866,6 +3869,88 @@ class Git {
|
|
|
3866
3869
|
)).stdout
|
|
3867
3870
|
});
|
|
3868
3871
|
}
|
|
3872
|
+
/** The upstream remote's default branch, then `origin/HEAD`, then local `main` or `master`. */
|
|
3873
|
+
async baseBranch(branch, signal) {
|
|
3874
|
+
const remote = branch ? (await this.optional(["config", "--get", `branch.${branch}.remote`], signal)).stdout.trim() : "";
|
|
3875
|
+
const candidates = [
|
|
3876
|
+
...remote && remote !== "." ? [`refs/remotes/${remote}/HEAD`] : [],
|
|
3877
|
+
"refs/remotes/origin/HEAD",
|
|
3878
|
+
"refs/heads/main",
|
|
3879
|
+
"refs/heads/master"
|
|
3880
|
+
];
|
|
3881
|
+
for (const ref of candidates) {
|
|
3882
|
+
const commit = await this.optional(
|
|
3883
|
+
["rev-parse", "--verify", "--quiet", "--end-of-options", `${ref}^{commit}`],
|
|
3884
|
+
signal
|
|
3885
|
+
);
|
|
3886
|
+
if (commit.exitCode) continue;
|
|
3887
|
+
const name = await this.optional(["rev-parse", "--abbrev-ref", ref], signal);
|
|
3888
|
+
return { name: name.stdout.trim() || ref, commit: commit.stdout.trim() };
|
|
3889
|
+
}
|
|
3890
|
+
return void 0;
|
|
3891
|
+
}
|
|
3892
|
+
async untrackedPatch(relative, signal) {
|
|
3893
|
+
const result = await this.run(
|
|
3894
|
+
["diff", "--no-index", "--no-ext-diff", "--no-textconv", "--no-color", "--src-prefix=a/", "--dst-prefix=b/", "--", "/dev/null", relative],
|
|
3895
|
+
signal,
|
|
3896
|
+
this.files.root,
|
|
3897
|
+
void 0,
|
|
3898
|
+
true
|
|
3899
|
+
);
|
|
3900
|
+
if (result.exitCode > 1)
|
|
3901
|
+
throw new RpcError("GIT_FAILED", result.stderr.trim() || `Git exited ${result.exitCode}`);
|
|
3902
|
+
return result.stdout;
|
|
3903
|
+
}
|
|
3904
|
+
/** Committed, staged, unstaged and untracked changes since the merge base with the base branch. */
|
|
3905
|
+
async branchDiff(params, signal) {
|
|
3906
|
+
const limit2 = Number(params.limit ?? BRANCH_DIFF_FILES);
|
|
3907
|
+
if (!Number.isInteger(limit2) || limit2 < 0 || limit2 > BRANCH_DIFF_FILES)
|
|
3908
|
+
throw new RpcError("INVALID_PARAMS", "Invalid file limit");
|
|
3909
|
+
const inside = await this.optional(["rev-parse", "--is-inside-work-tree"], signal);
|
|
3910
|
+
if (inside.exitCode || inside.stdout.trim() !== "true") {
|
|
3911
|
+
if (inside.exitCode && !inside.stderr.includes("not a git repository"))
|
|
3912
|
+
throw new RpcError("GIT_FAILED", inside.stderr.trim());
|
|
3913
|
+
return { repository: false };
|
|
3914
|
+
}
|
|
3915
|
+
const head = await this.head(signal);
|
|
3916
|
+
if (!head) throw new RpcError("NOT_FOUND", "This branch has no commits yet");
|
|
3917
|
+
const branch = (await this.optional(["symbolic-ref", "-q", "--short", "HEAD"], signal)).stdout.trim();
|
|
3918
|
+
const base = await this.baseBranch(branch, signal);
|
|
3919
|
+
if (!base) throw new RpcError("NOT_FOUND", "No base branch: origin/HEAD, main and master are missing");
|
|
3920
|
+
const mergeBase = await this.optional(["merge-base", base.commit, head], signal);
|
|
3921
|
+
if (mergeBase.exitCode)
|
|
3922
|
+
throw new RpcError("NOT_FOUND", `${branch || "HEAD"} has no common history with ${base.name}`);
|
|
3923
|
+
const from = mergeBase.stdout.trim();
|
|
3924
|
+
const names = async (args) => (await this.run(args, signal)).stdout.split("\0").filter(Boolean);
|
|
3925
|
+
const tracked = await names(["diff", "--name-only", "--relative", "-z", from, "--"]);
|
|
3926
|
+
const untracked = await names(["ls-files", "--others", "--exclude-standard", "-z", "--"]);
|
|
3927
|
+
const files = [];
|
|
3928
|
+
let size = 0, truncated = false;
|
|
3929
|
+
for (const [index, relative] of [...tracked, ...untracked].entries()) {
|
|
3930
|
+
if (files.length >= limit2 || size >= BRANCH_DIFF_TEXT) {
|
|
3931
|
+
truncated = true;
|
|
3932
|
+
break;
|
|
3933
|
+
}
|
|
3934
|
+
let diff = "";
|
|
3935
|
+
try {
|
|
3936
|
+
diff = index < tracked.length ? (await this.run(
|
|
3937
|
+
["diff", "--no-ext-diff", "--no-textconv", "--no-color", "--relative", "--src-prefix=a/", "--dst-prefix=b/", from, "--", relative],
|
|
3938
|
+
signal
|
|
3939
|
+
)).stdout : await this.untrackedPatch(relative, signal);
|
|
3940
|
+
} catch (error) {
|
|
3941
|
+
if (error.code !== "OUTPUT_LIMIT") throw error;
|
|
3942
|
+
truncated = true;
|
|
3943
|
+
}
|
|
3944
|
+
const binary2 = /^Binary files /m.test(diff);
|
|
3945
|
+
if (size + diff.length > BRANCH_DIFF_TEXT) {
|
|
3946
|
+
diff = diff.slice(0, BRANCH_DIFF_TEXT - size);
|
|
3947
|
+
truncated = true;
|
|
3948
|
+
}
|
|
3949
|
+
size += diff.length;
|
|
3950
|
+
files.push({ path: relative, diff, binary: binary2 });
|
|
3951
|
+
}
|
|
3952
|
+
return bounded({ base: base.name, head: branch || head.slice(0, 7), files, truncated });
|
|
3953
|
+
}
|
|
3869
3954
|
async action(method, params, signal, progress) {
|
|
3870
3955
|
const pending = this.queue.catch(() => {
|
|
3871
3956
|
}).then(() => this.execute(method, params, signal, progress));
|
|
@@ -4617,7 +4702,10 @@ class LanguageServer {
|
|
|
4617
4702
|
if (resume) this.paused = false;
|
|
4618
4703
|
if (!resume && this.phase === "failed") throw new RpcError("LSP_FAILED", this.error || "Language server failed. Retry from Language Servers.");
|
|
4619
4704
|
if (this.paused) throw new RpcError("LSP_STOPPED", "Language server is stopped. Start it from Language Servers.");
|
|
4620
|
-
if (this.starting)
|
|
4705
|
+
if (this.starting) {
|
|
4706
|
+
this.emit("oxbit/serverState", { state: this.phase });
|
|
4707
|
+
return this.starting;
|
|
4708
|
+
}
|
|
4621
4709
|
if (this.child && this.capabilities)
|
|
4622
4710
|
return { capabilities: this.capabilities, registrations: [...this.registrations.values()], rootUri: this.uri(""), projectRootUri: pathToFileURL(this.options.root ?? this.files.root).href, version: this.launchSpec?.version };
|
|
4623
4711
|
this.error = "";
|
|
@@ -5247,6 +5335,47 @@ function deferToRuff(spec) {
|
|
|
5247
5335
|
diagnostics: (diagnostics) => diagnostics.filter((item) => item.code !== void 0)
|
|
5248
5336
|
};
|
|
5249
5337
|
}
|
|
5338
|
+
const phpProbes = [
|
|
5339
|
+
{ command: ["herd", "which-php"], php: (output) => output.includes("No usable PHP version found") ? void 0 : [output.trim()] },
|
|
5340
|
+
{ command: ["valet", "which-php"], php: (output) => [output.trim()] },
|
|
5341
|
+
{ command: ["./vendor/bin/sail", "ps"], php: () => ["./vendor/bin/sail", "php"] },
|
|
5342
|
+
{ command: ["lando", "php", "-r", "echo PHP_BINARY;"], php: () => ["lando", "php"] },
|
|
5343
|
+
{ command: ["ddev", "php", "-r", "echo PHP_BINARY;"], php: () => ["ddev", "php"] },
|
|
5344
|
+
{ command: ["php", "-r", "echo PHP_BINARY;"], php: (output) => [output.trim()] }
|
|
5345
|
+
];
|
|
5346
|
+
function probe(command, cwd, env2, timeout, signal) {
|
|
5347
|
+
return new Promise((resolve) => {
|
|
5348
|
+
const child = spawn(command[0], command.slice(1), { cwd, env: env2, detached: process.platform !== "win32", stdio: ["ignore", "pipe", "ignore"] });
|
|
5349
|
+
trackChild(child);
|
|
5350
|
+
let output = "";
|
|
5351
|
+
const finish = (value) => {
|
|
5352
|
+
clearTimeout(timer);
|
|
5353
|
+
signal?.removeEventListener("abort", stop2);
|
|
5354
|
+
resolve(value);
|
|
5355
|
+
};
|
|
5356
|
+
const stop2 = () => {
|
|
5357
|
+
killProcess(child);
|
|
5358
|
+
finish();
|
|
5359
|
+
};
|
|
5360
|
+
const timer = setTimeout(stop2, timeout);
|
|
5361
|
+
signal?.addEventListener("abort", stop2, { once: true });
|
|
5362
|
+
child.stdout.on("data", (data) => {
|
|
5363
|
+
output = (output + data.toString()).slice(-4096);
|
|
5364
|
+
});
|
|
5365
|
+
child.on("error", () => finish());
|
|
5366
|
+
child.on("close", (code) => finish(code === 0 ? output : void 0));
|
|
5367
|
+
});
|
|
5368
|
+
}
|
|
5369
|
+
async function laravelPhpCommand(root, env2, signal, timeout = 5e3) {
|
|
5370
|
+
for (const { command, php } of phpProbes) {
|
|
5371
|
+
signal?.throwIfAborted();
|
|
5372
|
+
const output = await probe(command, root, env2, timeout, signal);
|
|
5373
|
+
const found = output === void 0 ? void 0 : php(output);
|
|
5374
|
+
if (found?.[0]) return found;
|
|
5375
|
+
}
|
|
5376
|
+
signal?.throwIfAborted();
|
|
5377
|
+
throw new Error("Laravel needs PHP on the runtime host. No PHP was found through Herd, Valet, Sail, Lando, DDEV or php on PATH. Install PHP or set languageServers.laravel.initializationOptions.phpCommand.");
|
|
5378
|
+
}
|
|
5250
5379
|
const npmPresets = {
|
|
5251
5380
|
typescript: ["typescript-language-server", "lib/cli.mjs", ["typescript"]],
|
|
5252
5381
|
html: ["vscode-langservers-extracted", "bin/vscode-html-language-server"],
|
|
@@ -5487,19 +5616,22 @@ class ManagedInstaller {
|
|
|
5487
5616
|
}
|
|
5488
5617
|
}
|
|
5489
5618
|
} catch {
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
} catch {
|
|
5619
|
+
}
|
|
5620
|
+
try {
|
|
5621
|
+
if (Date.now() - (await fs.stat(lock)).mtimeMs > 6e4) {
|
|
5622
|
+
await fs.rm(lock, { recursive: true, force: true });
|
|
5623
|
+
continue;
|
|
5496
5624
|
}
|
|
5625
|
+
} catch {
|
|
5497
5626
|
}
|
|
5498
5627
|
if (Date.now() > deadline) throw new Error("Timed out waiting for another language server installation");
|
|
5499
5628
|
await setTimeout$1(100, void 0, { signal });
|
|
5500
5629
|
}
|
|
5501
5630
|
}
|
|
5502
5631
|
const stage = path.join(base, `.staging-${randomUUID()}`);
|
|
5632
|
+
const heartbeat = setInterval(() => void fs.utimes(lock, /* @__PURE__ */ new Date(), /* @__PURE__ */ new Date()).catch(() => {
|
|
5633
|
+
}), 1e4);
|
|
5634
|
+
heartbeat.unref();
|
|
5503
5635
|
try {
|
|
5504
5636
|
if (await complete()) return target;
|
|
5505
5637
|
for (const name of await fs.readdir(base)) if (name.startsWith(".staging-")) await fs.rm(path.join(base, name), { recursive: true, force: true });
|
|
@@ -5515,6 +5647,7 @@ class ManagedInstaller {
|
|
|
5515
5647
|
await fs.rename(stage, target);
|
|
5516
5648
|
return target;
|
|
5517
5649
|
} finally {
|
|
5650
|
+
clearInterval(heartbeat);
|
|
5518
5651
|
await fs.rm(stage, { recursive: true, force: true });
|
|
5519
5652
|
await fs.rm(lock, { recursive: true, force: true });
|
|
5520
5653
|
}
|
|
@@ -5813,6 +5946,8 @@ class LanguageServerManager {
|
|
|
5813
5946
|
else spec = await resolveLaunch(definition2.id, root, this.installer, signal);
|
|
5814
5947
|
spec = { ...spec, args: definition2.args ?? spec.args, env: { ...spec.env, ...definition2.env }, initializationOptions: merge(spec.initializationOptions, definition2.initializationOptions), settings: merge(spec.settings, definition2.settings) };
|
|
5815
5948
|
if (ruff) spec = deferToRuff(spec);
|
|
5949
|
+
if (definition2.id === "laravel" && !spec.initializationOptions?.phpCommand && (spec.initializationOptions?.phpEnvironment ?? "auto") === "auto")
|
|
5950
|
+
spec.initializationOptions = { ...spec.initializationOptions, phpCommand: await laravelPhpCommand(root, { ...process.env, ...spec.env }, signal) };
|
|
5816
5951
|
if (definition2.id === "json") {
|
|
5817
5952
|
const options2 = this.project ? (await this.project.reload()).schemas : { catalog: true, download: true, associations: [] };
|
|
5818
5953
|
spec.settings = await this.schemas.settings(spec.settings ?? {}, options2);
|
|
@@ -5853,7 +5988,7 @@ class LanguageServerManager {
|
|
|
5853
5988
|
if (!instance.attachments.size && !instance.idle) {
|
|
5854
5989
|
instance.idle = setTimeout(() => {
|
|
5855
5990
|
instance.idle = void 0;
|
|
5856
|
-
void this.stop(false, instance.id);
|
|
5991
|
+
if (this.instances.get(instance.id) === instance) void this.stop(false, instance.id);
|
|
5857
5992
|
}, this.idleMs);
|
|
5858
5993
|
instance.idle.unref();
|
|
5859
5994
|
}
|
|
@@ -7390,7 +7525,7 @@ class SubagentRegistry {
|
|
|
7390
7525
|
let cached;
|
|
7391
7526
|
function runtimeVersion() {
|
|
7392
7527
|
if (cached) return cached;
|
|
7393
|
-
return cached = "0.
|
|
7528
|
+
return cached = "0.9.0";
|
|
7394
7529
|
}
|
|
7395
7530
|
const MAX_REQUEST_BYTES = 1024 * 1024;
|
|
7396
7531
|
const MAX_CONCURRENT_REQUESTS = 16;
|
|
@@ -7991,16 +8126,19 @@ function strings(value) {
|
|
|
7991
8126
|
}
|
|
7992
8127
|
class AgentACP {
|
|
7993
8128
|
constructor(files, emit, stateChanged = () => {
|
|
7994
|
-
}, acpRegistry) {
|
|
8129
|
+
}, acpRegistry, statusChanged = () => {
|
|
8130
|
+
}) {
|
|
7995
8131
|
this.files = files;
|
|
7996
8132
|
this.emit = emit;
|
|
7997
8133
|
this.stateChanged = stateChanged;
|
|
7998
8134
|
this.acpRegistry = acpRegistry;
|
|
8135
|
+
this.statusChanged = statusChanged;
|
|
7999
8136
|
}
|
|
8000
8137
|
files;
|
|
8001
8138
|
emit;
|
|
8002
8139
|
stateChanged;
|
|
8003
8140
|
acpRegistry;
|
|
8141
|
+
statusChanged;
|
|
8004
8142
|
agents = /* @__PURE__ */ new Map();
|
|
8005
8143
|
mcp = new AgentMCP((id, name, args) => this.tool(id, name, args));
|
|
8006
8144
|
get(owner, id) {
|
|
@@ -8050,6 +8188,20 @@ class AgentACP {
|
|
|
8050
8188
|
if (agent.client) this.emit(agent.client, event, payload);
|
|
8051
8189
|
this.stateChanged();
|
|
8052
8190
|
}
|
|
8191
|
+
report(agent, status2) {
|
|
8192
|
+
try {
|
|
8193
|
+
this.statusChanged({
|
|
8194
|
+
owner: agent.owner,
|
|
8195
|
+
agent: agent.connection.name ?? agent.connection.provider,
|
|
8196
|
+
status: status2,
|
|
8197
|
+
pending: agent.approvals.size,
|
|
8198
|
+
startedAt: agent.startedAt
|
|
8199
|
+
});
|
|
8200
|
+
} catch (error) {
|
|
8201
|
+
process.stderr.write(`Oxbit agent status listener failed: ${String(error)}
|
|
8202
|
+
`);
|
|
8203
|
+
}
|
|
8204
|
+
}
|
|
8053
8205
|
list(owner) {
|
|
8054
8206
|
return { sessions: [...this.agents.values()].filter((a) => a.owner === owner && !a.stopped).map((a) => ({
|
|
8055
8207
|
connection: a.connection,
|
|
@@ -8305,11 +8457,16 @@ class AgentACP {
|
|
|
8305
8457
|
agent.busy = false;
|
|
8306
8458
|
}
|
|
8307
8459
|
}
|
|
8308
|
-
if (["session/new", "session/load", "session/resume"].includes(method)) {
|
|
8460
|
+
if (["session/new", "session/load", "session/resume", "session/fork"].includes(method)) {
|
|
8309
8461
|
if (method === "session/load" && !agent.connection.capabilities?.loadSession)
|
|
8310
8462
|
throw new Error("This agent does not support loading conversations");
|
|
8311
8463
|
if (method === "session/resume" && !agent.connection.capabilities?.sessionCapabilities?.resume)
|
|
8312
8464
|
throw new Error("This agent does not support resuming conversations");
|
|
8465
|
+
if (method === "session/fork" && !agent.connection.capabilities?.sessionCapabilities?.fork)
|
|
8466
|
+
throw new Error("This agent does not support forking conversations");
|
|
8467
|
+
const source2 = agent.connection.sessionId;
|
|
8468
|
+
if (method === "session/fork" && !source2)
|
|
8469
|
+
throw new Error("Start a conversation first");
|
|
8313
8470
|
if (agent.subagents?.activeCount)
|
|
8314
8471
|
throw new Error(
|
|
8315
8472
|
"Wait for active subagents or disconnect before changing conversations"
|
|
@@ -8321,7 +8478,7 @@ class AgentACP {
|
|
|
8321
8478
|
const previousBytes = agent.eventBytes;
|
|
8322
8479
|
const previousTitle = agent.title;
|
|
8323
8480
|
const previousTruncated = agent.truncated;
|
|
8324
|
-
const target = method === "session/new" ? void 0 : requireString(params, "sessionId");
|
|
8481
|
+
const target = method === "session/new" || method === "session/fork" ? void 0 : requireString(params, "sessionId");
|
|
8325
8482
|
if (agent.approvals.size)
|
|
8326
8483
|
throw new Error(
|
|
8327
8484
|
"Resolve pending requests before changing conversations"
|
|
@@ -8342,7 +8499,7 @@ class AgentACP {
|
|
|
8342
8499
|
const result = await this.request(agent, method, {
|
|
8343
8500
|
cwd: this.files.root,
|
|
8344
8501
|
mcpServers: [await this.mcp.server(agent.connection.id, !!agent.connection.capabilities?.mcpCapabilities?.http)],
|
|
8345
|
-
...target ? { sessionId: target } : {}
|
|
8502
|
+
...target ? { sessionId: target } : method === "session/fork" ? { sessionId: source2 } : {}
|
|
8346
8503
|
});
|
|
8347
8504
|
const sessionId2 = target ?? result?.sessionId;
|
|
8348
8505
|
if (typeof sessionId2 !== "string" || !sessionId2)
|
|
@@ -8418,12 +8575,14 @@ class AgentACP {
|
|
|
8418
8575
|
const messageId = params.messageId === void 0 ? randomUUID() : requireString(params, "messageId", 256);
|
|
8419
8576
|
agent.busy = true;
|
|
8420
8577
|
agent.turn++;
|
|
8578
|
+
agent.startedAt = Date.now();
|
|
8421
8579
|
if (agent.title === "New conversation") agent.title = text2.slice(0, 100);
|
|
8422
8580
|
this.publish(agent, "acp.turnStarted", {
|
|
8423
8581
|
messageId,
|
|
8424
8582
|
text: text2,
|
|
8425
8583
|
context: JSON.parse(JSON.stringify(params.context ?? [], withoutImageData))
|
|
8426
8584
|
});
|
|
8585
|
+
this.report(agent, "working");
|
|
8427
8586
|
const abort = () => this.stopAgent(agent, "Agent request interrupted");
|
|
8428
8587
|
signal?.addEventListener("abort", abort, { once: true });
|
|
8429
8588
|
let stopReason;
|
|
@@ -8448,6 +8607,8 @@ class AgentACP {
|
|
|
8448
8607
|
signal?.removeEventListener("abort", abort);
|
|
8449
8608
|
if (!agent.stopped) {
|
|
8450
8609
|
this.publish(agent, "acp.turnEnded", { stopReason, error: failure2 });
|
|
8610
|
+
if (failure2 !== void 0) this.report(agent, "failed");
|
|
8611
|
+
else if (stopReason !== "cancelled") this.report(agent, "finished");
|
|
8451
8612
|
this.publishQueue(agent);
|
|
8452
8613
|
queueMicrotask(() => this.runQueue(agent));
|
|
8453
8614
|
}
|
|
@@ -8530,6 +8691,14 @@ ${content}`
|
|
|
8530
8691
|
this.publishQueue(agent);
|
|
8531
8692
|
return { prompt };
|
|
8532
8693
|
}
|
|
8694
|
+
moveQueued(owner, id, promptId, index) {
|
|
8695
|
+
const agent = this.get(owner, id);
|
|
8696
|
+
const from = agent.queue.findIndex((p) => p.id === promptId);
|
|
8697
|
+
if (from < 0) throw new Error("The queued message has already started or was removed");
|
|
8698
|
+
const [prompt] = agent.queue.splice(from, 1);
|
|
8699
|
+
agent.queue.splice(Math.max(0, Math.min(index, agent.queue.length)), 0, prompt);
|
|
8700
|
+
return this.publishQueue(agent);
|
|
8701
|
+
}
|
|
8533
8702
|
resumeQueue(owner, id) {
|
|
8534
8703
|
const agent = this.get(owner, id);
|
|
8535
8704
|
agent.queuePaused = false;
|
|
@@ -8691,6 +8860,7 @@ ${content}`
|
|
|
8691
8860
|
if (method !== "fs/read_text_file" && !method.startsWith("oxbit/"))
|
|
8692
8861
|
registry.waiting(sessionId, requestId, true, params.toolCallId ?? params.toolCall?.toolCallId);
|
|
8693
8862
|
this.publish(agent, "acp.request", this.requestEvent(agent, requestId, request));
|
|
8863
|
+
if (method === "session/request_permission") this.report(agent, "waiting");
|
|
8694
8864
|
});
|
|
8695
8865
|
}
|
|
8696
8866
|
async tool(id, name, args) {
|
|
@@ -12209,6 +12379,215 @@ function loginShellEnvironment(cwd, inherited = process.env, platform = process.
|
|
|
12209
12379
|
child.on("close", (code) => finish(code === 0 ? parseShellEnvironment(Buffer.concat(chunks).toString(), mark) : void 0));
|
|
12210
12380
|
});
|
|
12211
12381
|
}
|
|
12382
|
+
const PUSH_DEVICES_FILE = "push-devices.json";
|
|
12383
|
+
const MAX_DEVICES = 16;
|
|
12384
|
+
const RETENTION_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
12385
|
+
const WINDOW_SECONDS = 15 * 60;
|
|
12386
|
+
const RELAY_TIMEOUT_MS = 1e4;
|
|
12387
|
+
const HANDLE = /^[A-Za-z0-9_-]{1,2048}$/;
|
|
12388
|
+
const STATUSES = ["working", "waiting", "finished", "failed"];
|
|
12389
|
+
const TITLES = { waiting: "Agent needs your input", finished: "Agent finished", failed: "Agent turn failed" };
|
|
12390
|
+
const log = (message2) => process.stderr.write(`Oxbit push: ${message2}
|
|
12391
|
+
`);
|
|
12392
|
+
function deviceIdOf(params) {
|
|
12393
|
+
const value = requireString(params, "deviceId", 128);
|
|
12394
|
+
if (!value) throw new RpcError("INVALID_PARAMS", "Invalid deviceId");
|
|
12395
|
+
return value;
|
|
12396
|
+
}
|
|
12397
|
+
function handleOf(params, key) {
|
|
12398
|
+
const value = params[key];
|
|
12399
|
+
if (value === void 0 || value === null) return void 0;
|
|
12400
|
+
if (typeof value !== "string" || !HANDLE.test(value)) throw new RpcError("INVALID_PARAMS", `Invalid ${key}`);
|
|
12401
|
+
return value;
|
|
12402
|
+
}
|
|
12403
|
+
const text$1 = (value) => typeof value === "string" && value.length <= 1024;
|
|
12404
|
+
function activityOf(value) {
|
|
12405
|
+
if (value === null) return null;
|
|
12406
|
+
const v = value ?? {};
|
|
12407
|
+
const startedAt = v.startedAt;
|
|
12408
|
+
if (typeof value !== "object" || !text$1(v.agent) || !text$1(v.title) || !text$1(v.detail) || !STATUSES.includes(v.status) || !Number.isSafeInteger(v.pending) || v.pending < 0 || startedAt !== void 0 && (typeof startedAt !== "number" || !Number.isFinite(startedAt) || startedAt < 0))
|
|
12409
|
+
throw new RpcError("INVALID_PARAMS", "Invalid activity");
|
|
12410
|
+
return {
|
|
12411
|
+
agent: v.agent,
|
|
12412
|
+
title: v.title,
|
|
12413
|
+
status: v.status,
|
|
12414
|
+
detail: v.detail,
|
|
12415
|
+
pending: v.pending,
|
|
12416
|
+
...startedAt === void 0 ? {} : { startedAt }
|
|
12417
|
+
};
|
|
12418
|
+
}
|
|
12419
|
+
function restore(entry2) {
|
|
12420
|
+
try {
|
|
12421
|
+
const activity = entry2.activity === void 0 ? null : activityOf(entry2.activity);
|
|
12422
|
+
const device = {
|
|
12423
|
+
deviceId: deviceIdOf(entry2),
|
|
12424
|
+
session: requireString(entry2, "session", 128),
|
|
12425
|
+
alert: handleOf(entry2, "alert"),
|
|
12426
|
+
liveActivity: handleOf(entry2, "liveActivity"),
|
|
12427
|
+
active: false,
|
|
12428
|
+
...activity ? { activity } : {},
|
|
12429
|
+
updatedAt: entry2.updatedAt
|
|
12430
|
+
};
|
|
12431
|
+
return Number.isFinite(device.updatedAt) ? device : void 0;
|
|
12432
|
+
} catch {
|
|
12433
|
+
return void 0;
|
|
12434
|
+
}
|
|
12435
|
+
}
|
|
12436
|
+
function detail(status2, pending) {
|
|
12437
|
+
if (status2 === "working") return "Working";
|
|
12438
|
+
if (status2 === "waiting") return pending === 1 ? "1 request needs an answer" : `${pending} requests need an answer`;
|
|
12439
|
+
return TITLES[status2];
|
|
12440
|
+
}
|
|
12441
|
+
function activityState(snapshot, event) {
|
|
12442
|
+
return {
|
|
12443
|
+
status: event.status,
|
|
12444
|
+
title: snapshot.title,
|
|
12445
|
+
detail: detail(event.status, event.pending),
|
|
12446
|
+
pending: event.pending,
|
|
12447
|
+
...event.status === "working" && event.startedAt !== void 0 ? { startedAt: Math.floor(event.startedAt / 1e3) } : {}
|
|
12448
|
+
};
|
|
12449
|
+
}
|
|
12450
|
+
class PushDevices {
|
|
12451
|
+
constructor(file) {
|
|
12452
|
+
this.file = file;
|
|
12453
|
+
}
|
|
12454
|
+
file;
|
|
12455
|
+
devices = /* @__PURE__ */ new Map();
|
|
12456
|
+
/** Last Live Activity state sent per device. */
|
|
12457
|
+
sent = /* @__PURE__ */ new Map();
|
|
12458
|
+
persistence = Promise.resolve();
|
|
12459
|
+
static async open(dataDir) {
|
|
12460
|
+
const store = new PushDevices(path.join(dataDir, PUSH_DEVICES_FILE));
|
|
12461
|
+
try {
|
|
12462
|
+
const state2 = JSON.parse(await fs.readFile(store.file, "utf8"));
|
|
12463
|
+
if (state2?.version === 1 && Array.isArray(state2.devices))
|
|
12464
|
+
for (const entry2 of state2.devices) {
|
|
12465
|
+
const device = entry2 && typeof entry2 === "object" ? restore(entry2) : void 0;
|
|
12466
|
+
if (device) store.devices.set(device.deviceId, device);
|
|
12467
|
+
}
|
|
12468
|
+
} catch (error) {
|
|
12469
|
+
if (error.code !== "ENOENT") log(`ignoring unreadable ${PUSH_DEVICES_FILE}: ${String(error)}`);
|
|
12470
|
+
}
|
|
12471
|
+
store.prune();
|
|
12472
|
+
return store;
|
|
12473
|
+
}
|
|
12474
|
+
async register(session, connection, params) {
|
|
12475
|
+
const deviceId = deviceIdOf(params), alert = handleOf(params, "alert"), liveActivity = handleOf(params, "liveActivity");
|
|
12476
|
+
const previous = this.devices.get(deviceId);
|
|
12477
|
+
this.sent.delete(deviceId);
|
|
12478
|
+
this.devices.set(deviceId, {
|
|
12479
|
+
...previous,
|
|
12480
|
+
deviceId,
|
|
12481
|
+
session,
|
|
12482
|
+
alert,
|
|
12483
|
+
liveActivity,
|
|
12484
|
+
active: true,
|
|
12485
|
+
connection,
|
|
12486
|
+
updatedAt: Date.now()
|
|
12487
|
+
});
|
|
12488
|
+
await this.persist();
|
|
12489
|
+
return {};
|
|
12490
|
+
}
|
|
12491
|
+
async state(session, connection, params) {
|
|
12492
|
+
const deviceId = deviceIdOf(params);
|
|
12493
|
+
if (typeof params.active !== "boolean") throw new RpcError("INVALID_PARAMS", "active must be boolean");
|
|
12494
|
+
const activity = params.activity === void 0 ? void 0 : activityOf(params.activity);
|
|
12495
|
+
const device = this.devices.get(deviceId);
|
|
12496
|
+
if (!device || device.session !== session) throw new RpcError("NOT_FOUND", "Register the device first");
|
|
12497
|
+
device.active = params.active;
|
|
12498
|
+
if (params.active) device.connection = connection;
|
|
12499
|
+
if (activity) device.activity = activity;
|
|
12500
|
+
else if (activity === null) delete device.activity;
|
|
12501
|
+
device.updatedAt = Date.now();
|
|
12502
|
+
this.sent.delete(deviceId);
|
|
12503
|
+
await this.persist();
|
|
12504
|
+
return {};
|
|
12505
|
+
}
|
|
12506
|
+
async unregister(session, params) {
|
|
12507
|
+
const deviceId = deviceIdOf(params);
|
|
12508
|
+
if (this.devices.get(deviceId)?.session === session) {
|
|
12509
|
+
this.devices.delete(deviceId);
|
|
12510
|
+
this.sent.delete(deviceId);
|
|
12511
|
+
await this.persist();
|
|
12512
|
+
}
|
|
12513
|
+
return {};
|
|
12514
|
+
}
|
|
12515
|
+
/** Marks devices inactive when the connection that set them active closes. */
|
|
12516
|
+
disconnect(connection) {
|
|
12517
|
+
let changed = false;
|
|
12518
|
+
for (const device of this.devices.values())
|
|
12519
|
+
if (device.active && device.connection === connection) {
|
|
12520
|
+
device.active = false;
|
|
12521
|
+
changed = true;
|
|
12522
|
+
}
|
|
12523
|
+
if (changed) this.persist().catch((error) => log(`cannot save devices: ${String(error)}`));
|
|
12524
|
+
}
|
|
12525
|
+
/** Sends alert and Live Activity pushes to the owner's inactive devices; resolves after every send settles. */
|
|
12526
|
+
async notify(event) {
|
|
12527
|
+
const sends = [];
|
|
12528
|
+
for (const device of this.devices.values()) {
|
|
12529
|
+
if (device.active || device.session !== event.owner) continue;
|
|
12530
|
+
if (event.status !== "working" && device.alert)
|
|
12531
|
+
sends.push(this.send(device.deviceId, "alert", {
|
|
12532
|
+
handle: device.alert,
|
|
12533
|
+
alert: { title: TITLES[event.status], body: device.activity?.title || event.agent }
|
|
12534
|
+
}));
|
|
12535
|
+
if (!device.liveActivity || !device.activity) continue;
|
|
12536
|
+
const state2 = activityState(device.activity, event), end = event.status === "finished" || event.status === "failed";
|
|
12537
|
+
const key = JSON.stringify([end, state2]);
|
|
12538
|
+
if (this.sent.get(device.deviceId) === key) continue;
|
|
12539
|
+
this.sent.set(device.deviceId, key);
|
|
12540
|
+
const window = Math.floor(Date.now() / 1e3) + WINDOW_SECONDS;
|
|
12541
|
+
sends.push(this.send(device.deviceId, "liveActivity", {
|
|
12542
|
+
handle: device.liveActivity,
|
|
12543
|
+
activity: { event: end ? "end" : "update", state: state2, ...end ? { dismissalDate: window } : { staleDate: window } }
|
|
12544
|
+
}));
|
|
12545
|
+
}
|
|
12546
|
+
await Promise.all(sends);
|
|
12547
|
+
}
|
|
12548
|
+
flush() {
|
|
12549
|
+
return this.persistence.catch(() => {
|
|
12550
|
+
});
|
|
12551
|
+
}
|
|
12552
|
+
async send(deviceId, kind, request) {
|
|
12553
|
+
const relay = (process.env.OXBIT_PUSH_RELAY ?? PUSH_RELAY_URL).replace(/\/+$/, "");
|
|
12554
|
+
try {
|
|
12555
|
+
const response = await fetch(`${relay}/v1/push`, {
|
|
12556
|
+
method: "POST",
|
|
12557
|
+
headers: { "Content-Type": "application/json" },
|
|
12558
|
+
body: JSON.stringify(request),
|
|
12559
|
+
signal: AbortSignal.timeout(RELAY_TIMEOUT_MS)
|
|
12560
|
+
});
|
|
12561
|
+
const result = await response.json().catch(() => ({}));
|
|
12562
|
+
const device = this.devices.get(deviceId);
|
|
12563
|
+
if (result.gone && device?.[kind] === request.handle) {
|
|
12564
|
+
delete device[kind];
|
|
12565
|
+
if (kind === "liveActivity") this.sent.delete(deviceId);
|
|
12566
|
+
await this.persist();
|
|
12567
|
+
} else if (!response.ok || !result.sent)
|
|
12568
|
+
log(`relay did not send to ${deviceId}: ${result.reason ?? `HTTP ${response.status}`}`);
|
|
12569
|
+
} catch (error) {
|
|
12570
|
+
log(`push to ${deviceId} failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
12571
|
+
}
|
|
12572
|
+
}
|
|
12573
|
+
prune(now = Date.now()) {
|
|
12574
|
+
for (const [id, device] of this.devices)
|
|
12575
|
+
if (now - device.updatedAt > RETENTION_MS) this.devices.delete(id);
|
|
12576
|
+
const oldest = [...this.devices.values()].sort((a, b) => a.updatedAt - b.updatedAt);
|
|
12577
|
+
for (const device of oldest.slice(0, Math.max(0, oldest.length - MAX_DEVICES))) this.devices.delete(device.deviceId);
|
|
12578
|
+
for (const id of this.sent.keys()) if (!this.devices.has(id)) this.sent.delete(id);
|
|
12579
|
+
}
|
|
12580
|
+
persist() {
|
|
12581
|
+
this.prune();
|
|
12582
|
+
const payload = JSON.stringify({ version: 1, devices: [...this.devices.values()] });
|
|
12583
|
+
this.persistence = this.persistence.catch(() => {
|
|
12584
|
+
}).then(async () => {
|
|
12585
|
+
await fs.writeFile(this.file + ".tmp", payload, { mode: 384 });
|
|
12586
|
+
await fs.rename(this.file + ".tmp", this.file);
|
|
12587
|
+
});
|
|
12588
|
+
return this.persistence;
|
|
12589
|
+
}
|
|
12590
|
+
}
|
|
12212
12591
|
const MAX_SOCKET_BACKLOG_BYTES = MAX_FILE_WRITE_MESSAGE_BYTES;
|
|
12213
12592
|
const allCapabilities = [
|
|
12214
12593
|
"filesystem.read",
|
|
@@ -12351,10 +12730,11 @@ async function createRuntime(options2) {
|
|
|
12351
12730
|
return session;
|
|
12352
12731
|
};
|
|
12353
12732
|
const acpRegistry = new ACPRegistry(dataDir, options2.acpRegistryUrl);
|
|
12733
|
+
const pushDevices = await PushDevices.open(dataDir);
|
|
12354
12734
|
const agents = new AgentACP(files, (connectionId, name, params) => {
|
|
12355
12735
|
const connection = connections.get(connectionId);
|
|
12356
12736
|
if (connection?.session && !connection.session.revoked && trusted) event(connection, name, params);
|
|
12357
|
-
}, () => updateIdle(), acpRegistry);
|
|
12737
|
+
}, () => updateIdle(), acpRegistry, (status2) => void pushDevices.notify(status2));
|
|
12358
12738
|
const processEvent = ({ event: name, params, stream, seq }, ownerId) => {
|
|
12359
12739
|
const cap = name.startsWith("terminal.") ? "terminal" : "tasks";
|
|
12360
12740
|
for (const c of connections.values()) {
|
|
@@ -12701,7 +13081,7 @@ async function createRuntime(options2) {
|
|
|
12701
13081
|
if (method.startsWith("terminal.")) return { cap: "terminal", trust: true };
|
|
12702
13082
|
if (method.startsWith("tasks.")) return { cap: "tasks", trust: !["tasks.catalog", "tasks.list", "tasks.attach", "tasks.worktrees"].includes(method) };
|
|
12703
13083
|
if (method.startsWith("git.")) return { cap: "git", trust: true };
|
|
12704
|
-
if (method.startsWith("acp.")) return { cap: "extensions", trust: true };
|
|
13084
|
+
if (method.startsWith("acp.") || method.startsWith("push.")) return { cap: "extensions", trust: true };
|
|
12705
13085
|
if (method.startsWith("lsp.")) return { cap: "lsp", trust: true };
|
|
12706
13086
|
if (method.startsWith("collab.")) return { cap: "collaboration" };
|
|
12707
13087
|
if (method.startsWith("extensions."))
|
|
@@ -12734,6 +13114,7 @@ async function createRuntime(options2) {
|
|
|
12734
13114
|
if (!["acp.start", "acp.list", "acp.attach", "acp.detach", "acp.stop", "acp.disconnect", "acp.registry"].includes(method) && !method.startsWith("acp.checkpoint."))
|
|
12735
13115
|
agents.control(session.id, requireString(params, "id"), connection.id);
|
|
12736
13116
|
}
|
|
13117
|
+
if (method.startsWith("push.")) owner(connection);
|
|
12737
13118
|
if (method.startsWith("project.")) owner(connection);
|
|
12738
13119
|
if (method.startsWith("settings.")) owner(connection);
|
|
12739
13120
|
switch (method) {
|
|
@@ -12768,6 +13149,9 @@ async function createRuntime(options2) {
|
|
|
12768
13149
|
return agents.enqueue(session.id, requireString(params, "id"), params, method === "acp.interrupt");
|
|
12769
13150
|
case "acp.dequeue":
|
|
12770
13151
|
return agents.dequeue(session.id, requireString(params, "id"), requireString(params, "promptId"));
|
|
13152
|
+
case "acp.moveQueued":
|
|
13153
|
+
if (!Number.isInteger(params.index)) throw new RpcError("INVALID_PARAMS", "index must be an integer");
|
|
13154
|
+
return agents.moveQueued(session.id, requireString(params, "id"), requireString(params, "promptId"), params.index);
|
|
12771
13155
|
case "acp.resumeQueue":
|
|
12772
13156
|
return agents.resumeQueue(session.id, requireString(params, "id"));
|
|
12773
13157
|
case "acp.call":
|
|
@@ -12784,6 +13168,12 @@ async function createRuntime(options2) {
|
|
|
12784
13168
|
case "acp.disconnect":
|
|
12785
13169
|
agents.disconnect(session.id, connection.id);
|
|
12786
13170
|
return {};
|
|
13171
|
+
case "push.register":
|
|
13172
|
+
return pushDevices.register(session.id, connection.id, params);
|
|
13173
|
+
case "push.state":
|
|
13174
|
+
return pushDevices.state(session.id, connection.id, params);
|
|
13175
|
+
case "push.unregister":
|
|
13176
|
+
return pushDevices.unregister(session.id, params);
|
|
12787
13177
|
case "acp.checkpoint.create":
|
|
12788
13178
|
return checkpoints.create(signal);
|
|
12789
13179
|
case "acp.checkpoint.diff":
|
|
@@ -12965,6 +13355,8 @@ async function createRuntime(options2) {
|
|
|
12965
13355
|
return git.show(params.ref, signal);
|
|
12966
13356
|
case "git.commitDiff":
|
|
12967
13357
|
return git.commitDiff(params, signal);
|
|
13358
|
+
case "git.branchDiff":
|
|
13359
|
+
return git.branchDiff(params, signal);
|
|
12968
13360
|
case "git.stashes":
|
|
12969
13361
|
return git.stashes(signal);
|
|
12970
13362
|
case "git.stashDiff":
|
|
@@ -13129,6 +13521,25 @@ async function createRuntime(options2) {
|
|
|
13129
13521
|
params.encoding,
|
|
13130
13522
|
params.eol
|
|
13131
13523
|
);
|
|
13524
|
+
case "search.files": {
|
|
13525
|
+
const term = requireString(params, "query", 1024).trim().toLowerCase();
|
|
13526
|
+
if (!term) return [];
|
|
13527
|
+
const result = await runCommand(options2.desktop?.rgPath ?? "rg", ["--files", "--hidden", "--glob", "!.git", "--glob", "!node_modules", "--glob", "!.oxbit-tmp-*"], {
|
|
13528
|
+
cwd: root,
|
|
13529
|
+
signal,
|
|
13530
|
+
maxBytes: 64 * MAX_BUFFER_BYTES
|
|
13531
|
+
});
|
|
13532
|
+
if (result.exitCode > 1) throw new RpcError("SEARCH_FAILED", result.stderr.trim());
|
|
13533
|
+
const matches = (path2) => {
|
|
13534
|
+
let at = 0;
|
|
13535
|
+
for (const char of term) {
|
|
13536
|
+
at = path2.indexOf(char, at) + 1;
|
|
13537
|
+
if (!at) return false;
|
|
13538
|
+
}
|
|
13539
|
+
return true;
|
|
13540
|
+
};
|
|
13541
|
+
return result.stdout.split("\n").filter((path2) => path2 && matches(path2.toLowerCase())).sort().slice(0, 1e3);
|
|
13542
|
+
}
|
|
13132
13543
|
case "search.query": {
|
|
13133
13544
|
const query = requireString(params, "query", 8192);
|
|
13134
13545
|
if (!query) return [];
|
|
@@ -13394,6 +13805,7 @@ async function createRuntime(options2) {
|
|
|
13394
13805
|
clearTimeout(authDeadline);
|
|
13395
13806
|
agents.detach(connection.id);
|
|
13396
13807
|
lsp.detach(connection.id);
|
|
13808
|
+
pushDevices.disconnect(connection.id);
|
|
13397
13809
|
connections.delete(connection.id);
|
|
13398
13810
|
updateIdle();
|
|
13399
13811
|
for (const pending of connection.edits.values()) {
|
|
@@ -13544,6 +13956,7 @@ async function createRuntime(options2) {
|
|
|
13544
13956
|
await Promise.allSettled([...inflight.values()]);
|
|
13545
13957
|
await collaboration.close();
|
|
13546
13958
|
await persistence;
|
|
13959
|
+
await pushDevices.flush();
|
|
13547
13960
|
await new Promise((resolve) => websocket.close(() => resolve()));
|
|
13548
13961
|
await new Promise((resolve) => server.close(() => resolve()));
|
|
13549
13962
|
}
|
|
@@ -13741,7 +14154,7 @@ function lanAddresses() {
|
|
|
13741
14154
|
return { v4: of("IPv4"), v6: of("IPv6") };
|
|
13742
14155
|
}
|
|
13743
14156
|
const stderrLog = (line) => process.stderr.write(line + "\n");
|
|
13744
|
-
function advertise(ad,
|
|
14157
|
+
function advertise(ad, log2 = stderrLog) {
|
|
13745
14158
|
const instance = instanceLabel(ad.name, ad.id);
|
|
13746
14159
|
const current = (ttl) => records({ ...ad, ...(ad.addresses ?? lanAddresses)() }, ttl);
|
|
13747
14160
|
const timers = [];
|
|
@@ -13760,11 +14173,11 @@ function advertise(ad, log = stderrLog) {
|
|
|
13760
14173
|
};
|
|
13761
14174
|
const fail = (error) => {
|
|
13762
14175
|
if (closed) return;
|
|
13763
|
-
|
|
14176
|
+
log2(`mDNS advertising disabled: ${error.message}`);
|
|
13764
14177
|
stop2();
|
|
13765
14178
|
};
|
|
13766
14179
|
const sendFailure = (error) => {
|
|
13767
|
-
if (!sendFailed)
|
|
14180
|
+
if (!sendFailed) log2(`mDNS send failed: ${error.message}`);
|
|
13768
14181
|
sendFailed = true;
|
|
13769
14182
|
};
|
|
13770
14183
|
const send = (packet, port2 = PORT, address = GROUP, done) => {
|
|
@@ -14083,7 +14496,7 @@ Runtime id: ${daemon.id}
|
|
|
14083
14496
|
}
|
|
14084
14497
|
async function detach(invocation, target, dataDir, entry2) {
|
|
14085
14498
|
await fs.mkdir(dataDir, { recursive: true, mode: 448 });
|
|
14086
|
-
const
|
|
14499
|
+
const log2 = await fs.open(logFile(dataDir), "a", 384);
|
|
14087
14500
|
const args = [entry2, "--foreground", "--no-open", ...invocation.lan ? ["--lan"] : ["--host", invocation.host]];
|
|
14088
14501
|
if (invocation.port) args.push("--port", String(invocation.port));
|
|
14089
14502
|
args.push("--keep-alive", invocation.keepAlive ? String(invocation.keepAlive) : "forever");
|
|
@@ -14095,7 +14508,7 @@ async function detach(invocation, target, dataDir, entry2) {
|
|
|
14095
14508
|
delete env2.OXBIT_KEEP_ALIVE;
|
|
14096
14509
|
const child = spawn(process.execPath, args, {
|
|
14097
14510
|
detached: true,
|
|
14098
|
-
stdio: ["ignore",
|
|
14511
|
+
stdio: ["ignore", log2.fd, log2.fd],
|
|
14099
14512
|
env: env2
|
|
14100
14513
|
});
|
|
14101
14514
|
let exit;
|
|
@@ -14103,7 +14516,7 @@ async function detach(invocation, target, dataDir, entry2) {
|
|
|
14103
14516
|
exit = code ?? 1;
|
|
14104
14517
|
});
|
|
14105
14518
|
child.unref();
|
|
14106
|
-
await
|
|
14519
|
+
await log2.close();
|
|
14107
14520
|
const deadline = Date.now() + READY_TIMEOUT;
|
|
14108
14521
|
while (Date.now() < deadline) {
|
|
14109
14522
|
const daemon = await liveDaemon(dataDir);
|