zidane 5.13.13 → 5.13.16

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.
Files changed (121) hide show
  1. package/dist/acp-cli.js +8 -7
  2. package/dist/acp-cli.js.map +1 -1
  3. package/dist/{acp-CqXcM2Km.js → acp-eGzYbNGF.js} +8 -8
  4. package/dist/{acp-CqXcM2Km.js.map → acp-eGzYbNGF.js.map} +1 -1
  5. package/dist/acp.d.ts +2 -2
  6. package/dist/acp.js +1 -1
  7. package/dist/{agent-NkKgz5Dh.d.ts → agent-CNIOsTUg.d.ts} +44 -2
  8. package/dist/agent-CNIOsTUg.d.ts.map +1 -0
  9. package/dist/{auth-CGTf8v1_.js → auth-D9rP8khI.js} +2 -2
  10. package/dist/{auth-CGTf8v1_.js.map → auth-D9rP8khI.js.map} +1 -1
  11. package/dist/chat/pure.d.ts +3 -3
  12. package/dist/chat.d.ts +6 -6
  13. package/dist/chat.js +3 -3
  14. package/dist/contexts/daytona.d.ts +22 -4
  15. package/dist/contexts/daytona.d.ts.map +1 -1
  16. package/dist/contexts/daytona.js +6 -5
  17. package/dist/contexts/daytona.js.map +1 -1
  18. package/dist/contexts/docker.js +2 -1
  19. package/dist/contexts/docker.js.map +1 -1
  20. package/dist/contexts/e2b.d.ts +2 -2
  21. package/dist/contexts/sandbox.d.ts +2 -0
  22. package/dist/contexts/sandbox.js +55 -0
  23. package/dist/contexts/sandbox.js.map +1 -0
  24. package/dist/{contexts-DHi8LPCp.js → contexts-BebciJyQ.js} +3 -53
  25. package/dist/contexts-BebciJyQ.js.map +1 -0
  26. package/dist/contexts.d.ts +2 -1
  27. package/dist/contexts.js +2 -1
  28. package/dist/{errors-BpPfMo_4.js → errors-DJUxZg9b.js} +3 -2
  29. package/dist/{errors-BpPfMo_4.js.map → errors-DJUxZg9b.js.map} +1 -1
  30. package/dist/eval.d.ts +1 -1
  31. package/dist/eval.js +3 -3
  32. package/dist/{fetch-url-Cgbq-HYx.js → fetch-url-CWE8X5OD.js} +2 -2
  33. package/dist/{fetch-url-Cgbq-HYx.js.map → fetch-url-CWE8X5OD.js.map} +1 -1
  34. package/dist/{glob-DCWXy_tr.js → glob-D56-KpBp.js} +2 -12
  35. package/dist/glob-D56-KpBp.js.map +1 -0
  36. package/dist/glob-shell-rJMoCIGb.js +21 -0
  37. package/dist/glob-shell-rJMoCIGb.js.map +1 -0
  38. package/dist/{headless-C6Idunwh.js → headless-HAFnYaDY.js} +6 -6
  39. package/dist/{headless-C6Idunwh.js.map → headless-HAFnYaDY.js.map} +1 -1
  40. package/dist/headless.d.ts +1 -1
  41. package/dist/headless.js +1 -1
  42. package/dist/{index-BgB_425D.d.ts → index-Bzh-W2RD.d.ts} +26 -8
  43. package/dist/index-Bzh-W2RD.d.ts.map +1 -0
  44. package/dist/{index-BFY7mcar.d.ts → index-DuB7Cf02.d.ts} +2 -2
  45. package/dist/{index-BFY7mcar.d.ts.map → index-DuB7Cf02.d.ts.map} +1 -1
  46. package/dist/index-HQJDOWvo.d.ts +7 -0
  47. package/dist/index-HQJDOWvo.d.ts.map +1 -0
  48. package/dist/index.d.ts +6 -5
  49. package/dist/index.js +12 -11
  50. package/dist/index.js.map +1 -1
  51. package/dist/{interpolate-ConAiXGy.js → interpolate-BtIgcCuz.js} +2 -2
  52. package/dist/{interpolate-ConAiXGy.js.map → interpolate-BtIgcCuz.js.map} +1 -1
  53. package/dist/{logger-LQmSBfD_.d.ts → logger-HOG4EGv6.d.ts} +2 -2
  54. package/dist/{logger-LQmSBfD_.d.ts.map → logger-HOG4EGv6.d.ts.map} +1 -1
  55. package/dist/{login-DE-_d045.js → login-CCA-1lgK.js} +2 -2
  56. package/dist/{login-DE-_d045.js.map → login-CCA-1lgK.js.map} +1 -1
  57. package/dist/{mcp-2OGi_NQu.js → mcp-Dn5W65Lv.js} +2 -2
  58. package/dist/{mcp-2OGi_NQu.js.map → mcp-Dn5W65Lv.js.map} +1 -1
  59. package/dist/mcp.d.ts +1 -1
  60. package/dist/mcp.js +1 -1
  61. package/dist/{messages-U_87Z7GH.js → messages-FUqY3pci.js} +2 -2
  62. package/dist/{messages-U_87Z7GH.js.map → messages-FUqY3pci.js.map} +1 -1
  63. package/dist/output/stream-json.d.ts +2 -2
  64. package/dist/output/stream-json.js +1 -1
  65. package/dist/output/terminal.d.ts +2 -2
  66. package/dist/{presets-eC4VwuHh.js → presets-DDRkelUs.js} +2 -2
  67. package/dist/{presets-eC4VwuHh.js.map → presets-DDRkelUs.js.map} +1 -1
  68. package/dist/presets.d.ts +2 -2
  69. package/dist/presets.js +1 -1
  70. package/dist/{providers-DyMPTo51.js → providers-BPVOGmde.js} +13 -5
  71. package/dist/providers-BPVOGmde.js.map +1 -0
  72. package/dist/providers.d.ts +1 -1
  73. package/dist/providers.js +2 -2
  74. package/dist/restate.d.ts +38 -2
  75. package/dist/restate.d.ts.map +1 -1
  76. package/dist/restate.js +22 -0
  77. package/dist/restate.js.map +1 -1
  78. package/dist/{index-CF15aqlk.d.ts → sandbox-B-bMq3K6.d.ts} +2 -5
  79. package/dist/sandbox-B-bMq3K6.d.ts.map +1 -0
  80. package/dist/session/sqlite.d.ts +1 -1
  81. package/dist/session/sqlite.js +1 -1
  82. package/dist/{session-DQ4bEncf.js → session-C0D4p0Gy.js} +2 -2
  83. package/dist/{session-DQ4bEncf.js.map → session-C0D4p0Gy.js.map} +1 -1
  84. package/dist/session.d.ts +1 -1
  85. package/dist/session.js +2 -2
  86. package/dist/skills.d.ts +2 -2
  87. package/dist/skills.js +1 -1
  88. package/dist/{tool-formatters-DvtGhbJN.d.ts → tool-formatters-B4Ll4Xpz.d.ts} +2 -2
  89. package/dist/{tool-formatters-DvtGhbJN.d.ts.map → tool-formatters-B4Ll4Xpz.d.ts.map} +1 -1
  90. package/dist/tools/fetch-url.d.ts +1 -1
  91. package/dist/tools/fetch-url.js +1 -1
  92. package/dist/tools/web-search.d.ts +1 -1
  93. package/dist/tools/web-search.js +2 -2
  94. package/dist/{tools-BvATiiCO.js → tools-BwqbsLcJ.js} +83 -26
  95. package/dist/tools-BwqbsLcJ.js.map +1 -0
  96. package/dist/tools.d.ts +2 -2
  97. package/dist/tools.js +1 -1
  98. package/dist/{transcript-anchors-DFmfOesU.d.ts → transcript-anchors-CRnGrkTd.d.ts} +4 -4
  99. package/dist/{transcript-anchors-DFmfOesU.d.ts.map → transcript-anchors-CRnGrkTd.d.ts.map} +1 -1
  100. package/dist/{transcript-anchors-Cn1Unhn-.js → transcript-anchors-dPvyuqmU.js} +9 -9
  101. package/dist/{transcript-anchors-Cn1Unhn-.js.map → transcript-anchors-dPvyuqmU.js.map} +1 -1
  102. package/dist/tui.d.ts +3 -3
  103. package/dist/tui.js +10 -10
  104. package/dist/tui.js.map +1 -1
  105. package/dist/{turn-operations-DWUN8cHo.d.ts → turn-operations-DYbhKmSu.d.ts} +3 -3
  106. package/dist/{turn-operations-DWUN8cHo.d.ts.map → turn-operations-DYbhKmSu.d.ts.map} +1 -1
  107. package/dist/types.d.ts +3 -3
  108. package/dist/types.js +1 -1
  109. package/docs/ARCHITECTURE.md +2 -0
  110. package/docs/CHAT.md +3 -3
  111. package/docs/RESTATE.md +58 -0
  112. package/docs/SKILL.md +1 -0
  113. package/docs/TUI.md +1 -1
  114. package/package.json +6 -1
  115. package/dist/agent-NkKgz5Dh.d.ts.map +0 -1
  116. package/dist/contexts-DHi8LPCp.js.map +0 -1
  117. package/dist/glob-DCWXy_tr.js.map +0 -1
  118. package/dist/index-BgB_425D.d.ts.map +0 -1
  119. package/dist/index-CF15aqlk.d.ts.map +0 -1
  120. package/dist/providers-DyMPTo51.js.map +0 -1
  121. package/dist/tools-BvATiiCO.js.map +0 -1
package/dist/chat.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- import { B as Session, Cr as ContextMcpGroup, Er as buildContextBreakdown, P as SkillConfig, R as SkillsConfig, Sr as ContextItem, Tr as ContextUsageSplit, _r as ContextBreakdown, br as ContextCategoryId, ln as AutoCompact, r as AgentHooks, vr as ContextBreakdownOptions, wr as ContextSnapshot, xn as McpToolSchema, xr as ContextExactCounts, yn as McpServerConfig, yr as ContextCategory, yt as Provider, zn as SessionTurn } from "./agent-NkKgz5Dh.js";
2
- import { J as McpCredentialStore, q as McpCredentialEntry, t as Preset } from "./index-BgB_425D.js";
1
+ import { B as Session, Cr as ContextMcpGroup, Er as buildContextBreakdown, P as SkillConfig, R as SkillsConfig, Sr as ContextItem, Tr as ContextUsageSplit, _r as ContextBreakdown, br as ContextCategoryId, ln as AutoCompact, r as AgentHooks, vr as ContextBreakdownOptions, wr as ContextSnapshot, xn as McpToolSchema, xr as ContextExactCounts, yn as McpServerConfig, yr as ContextCategory, yt as Provider, zn as SessionTurn } from "./agent-CNIOsTUg.js";
2
+ import { J as McpCredentialStore, q as McpCredentialEntry, t as Preset } from "./index-Bzh-W2RD.js";
3
3
  import { a as effectiveContextWindow, i as OUTPUT_RESERVE_TOKENS, n as AutoCompactDecision, o as shouldAutoCompact, r as AutoCompactInput, t as AUTO_COMPACT_MIN_GROWTH_FRACTION } from "./policy-DcGlpaNs.js";
4
- import { _ as SourcedScanPath } from "./index-BFY7mcar.js";
5
- import { $ as useInteractionsQueue, $t as mergeKeybindings, A as InteractionsProvider, At as loadState, B as QuestionPayload, Bt as KEYBINDING_DEFS, C as ASK_USER_TOOL, Ct as TuiState, D as InteractionRequest, Dt as eventsFromTurns, E as CreateInteractionToolsOptions, Et as deriveSessionTitle, F as PlanRequest, Ft as titleFromTurns, G as TextQuestion, Gt as KeyBindingSection, H as QuestionResponse, Ht as KEYBINDING_KEY_COL_WIDTH, I as PlanResponse, It as toolCallPreview, J as isInteractionTool, Jt as ensureKeybindingsFile, K as buildResumedToolResultsTurn, Kt as KeyBindings, L as PlanStep, Lt as toolResultText, M as PendingInteractionEntry, Mt as saveState, N as PlanDecision, Nt as stripSpawnTokensLine, O as InteractionResponse, Ot as lastContextSizeFromTurns, P as PlanPayload, Pt as sumRunCosts, Q as useInteractionsActions, Qt as matchesBinding, R as Question, Rt as updateToolEventOutcomes, S as splitMarkdownCodeBlocks, St as StateStoreApi, T as ConfirmQuestion, Tt as createStateStore, U as QuestionType, Ut as KeyAction, V as QuestionRequest, Vt as KEYBINDING_DEF_BY_ACTION, W as SelectQuestion, Wt as KeyBindingDef, X as pendingInteractionsFromTurns, Xt as groupBindings, Y as makeRequestInteraction, Yt as formatBindingForDisplay, Z as serializeInteractionResponse, Zt as keybindingsPath, _ as SessionExportTarget, _n as DEFAULT_PERSIST_EXCLUDE_TOOLS, _t as ResolveStorageDirsOptions, a as ChipColorMap, an as EMPTY_HINTS, at as DiscoveryResult, b as writeSessionExport, bn as resolveAgentId, bt as StorageSlot, c as SyntaxTokenStyle, cn as hintsLength, ct as discoverProjectMcps, d as ThemeSelect, dn as AgentProfile, dt as ChatOptions, en as parseBindingSpec, et as EnabledAllowlistKey, f as ThemeSurfaces, fn as AgentRegistry, ft as ProviderRegistry, g as SessionExportFormat, gn as DEFAULT_BUDGET_EXCLUDE_TOOLS, gt as resolveStoragePaths, h as SessionExportAnchor, hn as DEFAULT_AGENT_ID, ht as resolveConfig, i as ChipColor, in as useCompletion, it as DiscoveryError, j as PRESENT_PLAN_TOOL, jt as marginTopFor, k as InteractionsActions, kt as listSessionMeta, l as Theme, ln as truncateTrailing, lt as parseMcpsFile, m as resolveTheme, mn as BUILTIN_AGENTS, mt as ResolvedPaths, n as computeTurnAnchors, nn as stripJsonComments, nt as useEnabledToggleSet, o as DEFAULT_THEME, on as Hint, ot as buildMcpServers, p as resolveChipColor, pn as BUILD_AGENT, pt as ResolvedConfig, q as createInteractionTools, qt as ParsedBinding, r as BUILTIN_THEMES, rn as CompletionState, rt as DiscoveredMcp, s as SyntaxStyles, sn as clipHintsToWidth, st as defaultMcpsConfigPaths, t as TranscriptItem, tn as readKeybindings, tt as EnabledToggleSet, u as ThemeColors, un as AgentAccent, ut as AutoUpdateConfig, v as renderSession, vn as PLAN_AGENT, vt as StorageDirs, w as AnswerValue, wt as compactSummaryEvent, x as MarkdownSegment, xn as singleAgentRegistry, xt as resolveStorageDirs, y as resolveSessionExportTarget, yn as accentColor, yt as StorageMode, z as QuestionChoice, zt as DEFAULT_KEYBINDINGS } from "./transcript-anchors-DFmfOesU.js";
6
- import { $ as cerebrasDescriptor, A as SessionMeta, B as collectReferences, C as EditHunk, D as Owner, E as EditPayload, F as CompletionContext, G as ProviderKey, H as mergeReferences, I as CompletionItem, J as CustomField, K as detectAuth, L as CompletionProvider, M as StreamEvent, N as ToolCallDisplay, O as Picked, P as ActiveTrigger, Q as anthropicDescriptor, R as CompletionReference, S as EditDiffDisplay, T as EditOutcomeKind, U as AuthMethod, V as findActiveTrigger, W as ProviderAuth, X as ModelOption, Y as ModelInfo, Z as ProviderDescriptor, _ as isEditErrorResult, a as formatToolCall, at as modelOptionsFor, b as selectableTurnIds, c as splitPromptSegments, ct as openaiDescriptor, d as RequestApproval, dt as restoreModelOptions, et as credKeyOf, f as SafeModeActions, h as useSafeModeQueue, i as displayNameFor, it as localDescriptor, j as Settings, k as Screen, l as ApprovalDecision, lt as openrouterDescriptor, m as useSafeModeActions, n as ToolDisplayMeta, nt as getContextWindow, o as PromptSegment, ot as modelSupportsReasoning, p as SafeModeProvider, q as BUILTIN_PROVIDERS, r as ToolFormatLine, rt as getModelInfo, s as PromptSegmentRef, st as modelsForDescriptor, t as TOOL_DISPLAY, tt as enabledModelOptions, u as ApprovalRequest, ut as piIdOf, v as isTurnHighlighted, w as EditOutcome, x as turnSelectionOwnership, y as isVisible, z as applyInsert } from "./tool-formatters-DvtGhbJN.js";
7
- import { $ as uniqueFilesFromReferences, A as buildUnifiedDiff, B as buildEditOutcomesAnnotation, C as EditSummary, D as PreviewResult, E as InlineSegment, F as previewEditPayload, G as rewriteMultiEditHeader, H as mergeApprovalAndBodyOutcomes, I as splitLines, J as SKILLS_TRIGGER, K as stripEditOutcomesAnnotation, L as summarizeEditPayload, M as computeLineDiff, N as extractEditPayload, O as applyEditPayload, P as filetypeFromPath, Q as createFilesCompletionProvider, R as tokenize, S as EditHunkSummary, T as InlineDiff, U as parseEditOutcomesFromResult, V as maskToOutcomeKinds, W as resolveApprovalForPayload, X as uniqueSkillNamesFromReferences, Y as createSkillsCompletionProvider, Z as FILES_TRIGGER, _ as formatTaskSummary, a as finalizeStreamingMarkdown, b as DiffLine, c as CatalogEntry, d as indexOfEntry, et as FileEntry, f as ageString, g as formatTaskStatus, h as formatDuration, i as turnAsText, it as buildLinearRamp, j as computeInlineDiff, k as buildContextualDiff, l as buildModelCatalog, m as fmtTokens, n as deleteTurnSafely, nt as listProjectFiles, o as finalizeStreamingMarkdownForOwner, p as compactPath, q as summarizeOutcomes, r as truncateTurnsAt, rt as blendHsl, s as turnContextSize, t as countNeighbors, tt as ListProjectFilesOptions, u as filterModelCatalog, v as previewLine, w as HunkResolution, x as DiffOp, y as shortId, z as ResolvedApproval } from "./turn-operations-DWUN8cHo.js";
4
+ import { _ as SourcedScanPath } from "./index-DuB7Cf02.js";
5
+ import { $ as useInteractionsQueue, $t as mergeKeybindings, A as InteractionsProvider, At as loadState, B as QuestionPayload, Bt as KEYBINDING_DEFS, C as ASK_USER_TOOL, Ct as TuiState, D as InteractionRequest, Dt as eventsFromTurns, E as CreateInteractionToolsOptions, Et as deriveSessionTitle, F as PlanRequest, Ft as titleFromTurns, G as TextQuestion, Gt as KeyBindingSection, H as QuestionResponse, Ht as KEYBINDING_KEY_COL_WIDTH, I as PlanResponse, It as toolCallPreview, J as isInteractionTool, Jt as ensureKeybindingsFile, K as buildResumedToolResultsTurn, Kt as KeyBindings, L as PlanStep, Lt as toolResultText, M as PendingInteractionEntry, Mt as saveState, N as PlanDecision, Nt as stripSpawnTokensLine, O as InteractionResponse, Ot as lastContextSizeFromTurns, P as PlanPayload, Pt as sumRunCosts, Q as useInteractionsActions, Qt as matchesBinding, R as Question, Rt as updateToolEventOutcomes, S as splitMarkdownCodeBlocks, St as StateStoreApi, T as ConfirmQuestion, Tt as createStateStore, U as QuestionType, Ut as KeyAction, V as QuestionRequest, Vt as KEYBINDING_DEF_BY_ACTION, W as SelectQuestion, Wt as KeyBindingDef, X as pendingInteractionsFromTurns, Xt as groupBindings, Y as makeRequestInteraction, Yt as formatBindingForDisplay, Z as serializeInteractionResponse, Zt as keybindingsPath, _ as SessionExportTarget, _n as DEFAULT_PERSIST_EXCLUDE_TOOLS, _t as ResolveStorageDirsOptions, a as ChipColorMap, an as EMPTY_HINTS, at as DiscoveryResult, b as writeSessionExport, bn as resolveAgentId, bt as StorageSlot, c as SyntaxTokenStyle, cn as hintsLength, ct as discoverProjectMcps, d as ThemeSelect, dn as AgentProfile, dt as ChatOptions, en as parseBindingSpec, et as EnabledAllowlistKey, f as ThemeSurfaces, fn as AgentRegistry, ft as ProviderRegistry, g as SessionExportFormat, gn as DEFAULT_BUDGET_EXCLUDE_TOOLS, gt as resolveStoragePaths, h as SessionExportAnchor, hn as DEFAULT_AGENT_ID, ht as resolveConfig, i as ChipColor, in as useCompletion, it as DiscoveryError, j as PRESENT_PLAN_TOOL, jt as marginTopFor, k as InteractionsActions, kt as listSessionMeta, l as Theme, ln as truncateTrailing, lt as parseMcpsFile, m as resolveTheme, mn as BUILTIN_AGENTS, mt as ResolvedPaths, n as computeTurnAnchors, nn as stripJsonComments, nt as useEnabledToggleSet, o as DEFAULT_THEME, on as Hint, ot as buildMcpServers, p as resolveChipColor, pn as BUILD_AGENT, pt as ResolvedConfig, q as createInteractionTools, qt as ParsedBinding, r as BUILTIN_THEMES, rn as CompletionState, rt as DiscoveredMcp, s as SyntaxStyles, sn as clipHintsToWidth, st as defaultMcpsConfigPaths, t as TranscriptItem, tn as readKeybindings, tt as EnabledToggleSet, u as ThemeColors, un as AgentAccent, ut as AutoUpdateConfig, v as renderSession, vn as PLAN_AGENT, vt as StorageDirs, w as AnswerValue, wt as compactSummaryEvent, x as MarkdownSegment, xn as singleAgentRegistry, xt as resolveStorageDirs, y as resolveSessionExportTarget, yn as accentColor, yt as StorageMode, z as QuestionChoice, zt as DEFAULT_KEYBINDINGS } from "./transcript-anchors-CRnGrkTd.js";
6
+ import { $ as cerebrasDescriptor, A as SessionMeta, B as collectReferences, C as EditHunk, D as Owner, E as EditPayload, F as CompletionContext, G as ProviderKey, H as mergeReferences, I as CompletionItem, J as CustomField, K as detectAuth, L as CompletionProvider, M as StreamEvent, N as ToolCallDisplay, O as Picked, P as ActiveTrigger, Q as anthropicDescriptor, R as CompletionReference, S as EditDiffDisplay, T as EditOutcomeKind, U as AuthMethod, V as findActiveTrigger, W as ProviderAuth, X as ModelOption, Y as ModelInfo, Z as ProviderDescriptor, _ as isEditErrorResult, a as formatToolCall, at as modelOptionsFor, b as selectableTurnIds, c as splitPromptSegments, ct as openaiDescriptor, d as RequestApproval, dt as restoreModelOptions, et as credKeyOf, f as SafeModeActions, h as useSafeModeQueue, i as displayNameFor, it as localDescriptor, j as Settings, k as Screen, l as ApprovalDecision, lt as openrouterDescriptor, m as useSafeModeActions, n as ToolDisplayMeta, nt as getContextWindow, o as PromptSegment, ot as modelSupportsReasoning, p as SafeModeProvider, q as BUILTIN_PROVIDERS, r as ToolFormatLine, rt as getModelInfo, s as PromptSegmentRef, st as modelsForDescriptor, t as TOOL_DISPLAY, tt as enabledModelOptions, u as ApprovalRequest, ut as piIdOf, v as isTurnHighlighted, w as EditOutcome, x as turnSelectionOwnership, y as isVisible, z as applyInsert } from "./tool-formatters-B4Ll4Xpz.js";
7
+ import { $ as uniqueFilesFromReferences, A as buildUnifiedDiff, B as buildEditOutcomesAnnotation, C as EditSummary, D as PreviewResult, E as InlineSegment, F as previewEditPayload, G as rewriteMultiEditHeader, H as mergeApprovalAndBodyOutcomes, I as splitLines, J as SKILLS_TRIGGER, K as stripEditOutcomesAnnotation, L as summarizeEditPayload, M as computeLineDiff, N as extractEditPayload, O as applyEditPayload, P as filetypeFromPath, Q as createFilesCompletionProvider, R as tokenize, S as EditHunkSummary, T as InlineDiff, U as parseEditOutcomesFromResult, V as maskToOutcomeKinds, W as resolveApprovalForPayload, X as uniqueSkillNamesFromReferences, Y as createSkillsCompletionProvider, Z as FILES_TRIGGER, _ as formatTaskSummary, a as finalizeStreamingMarkdown, b as DiffLine, c as CatalogEntry, d as indexOfEntry, et as FileEntry, f as ageString, g as formatTaskStatus, h as formatDuration, i as turnAsText, it as buildLinearRamp, j as computeInlineDiff, k as buildContextualDiff, l as buildModelCatalog, m as fmtTokens, n as deleteTurnSafely, nt as listProjectFiles, o as finalizeStreamingMarkdownForOwner, p as compactPath, q as summarizeOutcomes, r as truncateTurnsAt, rt as blendHsl, s as turnContextSize, t as countNeighbors, tt as ListProjectFilesOptions, u as filterModelCatalog, v as previewLine, w as HunkResolution, x as DiffOp, y as shortId, z as ResolvedApproval } from "./turn-operations-DYbhKmSu.js";
8
8
  import { Hookable } from "hookable";
9
9
  import { OAuthCredentials, OAuthDeviceCodeInfo, OAuthPrompt, OAuthPrompt as OAuthPrompt$1, OAuthSelectPrompt } from "@earendil-works/pi-ai/oauth";
10
10
  import { spawn } from "node:child_process";
package/dist/chat.js CHANGED
@@ -1,8 +1,8 @@
1
- import { $ as useMcpAuthDispatch, $n as singleAgentRegistry, $t as createStateStore, A as runOAuthLogin, An as bootTick, At as SettingsProvider, B as refreshMcpToolsCatalog, Bn as resolvePlatformPackage, Bt as CATPPUCCIN_FRAPPE, C as projectsFilePath, Cn as mergeKeybindings, Cr as TOKEN_DISCIPLINE_DOCTRINE, Ct as shortChord, D as formatPathForCwd, Dn as useCompletion, Dt as SETTINGS_CATEGORIES, E as writeProjects, En as stripJsonComments, Er as envSection, Et as DEFAULT_SETTINGS, F as parseMcpsFile, Fn as detectLibc, Ft as resolveChipColor, G as useMcpToolToggleSet, Gn as BUILD_AGENT, Gt as DiscoveryProvider, H as subscribeMcpToolsCache, Hn as discoverAgentsMd, Ht as CATPPUCCIN_MACCHIATO, I as projectUserPaths, In as detectPackageManager, It as resolveTheme, J as parentServerName, Jn as DEFAULT_BUDGET_EXCLUDE_TOOLS, Jt as ConfigProvider, K as buildVisibleMcpRows, Kn as BUILTIN_AGENTS, Kt as useDiscovery, L as clearMcpToolsCache, Ln as parseSemver, Lt as VAPORWAVE_THEME, M as buildMcpServers, Mn as useUpdateCheck, Mt as useSettings, N as defaultMcpsConfigPaths, Nn as checkForUpdate, Nt as BUILTIN_THEMES, O as fetchOAuthRedirect, On as tryOpenBrowser, Ot as SETTINGS_CHOICES, P as discoverProjectMcps, Pn as compareSemver, Pt as DEFAULT_THEME, Q as McpAuthProvider, Qn as resolveAgentId, Qt as compactSummaryEvent, R as loadMcpToolsCache, Rn as performInPlaceSelfUpdate, Rt as GRUVBOX_DARK, S as matchesSafelistEntry, Sn as matchesBinding, Sr as SUBAGENT_GUIDANCE, St as buildHints, T as suggestSafelistEntry, Tn as readKeybindings, Tr as buildPlanSystem, Tt as useEnabledToggleSet, U as buildToolToggle, Un as renderAgentsMdBlock, Ut as CATPPUCCIN_MOCHA, V as saveMcpToolsCache, Vn as chatAutoCompactBehavior, Vt as CATPPUCCIN_LATTE, W as useMcpToolToggleMap, Wn as findGitRoot, Wt as createDiscoverySlot, X as mcpCredentialsPath, Xn as PLAN_AGENT, Xt as resolveConfig, Y as createFileMcpCredentialStore, Yn as DEFAULT_PERSIST_EXCLUDE_TOOLS, Yt as useConfig, Z as patchMcpCredential, Zn as accentColor, Zt as resolveStoragePaths, _ as useSafeModeQueue, _n as KEYBINDING_KEY_COL_WIDTH, _r as IDENTITY_PREFIX, _t as clipHintsToWidth, a as useSurfaces, an as marginTopFor, ar as createTodoTools, at as ASK_USER_TOOL, b as getSafelist, bn as groupBindings, br as PLAN_MODE_DOCTRINE, bt as cleanTitle, c as useStreamBuffer, cn as stripSpawnTokensLine, cr as isTodoTool, ct as buildResumedToolResultsTurn, d as discoverProjectSkills, dn as toolCallPreview, dr as selectActiveTodos, dt as makeRequestInteraction, en as deriveSessionTitle, er as TODOREAD_TOOL, et as useMcpAuthState, f as renderSession, fn as toolResultText, fr as setTodosForRun, ft as pendingInteractionsFromTurns, g as useSafeModeActions, gn as KEYBINDING_DEF_BY_ACTION, gr as DOING_TASKS_DOCTRINE, gt as EMPTY_HINTS, h as SafeModeProvider, hn as KEYBINDING_DEFS, hr as COMMUNICATION_DOCTRINE, ht as useInteractionsQueue, i as useSelectStyle, in as loadState, ir as TODO_WRITE_COUNTS_METADATA_KEY, it as splitMarkdownCodeBlocks, j as supportsOAuth, jn as buildUpdateHint, k as oauthUsesManualCodePaste, kn as bootProfileEnabled, kt as SETTINGS_TOGGLES, l as buildSkillsConfig, ln as sumRunCosts, lr as pickActiveRunId, lt as createInteractionTools, m as writeSessionExport, mn as DEFAULT_KEYBINDINGS, mr as ACTIONS_WITH_CARE_DOCTRINE, mt as useInteractionsActions, n as ThemeProvider, nn as lastContextSizeFromTurns, nr as TODOWRITE_TOOL, nt as reduceMcpAuth, o as useSyntaxStyles, on as saveState, or as getArchivedTodosForRun, ot as InteractionsProvider, p as resolveSessionExportTarget, pn as updateToolEventOutcomes, pr as useActiveTodos, pt as serializeInteractionResponse, q as indexOfServerRow, qn as DEFAULT_AGENT_ID, qt as useDiscoveryOptional, r as useColors, rn as listSessionMeta, rr as TODO_STATUS_GLYPHS, s as useTheme, sr as getTodosForRun, st as PRESENT_PLAN_TOOL, t as computeTurnAnchors, tn as eventsFromTurns, tr as TODOS_METADATA_KEY, tt as getMcpAuthStatus, u as defaultSkillScanPaths, un as titleFromTurns, ur as pruneTodosByRun, ut as isInteractionTool, v as IMPLICITLY_SAFE_TOOLS, vn as ensureKeybindingsFile, vr as INTERACTION_GUIDANCE, vt as hintsLength, w as readProjects, wn as parseBindingSpec, wr as buildBuildSystem, wt as listProjectFiles, x as isOnSafelist, xn as keybindingsPath, xr as PLAN_MODE_DOCTRINE_NO_PROMPTS, xt as generateSessionTitle, y as addToSafelist, yn as formatBindingForDisplay, yr as INTERACTION_GUIDANCE_NO_PROMPTS, yt as truncateTrailing, z as mcpToolsCachePath, zn as performSelfUpdate, zt as GRUVBOX_LIGHT } from "./transcript-anchors-Cn1Unhn-.js";
2
- import { ct as OUTPUT_RESERVE_TOKENS, lt as effectiveContextWindow, st as AUTO_COMPACT_MIN_GROWTH_FRACTION, ut as shouldAutoCompact } from "./tools-BvATiiCO.js";
1
+ import { $ as useMcpAuthDispatch, $n as singleAgentRegistry, $t as createStateStore, A as runOAuthLogin, An as bootTick, At as SettingsProvider, B as refreshMcpToolsCatalog, Bn as resolvePlatformPackage, Bt as CATPPUCCIN_FRAPPE, C as projectsFilePath, Cn as mergeKeybindings, Cr as TOKEN_DISCIPLINE_DOCTRINE, Ct as shortChord, D as formatPathForCwd, Dn as useCompletion, Dt as SETTINGS_CATEGORIES, E as writeProjects, En as stripJsonComments, Er as envSection, Et as DEFAULT_SETTINGS, F as parseMcpsFile, Fn as detectLibc, Ft as resolveChipColor, G as useMcpToolToggleSet, Gn as BUILD_AGENT, Gt as DiscoveryProvider, H as subscribeMcpToolsCache, Hn as discoverAgentsMd, Ht as CATPPUCCIN_MACCHIATO, I as projectUserPaths, In as detectPackageManager, It as resolveTheme, J as parentServerName, Jn as DEFAULT_BUDGET_EXCLUDE_TOOLS, Jt as ConfigProvider, K as buildVisibleMcpRows, Kn as BUILTIN_AGENTS, Kt as useDiscovery, L as clearMcpToolsCache, Ln as parseSemver, Lt as VAPORWAVE_THEME, M as buildMcpServers, Mn as useUpdateCheck, Mt as useSettings, N as defaultMcpsConfigPaths, Nn as checkForUpdate, Nt as BUILTIN_THEMES, O as fetchOAuthRedirect, On as tryOpenBrowser, Ot as SETTINGS_CHOICES, P as discoverProjectMcps, Pn as compareSemver, Pt as DEFAULT_THEME, Q as McpAuthProvider, Qn as resolveAgentId, Qt as compactSummaryEvent, R as loadMcpToolsCache, Rn as performInPlaceSelfUpdate, Rt as GRUVBOX_DARK, S as matchesSafelistEntry, Sn as matchesBinding, Sr as SUBAGENT_GUIDANCE, St as buildHints, T as suggestSafelistEntry, Tn as readKeybindings, Tr as buildPlanSystem, Tt as useEnabledToggleSet, U as buildToolToggle, Un as renderAgentsMdBlock, Ut as CATPPUCCIN_MOCHA, V as saveMcpToolsCache, Vn as chatAutoCompactBehavior, Vt as CATPPUCCIN_LATTE, W as useMcpToolToggleMap, Wn as findGitRoot, Wt as createDiscoverySlot, X as mcpCredentialsPath, Xn as PLAN_AGENT, Xt as resolveConfig, Y as createFileMcpCredentialStore, Yn as DEFAULT_PERSIST_EXCLUDE_TOOLS, Yt as useConfig, Z as patchMcpCredential, Zn as accentColor, Zt as resolveStoragePaths, _ as useSafeModeQueue, _n as KEYBINDING_KEY_COL_WIDTH, _r as IDENTITY_PREFIX, _t as clipHintsToWidth, a as useSurfaces, an as marginTopFor, ar as createTodoTools, at as ASK_USER_TOOL, b as getSafelist, bn as groupBindings, br as PLAN_MODE_DOCTRINE, bt as cleanTitle, c as useStreamBuffer, cn as stripSpawnTokensLine, cr as isTodoTool, ct as buildResumedToolResultsTurn, d as discoverProjectSkills, dn as toolCallPreview, dr as selectActiveTodos, dt as makeRequestInteraction, en as deriveSessionTitle, er as TODOREAD_TOOL, et as useMcpAuthState, f as renderSession, fn as toolResultText, fr as setTodosForRun, ft as pendingInteractionsFromTurns, g as useSafeModeActions, gn as KEYBINDING_DEF_BY_ACTION, gr as DOING_TASKS_DOCTRINE, gt as EMPTY_HINTS, h as SafeModeProvider, hn as KEYBINDING_DEFS, hr as COMMUNICATION_DOCTRINE, ht as useInteractionsQueue, i as useSelectStyle, in as loadState, ir as TODO_WRITE_COUNTS_METADATA_KEY, it as splitMarkdownCodeBlocks, j as supportsOAuth, jn as buildUpdateHint, k as oauthUsesManualCodePaste, kn as bootProfileEnabled, kt as SETTINGS_TOGGLES, l as buildSkillsConfig, ln as sumRunCosts, lr as pickActiveRunId, lt as createInteractionTools, m as writeSessionExport, mn as DEFAULT_KEYBINDINGS, mr as ACTIONS_WITH_CARE_DOCTRINE, mt as useInteractionsActions, n as ThemeProvider, nn as lastContextSizeFromTurns, nr as TODOWRITE_TOOL, nt as reduceMcpAuth, o as useSyntaxStyles, on as saveState, or as getArchivedTodosForRun, ot as InteractionsProvider, p as resolveSessionExportTarget, pn as updateToolEventOutcomes, pr as useActiveTodos, pt as serializeInteractionResponse, q as indexOfServerRow, qn as DEFAULT_AGENT_ID, qt as useDiscoveryOptional, r as useColors, rn as listSessionMeta, rr as TODO_STATUS_GLYPHS, s as useTheme, sr as getTodosForRun, st as PRESENT_PLAN_TOOL, t as computeTurnAnchors, tn as eventsFromTurns, tr as TODOS_METADATA_KEY, tt as getMcpAuthStatus, u as defaultSkillScanPaths, un as titleFromTurns, ur as pruneTodosByRun, ut as isInteractionTool, v as IMPLICITLY_SAFE_TOOLS, vn as ensureKeybindingsFile, vr as INTERACTION_GUIDANCE, vt as hintsLength, w as readProjects, wn as parseBindingSpec, wr as buildBuildSystem, wt as listProjectFiles, x as isOnSafelist, xn as keybindingsPath, xr as PLAN_MODE_DOCTRINE_NO_PROMPTS, xt as generateSessionTitle, y as addToSafelist, yn as formatBindingForDisplay, yr as INTERACTION_GUIDANCE_NO_PROMPTS, yt as truncateTrailing, z as mcpToolsCachePath, zn as performSelfUpdate, zt as GRUVBOX_LIGHT } from "./transcript-anchors-dPvyuqmU.js";
2
+ import { ct as OUTPUT_RESERVE_TOKENS, lt as effectiveContextWindow, st as AUTO_COMPACT_MIN_GROWTH_FRACTION, ut as shouldAutoCompact } from "./tools-BwqbsLcJ.js";
3
3
  import { t as buildContextBreakdown } from "./context-breakdown-kO-pDsay.js";
4
4
  import { a as formatTaskStatus, c as shortId, i as formatDuration, n as compactPath, o as formatTaskSummary, r as fmtTokens, s as previewLine, t as ageString } from "./format-BNOXpl-1.js";
5
- import { C as piIdOf, S as openrouterDescriptor, _ as localDescriptor, a as readCredentials, b as modelsForDescriptor, c as setProviderCredential, d as anthropicDescriptor, f as cerebrasDescriptor, g as getModelInfo, h as getContextWindow, i as credentialsPath, l as writeCredentials, m as enabledModelOptions, n as resolveStorageDirs, o as readProviderCredential, p as credKeyOf, r as applyApiKeyEnv, s as removeProviderCredential, t as detectAuth, u as BUILTIN_PROVIDERS, v as modelOptionsFor, w as restoreModelOptions, x as openaiDescriptor, y as modelSupportsReasoning } from "./auth-CGTf8v1_.js";
5
+ import { C as piIdOf, S as openrouterDescriptor, _ as localDescriptor, a as readCredentials, b as modelsForDescriptor, c as setProviderCredential, d as anthropicDescriptor, f as cerebrasDescriptor, g as getModelInfo, h as getContextWindow, i as credentialsPath, l as writeCredentials, m as enabledModelOptions, n as resolveStorageDirs, o as readProviderCredential, p as credKeyOf, r as applyApiKeyEnv, s as removeProviderCredential, t as detectAuth, u as BUILTIN_PROVIDERS, v as modelOptionsFor, w as restoreModelOptions, x as openaiDescriptor, y as modelSupportsReasoning } from "./auth-D9rP8khI.js";
6
6
  import { A as splitLines, B as summarizeOutcomes, C as buildContextualDiff, D as extractEditPayload, E as computeLineDiff, F as mergeApprovalAndBodyOutcomes, G as createFilesCompletionProvider, H as createSkillsCompletionProvider, I as parseEditOutcomesFromResult, J as collectReferences, K as uniqueFilesFromReferences, L as resolveApprovalForPayload, M as tokenize, N as buildEditOutcomesAnnotation, O as filetypeFromPath, P as maskToOutcomeKinds, Q as buildLinearRamp, R as rewriteMultiEditHeader, S as applyEditPayload, T as computeInlineDiff, U as uniqueSkillNamesFromReferences, V as SKILLS_TRIGGER, W as FILES_TRIGGER, X as mergeReferences, Y as findActiveTrigger, Z as blendHsl, _ as isEditErrorResult, a as TOOL_DISPLAY, b as selectableTurnIds, c as finalizeStreamingMarkdown, d as turnContextSize, f as splitPromptSegments, h as indexOfEntry, i as turnAsText, j as summarizeEditPayload, k as previewEditPayload, l as finalizeStreamingMarkdownForOwner, m as filterModelCatalog, n as deleteTurnSafely, o as displayNameFor, p as buildModelCatalog, q as applyInsert, r as truncateTurnsAt, s as formatToolCall, t as countNeighbors, v as isTurnHighlighted, w as buildUnifiedDiff, x as turnSelectionOwnership, y as isVisible, z as stripEditOutcomesAnnotation } from "./turn-operations-DLWN2J7f.js";
7
7
  //#region src/chat/auto-update-cli.ts
8
8
  const UPGRADE_HELP = `Usage: zidane upgrade [options]
@@ -1,6 +1,6 @@
1
1
  import { s as ExecResult } from "../types-Bs2oY7Ux.js";
2
- import { t as SandboxProvider } from "../index-CF15aqlk.js";
3
- import { a as Logger } from "../logger-LQmSBfD_.js";
2
+ import { t as SandboxProvider } from "../sandbox-B-bMq3K6.js";
3
+ import { a as Logger } from "../logger-HOG4EGv6.js";
4
4
  import { Buffer } from "node:buffer";
5
5
 
6
6
  //#region src/contexts/daytona.d.ts
@@ -61,10 +61,28 @@ interface DaytonaProviderOptions {
61
61
  target?: string;
62
62
  /**
63
63
  * Attach to a pre-existing sandbox by id or name instead of creating a fresh
64
- * one. The provider treats attached sandboxes as externally owned and leaves
65
- * them running on destroy/failure.
64
+ * one. By default the provider treats attached sandboxes as externally owned
65
+ * and leaves them running on destroy/failure (set {@link ownAttached} to take
66
+ * over the lifecycle).
66
67
  */
67
68
  sandboxId?: string;
69
+ /**
70
+ * Take ownership of an attached ({@link sandboxId}) sandbox's lifecycle, so
71
+ * `destroy()` applies {@link onDestroy} to it (stop / archive / delete)
72
+ * instead of leaving it running.
73
+ *
74
+ * The intended caller is a durable host that *owns* the sandbox across
75
+ * invocations: mint it once, journal its id, re-attach via `sandboxId` on
76
+ * every replay/resume, and clean it up at the end of the logical run. Without
77
+ * this an attached sandbox can never be stopped/deleted through the provider —
78
+ * a leak for host-owned sandboxes. No effect when creating a fresh sandbox
79
+ * (those are always owned). Spawn-time failures (readiness timeout, pregame
80
+ * error) still never delete a pre-existing attached sandbox — only sandboxes
81
+ * this provider *created* are auto-cleaned on spawn failure.
82
+ *
83
+ * Default: `false`.
84
+ */
85
+ ownAttached?: boolean;
68
86
  /** Daytona snapshot used when creating a fresh sandbox. */
69
87
  snapshot?: string;
70
88
  /** Runtime used for Daytona's code tooling. Shell execution works either way. */
@@ -1 +1 @@
1
- {"version":3,"file":"daytona.d.ts","names":[],"sources":["../../src/contexts/daytona.ts"],"mappings":";;;;;;UA6BU,sBAAA;EACR,QAAA;EACA,MAAA;EACA,MAAA;EACA,MAAA;EACA,MAAA;EACA,SAAA;IAAc,MAAA;EAAA;AAAA;AAAA,UAGN,gBAAA;EACR,IAAI;AAAA;AAAA,UAGI,cAAA;EACR,EAAA;EACA,KAAA;EACA,OAAA;IACE,cAAA,GAAiB,OAAA,UAAiB,GAAA,WAAc,GAAA,GAAM,MAAA,kBAAwB,OAAA,cAAqB,OAAA,CAAQ,sBAAA;EAAA;EAE7G,EAAA;IACE,YAAA,GAAe,IAAA,aAAiB,OAAA,CAAQ,UAAA,GAAa,WAAA;MAAgB,QAAA,GAAW,QAAA,GAAW,cAAA;IAAA;IAC3F,UAAA,GAAa,OAAA,EAAS,UAAA,GAAa,MAAA,EAAQ,IAAA,aAAiB,OAAA;IAC5D,SAAA,GAAY,IAAA,aAAiB,OAAA,CAAQ,gBAAA;EAAA;EAEvC,UAAA,SAAmB,OAAA;EACnB,KAAA,IAAS,OAAA,cAAqB,OAAA;EAC9B,MAAA,GAAS,OAAA,cAAqB,OAAA;EAC9B,IAAA,IAAQ,OAAA,cAAqB,OAAA;EAC7B,OAAA,SAAgB,OAAA;AAAA;AAAA,UASR,gBAAA;EACR,GAAA;EACA,MAAA;EACA,IAAA;EACA,GAAA;EAAA,CACC,GAAA;AAAA;AAAA,UAGO,mBAAA;EACR,QAAA;EACA,QAAA;EACA,KAAA;EACA,SAAA,GAAY,gBAAA;EACZ,OAAA,GAAU,MAAM;EAAA,CACf,GAAA;AAAA;AAAA,KAcS,gBAAA;AAAA,UAEK,sBAAA;EA9C8B;EAgD7C,MAAA;EA/CE;EAiDF,MAAA;EAjD+B;EAmD/B,MAAA;EAjDA;;;;;EAuDA,SAAA;EArDS;EAuDT,QAAA;EAtDA;EAwDA,QAAA;EAxD6B;EA0D7B,KAAA;EAzDgB;EA2DhB,SAAA,GAAY,gBAAA;EA3DW;EA6DvB,GAAA;EApDwB;EAsDxB,GAAA,GAAM,MAAA;EAtDkB;EAwDxB,MAAA,GAAS,MAAA;EAtDT;EAwDA,uBAAA;EAtDA;EAwDA,OAAA;IAAY,IAAA;IAAc,OAAA;EAAA;EApDC;;;;;;;;;EA8D3B,SAAA,GAAY,gBAAA;AAAA;AAAA,UAUG,uBAAA;EAlEH;EAoEZ,cAAA;EAtD0B;EAwD1B,gBAAA,SAAyB,OAAA;EAxDC;EA0D1B,GAAA;EAxDe;EA0Df,KAAA,IAAS,EAAA,aAAe,OAAO;AAAA;AAAA,iBAGjB,iBAAA,CACd,SAAA,EAAW,MAAA,8BACX,WAAA,EAAa,MAAA,+BACZ,MAAA;AAAA,iBAKa,0BAAA,CAA2B,QAAA,EAAU,sBAAA,GAAyB,UAAU;AAAA,iBAmDxE,0BAAA,CACd,aAAA,EAAe,MAAA,mBACf,OAAA,EAAS,sBAAA,EACT,OAAA,EAAS,MAAA,+BACR,mBAAA;AAAA,iBA8BmB,mBAAA,CACpB,OAAA,EAAS,cAAA,EACT,MAAA,EAAQ,MAAA,EACR,IAAA,EAAM,uBAAA,GACL,OAAA;AAAA,iBA2BmB,iBAAA,CACpB,OAAA,EAAS,cAAA,EACT,MAAA,EAAQ,MAAA,EACR,IAAA;EAAQ,IAAA;EAAc,OAAA;EAAiB,GAAA;EAAc,OAAA,GAAU,MAAA;AAAA,IAC9D,OAAA;AAAA,iBA4Ba,qBAAA,CAAsB,OAAA,GAAS,sBAAA,GAA8B,eAAe"}
1
+ {"version":3,"file":"daytona.d.ts","names":[],"sources":["../../src/contexts/daytona.ts"],"mappings":";;;;;;UA6BU,sBAAA;EACR,QAAA;EACA,MAAA;EACA,MAAA;EACA,MAAA;EACA,MAAA;EACA,SAAA;IAAc,MAAA;EAAA;AAAA;AAAA,UAGN,gBAAA;EACR,IAAI;AAAA;AAAA,UAGI,cAAA;EACR,EAAA;EACA,KAAA;EACA,OAAA;IACE,cAAA,GAAiB,OAAA,UAAiB,GAAA,WAAc,GAAA,GAAM,MAAA,kBAAwB,OAAA,cAAqB,OAAA,CAAQ,sBAAA;EAAA;EAE7G,EAAA;IACE,YAAA,GAAe,IAAA,aAAiB,OAAA,CAAQ,UAAA,GAAa,WAAA;MAAgB,QAAA,GAAW,QAAA,GAAW,cAAA;IAAA;IAC3F,UAAA,GAAa,OAAA,EAAS,UAAA,GAAa,MAAA,EAAQ,IAAA,aAAiB,OAAA;IAC5D,SAAA,GAAY,IAAA,aAAiB,OAAA,CAAQ,gBAAA;EAAA;EAEvC,UAAA,SAAmB,OAAA;EACnB,KAAA,IAAS,OAAA,cAAqB,OAAA;EAC9B,MAAA,GAAS,OAAA,cAAqB,OAAA;EAC9B,IAAA,IAAQ,OAAA,cAAqB,OAAA;EAC7B,OAAA,SAAgB,OAAA;AAAA;AAAA,UASR,gBAAA;EACR,GAAA;EACA,MAAA;EACA,IAAA;EACA,GAAA;EAAA,CACC,GAAA;AAAA;AAAA,UAGO,mBAAA;EACR,QAAA;EACA,QAAA;EACA,KAAA;EACA,SAAA,GAAY,gBAAA;EACZ,OAAA,GAAU,MAAM;EAAA,CACf,GAAA;AAAA;AAAA,KAcS,gBAAA;AAAA,UAEK,sBAAA;EA9C8B;EAgD7C,MAAA;EA/CE;EAiDF,MAAA;EAjD+B;EAmD/B,MAAA;EAjDA;;;;;;EAwDA,SAAA;EAtD8B;;;;;;;AAEP;AAAA;;;;;;;;EAqEvB,WAAA;EAvDY;EAyDZ,QAAA;EAtDQ;EAwDR,QAAA;;EAEA,KAAA;EAzDA;EA2DA,SAAA,GAAY,gBAAA;EAzDZ;EA2DA,GAAA;EA1DY;EA4DZ,GAAA,GAAM,MAAA;EA3DI;EA6DV,MAAA,GAAS,MAAA;EA5DG;EA8DZ,uBAAA;EAhDU;EAkDV,OAAA;IAAY,IAAA;IAAc,OAAA;EAAA;EAhDX;;;;;;;;;EA0Df,SAAA,GAAY,gBAAA;AAAA;AAAA,UAUG,uBAAA;EAvDf;EAyDA,cAAA;EAtCA;EAwCA,gBAAA,SAAyB,OAAA;EApCzB;EAsCA,GAAA;EApCY;EAsCZ,KAAA,IAAS,EAAA,aAAe,OAAO;AAAA;AAAA,iBAGjB,iBAAA,CACd,SAAA,EAAW,MAAA,8BACX,WAAA,EAAa,MAAA,+BACZ,MAAA;AAAA,iBAKa,0BAAA,CAA2B,QAAA,EAAU,sBAAA,GAAyB,UAAU;AAAA,iBAmDxE,0BAAA,CACd,aAAA,EAAe,MAAA,mBACf,OAAA,EAAS,sBAAA,EACT,OAAA,EAAS,MAAA,+BACR,mBAAA;AAAA,iBA8BmB,mBAAA,CACpB,OAAA,EAAS,cAAA,EACT,MAAA,EAAQ,MAAA,EACR,IAAA,EAAM,uBAAA,GACL,OAAA;AAAA,iBA2BmB,iBAAA,CACpB,OAAA,EAAS,cAAA,EACT,MAAA,EAAQ,MAAA,EACR,IAAA;EAAQ,IAAA;EAAc,OAAA;EAAiB,GAAA;EAAc,OAAA,GAAU,MAAA;AAAA,IAC9D,OAAA;AAAA,iBA4Ba,qBAAA,CAAsB,OAAA,GAAS,sBAAA,GAA8B,eAAe"}
@@ -202,9 +202,10 @@ function createDaytonaProvider(options = {}) {
202
202
  const connectId = takeString(sb.sandboxId) ?? options.sandboxId;
203
203
  const envVars = resolveDaytonaEnv(options.env, config.env);
204
204
  const daytona = new Daytona(toClientConfig(apiKey, apiUrl, target));
205
- const owned = connectId === void 0;
206
- const sandbox = connectId !== void 0 ? await daytona.get(connectId) : await daytona.create(resolveDaytonaCreateParams(sb, options, envVars));
207
- if (!owned) await startAttachedSandboxIfNeeded(sandbox);
205
+ const attached = connectId !== void 0;
206
+ const owned = !attached || options.ownAttached === true;
207
+ const sandbox = attached ? await daytona.get(connectId) : await daytona.create(resolveDaytonaCreateParams(sb, options, envVars));
208
+ if (attached) await startAttachedSandboxIfNeeded(sandbox);
208
209
  live.set(sandbox.id, {
209
210
  sandbox,
210
211
  env: envVars,
@@ -213,7 +214,7 @@ function createDaytonaProvider(options = {}) {
213
214
  try {
214
215
  await waitForDaytonaReady(sandbox, logger, {
215
216
  timeoutSeconds: readinessTimeoutSeconds,
216
- ...owned ? { cleanupOnTimeout: () => deleteOwnedSandbox(sandbox) } : {}
217
+ ...!attached ? { cleanupOnTimeout: () => deleteOwnedSandbox(sandbox) } : {}
217
218
  });
218
219
  } catch (err) {
219
220
  live.delete(sandbox.id);
@@ -236,7 +237,7 @@ function createDaytonaProvider(options = {}) {
236
237
  envVars
237
238
  });
238
239
  } catch (err) {
239
- if (owned) await deleteOwnedSandbox(sandbox);
240
+ if (!attached) await deleteOwnedSandbox(sandbox);
240
241
  live.delete(sandbox.id);
241
242
  throw err;
242
243
  }
@@ -1 +1 @@
1
- {"version":3,"file":"daytona.js","names":[],"sources":["../../src/contexts/daytona.ts"],"sourcesContent":["/**\n * Daytona sandbox provider.\n *\n * Implements {@link SandboxProvider} on top of Daytona sandboxes. Pair it with\n * {@link createSandboxContext} to run an agent's shell + filesystem tools\n * inside a Daytona sandbox:\n *\n * ```ts\n * import { createSandboxContext } from 'zidane/contexts'\n * import { createDaytonaProvider } from 'zidane/contexts/daytona'\n *\n * const execution = createSandboxContext(createDaytonaProvider())\n * ```\n *\n * Requires `@daytona/sdk` as an optional peer dependency:\n * `bun add @daytona/sdk`.\n */\n\nimport type { Logger } from '../logger'\nimport type { SandboxProvider } from './sandbox'\nimport type { ExecResult, SpawnConfig } from './types'\nimport { Buffer } from 'node:buffer'\nimport { consoleSink, createLogger } from '../logger'\n\n// ---------------------------------------------------------------------------\n// Minimal structural views of the `@daytona/sdk` surface we touch. Declared\n// locally so zidane typechecks without the optional peer dependency installed.\n// ---------------------------------------------------------------------------\n\ninterface DaytonaExecuteResponse {\n exitCode?: number | null\n result?: string | null\n output?: string | null\n stdout?: string | null\n stderr?: string | null\n artifacts?: { stdout?: string | null }\n}\n\ninterface DaytonaFileEntry {\n name: string\n}\n\ninterface DaytonaSandbox {\n id: string\n state?: string\n process: {\n executeCommand: (command: string, cwd?: string, env?: Record<string, string>, timeout?: number) => Promise<DaytonaExecuteResponse>\n }\n fs: {\n downloadFile: (path: string) => Promise<Uint8Array | ArrayBuffer | { toString: (encoding?: BufferEncoding) => string }>\n uploadFile: (content: Uint8Array | Buffer, path: string) => Promise<unknown>\n listFiles: (path: string) => Promise<DaytonaFileEntry[]>\n }\n getWorkDir?: () => Promise<string>\n start?: (timeout?: number) => Promise<unknown>\n delete: (timeout?: number) => Promise<unknown>\n stop?: (timeout?: number) => Promise<unknown>\n archive?: () => Promise<unknown>\n}\n\ninterface DaytonaClientConfig {\n apiKey?: string\n apiUrl?: string\n target?: string\n}\n\ninterface DaytonaResources {\n cpu?: number\n memory?: number\n disk?: number\n gpu?: number\n [key: string]: unknown\n}\n\ninterface DaytonaCreateParams {\n language?: string\n snapshot?: string\n image?: unknown\n resources?: DaytonaResources\n envVars?: Record<string, string>\n [key: string]: unknown\n}\n\ninterface DaytonaClient {\n create: (params?: DaytonaCreateParams) => Promise<DaytonaSandbox>\n get: (sandboxIdOrName: string) => Promise<DaytonaSandbox>\n}\n\ntype DaytonaConstructor = new (config?: DaytonaClientConfig) => DaytonaClient\n\n// ---------------------------------------------------------------------------\n// Provider options\n// ---------------------------------------------------------------------------\n\nexport type DaytonaOnDestroy = 'delete' | 'kill' | 'stop' | 'pause' | 'archive' | 'leave'\n\nexport interface DaytonaProviderOptions {\n /** Daytona API key. Falls back to the `DAYTONA_API_KEY` env var when omitted. */\n apiKey?: string\n /** Daytona API URL. Falls back to `DAYTONA_API_URL`, then Daytona's hosted default. */\n apiUrl?: string\n /** Daytona target / region. Falls back to `DAYTONA_TARGET`, then the org default. */\n target?: string\n /**\n * Attach to a pre-existing sandbox by id or name instead of creating a fresh\n * one. The provider treats attached sandboxes as externally owned and leaves\n * them running on destroy/failure.\n */\n sandboxId?: string\n /** Daytona snapshot used when creating a fresh sandbox. */\n snapshot?: string\n /** Runtime used for Daytona's code tooling. Shell execution works either way. */\n language?: string\n /** Daytona image/declarative builder input used when creating a fresh sandbox. */\n image?: unknown\n /** Daytona sandbox resources. */\n resources?: DaytonaResources\n /** Default working directory, applied when a spawn doesn't set `SpawnConfig.cwd`. */\n cwd?: string\n /** Environment variables baked into the sandbox and re-sent on every command. */\n env?: Record<string, string>\n /** Logger for provider-level lifecycle lines. */\n logger?: Logger\n /** Total deadline, in seconds, for the post-create readiness probe. Defaults to `60`. */\n readinessTimeoutSeconds?: number\n /** Setup script to upload and run once the sandbox is ready. */\n pregame?: { name: string, content: string }\n /**\n * What to do with an owned sandbox on destroy:\n *\n * - `'delete'` / `'kill'` (default) — call `sandbox.delete()`.\n * - `'stop'` / `'pause'` — call `sandbox.stop()` so Daytona preserves state\n * according to the runner's stop semantics.\n * - `'archive'` — stop, then archive for longer-term persistence.\n * - `'leave'` — make no API call.\n */\n onDestroy?: DaytonaOnDestroy\n}\n\n/** Per-probe timeout for the readiness `true` command. */\nconst READINESS_PROBE_TIMEOUT_SECONDS = 5\n/** Pause between readiness probes while the sandbox is still warming up. */\nconst READINESS_BACKOFF_MS = 250\n/** Setup scripts commonly install dependencies, so give them a generous cap. */\nconst PREGAME_TIMEOUT_SECONDS = 30 * 60\n\nexport interface DaytonaReadinessOptions {\n /** Total deadline in seconds. `<= 0` disables the probe entirely. */\n timeoutSeconds: number\n /** Optional cleanup for owned sandboxes that never become ready. */\n cleanupOnTimeout?: () => Promise<void>\n /** Clock source — injectable for deterministic tests. */\n now?: () => number\n /** Sleep between probes — injectable for deterministic tests. */\n sleep?: (ms: number) => Promise<void>\n}\n\nexport function resolveDaytonaEnv(\n optionEnv: Record<string, string> | undefined,\n perSpawnEnv: Record<string, string> | undefined,\n): Record<string, string> | undefined {\n const merged = { ...optionEnv, ...perSpawnEnv }\n return Object.keys(merged).length > 0 ? merged : undefined\n}\n\nexport function normalizeDaytonaExecResult(response: DaytonaExecuteResponse): ExecResult {\n return {\n stdout: response.stdout ?? response.artifacts?.stdout ?? response.result ?? response.output ?? '',\n stderr: response.stderr ?? '',\n exitCode: typeof response.exitCode === 'number' ? response.exitCode : 0,\n }\n}\n\nfunction normalizeDaytonaExecError(error: unknown): ExecResult {\n const err = error as { exitCode?: unknown, stdout?: unknown, stderr?: unknown, result?: unknown, output?: unknown, message?: unknown }\n if (typeof err.exitCode === 'number') {\n return {\n stdout: typeof err.stdout === 'string'\n ? err.stdout\n : typeof err.result === 'string'\n ? err.result\n : typeof err.output === 'string'\n ? err.output\n : '',\n stderr: typeof err.stderr === 'string' ? err.stderr : typeof err.message === 'string' ? err.message : '',\n exitCode: err.exitCode,\n }\n }\n return { stdout: '', stderr: error instanceof Error ? error.message : String(error), exitCode: 124 }\n}\n\nfunction bufferToString(value: Uint8Array | ArrayBuffer | { toString: (encoding?: BufferEncoding) => string }): string {\n if (Buffer.isBuffer(value))\n return value.toString('utf8')\n if (value instanceof ArrayBuffer)\n return new TextDecoder().decode(new Uint8Array(value))\n if (value instanceof Uint8Array)\n return new TextDecoder().decode(value)\n return value.toString('utf8')\n}\n\nfunction toClientConfig(apiKey?: string, apiUrl?: string, target?: string): DaytonaClientConfig | undefined {\n const config: DaytonaClientConfig = {}\n if (apiKey !== undefined)\n config.apiKey = apiKey\n if (apiUrl !== undefined)\n config.apiUrl = apiUrl\n if (target !== undefined)\n config.target = target\n return Object.keys(config).length > 0 ? config : undefined\n}\n\nfunction takeString(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined\n}\n\nexport function resolveDaytonaCreateParams(\n sandboxConfig: Record<string, unknown>,\n options: DaytonaProviderOptions,\n envVars: Record<string, string> | undefined,\n): DaytonaCreateParams | undefined {\n const reserved = new Set(['provider', 'apiKey', 'apiUrl', 'target', 'sandboxId'])\n const params: DaytonaCreateParams = {}\n\n for (const [key, value] of Object.entries(sandboxConfig)) {\n if (!reserved.has(key) && value !== undefined)\n params[key] = value\n }\n\n const language = takeString(sandboxConfig.language) ?? options.language\n const snapshot = takeString(sandboxConfig.snapshot) ?? options.snapshot\n const image = sandboxConfig.image ?? options.image\n const resources = (sandboxConfig.resources as DaytonaResources | undefined) ?? options.resources\n const configEnvVars = sandboxConfig.envVars as Record<string, string> | undefined\n const mergedEnvVars = resolveDaytonaEnv(envVars, configEnvVars)\n\n if (language !== undefined)\n params.language = language\n if (snapshot !== undefined)\n params.snapshot = snapshot\n if (image !== undefined)\n params.image = image\n if (resources !== undefined)\n params.resources = resources\n if (mergedEnvVars !== undefined)\n params.envVars = mergedEnvVars\n\n return Object.keys(params).length > 0 ? params : undefined\n}\n\nexport async function waitForDaytonaReady(\n sandbox: DaytonaSandbox,\n logger: Logger,\n opts: DaytonaReadinessOptions,\n): Promise<void> {\n if (opts.timeoutSeconds <= 0)\n return\n\n const now = opts.now ?? Date.now\n const sleep = opts.sleep ?? (ms => new Promise<void>(resolve => setTimeout(resolve, ms)))\n const start = now()\n const deadline = start + opts.timeoutSeconds * 1000\n\n logger.info('waiting for Daytona sandbox to initialize', { sandboxId: sandbox.id })\n\n while (true) {\n try {\n await sandbox.process.executeCommand('true', undefined, undefined, READINESS_PROBE_TIMEOUT_SECONDS)\n logger.info('Daytona sandbox ready', { sandboxId: sandbox.id, elapsedMs: now() - start })\n return\n }\n catch {\n if (now() >= deadline) {\n await opts.cleanupOnTimeout?.().catch(() => {})\n throw new Error(`Daytona sandbox ${sandbox.id} did not become ready within ${opts.timeoutSeconds}s`)\n }\n await sleep(READINESS_BACKOFF_MS)\n }\n }\n}\n\nexport async function runDaytonaPregame(\n sandbox: DaytonaSandbox,\n logger: Logger,\n opts: { name: string, content: string, cwd?: string, envVars?: Record<string, string> },\n): Promise<void> {\n const path = `/tmp/${opts.name}`\n logger.info('running Daytona pregame script', { sandboxId: sandbox.id, path })\n await sandbox.fs.uploadFile(Buffer.from(opts.content), path)\n\n const quoted = JSON.stringify(path)\n let result: ExecResult\n try {\n result = normalizeDaytonaExecResult(\n await sandbox.process.executeCommand(`chmod +x ${quoted} && ${quoted}`, opts.cwd, opts.envVars, PREGAME_TIMEOUT_SECONDS),\n )\n }\n catch (err) {\n result = normalizeDaytonaExecError(err)\n }\n\n if (result.exitCode !== 0) {\n logger.error('Daytona pregame script failed', { sandboxId: sandbox.id, exitCode: result.exitCode, stdout: result.stdout, stderr: result.stderr })\n throw new Error(`Daytona pregame script ${opts.name} failed with exit code ${result.exitCode}`)\n }\n\n logger.info('Daytona pregame ready', { sandboxId: sandbox.id, stdout: result.stdout, stderr: result.stderr })\n}\n\n// ---------------------------------------------------------------------------\n// Provider\n// ---------------------------------------------------------------------------\n\nexport function createDaytonaProvider(options: DaytonaProviderOptions = {}): SandboxProvider {\n const live = new Map<string, { sandbox: DaytonaSandbox, env?: Record<string, string>, owned: boolean }>()\n const logger = options.logger ?? createLogger(consoleSink())\n const readinessTimeoutSeconds = options.readinessTimeoutSeconds ?? 60\n\n async function loadSdk(): Promise<DaytonaConstructor> {\n try {\n const mod = await import('@daytona/sdk') as { Daytona: DaytonaConstructor }\n return mod.Daytona\n }\n catch {\n throw new Error('@daytona/sdk is required for the Daytona sandbox provider. Install it with: bun add @daytona/sdk')\n }\n }\n\n function get(sandboxId: string): { sandbox: DaytonaSandbox, env?: Record<string, string>, owned: boolean } {\n const entry = live.get(sandboxId)\n if (!entry)\n throw new Error(`Daytona sandbox ${sandboxId} is not tracked by this provider`)\n return entry\n }\n\n async function deleteOwnedSandbox(sandbox: DaytonaSandbox): Promise<void> {\n try {\n await sandbox.delete()\n }\n catch {\n // Already gone — nothing to clean up.\n }\n }\n\n async function stopOwnedSandbox(sandbox: DaytonaSandbox): Promise<void> {\n if (!sandbox.stop) {\n logger.error('cannot stop Daytona sandbox: this @daytona/sdk install exposes no stop() method; leaving it running', { sandboxId: sandbox.id })\n return\n }\n try {\n await sandbox.stop()\n logger.info('stopped Daytona sandbox; reconnect later via the sandboxId option (CLI: --sandbox)', { sandboxId: sandbox.id })\n }\n catch (err) {\n logger.error('failed to stop Daytona sandbox; it will run until Daytona lifecycle policy stops it', { sandboxId: sandbox.id, error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n async function archiveOwnedSandbox(sandbox: DaytonaSandbox): Promise<void> {\n if (!sandbox.stop || !sandbox.archive) {\n logger.error('cannot archive Daytona sandbox: this @daytona/sdk install exposes no stop() and archive() pair; leaving it running', { sandboxId: sandbox.id })\n return\n }\n try {\n await sandbox.stop()\n await sandbox.archive()\n logger.info('archived Daytona sandbox; reconnect later via the sandboxId option (CLI: --sandbox)', { sandboxId: sandbox.id })\n }\n catch (err) {\n logger.error('failed to archive Daytona sandbox; it will run until Daytona lifecycle policy stops it', { sandboxId: sandbox.id, error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n async function startAttachedSandboxIfNeeded(sandbox: DaytonaSandbox): Promise<void> {\n if (sandbox.state !== 'stopped' && sandbox.state !== 'archived')\n return\n if (!sandbox.start) {\n logger.error('cannot start Daytona sandbox before attach readiness probe: this @daytona/sdk install exposes no start() method', { sandboxId: sandbox.id, state: sandbox.state })\n return\n }\n logger.info('starting Daytona sandbox before attach readiness probe', { sandboxId: sandbox.id, state: sandbox.state })\n await sandbox.start(readinessTimeoutSeconds > 0 ? readinessTimeoutSeconds : undefined)\n }\n\n return {\n name: 'daytona',\n\n async spawn(config: SpawnConfig = {}): Promise<{ id: string, cwd: string }> {\n const Daytona = await loadSdk()\n const sb: Record<string, unknown> = config.sandbox ?? {}\n\n const apiKey = takeString(sb.apiKey) ?? options.apiKey\n const apiUrl = takeString(sb.apiUrl) ?? options.apiUrl\n const target = takeString(sb.target) ?? options.target\n const connectId = takeString(sb.sandboxId) ?? options.sandboxId\n const envVars = resolveDaytonaEnv(options.env, config.env)\n\n const daytona = new Daytona(toClientConfig(apiKey, apiUrl, target))\n const owned = connectId === undefined\n const sandbox = connectId !== undefined\n ? await daytona.get(connectId)\n : await daytona.create(resolveDaytonaCreateParams(sb, options, envVars))\n\n if (!owned)\n await startAttachedSandboxIfNeeded(sandbox)\n\n live.set(sandbox.id, { sandbox, env: envVars, owned })\n\n try {\n await waitForDaytonaReady(sandbox, logger, {\n timeoutSeconds: readinessTimeoutSeconds,\n ...(owned ? { cleanupOnTimeout: () => deleteOwnedSandbox(sandbox) } : {}),\n })\n }\n catch (err) {\n live.delete(sandbox.id)\n throw err\n }\n\n const requestedCwd = config.cwd ?? options.cwd\n let cwd: string\n if (requestedCwd) {\n cwd = requestedCwd\n await sandbox.process.executeCommand(`mkdir -p ${JSON.stringify(cwd)}`).catch(() => {})\n }\n else if (sandbox.getWorkDir) {\n cwd = await sandbox.getWorkDir().catch(() => '')\n if (!cwd)\n cwd = await sandbox.process.executeCommand('pwd').then(r => normalizeDaytonaExecResult(r).stdout.trim()).catch(() => '') || '/home/daytona'\n }\n else {\n cwd = await sandbox.process.executeCommand('pwd').then(r => normalizeDaytonaExecResult(r).stdout.trim()).catch(() => '') || '/home/daytona'\n }\n\n if (options.pregame) {\n try {\n await runDaytonaPregame(sandbox, logger, { name: options.pregame.name, content: options.pregame.content, cwd, envVars })\n }\n catch (err) {\n if (owned)\n await deleteOwnedSandbox(sandbox)\n live.delete(sandbox.id)\n throw err\n }\n }\n\n return { id: sandbox.id, cwd }\n },\n\n async exec(sandboxId, command, opts): Promise<ExecResult> {\n const { sandbox, env } = get(sandboxId)\n const timeoutSeconds = opts?.timeout ?? 30\n try {\n return normalizeDaytonaExecResult(\n await sandbox.process.executeCommand(\n command,\n opts?.cwd,\n resolveDaytonaEnv(env, opts?.env),\n timeoutSeconds > 0 ? timeoutSeconds : undefined,\n ),\n )\n }\n catch (err) {\n return normalizeDaytonaExecError(err)\n }\n },\n\n async readFile(sandboxId, path): Promise<string> {\n return bufferToString(await get(sandboxId).sandbox.fs.downloadFile(path))\n },\n\n async writeFile(sandboxId, path, content): Promise<void> {\n await get(sandboxId).sandbox.fs.uploadFile(Buffer.from(content), path)\n },\n\n async listFiles(sandboxId, path): Promise<string[]> {\n const entries = await get(sandboxId).sandbox.fs.listFiles(path)\n return entries.map(e => e.name)\n },\n\n async destroy(sandboxId): Promise<void> {\n const entry = live.get(sandboxId)\n if (!entry)\n return\n if (entry.owned) {\n const action = options.onDestroy ?? 'delete'\n if (action === 'stop' || action === 'pause')\n await stopOwnedSandbox(entry.sandbox)\n else if (action === 'archive')\n await archiveOwnedSandbox(entry.sandbox)\n else if (action === 'delete' || action === 'kill')\n await deleteOwnedSandbox(entry.sandbox)\n }\n live.delete(sandboxId)\n },\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"daytona.js","names":[],"sources":["../../src/contexts/daytona.ts"],"sourcesContent":["/**\n * Daytona sandbox provider.\n *\n * Implements {@link SandboxProvider} on top of Daytona sandboxes. Pair it with\n * {@link createSandboxContext} to run an agent's shell + filesystem tools\n * inside a Daytona sandbox:\n *\n * ```ts\n * import { createSandboxContext } from 'zidane/contexts'\n * import { createDaytonaProvider } from 'zidane/contexts/daytona'\n *\n * const execution = createSandboxContext(createDaytonaProvider())\n * ```\n *\n * Requires `@daytona/sdk` as an optional peer dependency:\n * `bun add @daytona/sdk`.\n */\n\nimport type { Logger } from '../logger'\nimport type { SandboxProvider } from './sandbox'\nimport type { ExecResult, SpawnConfig } from './types'\nimport { Buffer } from 'node:buffer'\nimport { consoleSink, createLogger } from '../logger'\n\n// ---------------------------------------------------------------------------\n// Minimal structural views of the `@daytona/sdk` surface we touch. Declared\n// locally so zidane typechecks without the optional peer dependency installed.\n// ---------------------------------------------------------------------------\n\ninterface DaytonaExecuteResponse {\n exitCode?: number | null\n result?: string | null\n output?: string | null\n stdout?: string | null\n stderr?: string | null\n artifacts?: { stdout?: string | null }\n}\n\ninterface DaytonaFileEntry {\n name: string\n}\n\ninterface DaytonaSandbox {\n id: string\n state?: string\n process: {\n executeCommand: (command: string, cwd?: string, env?: Record<string, string>, timeout?: number) => Promise<DaytonaExecuteResponse>\n }\n fs: {\n downloadFile: (path: string) => Promise<Uint8Array | ArrayBuffer | { toString: (encoding?: BufferEncoding) => string }>\n uploadFile: (content: Uint8Array | Buffer, path: string) => Promise<unknown>\n listFiles: (path: string) => Promise<DaytonaFileEntry[]>\n }\n getWorkDir?: () => Promise<string>\n start?: (timeout?: number) => Promise<unknown>\n delete: (timeout?: number) => Promise<unknown>\n stop?: (timeout?: number) => Promise<unknown>\n archive?: () => Promise<unknown>\n}\n\ninterface DaytonaClientConfig {\n apiKey?: string\n apiUrl?: string\n target?: string\n}\n\ninterface DaytonaResources {\n cpu?: number\n memory?: number\n disk?: number\n gpu?: number\n [key: string]: unknown\n}\n\ninterface DaytonaCreateParams {\n language?: string\n snapshot?: string\n image?: unknown\n resources?: DaytonaResources\n envVars?: Record<string, string>\n [key: string]: unknown\n}\n\ninterface DaytonaClient {\n create: (params?: DaytonaCreateParams) => Promise<DaytonaSandbox>\n get: (sandboxIdOrName: string) => Promise<DaytonaSandbox>\n}\n\ntype DaytonaConstructor = new (config?: DaytonaClientConfig) => DaytonaClient\n\n// ---------------------------------------------------------------------------\n// Provider options\n// ---------------------------------------------------------------------------\n\nexport type DaytonaOnDestroy = 'delete' | 'kill' | 'stop' | 'pause' | 'archive' | 'leave'\n\nexport interface DaytonaProviderOptions {\n /** Daytona API key. Falls back to the `DAYTONA_API_KEY` env var when omitted. */\n apiKey?: string\n /** Daytona API URL. Falls back to `DAYTONA_API_URL`, then Daytona's hosted default. */\n apiUrl?: string\n /** Daytona target / region. Falls back to `DAYTONA_TARGET`, then the org default. */\n target?: string\n /**\n * Attach to a pre-existing sandbox by id or name instead of creating a fresh\n * one. By default the provider treats attached sandboxes as externally owned\n * and leaves them running on destroy/failure (set {@link ownAttached} to take\n * over the lifecycle).\n */\n sandboxId?: string\n /**\n * Take ownership of an attached ({@link sandboxId}) sandbox's lifecycle, so\n * `destroy()` applies {@link onDestroy} to it (stop / archive / delete)\n * instead of leaving it running.\n *\n * The intended caller is a durable host that *owns* the sandbox across\n * invocations: mint it once, journal its id, re-attach via `sandboxId` on\n * every replay/resume, and clean it up at the end of the logical run. Without\n * this an attached sandbox can never be stopped/deleted through the provider —\n * a leak for host-owned sandboxes. No effect when creating a fresh sandbox\n * (those are always owned). Spawn-time failures (readiness timeout, pregame\n * error) still never delete a pre-existing attached sandbox — only sandboxes\n * this provider *created* are auto-cleaned on spawn failure.\n *\n * Default: `false`.\n */\n ownAttached?: boolean\n /** Daytona snapshot used when creating a fresh sandbox. */\n snapshot?: string\n /** Runtime used for Daytona's code tooling. Shell execution works either way. */\n language?: string\n /** Daytona image/declarative builder input used when creating a fresh sandbox. */\n image?: unknown\n /** Daytona sandbox resources. */\n resources?: DaytonaResources\n /** Default working directory, applied when a spawn doesn't set `SpawnConfig.cwd`. */\n cwd?: string\n /** Environment variables baked into the sandbox and re-sent on every command. */\n env?: Record<string, string>\n /** Logger for provider-level lifecycle lines. */\n logger?: Logger\n /** Total deadline, in seconds, for the post-create readiness probe. Defaults to `60`. */\n readinessTimeoutSeconds?: number\n /** Setup script to upload and run once the sandbox is ready. */\n pregame?: { name: string, content: string }\n /**\n * What to do with an owned sandbox on destroy:\n *\n * - `'delete'` / `'kill'` (default) — call `sandbox.delete()`.\n * - `'stop'` / `'pause'` — call `sandbox.stop()` so Daytona preserves state\n * according to the runner's stop semantics.\n * - `'archive'` — stop, then archive for longer-term persistence.\n * - `'leave'` — make no API call.\n */\n onDestroy?: DaytonaOnDestroy\n}\n\n/** Per-probe timeout for the readiness `true` command. */\nconst READINESS_PROBE_TIMEOUT_SECONDS = 5\n/** Pause between readiness probes while the sandbox is still warming up. */\nconst READINESS_BACKOFF_MS = 250\n/** Setup scripts commonly install dependencies, so give them a generous cap. */\nconst PREGAME_TIMEOUT_SECONDS = 30 * 60\n\nexport interface DaytonaReadinessOptions {\n /** Total deadline in seconds. `<= 0` disables the probe entirely. */\n timeoutSeconds: number\n /** Optional cleanup for owned sandboxes that never become ready. */\n cleanupOnTimeout?: () => Promise<void>\n /** Clock source — injectable for deterministic tests. */\n now?: () => number\n /** Sleep between probes — injectable for deterministic tests. */\n sleep?: (ms: number) => Promise<void>\n}\n\nexport function resolveDaytonaEnv(\n optionEnv: Record<string, string> | undefined,\n perSpawnEnv: Record<string, string> | undefined,\n): Record<string, string> | undefined {\n const merged = { ...optionEnv, ...perSpawnEnv }\n return Object.keys(merged).length > 0 ? merged : undefined\n}\n\nexport function normalizeDaytonaExecResult(response: DaytonaExecuteResponse): ExecResult {\n return {\n stdout: response.stdout ?? response.artifacts?.stdout ?? response.result ?? response.output ?? '',\n stderr: response.stderr ?? '',\n exitCode: typeof response.exitCode === 'number' ? response.exitCode : 0,\n }\n}\n\nfunction normalizeDaytonaExecError(error: unknown): ExecResult {\n const err = error as { exitCode?: unknown, stdout?: unknown, stderr?: unknown, result?: unknown, output?: unknown, message?: unknown }\n if (typeof err.exitCode === 'number') {\n return {\n stdout: typeof err.stdout === 'string'\n ? err.stdout\n : typeof err.result === 'string'\n ? err.result\n : typeof err.output === 'string'\n ? err.output\n : '',\n stderr: typeof err.stderr === 'string' ? err.stderr : typeof err.message === 'string' ? err.message : '',\n exitCode: err.exitCode,\n }\n }\n return { stdout: '', stderr: error instanceof Error ? error.message : String(error), exitCode: 124 }\n}\n\nfunction bufferToString(value: Uint8Array | ArrayBuffer | { toString: (encoding?: BufferEncoding) => string }): string {\n if (Buffer.isBuffer(value))\n return value.toString('utf8')\n if (value instanceof ArrayBuffer)\n return new TextDecoder().decode(new Uint8Array(value))\n if (value instanceof Uint8Array)\n return new TextDecoder().decode(value)\n return value.toString('utf8')\n}\n\nfunction toClientConfig(apiKey?: string, apiUrl?: string, target?: string): DaytonaClientConfig | undefined {\n const config: DaytonaClientConfig = {}\n if (apiKey !== undefined)\n config.apiKey = apiKey\n if (apiUrl !== undefined)\n config.apiUrl = apiUrl\n if (target !== undefined)\n config.target = target\n return Object.keys(config).length > 0 ? config : undefined\n}\n\nfunction takeString(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined\n}\n\nexport function resolveDaytonaCreateParams(\n sandboxConfig: Record<string, unknown>,\n options: DaytonaProviderOptions,\n envVars: Record<string, string> | undefined,\n): DaytonaCreateParams | undefined {\n const reserved = new Set(['provider', 'apiKey', 'apiUrl', 'target', 'sandboxId'])\n const params: DaytonaCreateParams = {}\n\n for (const [key, value] of Object.entries(sandboxConfig)) {\n if (!reserved.has(key) && value !== undefined)\n params[key] = value\n }\n\n const language = takeString(sandboxConfig.language) ?? options.language\n const snapshot = takeString(sandboxConfig.snapshot) ?? options.snapshot\n const image = sandboxConfig.image ?? options.image\n const resources = (sandboxConfig.resources as DaytonaResources | undefined) ?? options.resources\n const configEnvVars = sandboxConfig.envVars as Record<string, string> | undefined\n const mergedEnvVars = resolveDaytonaEnv(envVars, configEnvVars)\n\n if (language !== undefined)\n params.language = language\n if (snapshot !== undefined)\n params.snapshot = snapshot\n if (image !== undefined)\n params.image = image\n if (resources !== undefined)\n params.resources = resources\n if (mergedEnvVars !== undefined)\n params.envVars = mergedEnvVars\n\n return Object.keys(params).length > 0 ? params : undefined\n}\n\nexport async function waitForDaytonaReady(\n sandbox: DaytonaSandbox,\n logger: Logger,\n opts: DaytonaReadinessOptions,\n): Promise<void> {\n if (opts.timeoutSeconds <= 0)\n return\n\n const now = opts.now ?? Date.now\n const sleep = opts.sleep ?? (ms => new Promise<void>(resolve => setTimeout(resolve, ms)))\n const start = now()\n const deadline = start + opts.timeoutSeconds * 1000\n\n logger.info('waiting for Daytona sandbox to initialize', { sandboxId: sandbox.id })\n\n while (true) {\n try {\n await sandbox.process.executeCommand('true', undefined, undefined, READINESS_PROBE_TIMEOUT_SECONDS)\n logger.info('Daytona sandbox ready', { sandboxId: sandbox.id, elapsedMs: now() - start })\n return\n }\n catch {\n if (now() >= deadline) {\n await opts.cleanupOnTimeout?.().catch(() => {})\n throw new Error(`Daytona sandbox ${sandbox.id} did not become ready within ${opts.timeoutSeconds}s`)\n }\n await sleep(READINESS_BACKOFF_MS)\n }\n }\n}\n\nexport async function runDaytonaPregame(\n sandbox: DaytonaSandbox,\n logger: Logger,\n opts: { name: string, content: string, cwd?: string, envVars?: Record<string, string> },\n): Promise<void> {\n const path = `/tmp/${opts.name}`\n logger.info('running Daytona pregame script', { sandboxId: sandbox.id, path })\n await sandbox.fs.uploadFile(Buffer.from(opts.content), path)\n\n const quoted = JSON.stringify(path)\n let result: ExecResult\n try {\n result = normalizeDaytonaExecResult(\n await sandbox.process.executeCommand(`chmod +x ${quoted} && ${quoted}`, opts.cwd, opts.envVars, PREGAME_TIMEOUT_SECONDS),\n )\n }\n catch (err) {\n result = normalizeDaytonaExecError(err)\n }\n\n if (result.exitCode !== 0) {\n logger.error('Daytona pregame script failed', { sandboxId: sandbox.id, exitCode: result.exitCode, stdout: result.stdout, stderr: result.stderr })\n throw new Error(`Daytona pregame script ${opts.name} failed with exit code ${result.exitCode}`)\n }\n\n logger.info('Daytona pregame ready', { sandboxId: sandbox.id, stdout: result.stdout, stderr: result.stderr })\n}\n\n// ---------------------------------------------------------------------------\n// Provider\n// ---------------------------------------------------------------------------\n\nexport function createDaytonaProvider(options: DaytonaProviderOptions = {}): SandboxProvider {\n const live = new Map<string, { sandbox: DaytonaSandbox, env?: Record<string, string>, owned: boolean }>()\n const logger = options.logger ?? createLogger(consoleSink())\n const readinessTimeoutSeconds = options.readinessTimeoutSeconds ?? 60\n\n async function loadSdk(): Promise<DaytonaConstructor> {\n try {\n const mod = await import('@daytona/sdk') as { Daytona: DaytonaConstructor }\n return mod.Daytona\n }\n catch {\n throw new Error('@daytona/sdk is required for the Daytona sandbox provider. Install it with: bun add @daytona/sdk')\n }\n }\n\n function get(sandboxId: string): { sandbox: DaytonaSandbox, env?: Record<string, string>, owned: boolean } {\n const entry = live.get(sandboxId)\n if (!entry)\n throw new Error(`Daytona sandbox ${sandboxId} is not tracked by this provider`)\n return entry\n }\n\n async function deleteOwnedSandbox(sandbox: DaytonaSandbox): Promise<void> {\n try {\n await sandbox.delete()\n }\n catch {\n // Already gone — nothing to clean up.\n }\n }\n\n async function stopOwnedSandbox(sandbox: DaytonaSandbox): Promise<void> {\n if (!sandbox.stop) {\n logger.error('cannot stop Daytona sandbox: this @daytona/sdk install exposes no stop() method; leaving it running', { sandboxId: sandbox.id })\n return\n }\n try {\n await sandbox.stop()\n logger.info('stopped Daytona sandbox; reconnect later via the sandboxId option (CLI: --sandbox)', { sandboxId: sandbox.id })\n }\n catch (err) {\n logger.error('failed to stop Daytona sandbox; it will run until Daytona lifecycle policy stops it', { sandboxId: sandbox.id, error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n async function archiveOwnedSandbox(sandbox: DaytonaSandbox): Promise<void> {\n if (!sandbox.stop || !sandbox.archive) {\n logger.error('cannot archive Daytona sandbox: this @daytona/sdk install exposes no stop() and archive() pair; leaving it running', { sandboxId: sandbox.id })\n return\n }\n try {\n await sandbox.stop()\n await sandbox.archive()\n logger.info('archived Daytona sandbox; reconnect later via the sandboxId option (CLI: --sandbox)', { sandboxId: sandbox.id })\n }\n catch (err) {\n logger.error('failed to archive Daytona sandbox; it will run until Daytona lifecycle policy stops it', { sandboxId: sandbox.id, error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n async function startAttachedSandboxIfNeeded(sandbox: DaytonaSandbox): Promise<void> {\n if (sandbox.state !== 'stopped' && sandbox.state !== 'archived')\n return\n if (!sandbox.start) {\n logger.error('cannot start Daytona sandbox before attach readiness probe: this @daytona/sdk install exposes no start() method', { sandboxId: sandbox.id, state: sandbox.state })\n return\n }\n logger.info('starting Daytona sandbox before attach readiness probe', { sandboxId: sandbox.id, state: sandbox.state })\n await sandbox.start(readinessTimeoutSeconds > 0 ? readinessTimeoutSeconds : undefined)\n }\n\n return {\n name: 'daytona',\n\n async spawn(config: SpawnConfig = {}): Promise<{ id: string, cwd: string }> {\n const Daytona = await loadSdk()\n const sb: Record<string, unknown> = config.sandbox ?? {}\n\n const apiKey = takeString(sb.apiKey) ?? options.apiKey\n const apiUrl = takeString(sb.apiUrl) ?? options.apiUrl\n const target = takeString(sb.target) ?? options.target\n const connectId = takeString(sb.sandboxId) ?? options.sandboxId\n const envVars = resolveDaytonaEnv(options.env, config.env)\n\n const daytona = new Daytona(toClientConfig(apiKey, apiUrl, target))\n const attached = connectId !== undefined\n // Lifecycle ownership drives `destroy()` (onDestroy). A created sandbox is\n // always owned; an attached one is owned only when the host opts in via\n // `ownAttached`. Spawn-FAILURE cleanup is separate (see below) and keyed\n // on `!attached` so a pre-existing sandbox is never auto-deleted.\n const owned = !attached || options.ownAttached === true\n const sandbox = attached\n ? await daytona.get(connectId)\n : await daytona.create(resolveDaytonaCreateParams(sb, options, envVars))\n\n if (attached)\n await startAttachedSandboxIfNeeded(sandbox)\n\n live.set(sandbox.id, { sandbox, env: envVars, owned })\n\n try {\n await waitForDaytonaReady(sandbox, logger, {\n timeoutSeconds: readinessTimeoutSeconds,\n // Only auto-delete a sandbox we CREATED on readiness failure — never a\n // pre-existing attached one, even when we own its lifecycle.\n ...(!attached ? { cleanupOnTimeout: () => deleteOwnedSandbox(sandbox) } : {}),\n })\n }\n catch (err) {\n live.delete(sandbox.id)\n throw err\n }\n\n const requestedCwd = config.cwd ?? options.cwd\n let cwd: string\n if (requestedCwd) {\n cwd = requestedCwd\n await sandbox.process.executeCommand(`mkdir -p ${JSON.stringify(cwd)}`).catch(() => {})\n }\n else if (sandbox.getWorkDir) {\n cwd = await sandbox.getWorkDir().catch(() => '')\n if (!cwd)\n cwd = await sandbox.process.executeCommand('pwd').then(r => normalizeDaytonaExecResult(r).stdout.trim()).catch(() => '') || '/home/daytona'\n }\n else {\n cwd = await sandbox.process.executeCommand('pwd').then(r => normalizeDaytonaExecResult(r).stdout.trim()).catch(() => '') || '/home/daytona'\n }\n\n if (options.pregame) {\n try {\n await runDaytonaPregame(sandbox, logger, { name: options.pregame.name, content: options.pregame.content, cwd, envVars })\n }\n catch (err) {\n // Spawn-failure cleanup: only delete a sandbox we created, never a\n // pre-existing attached one (the host owns its prior state).\n if (!attached)\n await deleteOwnedSandbox(sandbox)\n live.delete(sandbox.id)\n throw err\n }\n }\n\n return { id: sandbox.id, cwd }\n },\n\n async exec(sandboxId, command, opts): Promise<ExecResult> {\n const { sandbox, env } = get(sandboxId)\n const timeoutSeconds = opts?.timeout ?? 30\n try {\n return normalizeDaytonaExecResult(\n await sandbox.process.executeCommand(\n command,\n opts?.cwd,\n resolveDaytonaEnv(env, opts?.env),\n timeoutSeconds > 0 ? timeoutSeconds : undefined,\n ),\n )\n }\n catch (err) {\n return normalizeDaytonaExecError(err)\n }\n },\n\n async readFile(sandboxId, path): Promise<string> {\n return bufferToString(await get(sandboxId).sandbox.fs.downloadFile(path))\n },\n\n async writeFile(sandboxId, path, content): Promise<void> {\n await get(sandboxId).sandbox.fs.uploadFile(Buffer.from(content), path)\n },\n\n async listFiles(sandboxId, path): Promise<string[]> {\n const entries = await get(sandboxId).sandbox.fs.listFiles(path)\n return entries.map(e => e.name)\n },\n\n async destroy(sandboxId): Promise<void> {\n const entry = live.get(sandboxId)\n if (!entry)\n return\n if (entry.owned) {\n const action = options.onDestroy ?? 'delete'\n if (action === 'stop' || action === 'pause')\n await stopOwnedSandbox(entry.sandbox)\n else if (action === 'archive')\n await archiveOwnedSandbox(entry.sandbox)\n else if (action === 'delete' || action === 'kill')\n await deleteOwnedSandbox(entry.sandbox)\n }\n live.delete(sandboxId)\n },\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
- import { n as globFilesViaShell } from "../glob-DCWXy_tr.js";
1
+ import { t as globFilesViaShell } from "../glob-shell-rJMoCIGb.js";
2
+ import "../glob-D56-KpBp.js";
2
3
  import { t as alwaysQuote } from "../shell-quote-BmnhZmdM.js";
3
4
  //#region src/contexts/docker.ts
4
5
  const SINGLE_QUOTE_RE = /'/g;
@@ -1 +1 @@
1
- {"version":3,"file":"docker.js","names":[],"sources":["../../src/contexts/docker.ts"],"sourcesContent":["/**\n * Docker execution context.\n *\n * Runs tools inside a Docker container via dockerode.\n * Full isolation with configurable resource limits.\n *\n * Requires `dockerode` as an optional peer dependency.\n */\n\nimport type { Buffer } from 'node:buffer'\nimport type { ContextCapabilities, ExecResult, ExecutionContext, ExecutionHandle, ListFilesEntry, SpawnConfig } from './types'\nimport { alwaysQuote } from '../tools/shell-quote'\nimport { globFilesViaShell } from './glob'\n\nconst SINGLE_QUOTE_RE = /'/g\n\n/**\n * dockerode surfaces HTTP errors with a `statusCode`. 304 = container\n * already stopped, 404 = already gone — both are fine during teardown.\n */\nfunction isGoneOrAlreadyStopped(err: unknown): boolean {\n const code = (err as { statusCode?: number } | null)?.statusCode\n return code === 304 || code === 404\n}\n\ninterface ContainerRef {\n handle: ExecutionHandle\n container: any\n docker: any\n}\n\nexport function createDockerContext(config?: SpawnConfig): ExecutionContext {\n let counter = 0\n const containers = new Map<string, ContainerRef>()\n const defaultImage = config?.image ?? 'oven/bun:latest'\n const defaultCwd = config?.cwd ?? '/workspace'\n const defaultEnv = config?.env\n const defaultLimits = config?.limits\n const defaultMounts = config?.mounts ?? []\n const defaultName = config?.name\n\n async function getDockerode() {\n try {\n const Dockerode = (await import('dockerode')).default\n return new Dockerode()\n }\n catch {\n throw new Error('dockerode is required for Docker execution context. Install it with: bun add dockerode')\n }\n }\n\n const ctx: ExecutionContext = {\n type: 'docker',\n\n capabilities: {\n shell: true,\n filesystem: true,\n glob: true,\n network: true,\n gpu: false,\n } satisfies ContextCapabilities,\n\n async spawn(overrides?: SpawnConfig): Promise<ExecutionHandle> {\n const docker = await getDockerode()\n const id = `docker-${++counter}`\n const image = overrides?.image ?? defaultImage\n const cwd = overrides?.cwd ?? defaultCwd\n const mounts = [...defaultMounts, ...(overrides?.mounts ?? [])]\n const name = overrides?.name ?? defaultName\n\n // Pull image if not available\n try {\n await docker.getImage(image).inspect()\n }\n catch {\n await new Promise<void>((resolve, reject) => {\n docker.pull(image, (err: Error | null, stream: NodeJS.ReadableStream) => {\n if (err)\n return reject(err)\n docker.modem.followProgress(stream, (err2: Error | null) => {\n err2 ? reject(err2) : resolve()\n })\n })\n })\n }\n\n const limits = { ...defaultLimits, ...overrides?.limits }\n const hostConfig: Record<string, unknown> = {}\n\n if (limits?.memory) {\n hostConfig.Memory = limits.memory * 1024 * 1024\n }\n if (limits?.cpu) {\n hostConfig.NanoCpus = Number.parseFloat(limits.cpu) * 1e9\n }\n\n // Opt-in hardening (all OFF by default — see ContextHardening).\n const hardening = { ...config?.hardening, ...overrides?.hardening }\n if (hardening.dropAllCapabilities)\n hostConfig.CapDrop = ['ALL']\n if (hardening.noNewPrivileges)\n hostConfig.SecurityOpt = ['no-new-privileges']\n if (hardening.readonlyRootfs)\n hostConfig.ReadonlyRootfs = true\n if (hardening.pidsLimit != null)\n hostConfig.PidsLimit = hardening.pidsLimit\n\n const env = { ...defaultEnv, ...overrides?.env }\n\n const bindSpecs = buildBindSpecs(mounts)\n if (bindSpecs.length > 0) {\n hostConfig.Binds = bindSpecs\n }\n\n const portSpec = overrides?.ports ?? config?.ports\n const exposedPorts: Record<string, Record<string, never>> = {}\n const portBindings: Record<string, Array<{ HostPort: string }>> = {}\n\n if (portSpec?.length) {\n for (const p of portSpec) {\n const key = `${p.container}/${p.proto ?? 'tcp'}`\n exposedPorts[key] = {}\n portBindings[key] = [{ HostPort: p.host == null ? '' : String(p.host) }]\n }\n hostConfig.PortBindings = portBindings\n }\n\n const user = overrides?.user ?? config?.user\n const network = overrides?.network ?? config?.network\n if (network) {\n hostConfig.NetworkMode = network\n }\n\n const labels = { ...config?.labels, ...overrides?.labels }\n\n const container = await docker.createContainer({\n // Suffix with a short random token so a crashed run's leftover container\n // (same prefix) never blocks a fresh one with HTTP 409 name conflict.\n ...(name ? { name: `${name}-${counter}-${Math.random().toString(36).slice(2, 8)}` } : {}),\n Image: image,\n Cmd: ['sleep', 'infinity'],\n WorkingDir: cwd,\n Env: Object.entries(env).map(([k, v]) => `${k}=${v}`),\n HostConfig: hostConfig,\n ...(Object.keys(exposedPorts).length ? { ExposedPorts: exposedPorts } : {}),\n ...(user ? { User: user } : {}),\n ...(Object.keys(labels).length ? { Labels: labels } : {}),\n })\n\n try {\n await container.start()\n }\n catch (err) {\n // The container was created but never started — remove it so a\n // failed spawn doesn't leak a stopped container on the daemon.\n await container.remove({ force: true }).catch(() => {})\n throw err\n }\n\n const handle: ExecutionHandle = { id, type: 'docker', cwd }\n containers.set(id, { handle, container, docker })\n\n return handle\n },\n\n async exec(handle: ExecutionHandle, command: string, options?: { cwd?: string, env?: Record<string, string>, timeout?: number }): Promise<ExecResult> {\n const ref = containers.get(handle.id)\n if (!ref)\n throw new Error(`Container ${handle.id} not found`)\n\n const execCwd = options?.cwd ?? handle.cwd\n const env = options?.env\n ? Object.entries(options.env).map(([k, v]) => `${k}=${v}`)\n : []\n\n const timeout = options?.timeout ?? defaultLimits?.timeout ?? 30\n\n const exec = await ref.container.exec({\n // Wrap with coreutils `timeout` so a runaway command is killed\n // server-side too — the host-side timer below only detaches the\n // stream; without this the process would keep running in the\n // container until destroy(). Exec-array form avoids re-quoting the\n // command. `timeout` exits 124 on expiry, matching the host\n // sentinel. (Default image oven/bun is Debian-based → coreutils.)\n Cmd: ['timeout', String(timeout), 'sh', '-c', command],\n WorkingDir: execCwd,\n Env: env,\n AttachStdout: true,\n AttachStderr: true,\n })\n\n const stream = await exec.start({ Detach: false })\n\n return new Promise<ExecResult>((resolve) => {\n let stdout = ''\n let stderr = ''\n let resolved = false\n\n // Docker's exec stream is a multiplexed protocol — a single byte\n // stream that interleaves stdout/stderr frames. `demuxStream`\n // splits the two onto separate writable sinks. Without it, every\n // byte landed on `stdout` and `stderr` was permanently empty.\n const stdoutSink = {\n write(chunk: Buffer | string) {\n stdout += typeof chunk === 'string' ? chunk : chunk.toString('utf-8')\n return true\n },\n end() {},\n on() {},\n once() {},\n emit() { return true },\n }\n const stderrSink = {\n write(chunk: Buffer | string) {\n stderr += typeof chunk === 'string' ? chunk : chunk.toString('utf-8')\n return true\n },\n end() {},\n on() {},\n once() {},\n emit() { return true },\n }\n try {\n ref.docker.modem.demuxStream(stream, stdoutSink, stderrSink)\n }\n catch {\n // Older / different transports may not be multiplexed (TTY mode);\n // fall back to a raw stdout reader so we don't lose output entirely.\n stream.on('data', (chunk: Buffer) => {\n stdout += chunk.toString('utf-8')\n })\n }\n\n // Host-side fallback timer. The server-side `timeout` wrapper is\n // the primary kill mechanism; give it a grace second so the\n // stream-end path (which carries the real exit code) usually wins.\n const timer = setTimeout(() => {\n if (resolved)\n return\n resolved = true\n // Best-effort: detach the stream so we stop accumulating bytes.\n // The server-side `timeout` wrapper kills the process itself.\n try { stream.destroy?.() }\n catch { /* swallow */ }\n resolve({ stdout, stderr: stderr ? `${stderr}\\n[timeout]` : '[timeout]', exitCode: 124 })\n }, timeout * 1000 + 1000)\n\n stream.on('end', async () => {\n if (resolved)\n return\n resolved = true\n clearTimeout(timer)\n let exitCode: number\n let inspectNote = ''\n try {\n const inspect = await exec.inspect()\n // `ExitCode: null` means Docker hasn't recorded an exit yet —\n // the outcome is unknown, not success. Use a sentinel so\n // callers don't mistake it for a clean exit.\n if (inspect.ExitCode == null) {\n exitCode = -1\n inspectNote = '[exit code unavailable: exec still marked running by daemon]'\n }\n else {\n exitCode = inspect.ExitCode\n }\n }\n catch (err) {\n exitCode = -1\n inspectNote = `[exit code unavailable: exec inspect failed: ${(err as Error)?.message ?? String(err)}]`\n }\n resolve({\n stdout,\n stderr: inspectNote ? (stderr ? `${stderr}\\n${inspectNote}` : inspectNote) : stderr,\n exitCode,\n })\n })\n\n stream.on('error', (err: Error) => {\n if (resolved)\n return\n resolved = true\n clearTimeout(timer)\n resolve({ stdout, stderr: stderr ? `${stderr}\\n${err.message}` : err.message, exitCode: 1 })\n })\n })\n },\n\n // Paths are model-supplied — single-quote them (`alwaysQuote`) rather\n // than JSON.stringify: `$(…)` and backticks still expand inside the\n // double quotes JSON produces, which was a command-injection vector.\n async readFile(handle: ExecutionHandle, path: string): Promise<string> {\n const result = await ctx.exec(handle, `cat ${alwaysQuote(path)}`)\n if (result.exitCode !== 0)\n throw new Error(`Failed to read file: ${result.stderr}`)\n return result.stdout\n },\n\n async writeFile(handle: ExecutionHandle, path: string, content: string): Promise<void> {\n const escaped = content.replace(SINGLE_QUOTE_RE, String.raw`'\\''`)\n const result = await ctx.exec(handle, `mkdir -p \"$(dirname ${alwaysQuote(path)})\" && printf '%s' '${escaped}' > ${alwaysQuote(path)}`)\n if (result.exitCode !== 0)\n throw new Error(`Failed to write file: ${result.stderr}`)\n },\n\n async listFiles(handle: ExecutionHandle, path: string, options): Promise<ListFilesEntry[]> {\n if (options?.glob)\n return globFilesViaShell(path, command => ctx.exec(handle, command), options?.limit ?? 1000)\n const result = await ctx.exec(handle, `ls -1 ${alwaysQuote(path)}`)\n if (result.exitCode !== 0)\n return []\n return result.stdout.trim().split('\\n').filter(Boolean)\n },\n\n async getMappedPort(handle: ExecutionHandle, containerPort: number): Promise<number | null> {\n const ref = containers.get(handle.id)\n if (!ref)\n return null\n\n const info = await ref.container.inspect()\n const bindings = info?.NetworkSettings?.Ports ?? {}\n\n for (const proto of ['tcp', 'udp']) {\n const list = bindings[`${containerPort}/${proto}`]\n if (Array.isArray(list) && list.length > 0 && list[0]?.HostPort) {\n return Number.parseInt(list[0].HostPort, 10)\n }\n }\n\n return null\n },\n\n async destroy(handle: ExecutionHandle): Promise<void> {\n const ref = containers.get(handle.id)\n if (!ref)\n return\n\n try {\n try {\n await ref.container.stop({ t: 5 })\n }\n catch {\n // 304 (already stopped) / 404 (already gone) are expected here.\n // Any other stop failure must not prevent the remove({force})\n // below — force removal also works on running containers.\n }\n try {\n await ref.container.remove({ force: true })\n }\n catch (err) {\n if (!isGoneOrAlreadyStopped(err))\n throw err\n }\n }\n finally {\n containers.delete(handle.id)\n }\n },\n }\n\n return ctx\n}\n\n/**\n * Format one {@link ContextMount} as a dockerode `HostConfig.Binds` entry.\n * Supports read-only (`:ro`) and SELinux shared-label (`:z`) options; the two\n * are mutually exclusive (a read-only mount can't also be a shared rw mount).\n */\nfunction formatBindMount(mount: NonNullable<SpawnConfig['mounts']>[number]): string {\n if (!mount.source)\n throw new Error('Docker mount source is required')\n if (!mount.target || !mount.target.startsWith('/'))\n throw new Error(`Docker mount target must be an absolute path: ${mount.target}`)\n if (mount.readonly && mount.shared)\n throw new Error(`Docker mount cannot be both readonly and shared: ${mount.target}`)\n const opts = mount.readonly ? ':ro' : mount.shared ? ':z' : ''\n return `${mount.source}:${mount.target}${opts}`\n}\n\n/** Assemble dockerode `HostConfig.Binds` from the context's `mounts`. */\nexport function buildBindSpecs(mounts: NonNullable<SpawnConfig['mounts']>): string[] {\n return mounts.map(formatBindMount)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"docker.js","names":[],"sources":["../../src/contexts/docker.ts"],"sourcesContent":["/**\n * Docker execution context.\n *\n * Runs tools inside a Docker container via dockerode.\n * Full isolation with configurable resource limits.\n *\n * Requires `dockerode` as an optional peer dependency.\n */\n\nimport type { Buffer } from 'node:buffer'\nimport type { ContextCapabilities, ExecResult, ExecutionContext, ExecutionHandle, ListFilesEntry, SpawnConfig } from './types'\nimport { alwaysQuote } from '../tools/shell-quote'\nimport { globFilesViaShell } from './glob'\n\nconst SINGLE_QUOTE_RE = /'/g\n\n/**\n * dockerode surfaces HTTP errors with a `statusCode`. 304 = container\n * already stopped, 404 = already gone — both are fine during teardown.\n */\nfunction isGoneOrAlreadyStopped(err: unknown): boolean {\n const code = (err as { statusCode?: number } | null)?.statusCode\n return code === 304 || code === 404\n}\n\ninterface ContainerRef {\n handle: ExecutionHandle\n container: any\n docker: any\n}\n\nexport function createDockerContext(config?: SpawnConfig): ExecutionContext {\n let counter = 0\n const containers = new Map<string, ContainerRef>()\n const defaultImage = config?.image ?? 'oven/bun:latest'\n const defaultCwd = config?.cwd ?? '/workspace'\n const defaultEnv = config?.env\n const defaultLimits = config?.limits\n const defaultMounts = config?.mounts ?? []\n const defaultName = config?.name\n\n async function getDockerode() {\n try {\n const Dockerode = (await import('dockerode')).default\n return new Dockerode()\n }\n catch {\n throw new Error('dockerode is required for Docker execution context. Install it with: bun add dockerode')\n }\n }\n\n const ctx: ExecutionContext = {\n type: 'docker',\n\n capabilities: {\n shell: true,\n filesystem: true,\n glob: true,\n network: true,\n gpu: false,\n } satisfies ContextCapabilities,\n\n async spawn(overrides?: SpawnConfig): Promise<ExecutionHandle> {\n const docker = await getDockerode()\n const id = `docker-${++counter}`\n const image = overrides?.image ?? defaultImage\n const cwd = overrides?.cwd ?? defaultCwd\n const mounts = [...defaultMounts, ...(overrides?.mounts ?? [])]\n const name = overrides?.name ?? defaultName\n\n // Pull image if not available\n try {\n await docker.getImage(image).inspect()\n }\n catch {\n await new Promise<void>((resolve, reject) => {\n docker.pull(image, (err: Error | null, stream: NodeJS.ReadableStream) => {\n if (err)\n return reject(err)\n docker.modem.followProgress(stream, (err2: Error | null) => {\n err2 ? reject(err2) : resolve()\n })\n })\n })\n }\n\n const limits = { ...defaultLimits, ...overrides?.limits }\n const hostConfig: Record<string, unknown> = {}\n\n if (limits?.memory) {\n hostConfig.Memory = limits.memory * 1024 * 1024\n }\n if (limits?.cpu) {\n hostConfig.NanoCpus = Number.parseFloat(limits.cpu) * 1e9\n }\n\n // Opt-in hardening (all OFF by default — see ContextHardening).\n const hardening = { ...config?.hardening, ...overrides?.hardening }\n if (hardening.dropAllCapabilities)\n hostConfig.CapDrop = ['ALL']\n if (hardening.noNewPrivileges)\n hostConfig.SecurityOpt = ['no-new-privileges']\n if (hardening.readonlyRootfs)\n hostConfig.ReadonlyRootfs = true\n if (hardening.pidsLimit != null)\n hostConfig.PidsLimit = hardening.pidsLimit\n\n const env = { ...defaultEnv, ...overrides?.env }\n\n const bindSpecs = buildBindSpecs(mounts)\n if (bindSpecs.length > 0) {\n hostConfig.Binds = bindSpecs\n }\n\n const portSpec = overrides?.ports ?? config?.ports\n const exposedPorts: Record<string, Record<string, never>> = {}\n const portBindings: Record<string, Array<{ HostPort: string }>> = {}\n\n if (portSpec?.length) {\n for (const p of portSpec) {\n const key = `${p.container}/${p.proto ?? 'tcp'}`\n exposedPorts[key] = {}\n portBindings[key] = [{ HostPort: p.host == null ? '' : String(p.host) }]\n }\n hostConfig.PortBindings = portBindings\n }\n\n const user = overrides?.user ?? config?.user\n const network = overrides?.network ?? config?.network\n if (network) {\n hostConfig.NetworkMode = network\n }\n\n const labels = { ...config?.labels, ...overrides?.labels }\n\n const container = await docker.createContainer({\n // Suffix with a short random token so a crashed run's leftover container\n // (same prefix) never blocks a fresh one with HTTP 409 name conflict.\n ...(name ? { name: `${name}-${counter}-${Math.random().toString(36).slice(2, 8)}` } : {}),\n Image: image,\n Cmd: ['sleep', 'infinity'],\n WorkingDir: cwd,\n Env: Object.entries(env).map(([k, v]) => `${k}=${v}`),\n HostConfig: hostConfig,\n ...(Object.keys(exposedPorts).length ? { ExposedPorts: exposedPorts } : {}),\n ...(user ? { User: user } : {}),\n ...(Object.keys(labels).length ? { Labels: labels } : {}),\n })\n\n try {\n await container.start()\n }\n catch (err) {\n // The container was created but never started — remove it so a\n // failed spawn doesn't leak a stopped container on the daemon.\n await container.remove({ force: true }).catch(() => {})\n throw err\n }\n\n const handle: ExecutionHandle = { id, type: 'docker', cwd }\n containers.set(id, { handle, container, docker })\n\n return handle\n },\n\n async exec(handle: ExecutionHandle, command: string, options?: { cwd?: string, env?: Record<string, string>, timeout?: number }): Promise<ExecResult> {\n const ref = containers.get(handle.id)\n if (!ref)\n throw new Error(`Container ${handle.id} not found`)\n\n const execCwd = options?.cwd ?? handle.cwd\n const env = options?.env\n ? Object.entries(options.env).map(([k, v]) => `${k}=${v}`)\n : []\n\n const timeout = options?.timeout ?? defaultLimits?.timeout ?? 30\n\n const exec = await ref.container.exec({\n // Wrap with coreutils `timeout` so a runaway command is killed\n // server-side too — the host-side timer below only detaches the\n // stream; without this the process would keep running in the\n // container until destroy(). Exec-array form avoids re-quoting the\n // command. `timeout` exits 124 on expiry, matching the host\n // sentinel. (Default image oven/bun is Debian-based → coreutils.)\n Cmd: ['timeout', String(timeout), 'sh', '-c', command],\n WorkingDir: execCwd,\n Env: env,\n AttachStdout: true,\n AttachStderr: true,\n })\n\n const stream = await exec.start({ Detach: false })\n\n return new Promise<ExecResult>((resolve) => {\n let stdout = ''\n let stderr = ''\n let resolved = false\n\n // Docker's exec stream is a multiplexed protocol — a single byte\n // stream that interleaves stdout/stderr frames. `demuxStream`\n // splits the two onto separate writable sinks. Without it, every\n // byte landed on `stdout` and `stderr` was permanently empty.\n const stdoutSink = {\n write(chunk: Buffer | string) {\n stdout += typeof chunk === 'string' ? chunk : chunk.toString('utf-8')\n return true\n },\n end() {},\n on() {},\n once() {},\n emit() { return true },\n }\n const stderrSink = {\n write(chunk: Buffer | string) {\n stderr += typeof chunk === 'string' ? chunk : chunk.toString('utf-8')\n return true\n },\n end() {},\n on() {},\n once() {},\n emit() { return true },\n }\n try {\n ref.docker.modem.demuxStream(stream, stdoutSink, stderrSink)\n }\n catch {\n // Older / different transports may not be multiplexed (TTY mode);\n // fall back to a raw stdout reader so we don't lose output entirely.\n stream.on('data', (chunk: Buffer) => {\n stdout += chunk.toString('utf-8')\n })\n }\n\n // Host-side fallback timer. The server-side `timeout` wrapper is\n // the primary kill mechanism; give it a grace second so the\n // stream-end path (which carries the real exit code) usually wins.\n const timer = setTimeout(() => {\n if (resolved)\n return\n resolved = true\n // Best-effort: detach the stream so we stop accumulating bytes.\n // The server-side `timeout` wrapper kills the process itself.\n try { stream.destroy?.() }\n catch { /* swallow */ }\n resolve({ stdout, stderr: stderr ? `${stderr}\\n[timeout]` : '[timeout]', exitCode: 124 })\n }, timeout * 1000 + 1000)\n\n stream.on('end', async () => {\n if (resolved)\n return\n resolved = true\n clearTimeout(timer)\n let exitCode: number\n let inspectNote = ''\n try {\n const inspect = await exec.inspect()\n // `ExitCode: null` means Docker hasn't recorded an exit yet —\n // the outcome is unknown, not success. Use a sentinel so\n // callers don't mistake it for a clean exit.\n if (inspect.ExitCode == null) {\n exitCode = -1\n inspectNote = '[exit code unavailable: exec still marked running by daemon]'\n }\n else {\n exitCode = inspect.ExitCode\n }\n }\n catch (err) {\n exitCode = -1\n inspectNote = `[exit code unavailable: exec inspect failed: ${(err as Error)?.message ?? String(err)}]`\n }\n resolve({\n stdout,\n stderr: inspectNote ? (stderr ? `${stderr}\\n${inspectNote}` : inspectNote) : stderr,\n exitCode,\n })\n })\n\n stream.on('error', (err: Error) => {\n if (resolved)\n return\n resolved = true\n clearTimeout(timer)\n resolve({ stdout, stderr: stderr ? `${stderr}\\n${err.message}` : err.message, exitCode: 1 })\n })\n })\n },\n\n // Paths are model-supplied — single-quote them (`alwaysQuote`) rather\n // than JSON.stringify: `$(…)` and backticks still expand inside the\n // double quotes JSON produces, which was a command-injection vector.\n async readFile(handle: ExecutionHandle, path: string): Promise<string> {\n const result = await ctx.exec(handle, `cat ${alwaysQuote(path)}`)\n if (result.exitCode !== 0)\n throw new Error(`Failed to read file: ${result.stderr}`)\n return result.stdout\n },\n\n async writeFile(handle: ExecutionHandle, path: string, content: string): Promise<void> {\n const escaped = content.replace(SINGLE_QUOTE_RE, String.raw`'\\''`)\n const result = await ctx.exec(handle, `mkdir -p \"$(dirname ${alwaysQuote(path)})\" && printf '%s' '${escaped}' > ${alwaysQuote(path)}`)\n if (result.exitCode !== 0)\n throw new Error(`Failed to write file: ${result.stderr}`)\n },\n\n async listFiles(handle: ExecutionHandle, path: string, options): Promise<ListFilesEntry[]> {\n if (options?.glob)\n return globFilesViaShell(path, command => ctx.exec(handle, command), options?.limit ?? 1000)\n const result = await ctx.exec(handle, `ls -1 ${alwaysQuote(path)}`)\n if (result.exitCode !== 0)\n return []\n return result.stdout.trim().split('\\n').filter(Boolean)\n },\n\n async getMappedPort(handle: ExecutionHandle, containerPort: number): Promise<number | null> {\n const ref = containers.get(handle.id)\n if (!ref)\n return null\n\n const info = await ref.container.inspect()\n const bindings = info?.NetworkSettings?.Ports ?? {}\n\n for (const proto of ['tcp', 'udp']) {\n const list = bindings[`${containerPort}/${proto}`]\n if (Array.isArray(list) && list.length > 0 && list[0]?.HostPort) {\n return Number.parseInt(list[0].HostPort, 10)\n }\n }\n\n return null\n },\n\n async destroy(handle: ExecutionHandle): Promise<void> {\n const ref = containers.get(handle.id)\n if (!ref)\n return\n\n try {\n try {\n await ref.container.stop({ t: 5 })\n }\n catch {\n // 304 (already stopped) / 404 (already gone) are expected here.\n // Any other stop failure must not prevent the remove({force})\n // below — force removal also works on running containers.\n }\n try {\n await ref.container.remove({ force: true })\n }\n catch (err) {\n if (!isGoneOrAlreadyStopped(err))\n throw err\n }\n }\n finally {\n containers.delete(handle.id)\n }\n },\n }\n\n return ctx\n}\n\n/**\n * Format one {@link ContextMount} as a dockerode `HostConfig.Binds` entry.\n * Supports read-only (`:ro`) and SELinux shared-label (`:z`) options; the two\n * are mutually exclusive (a read-only mount can't also be a shared rw mount).\n */\nfunction formatBindMount(mount: NonNullable<SpawnConfig['mounts']>[number]): string {\n if (!mount.source)\n throw new Error('Docker mount source is required')\n if (!mount.target || !mount.target.startsWith('/'))\n throw new Error(`Docker mount target must be an absolute path: ${mount.target}`)\n if (mount.readonly && mount.shared)\n throw new Error(`Docker mount cannot be both readonly and shared: ${mount.target}`)\n const opts = mount.readonly ? ':ro' : mount.shared ? ':z' : ''\n return `${mount.source}:${mount.target}${opts}`\n}\n\n/** Assemble dockerode `HostConfig.Binds` from the context's `mounts`. */\nexport function buildBindSpecs(mounts: NonNullable<SpawnConfig['mounts']>): string[] {\n return mounts.map(formatBindMount)\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { t as SandboxProvider } from "../index-CF15aqlk.js";
2
- import { a as Logger } from "../logger-LQmSBfD_.js";
1
+ import { t as SandboxProvider } from "../sandbox-B-bMq3K6.js";
2
+ import { a as Logger } from "../logger-HOG4EGv6.js";
3
3
 
4
4
  //#region src/contexts/e2b.d.ts
5
5
  interface E2BCommandResult {
@@ -0,0 +1,2 @@
1
+ import { n as createSandboxContext, t as SandboxProvider } from "../sandbox-B-bMq3K6.js";
2
+ export { SandboxProvider, createSandboxContext };
@@ -0,0 +1,55 @@
1
+ import { t as globFilesViaShell } from "../glob-shell-rJMoCIGb.js";
2
+ //#region src/contexts/sandbox.ts
3
+ function createSandboxContext(provider) {
4
+ const sandboxes = /* @__PURE__ */ new Map();
5
+ const destroyed = /* @__PURE__ */ new Set();
6
+ function getSandboxId(handle) {
7
+ if (destroyed.has(handle.id)) throw new Error(`Sandbox ${handle.id} not found`);
8
+ return sandboxes.get(handle.id) ?? handle.id;
9
+ }
10
+ return {
11
+ type: "sandbox",
12
+ capabilities: {
13
+ shell: true,
14
+ filesystem: true,
15
+ glob: true,
16
+ network: true,
17
+ gpu: false
18
+ },
19
+ async spawn(config) {
20
+ const result = await provider.spawn(config ?? {});
21
+ const handle = {
22
+ id: result.id,
23
+ type: "sandbox",
24
+ cwd: result.cwd
25
+ };
26
+ sandboxes.set(handle.id, result.id);
27
+ return handle;
28
+ },
29
+ async exec(handle, command, options) {
30
+ return provider.exec(getSandboxId(handle), command, options);
31
+ },
32
+ async readFile(handle, path) {
33
+ return provider.readFile(getSandboxId(handle), path);
34
+ },
35
+ async writeFile(handle, path, content) {
36
+ return provider.writeFile(getSandboxId(handle), path, content);
37
+ },
38
+ async listFiles(handle, path, options) {
39
+ const sandboxId = getSandboxId(handle);
40
+ if (options?.glob) return globFilesViaShell(path, (command) => provider.exec(sandboxId, command, { cwd: handle.cwd }), options?.limit ?? 1e3);
41
+ return provider.listFiles(sandboxId, path, options);
42
+ },
43
+ async destroy(handle) {
44
+ const id = sandboxes.get(handle.id);
45
+ if (!id) return;
46
+ await provider.destroy(id);
47
+ sandboxes.delete(handle.id);
48
+ destroyed.add(handle.id);
49
+ }
50
+ };
51
+ }
52
+ //#endregion
53
+ export { createSandboxContext };
54
+
55
+ //# sourceMappingURL=sandbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.js","names":[],"sources":["../../src/contexts/sandbox.ts"],"sourcesContent":["/**\n * Remote sandbox execution context.\n *\n * Offloads execution to a remote sandbox API (e.g. Rivet, E2B).\n * Specific providers implement the SandboxProvider interface.\n */\n\nimport type { ContextCapabilities, ExecResult, ExecutionContext, ExecutionHandle, ListFilesOptions, SpawnConfig } from './types'\nimport { globFilesViaShell } from './glob-shell'\n\n// ---------------------------------------------------------------------------\n// Sandbox provider interface\n// ---------------------------------------------------------------------------\n\nexport interface SandboxProvider {\n name: string\n spawn: (config: SpawnConfig) => Promise<{ id: string, cwd: string }>\n exec: (sandboxId: string, command: string, options?: { cwd?: string, env?: Record<string, string>, timeout?: number }) => Promise<ExecResult>\n readFile: (sandboxId: string, path: string) => Promise<string>\n writeFile: (sandboxId: string, path: string, content: string) => Promise<void>\n listFiles: (sandboxId: string, path: string, options?: ListFilesOptions) => Promise<string[]>\n destroy: (sandboxId: string) => Promise<void>\n}\n\n// ---------------------------------------------------------------------------\n// Sandbox execution context\n// ---------------------------------------------------------------------------\n\nexport function createSandboxContext(provider: SandboxProvider): ExecutionContext {\n const sandboxes = new Map<string, string>()\n const destroyed = new Set<string>()\n\n // The handle id IS the sandbox id (set in `spawn` below), so the map is an\n // identity record of sandboxes this context instance spawned. A handle this\n // instance never spawned falls back to `handle.id` — the re-attach path for\n // durable hosts that journal the handle and hand it back via\n // `AgentOptions.handle` on a replay where `spawn` never re-ran. An\n // EXPLICITLY-destroyed handle still throws (a use-after-free guard, distinct\n // from never-spawned).\n function getSandboxId(handle: ExecutionHandle): string {\n if (destroyed.has(handle.id))\n throw new Error(`Sandbox ${handle.id} not found`)\n return sandboxes.get(handle.id) ?? handle.id\n }\n\n return {\n type: 'sandbox',\n\n capabilities: {\n shell: true,\n filesystem: true,\n glob: true,\n network: true,\n gpu: false,\n } satisfies ContextCapabilities,\n\n async spawn(config?: SpawnConfig): Promise<ExecutionHandle> {\n const result = await provider.spawn(config ?? {})\n const handle: ExecutionHandle = { id: result.id, type: 'sandbox', cwd: result.cwd }\n sandboxes.set(handle.id, result.id)\n return handle\n },\n\n async exec(handle: ExecutionHandle, command: string, options?): Promise<ExecResult> {\n return provider.exec(getSandboxId(handle), command, options)\n },\n\n async readFile(handle: ExecutionHandle, path: string): Promise<string> {\n return provider.readFile(getSandboxId(handle), path)\n },\n\n async writeFile(handle: ExecutionHandle, path: string, content: string): Promise<void> {\n return provider.writeFile(getSandboxId(handle), path, content)\n },\n\n async listFiles(handle: ExecutionHandle, path: string, options?: ListFilesOptions): Promise<string[]> {\n const sandboxId = getSandboxId(handle)\n if (options?.glob) {\n return globFilesViaShell(\n path,\n command => provider.exec(sandboxId, command, { cwd: handle.cwd }),\n options?.limit ?? 1000,\n )\n }\n return provider.listFiles(sandboxId, path, options)\n },\n\n async destroy(handle: ExecutionHandle): Promise<void> {\n const id = sandboxes.get(handle.id)\n if (!id)\n return\n await provider.destroy(id)\n sandboxes.delete(handle.id)\n // Mark as torn down so a later op on this exact handle fails loudly\n // (use-after-free) instead of silently re-attaching by id.\n destroyed.add(handle.id)\n },\n }\n}\n"],"mappings":";;AA4BA,SAAgB,qBAAqB,UAA6C;CAChF,MAAM,4BAAY,IAAI,IAAoB;CAC1C,MAAM,4BAAY,IAAI,IAAY;CASlC,SAAS,aAAa,QAAiC;EACrD,IAAI,UAAU,IAAI,OAAO,EAAE,GACzB,MAAM,IAAI,MAAM,WAAW,OAAO,GAAG,WAAW;EAClD,OAAO,UAAU,IAAI,OAAO,EAAE,KAAK,OAAO;CAC5C;CAEA,OAAO;EACL,MAAM;EAEN,cAAc;GACZ,OAAO;GACP,YAAY;GACZ,MAAM;GACN,SAAS;GACT,KAAK;EACP;EAEA,MAAM,MAAM,QAAgD;GAC1D,MAAM,SAAS,MAAM,SAAS,MAAM,UAAU,CAAC,CAAC;GAChD,MAAM,SAA0B;IAAE,IAAI,OAAO;IAAI,MAAM;IAAW,KAAK,OAAO;GAAI;GAClF,UAAU,IAAI,OAAO,IAAI,OAAO,EAAE;GAClC,OAAO;EACT;EAEA,MAAM,KAAK,QAAyB,SAAiB,SAA+B;GAClF,OAAO,SAAS,KAAK,aAAa,MAAM,GAAG,SAAS,OAAO;EAC7D;EAEA,MAAM,SAAS,QAAyB,MAA+B;GACrE,OAAO,SAAS,SAAS,aAAa,MAAM,GAAG,IAAI;EACrD;EAEA,MAAM,UAAU,QAAyB,MAAc,SAAgC;GACrF,OAAO,SAAS,UAAU,aAAa,MAAM,GAAG,MAAM,OAAO;EAC/D;EAEA,MAAM,UAAU,QAAyB,MAAc,SAA+C;GACpG,MAAM,YAAY,aAAa,MAAM;GACrC,IAAI,SAAS,MACX,OAAO,kBACL,OACA,YAAW,SAAS,KAAK,WAAW,SAAS,EAAE,KAAK,OAAO,IAAI,CAAC,GAChE,SAAS,SAAS,GACpB;GAEF,OAAO,SAAS,UAAU,WAAW,MAAM,OAAO;EACpD;EAEA,MAAM,QAAQ,QAAwC;GACpD,MAAM,KAAK,UAAU,IAAI,OAAO,EAAE;GAClC,IAAI,CAAC,IACH;GACF,MAAM,SAAS,QAAQ,EAAE;GACzB,UAAU,OAAO,OAAO,EAAE;GAG1B,UAAU,IAAI,OAAO,EAAE;EACzB;CACF;AACF"}
@@ -1,5 +1,5 @@
1
1
  import { t as lazyAsync } from "./lazy-DLOurOC_.js";
2
- import { n as globFilesViaShell, r as globLiteralPrefix, t as globFilesLocal } from "./glob-DCWXy_tr.js";
2
+ import { n as globLiteralPrefix, t as globFilesLocal } from "./glob-D56-KpBp.js";
3
3
  import { dirname, isAbsolute, relative, resolve } from "node:path";
4
4
  import { createWriteStream } from "node:fs";
5
5
  import { mkdir, readFile, readdir, realpath, stat, writeFile } from "node:fs/promises";
@@ -674,56 +674,6 @@ function stateToTaskExitInfo(state) {
674
674
  };
675
675
  }
676
676
  //#endregion
677
- //#region src/contexts/sandbox.ts
678
- function createSandboxContext(provider) {
679
- const sandboxes = /* @__PURE__ */ new Map();
680
- function getSandboxId(handle) {
681
- const id = sandboxes.get(handle.id);
682
- if (!id) throw new Error(`Sandbox ${handle.id} not found`);
683
- return id;
684
- }
685
- return {
686
- type: "sandbox",
687
- capabilities: {
688
- shell: true,
689
- filesystem: true,
690
- glob: true,
691
- network: true,
692
- gpu: false
693
- },
694
- async spawn(config) {
695
- const result = await provider.spawn(config ?? {});
696
- const handle = {
697
- id: result.id,
698
- type: "sandbox",
699
- cwd: result.cwd
700
- };
701
- sandboxes.set(handle.id, result.id);
702
- return handle;
703
- },
704
- async exec(handle, command, options) {
705
- return provider.exec(getSandboxId(handle), command, options);
706
- },
707
- async readFile(handle, path) {
708
- return provider.readFile(getSandboxId(handle), path);
709
- },
710
- async writeFile(handle, path, content) {
711
- return provider.writeFile(getSandboxId(handle), path, content);
712
- },
713
- async listFiles(handle, path, options) {
714
- const sandboxId = getSandboxId(handle);
715
- if (options?.glob) return globFilesViaShell(path, (command) => provider.exec(sandboxId, command, { cwd: handle.cwd }), options?.limit ?? 1e3);
716
- return provider.listFiles(sandboxId, path, options);
717
- },
718
- async destroy(handle) {
719
- const id = sandboxes.get(handle.id);
720
- if (!id) return;
721
- await provider.destroy(id);
722
- sandboxes.delete(handle.id);
723
- }
724
- };
725
- }
726
- //#endregion
727
677
  //#region src/contexts/types.ts
728
678
  /**
729
679
  * Effective {@link DetachedTasksCapability} of a context, with the
@@ -733,6 +683,6 @@ function resolveDetachedTasksCapability(context) {
733
683
  return context.capabilities.detachedTasks ?? (context.execBackground ? "process-lifetime" : "none");
734
684
  }
735
685
  //#endregion
736
- export { createSandboxContext as n, createProcessContext as r, resolveDetachedTasksCapability as t };
686
+ export { createProcessContext as n, resolveDetachedTasksCapability as t };
737
687
 
738
- //# sourceMappingURL=contexts-DHi8LPCp.js.map
688
+ //# sourceMappingURL=contexts-BebciJyQ.js.map