@elie-laloum/outpost 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/LICENSE +21 -0
  3. package/README.fr.md +251 -0
  4. package/README.md +226 -0
  5. package/ROADMAP.md +34 -0
  6. package/SECURITY.md +15 -0
  7. package/dist/application/campaign.d.ts +33 -0
  8. package/dist/application/campaign.js +195 -0
  9. package/dist/application/campaign.js.map +1 -0
  10. package/dist/application/execution.d.ts +48 -0
  11. package/dist/application/execution.js +322 -0
  12. package/dist/application/execution.js.map +1 -0
  13. package/dist/application/interactive-brief.d.ts +3 -0
  14. package/dist/application/interactive-brief.js +35 -0
  15. package/dist/application/interactive-brief.js.map +1 -0
  16. package/dist/application/outpost.d.ts +91 -0
  17. package/dist/application/outpost.js +629 -0
  18. package/dist/application/outpost.js.map +1 -0
  19. package/dist/application/remote-workspace.d.ts +11 -0
  20. package/dist/application/remote-workspace.js +264 -0
  21. package/dist/application/remote-workspace.js.map +1 -0
  22. package/dist/application/tasks.d.ts +17 -0
  23. package/dist/application/tasks.js +36 -0
  24. package/dist/application/tasks.js.map +1 -0
  25. package/dist/cli/main.d.ts +2 -0
  26. package/dist/cli/main.js +94 -0
  27. package/dist/cli/main.js.map +1 -0
  28. package/dist/cli/scaffold.d.ts +28 -0
  29. package/dist/cli/scaffold.js +169 -0
  30. package/dist/cli/scaffold.js.map +1 -0
  31. package/dist/cli/starters.d.ts +3 -0
  32. package/dist/cli/starters.js +34 -0
  33. package/dist/cli/starters.js.map +1 -0
  34. package/dist/domain/backlog.d.ts +16 -0
  35. package/dist/domain/backlog.js +23 -0
  36. package/dist/domain/backlog.js.map +1 -0
  37. package/dist/domain/errors.d.ts +11 -0
  38. package/dist/domain/errors.js +37 -0
  39. package/dist/domain/errors.js.map +1 -0
  40. package/dist/domain/ports.d.ts +183 -0
  41. package/dist/domain/ports.js +2 -0
  42. package/dist/domain/ports.js.map +1 -0
  43. package/dist/domain/prompts.d.ts +22 -0
  44. package/dist/domain/prompts.js +45 -0
  45. package/dist/domain/prompts.js.map +1 -0
  46. package/dist/domain/response.d.ts +37 -0
  47. package/dist/domain/response.js +50 -0
  48. package/dist/domain/response.js.map +1 -0
  49. package/dist/domain/workflow.d.ts +68 -0
  50. package/dist/domain/workflow.js +246 -0
  51. package/dist/domain/workflow.js.map +1 -0
  52. package/dist/index.d.ts +27 -0
  53. package/dist/index.js +13 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/infrastructure/abort.d.ts +1 -0
  56. package/dist/infrastructure/abort.js +16 -0
  57. package/dist/infrastructure/abort.js.map +1 -0
  58. package/dist/infrastructure/conversations.d.ts +30 -0
  59. package/dist/infrastructure/conversations.js +222 -0
  60. package/dist/infrastructure/conversations.js.map +1 -0
  61. package/dist/infrastructure/files.d.ts +5 -0
  62. package/dist/infrastructure/files.js +85 -0
  63. package/dist/infrastructure/files.js.map +1 -0
  64. package/dist/infrastructure/git.d.ts +14 -0
  65. package/dist/infrastructure/git.js +304 -0
  66. package/dist/infrastructure/git.js.map +1 -0
  67. package/dist/infrastructure/journal.d.ts +10 -0
  68. package/dist/infrastructure/journal.js +53 -0
  69. package/dist/infrastructure/journal.js.map +1 -0
  70. package/dist/infrastructure/process.d.ts +6 -0
  71. package/dist/infrastructure/process.js +133 -0
  72. package/dist/infrastructure/process.js.map +1 -0
  73. package/dist/infrastructure/reporter.d.ts +10 -0
  74. package/dist/infrastructure/reporter.js +47 -0
  75. package/dist/infrastructure/reporter.js.map +1 -0
  76. package/dist/infrastructure/settings.d.ts +3 -0
  77. package/dist/infrastructure/settings.js +41 -0
  78. package/dist/infrastructure/settings.js.map +1 -0
  79. package/dist/infrastructure/shutdown.d.ts +1 -0
  80. package/dist/infrastructure/shutdown.js +67 -0
  81. package/dist/infrastructure/shutdown.js.map +1 -0
  82. package/dist/infrastructure/terminal.d.ts +11 -0
  83. package/dist/infrastructure/terminal.js +19 -0
  84. package/dist/infrastructure/terminal.js.map +1 -0
  85. package/dist/infrastructure/transfer.d.ts +3 -0
  86. package/dist/infrastructure/transfer.js +29 -0
  87. package/dist/infrastructure/transfer.js.map +1 -0
  88. package/dist/providers/agents.d.ts +17 -0
  89. package/dist/providers/agents.js +204 -0
  90. package/dist/providers/agents.js.map +1 -0
  91. package/dist/providers/backlogs.d.ts +9 -0
  92. package/dist/providers/backlogs.js +82 -0
  93. package/dist/providers/backlogs.js.map +1 -0
  94. package/dist/providers/cloud-files.d.ts +4 -0
  95. package/dist/providers/cloud-files.js +66 -0
  96. package/dist/providers/cloud-files.js.map +1 -0
  97. package/dist/providers/container.d.ts +21 -0
  98. package/dist/providers/container.js +310 -0
  99. package/dist/providers/container.js.map +1 -0
  100. package/dist/providers/daytona.d.ts +10 -0
  101. package/dist/providers/daytona.js +153 -0
  102. package/dist/providers/daytona.js.map +1 -0
  103. package/dist/providers/docker.d.ts +3 -0
  104. package/dist/providers/docker.js +3 -0
  105. package/dist/providers/docker.js.map +1 -0
  106. package/dist/providers/factories.d.ts +9 -0
  107. package/dist/providers/factories.js +12 -0
  108. package/dist/providers/factories.js.map +1 -0
  109. package/dist/providers/local.d.ts +4 -0
  110. package/dist/providers/local.js +64 -0
  111. package/dist/providers/local.js.map +1 -0
  112. package/dist/providers/podman.d.ts +3 -0
  113. package/dist/providers/podman.js +3 -0
  114. package/dist/providers/podman.js.map +1 -0
  115. package/dist/providers/vercel.d.ts +9 -0
  116. package/dist/providers/vercel.js +158 -0
  117. package/dist/providers/vercel.js.map +1 -0
  118. package/dist/providers/versions.d.ts +4 -0
  119. package/dist/providers/versions.js +5 -0
  120. package/dist/providers/versions.js.map +1 -0
  121. package/docs/api.md +147 -0
  122. package/docs/architecture.md +21 -0
  123. package/docs/migration-1.1.fr.md +44 -0
  124. package/docs/migration-1.1.md +38 -0
  125. package/docs/operations.md +101 -0
  126. package/docs/providers.md +119 -0
  127. package/docs/workflows.md +101 -0
  128. package/package.json +95 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outpost.js","sourceRoot":"","sources":["../../src/application/outpost.ts"],"names":[],"mappings":"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","sourcesContent":["import { join, posix } from \"node:path\";\nimport { readFile, stat } from \"node:fs/promises\";\nimport { OutpostError, invariant, recordRecovery } from \"../domain/errors.ts\";\nimport type {\n AgentAdapter,\n BranchPolicy,\n Command,\n CommandResult,\n Commit,\n ConversationRecord,\n Disposal,\n LifecycleHooks,\n SandboxLease,\n SandboxProvider,\n StageLimits,\n WorkspaceRecord,\n} from \"../domain/ports.ts\";\nimport type { Brief } from \"../domain/prompts.ts\";\nimport { validateBrief } from \"../domain/prompts.ts\";\nimport {\n acquireWorkspace,\n commits,\n git,\n type WorkspaceLease,\n} from \"../infrastructure/git.ts\";\nimport { nativeConversations } from \"../infrastructure/conversations.ts\";\nimport { resolveVariables } from \"../infrastructure/settings.ts\";\nimport {\n executeProcess,\n quote,\n requireSuccess,\n} from \"../infrastructure/process.ts\";\nimport { journal, type Logging } from \"../infrastructure/journal.ts\";\nimport { registerCleanup } from \"../infrastructure/shutdown.ts\";\nimport { restoreTerminal } from \"../infrastructure/terminal.ts\";\nimport { boundedTransfers } from \"../infrastructure/transfer.ts\";\nimport { docker } from \"../providers/docker.ts\";\nimport { agentVersions } from \"../providers/versions.ts\";\nimport {\n execute,\n notify,\n renderBrief,\n validateDispatch,\n preflightDispatch,\n type DispatchOptions,\n type Execution,\n} from \"./execution.ts\";\nimport { seedRemote, type RemoteSync } from \"./remote-workspace.ts\";\nimport { completeBrief, type VariableQuestion } from \"./interactive-brief.ts\";\n\nexport interface WorkspaceOptions {\n readonly signal?: AbortSignal;\n readonly repository?: string;\n readonly branch?: BranchPolicy;\n readonly copies?: readonly string[];\n readonly limits?: StageLimits;\n readonly label?: string;\n readonly hooks?: LifecycleHooks;\n}\n\nexport interface Workspace extends WorkspaceRecord {\n dispatch<T = undefined>(\n options: Omit<\n SandboxOptions,\n Exclude<keyof WorkspaceOptions, \"hooks\" | \"label\"> | \"workspace\"\n > &\n DispatchOptions<T> & { readonly agent: AgentAdapter },\n ): Promise<DispatchResult<T>>;\n sandbox(\n options?: Omit<\n SandboxOptions,\n Exclude<keyof WorkspaceOptions, \"hooks\" | \"label\"> | \"workspace\"\n >,\n ): Promise<Sandbox>;\n attach(\n options: Omit<\n SandboxOptions,\n Exclude<keyof WorkspaceOptions, \"hooks\" | \"label\"> | \"workspace\"\n > &\n AttachOptions & { readonly agent: AgentAdapter },\n ): Promise<AttachResult>;\n close(options?: { readonly preserve?: boolean }): Promise<Disposal>;\n integrate(): Promise<void>;\n [Symbol.asyncDispose](): Promise<void>;\n}\n\nconst workspaces = new WeakMap<\n Workspace,\n {\n lease: WorkspaceLease;\n active: boolean;\n closed: boolean;\n hooks?: LifecycleHooks;\n }\n>();\n\nconst storageFor = (agent: AgentAdapter) =>\n agent.storage ??\n (agent.conversations ? nativeConversations(agent.conversations) : undefined);\n\nasync function startupFailure(\n workspace: WorkspaceRecord,\n cause: unknown,\n options: { logging?: Logging; label?: string },\n): Promise<void> {\n try {\n const log = await journal(\n workspace.repository,\n options.logging,\n options.label,\n );\n log.record({\n kind: \"phase\",\n name: \"preparation failed\",\n branch: workspace.branch,\n directory: workspace.directory,\n });\n log.record({\n kind: \"failure\",\n message: cause instanceof Error ? cause.message : String(cause),\n });\n await log.close();\n recordRecovery(cause, {\n branch: workspace.branch,\n directory: workspace.directory,\n log: log.file,\n });\n } catch {\n /* Logging must preserve the preparation error. */\n }\n}\n\nexport async function openWorkspace(\n options: WorkspaceOptions = {},\n): Promise<Workspace> {\n options.signal?.throwIfAborted();\n const lease = await acquireWorkspace(options);\n try {\n await hooks(\n options.hooks?.workspaceReady ?? [],\n lease.directory,\n executeProcess,\n options.signal,\n );\n } catch (cause) {\n await startupFailure(lease, cause, options);\n await lease.dispose();\n throw cause;\n }\n const state = {\n lease,\n active: false,\n closed: false,\n ...(options.hooks ? { hooks: options.hooks } : {}),\n };\n const result: Workspace = {\n ...lease,\n dispatch(options) {\n return dispatch({ ...options, workspace: result });\n },\n sandbox(options = {}) {\n return createSandbox({ ...options, workspace: result });\n },\n attach(options) {\n return attach({ ...options, workspace: result });\n },\n async close(settings = {}) {\n invariant(\n !state.active,\n \"Close the sandbox before closing its workspace\",\n );\n state.closed = true;\n return lease.dispose(settings.preserve);\n },\n async [Symbol.asyncDispose]() {\n await result.close();\n },\n };\n workspaces.set(result, state);\n return result;\n}\n\nexport interface SandboxOptions extends WorkspaceOptions {\n readonly includeUncommitted?: boolean;\n readonly agent?: AgentAdapter;\n readonly provider?: SandboxProvider;\n readonly workspace?: Workspace;\n readonly hooks?: LifecycleHooks;\n readonly signal?: AbortSignal;\n readonly logging?: Logging;\n readonly bootstrap?: boolean;\n readonly conversationHome?: string;\n}\n\nexport interface AttachOptions {\n readonly ask?: VariableQuestion;\n readonly agent?: AgentAdapter;\n readonly brief?: Brief;\n readonly continuation?: { readonly id: string; readonly fork?: boolean };\n readonly signal?: AbortSignal;\n readonly terminal?: Command[\"terminal\"];\n}\n\nexport interface AttachResult extends CommandResult, Disposal {\n readonly commits: readonly Commit[];\n readonly branch: string;\n readonly directory: string;\n}\n\nexport interface DispatchResult<T> extends Execution<T> {\n readonly branch: string;\n readonly directory: string;\n readonly commits: readonly Commit[];\n readonly transcript?: string;\n readonly log?: string;\n readonly retainedDirectory?: string;\n resume<U = undefined>(\n options: ContinuationOptions<U>,\n ): Promise<DispatchResult<U>>;\n fork<U = undefined>(\n options: ContinuationOptions<U>,\n ): Promise<DispatchResult<U>>;\n}\n\nexport type ContinuationOptions<T = undefined> = DispatchOptions<T> &\n Omit<SandboxOptions, \"agent\">;\n\nfunction continuationConfiguration<T extends SandboxOptions>(\n configuration: T,\n next: SandboxOptions,\n): T {\n if (next.repository || next.branch || next.copies) {\n const { workspace, ...rest } = configuration;\n return {\n ...(workspace ? { repository: workspace.repository } : {}),\n ...rest,\n } as T;\n }\n return configuration;\n}\n\nexport interface WarmDispatchResult<T> extends Omit<\n DispatchResult<T>,\n \"resume\" | \"fork\"\n> {\n resume<U = undefined>(\n options: DispatchOptions<U>,\n ): Promise<WarmDispatchResult<U>>;\n fork<U = undefined>(\n options: DispatchOptions<U>,\n ): Promise<WarmDispatchResult<U>>;\n}\n\nfunction warmContinuation(options: object): void {\n invariant(\n ![\n \"repository\",\n \"branch\",\n \"provider\",\n \"workspace\",\n \"copies\",\n \"hooks\",\n \"limits\",\n \"bootstrap\",\n \"conversationHome\",\n \"includeUncommitted\",\n ].some((key) => key in options),\n \"Warm continuation uses its existing sandbox; use dispatch() to change sandbox settings\",\n );\n}\n\nexport interface Sandbox {\n readonly workspace: Workspace;\n readonly root: string;\n dispatch<T = undefined>(\n options: DispatchOptions<T>,\n ): Promise<WarmDispatchResult<T>>;\n resume<T = undefined>(\n id: string,\n options: DispatchOptions<T>,\n ): Promise<WarmDispatchResult<T>>;\n fork<T = undefined>(\n id: string,\n options: DispatchOptions<T>,\n ): Promise<WarmDispatchResult<T>>;\n attach(options?: AttachOptions): Promise<AttachResult>;\n command(command: Command): Promise<CommandResult>;\n close(options?: { readonly preserve?: boolean }): Promise<Disposal>;\n [Symbol.asyncDispose](): Promise<void>;\n}\n\nasync function hooks(\n commands: readonly Command[],\n directory: string,\n invoke: SandboxLease[\"invoke\"],\n signal?: AbortSignal,\n parallel = false,\n): Promise<void> {\n if (parallel) {\n const controller = new AbortController();\n const combined = signal\n ? AbortSignal.any([signal, controller.signal])\n : controller.signal;\n const outcomes = await Promise.allSettled(\n commands.map((command) =>\n hooks([command], directory, invoke, combined).catch((cause) => {\n controller.abort(cause);\n throw cause;\n }),\n ),\n );\n const failure = outcomes.find((outcome) => outcome.status === \"rejected\");\n if (failure?.status === \"rejected\") throw failure.reason;\n return;\n }\n for (const command of commands)\n await requireSuccess(\n {\n ...command,\n directory: command.directory ?? directory,\n deadlineMs: command.deadlineMs ?? 600_000,\n ...(signal ? { signal } : {}),\n },\n invoke,\n );\n}\n\nasync function prepareAdapter(\n agent: AgentAdapter,\n runtime: SandboxLease,\n signal: AbortSignal,\n): Promise<AgentAdapter> {\n if (!agent.conversations) return agent;\n const executable = agent.conversations;\n const cli =\n executable === \"claude\"\n ? `@anthropic-ai/claude-code@${agentVersions.claude}`\n : `@openai/codex@${agentVersions.codex}`;\n const prefix = posix.join(runtime.home, \".outpost-tools\"),\n target = posix.join(prefix, \"bin\", executable);\n const installed = await requireSuccess(\n {\n executable: \"sh\",\n arguments: [\n \"-c\",\n `if command -v ${executable} >/dev/null 2>&1; then command -v ${executable}; elif test -x ${quote(target)}; then printf '%s\\\\n' ${quote(target)}; else npm install --global --allow-scripts=@anthropic-ai/claude-code --prefix ${quote(prefix)} ${cli} >&2 && printf '%s\\\\n' ${quote(target)}; fi`,\n ],\n signal,\n },\n runtime.invoke.bind(runtime),\n );\n const binary = installed.stdout.trim();\n invariant(\n binary.startsWith(\"/\") && !binary.includes(\"\\n\"),\n \"Agent bootstrap returned an invalid executable path\",\n );\n return {\n ...agent,\n request(input) {\n return { ...agent.request(input), executable: binary };\n },\n };\n}\n\nexport async function createSandbox(\n options: SandboxOptions = {},\n): Promise<Sandbox> {\n options.signal?.throwIfAborted();\n const provider = options.provider ?? docker();\n if (provider.placement === \"remote\" && !options.workspace && !options.branch)\n options = { ...options, branch: { mode: \"integrate\" } };\n invariant(\n !options.workspace ||\n (!options.repository && !options.branch && !options.copies),\n \"A supplied workspace owns its repository, branch and copied inputs\",\n );\n const owned = !options.workspace;\n invariant(\n provider.placement !== \"remote\" ||\n ((options.workspace?.policy ?? options.branch)?.mode !== \"current\" &&\n (options.workspace || options.branch)),\n \"Remote providers require a named or integration workspace\",\n );\n const workspace = options.workspace ?? (await openWorkspace(options));\n const state = workspaces.get(workspace);\n invariant(\n state && !state.closed && !state.active,\n \"Workspace must be open and cannot belong to another sandbox\",\n );\n state.active = true;\n const lifecycle = options.hooks ?? state.hooks;\n const stop = new AbortController();\n const setupSignal = options.signal\n ? AbortSignal.any([options.signal, stop.signal])\n : stop.signal;\n let lease: SandboxLease | undefined, sync: RemoteSync | undefined;\n const prepared = new Map<AgentAdapter, AgentAdapter>();\n const staging = join(\n workspace.repository,\n \".outpost\",\n \"recovery\",\n \"conversations\",\n );\n try {\n const configured = await resolveVariables(\n workspace.repository,\n {},\n provider.variables,\n );\n const name = (\n await git(workspace.repository, [\"config\", \"--get\", \"user.name\"]).catch(\n () => \"Outpost\",\n )\n ).trim();\n const email = (\n await git(workspace.repository, [\"config\", \"--get\", \"user.email\"]).catch(\n () => \"outpost@localhost\",\n )\n ).trim();\n const variables = {\n GIT_AUTHOR_NAME: name,\n GIT_COMMITTER_NAME: name,\n GIT_AUTHOR_EMAIL: email,\n GIT_COMMITTER_EMAIL: email,\n ...configured,\n };\n lease = boundedTransfers(\n await provider.acquire({\n repository: workspace.repository,\n directory: workspace.directory,\n gitDirectories: workspace.gitDirectories,\n variables,\n signal: setupSignal,\n }),\n {\n ...(options.limits?.copyMs\n ? { deadlineMs: options.limits.copyMs }\n : {}),\n },\n );\n if (provider.placement === \"remote\") {\n sync = await seedRemote(workspace, lease, {\n ...(options.includeUncommitted ? { includeUncommitted: true } : {}),\n ...(options.limits ? { limits: options.limits } : {}),\n signal: setupSignal,\n });\n for (const path of options.copies ?? [])\n if (\n await stat(join(workspace.directory, path)).catch((error) => {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\")\n return undefined;\n throw error;\n })\n )\n await lease.upload(\n join(workspace.directory, path),\n posix.join(lease.root, path.replaceAll(\"\\\\\", \"/\")),\n );\n if (options.bootstrap !== false && options.agent)\n prepared.set(\n options.agent,\n await prepareAdapter(options.agent, lease, setupSignal),\n );\n }\n const initialized = await Promise.allSettled(\n [\n hooks(\n lifecycle?.hostReady ?? [],\n workspace.directory,\n executeProcess,\n setupSignal,\n ),\n hooks(\n lifecycle?.sandboxReady ?? [],\n lease.root,\n lease.invoke.bind(lease),\n setupSignal,\n true,\n ),\n ].map((pending) =>\n pending.catch((cause) => {\n stop.abort(cause);\n throw cause;\n }),\n ),\n );\n const failure = initialized.find((item) => item.status === \"rejected\");\n if (failure?.status === \"rejected\") throw failure.reason;\n } catch (cause) {\n await startupFailure(workspace, cause, options);\n await lease?.release().catch(() => undefined);\n state.active = false;\n if (owned) await workspace.close();\n throw cause;\n }\n const runtime = lease;\n let busy: Promise<unknown> | undefined,\n closing: Promise<Disposal> | undefined,\n closed = false;\n const known = new Set<string>();\n const exclusive = <T>(action: () => Promise<T>): Promise<T> => {\n invariant(!closed && !closing, \"Sandbox is closed\");\n invariant(\n !busy,\n \"Sandbox already has an active operation; use another sandbox for parallel work\",\n );\n const pending = Promise.resolve().then(action);\n busy = pending;\n void pending.then(\n () => {\n busy = undefined;\n },\n () => {\n busy = undefined;\n },\n );\n return pending;\n };\n const selectAgent = async (\n selected: AgentAdapter | undefined,\n signal: AbortSignal,\n ) => {\n invariant(selected, \"Provide an agent on the sandbox or this operation\");\n if (!prepared.has(selected))\n prepared.set(\n selected,\n provider.placement === \"remote\" && options.bootstrap !== false\n ? await prepareAdapter(selected, runtime, signal)\n : selected,\n );\n const variables = await resolveVariables(\n workspace.repository,\n selected.variables,\n provider.variables,\n );\n const adapter = prepared.get(selected)!;\n return {\n selected,\n adapter,\n executionLease: {\n ...runtime,\n invoke(command: Command) {\n return runtime.invoke({\n ...command,\n variables: { ...variables, ...command.variables },\n });\n },\n },\n };\n };\n const conversationKey = (agent: AgentAdapter, id: string) =>\n `${agent.storage?.name ?? agent.conversations ?? agent.name}:${id}`;\n const restore = async (id: string, agent: AgentAdapter) => {\n if (known.has(conversationKey(agent, id))) return;\n const storage = storageFor(agent);\n invariant(storage, \"This adapter does not support native conversations\");\n const found = await storage.locate(\n id,\n workspace.repository,\n options.conversationHome,\n );\n if (\n provider.placement !== \"host\" ||\n workspace.directory !== workspace.repository\n )\n await storage.restore(found, {\n repository: workspace.repository,\n sandbox: runtime,\n staging,\n });\n known.add(conversationKey(agent, id));\n };\n const result: Sandbox = {\n workspace,\n root: runtime.root,\n dispatch<T>(dispatch: DispatchOptions<T>) {\n validateDispatch(dispatch);\n return exclusive(async () => {\n await preflightDispatch(\n dispatch,\n workspace.repository,\n dispatch.agent ?? options.agent,\n );\n const signal = dispatch.signal\n ? AbortSignal.any([dispatch.signal, stop.signal])\n : stop.signal;\n const { selected, adapter, executionLease } = await selectAgent(\n dispatch.agent ?? options.agent,\n signal,\n );\n if (dispatch.continuation)\n await restore(dispatch.continuation.id, selected);\n const baseline = (\n await git(workspace.directory, [\"rev-parse\", \"HEAD\"])\n ).trim();\n const log = await journal(\n workspace.repository,\n dispatch.logging ?? options.logging,\n dispatch.label,\n );\n let execution: Execution<T> | undefined,\n transcript: ConversationRecord | undefined;\n const captured = new Map<string, ConversationRecord>();\n const storage = storageFor(selected);\n let failure: unknown;\n let conversation = dispatch.continuation?.id;\n const conversations = new Set<string>(\n conversation ? [conversation] : [],\n );\n const save = async (id: string) => {\n invariant(storage, \"Conversation storage is unavailable\");\n const location = await storage.capture(id, {\n repository: workspace.repository,\n sandbox: runtime,\n staging,\n ...(options.conversationHome\n ? { home: options.conversationHome }\n : {}),\n ...(dispatch.warn ? { warn: dispatch.warn } : {}),\n local: provider.placement === \"host\",\n });\n captured.set(id, location);\n transcript = location;\n return location;\n };\n try {\n execution = await execute(\n workspace,\n executionLease,\n adapter,\n provider.placement === \"host\",\n {\n ...dispatch,\n signal,\n observe(event) {\n if (event.kind === \"conversation\") {\n conversation = event.id;\n conversations.add(event.id);\n known.add(conversationKey(selected, event.id));\n }\n log.record(event);\n notify(dispatch.observe, event);\n },\n },\n async (turn) => {\n if (!turn.conversation || !storage || selected.capture === false)\n return turn;\n const location = await save(turn.conversation);\n const usage = selected.transcriptUsage?.(\n await readFile(location.file, \"utf8\"),\n );\n return {\n ...turn,\n transcript: location.file,\n ...(usage ? { usage } : {}),\n };\n },\n );\n } catch (cause) {\n failure = cause;\n log.record({\n kind: \"failure\",\n message: cause instanceof Error ? cause.message : String(cause),\n });\n }\n try {\n await sync?.pull();\n if (storage && selected.capture !== false)\n for (const id of conversations)\n if (failure || !captured.has(id)) await save(id);\n } catch (cause) {\n failure = failure\n ? new AggregateError(\n [failure, cause],\n \"Execution and recovery both failed\",\n )\n : cause;\n }\n try {\n await log.close();\n } catch (cause) {\n failure ??= cause;\n }\n const changes = await commits(\n workspace.directory,\n baseline,\n options.limits?.collectMs,\n );\n if (failure) {\n recordRecovery(failure, {\n branch: workspace.branch,\n directory: workspace.directory,\n commits: changes,\n transcript: transcript?.file,\n log: log.file,\n });\n throw failure;\n }\n invariant(execution, \"Execution did not produce a result\");\n return {\n ...execution,\n branch: workspace.branch,\n directory: workspace.directory,\n commits: changes,\n ...(transcript ? { transcript: transcript.file } : {}),\n ...(log.file ? { log: log.file } : {}),\n resume<U>(next: DispatchOptions<U>) {\n warmContinuation(next);\n invariant(conversation, \"No conversation was emitted\");\n return result.resume(conversation, { agent: selected, ...next });\n },\n fork<U>(next: DispatchOptions<U>) {\n warmContinuation(next);\n invariant(conversation, \"No conversation was emitted\");\n return result.fork(conversation, { agent: selected, ...next });\n },\n };\n });\n },\n resume(id, dispatch) {\n return result.dispatch({ ...dispatch, continuation: { id } });\n },\n fork(id, dispatch) {\n return result.dispatch({ ...dispatch, continuation: { id, fork: true } });\n },\n attach(settings = {}) {\n settings.signal?.throwIfAborted();\n validateBrief(settings.brief, true);\n return exclusive(async () => {\n const signal = settings.signal\n ? AbortSignal.any([settings.signal, stop.signal])\n : stop.signal;\n const { selected, adapter, executionLease } = await selectAgent(\n settings.agent ?? options.agent,\n signal,\n );\n if (settings.continuation)\n await restore(settings.continuation.id, selected);\n const brief = await completeBrief(settings.brief, signal, settings.ask);\n const text = brief\n ? await renderBrief(\n brief,\n workspace,\n executionLease,\n provider.placement === \"host\",\n settings,\n )\n : undefined;\n const command = adapter.request({\n interactive: true,\n ...(text === undefined ? {} : { text }),\n ...(settings.continuation\n ? { continuation: settings.continuation }\n : {}),\n });\n const baseline = (\n await git(workspace.directory, [\"rev-parse\", \"HEAD\"])\n ).trim();\n let output: CommandResult;\n try {\n output = await executionLease.invoke({\n ...command,\n ...(settings.terminal ? { terminal: settings.terminal } : {}),\n deadlineMs: 86_400_000,\n signal: settings.signal\n ? AbortSignal.any([settings.signal, stop.signal])\n : stop.signal,\n });\n } finally {\n restoreTerminal();\n await sync?.pull();\n }\n return {\n ...output,\n branch: workspace.branch,\n directory: workspace.directory,\n commits: await commits(\n workspace.directory,\n baseline,\n options.limits?.collectMs,\n ),\n };\n });\n },\n command(command) {\n command.signal?.throwIfAborted();\n return exclusive(async () => {\n try {\n return await runtime.invoke({\n ...command,\n signal: command.signal\n ? AbortSignal.any([command.signal, stop.signal])\n : stop.signal,\n });\n } finally {\n await sync?.pull();\n }\n });\n },\n close(settings = {}) {\n if (closing) return closing;\n closing = (async () => {\n stop.abort(new OutpostError(\"aborted\", \"Sandbox closed\"));\n await busy?.catch(() => undefined);\n let failure: unknown;\n try {\n await runtime.release();\n await sync?.close();\n } catch (cause) {\n failure = cause;\n }\n state.active = false;\n closed = true;\n unregister();\n const disposal = owned\n ? await workspace.close({ preserve: settings.preserve || !!failure })\n : {};\n if (failure) throw failure;\n return disposal;\n })();\n return closing;\n },\n async [Symbol.asyncDispose]() {\n await result.close();\n },\n };\n const unregister = registerCleanup(() => result.close({ preserve: true }));\n return result;\n}\n\nexport async function dispatch<T = undefined>(\n options: SandboxOptions &\n DispatchOptions<T> & { readonly agent: AgentAdapter },\n): Promise<DispatchResult<T>> {\n options.signal?.throwIfAborted();\n await preflightDispatch(\n options,\n options.workspace?.repository ?? options.repository ?? process.cwd(),\n options.agent,\n );\n if ((options.passes ?? 1) > 1) {\n const outputs: DispatchResult<T>[] = [];\n for (let index = 0; index < options.passes!; index++) {\n options.signal?.throwIfAborted();\n const output = await dispatch({\n ...options,\n passes: 1,\n observe: (event) =>\n notify(options.observe, { ...event, pass: index + 1 }),\n });\n outputs.push(output);\n if (output.completed) break;\n }\n const last = outputs.at(-1)!;\n return {\n ...last,\n text: outputs.map((output) => output.text).join(\"\\n\"),\n turns: outputs.flatMap((output) => output.turns),\n commits: outputs.flatMap((output) => output.commits),\n usage: outputs.reduce(\n (sum, output) => ({\n input: sum.input + output.usage.input,\n cached: sum.cached + output.usage.cached,\n output: sum.output + output.usage.output,\n ...(sum.cacheCreated !== undefined ||\n output.usage.cacheCreated !== undefined\n ? {\n cacheCreated:\n (sum.cacheCreated ?? 0) + (output.usage.cacheCreated ?? 0),\n }\n : {}),\n }),\n {\n input: 0,\n cached: 0,\n output: 0,\n } as import(\"../domain/ports.ts\").Usage,\n ),\n };\n }\n if (options.continuation) {\n const storage = storageFor(options.agent);\n invariant(storage, \"This adapter does not support native conversations\");\n await storage.locate(\n options.continuation.id,\n options.workspace?.repository ?? options.repository ?? process.cwd(),\n options.conversationHome,\n );\n }\n const sandbox = await createSandbox(options);\n const {\n brief: _brief,\n response: _response,\n continuation: _continuation,\n passes: _passes,\n ...configuration\n } = options;\n let successful = false;\n try {\n const output = await sandbox.dispatch(options);\n await sandbox.workspace.integrate();\n successful = true;\n const disposed = await sandbox.close();\n const continuation = output.conversation;\n return {\n ...output,\n ...disposed,\n resume<U>(next: ContinuationOptions<U>) {\n invariant(continuation, \"No conversation was emitted\");\n return dispatch({\n ...continuationConfiguration(configuration, next),\n ...next,\n continuation: { id: continuation },\n });\n },\n fork<U>(next: ContinuationOptions<U>) {\n invariant(continuation, \"No conversation was emitted\");\n return dispatch({\n ...continuationConfiguration(configuration, next),\n ...next,\n continuation: { id: continuation, fork: true },\n });\n },\n };\n } catch (cause) {\n recordRecovery(cause, {\n branch: sandbox.workspace.branch,\n directory: sandbox.workspace.directory,\n });\n throw cause;\n } finally {\n if (!successful) await sandbox.close({ preserve: true });\n }\n}\n\nexport async function attach(\n options: SandboxOptions & AttachOptions & { readonly agent: AgentAdapter },\n): Promise<AttachResult> {\n options.signal?.throwIfAborted();\n validateBrief(options.brief, true);\n const brief = await completeBrief(options.brief, options.signal, options.ask);\n if (brief) options = { ...options, brief };\n if (options.continuation) {\n const storage = storageFor(options.agent);\n invariant(storage, \"This adapter does not support native conversations\");\n await storage.locate(\n options.continuation.id,\n options.workspace?.repository ?? options.repository ?? process.cwd(),\n options.conversationHome,\n );\n }\n const sandbox = await createSandbox(options);\n let successful = false;\n try {\n const baseline = (\n await git(sandbox.workspace.directory, [\"rev-parse\", \"HEAD\"])\n ).trim();\n const result = await sandbox.attach(options);\n const changes = await commits(\n sandbox.workspace.directory,\n baseline,\n options.limits?.collectMs,\n );\n if (result.status === 0) await sandbox.workspace.integrate();\n const disposal = await sandbox.close({ preserve: result.status !== 0 });\n successful = true;\n return {\n ...result,\n ...disposal,\n branch: sandbox.workspace.branch,\n directory: sandbox.workspace.directory,\n commits: changes,\n };\n } finally {\n if (!successful) await sandbox.close({ preserve: true });\n }\n}\n"]}
@@ -0,0 +1,11 @@
1
+ import type { SandboxLease, StageLimits, WorkspaceRecord } from "../domain/ports.ts";
2
+ export interface RemoteSync {
3
+ pull(): Promise<void>;
4
+ close(): Promise<void>;
5
+ }
6
+ export interface RemoteSyncOptions {
7
+ readonly includeUncommitted?: boolean;
8
+ readonly signal?: AbortSignal;
9
+ readonly limits?: StageLimits;
10
+ }
11
+ export declare function seedRemote(workspace: WorkspaceRecord, lease: SandboxLease, options?: RemoteSyncOptions): Promise<RemoteSync>;
@@ -0,0 +1,264 @@
1
+ import { cp, lstat, mkdir, readFile, readlink, rm, writeFile, } from "node:fs/promises";
2
+ import { dirname, join, posix } from "node:path";
3
+ import { createHash, randomUUID } from "node:crypto";
4
+ import { OutpostError } from "../domain/errors.js";
5
+ import { git } from "../infrastructure/git.js";
6
+ import { safeDestination } from "../infrastructure/files.js";
7
+ async function extras(directory) {
8
+ return (await git(directory, ["ls-files", "--others", "--exclude-standard", "-z"]))
9
+ .split("\0")
10
+ .filter((file) => file && !file.startsWith(".outpost/"));
11
+ }
12
+ async function digest(directory, recovery) {
13
+ const hash = createHash("sha256");
14
+ hash.update(await git(directory, ["rev-parse", "HEAD"]));
15
+ const patch = join(recovery, "fingerprint.patch");
16
+ await git(directory, ["diff", "--binary", "HEAD", `--output=${patch}`]);
17
+ hash.update(await readFile(patch));
18
+ hash.update(await git(directory, ["diff", "--cached", "--binary"]));
19
+ for (const file of await extras(directory)) {
20
+ const path = await safeDestination(directory, file), info = await lstat(path);
21
+ hash.update(file).update(String(info.mode));
22
+ hash.update(info.isSymbolicLink() ? await readlink(path) : await readFile(path));
23
+ }
24
+ return hash.digest("hex");
25
+ }
26
+ export async function seedRemote(workspace, lease, options = {}) {
27
+ options.signal?.throwIfAborted();
28
+ const recovery = join(workspace.repository, ".outpost", "recovery", randomUUID());
29
+ await mkdir(recovery, { recursive: true });
30
+ const bundle = join(recovery, "initial.bundle");
31
+ await git(workspace.directory, ["bundle", "create", bundle, "--all", "HEAD"]);
32
+ const remoteBundle = posix.join(lease.root.replaceAll("\\", "/"), "..", `outpost-${randomUUID()}.bundle`);
33
+ await lease.upload(bundle, remoteBundle);
34
+ let initializing = true, failed = false;
35
+ const run = async (args) => {
36
+ let result;
37
+ for (let attempt = 0; attempt < 3; attempt++) {
38
+ result = await lease.invoke({
39
+ executable: "git",
40
+ arguments: args,
41
+ directory: lease.root,
42
+ retain: 16_777_216,
43
+ ...(initializing && options.signal ? { signal: options.signal } : {}),
44
+ ...(options.limits?.gitMs ? { deadlineMs: options.limits.gitMs } : {}),
45
+ });
46
+ if (!initializing || result.status !== 126)
47
+ break;
48
+ }
49
+ if (!result)
50
+ throw new OutpostError("workspace", "Remote Git did not start");
51
+ if (result.status !== 0)
52
+ throw new OutpostError("workspace", "Remote Git operation failed", {
53
+ ...result,
54
+ recovery,
55
+ });
56
+ return result.stdout;
57
+ };
58
+ await run(["init"]);
59
+ await run(["config", "core.autocrlf", "false"]);
60
+ await run(["fetch", remoteBundle, "HEAD"]);
61
+ await run(["checkout", "-B", workspace.branch, "FETCH_HEAD"]);
62
+ for (const key of ["user.name", "user.email"]) {
63
+ const fallback = key === "user.name" ? "Outpost" : "outpost@localhost";
64
+ const value = (await git(workspace.repository, ["config", "--get", key]).catch(() => fallback)).trim() || fallback;
65
+ await run(["config", key, value]);
66
+ }
67
+ const initialPatch = join(recovery, "initial.patch");
68
+ await git(workspace.directory, [
69
+ "diff",
70
+ "--binary",
71
+ "HEAD",
72
+ `--output=${initialPatch}`,
73
+ ]);
74
+ const initialIndex = join(recovery, "initial-index.patch");
75
+ await git(workspace.directory, [
76
+ "diff",
77
+ "--cached",
78
+ "--binary",
79
+ `--output=${initialIndex}`,
80
+ ]);
81
+ const protectedFiles = options.includeUncommitted
82
+ ? []
83
+ : [
84
+ ...(await git(workspace.directory, ["diff", "--name-only", "-z", "HEAD"]))
85
+ .split("\0")
86
+ .filter(Boolean),
87
+ ...(await extras(workspace.directory)),
88
+ ];
89
+ const originalHead = (await git(workspace.directory, ["rev-parse", "HEAD"])).trim();
90
+ if (options.includeUncommitted && (await readFile(initialPatch)).length) {
91
+ await lease.upload(initialPatch, `${remoteBundle}.patch`);
92
+ await run(["apply", "--binary", `${remoteBundle}.patch`]);
93
+ }
94
+ for (const file of options.includeUncommitted
95
+ ? await extras(workspace.directory)
96
+ : [])
97
+ await lease.upload(await safeDestination(workspace.directory, file), posix.join(lease.root, file));
98
+ let synchronized = (await run(["rev-parse", "HEAD"])).trim();
99
+ initializing = false;
100
+ let expected = await digest(workspace.directory, recovery);
101
+ return {
102
+ async close() {
103
+ if (!failed)
104
+ await rm(recovery, { recursive: true, force: true });
105
+ },
106
+ async pull() {
107
+ const transfer = join(recovery, randomUUID());
108
+ await mkdir(transfer, { recursive: true });
109
+ try {
110
+ const head = (await run(["rev-parse", "HEAD"])).trim(), patch = join(transfer, "remote.patch");
111
+ await run([
112
+ "diff",
113
+ "--binary",
114
+ "HEAD",
115
+ `--output=${remoteBundle}.patch`,
116
+ ]);
117
+ await lease.download(`${remoteBundle}.patch`, patch);
118
+ const incoming = (await run(["ls-files", "--others", "--exclude-standard", "-z"]))
119
+ .split("\0")
120
+ .filter(Boolean);
121
+ for (const file of incoming) {
122
+ if (/^\.outpost\/(locks|recovery|workspaces|logs)(\/|$)/i.test(file))
123
+ throw new OutpostError("workspace", "Remote file overlaps Outpost runtime state", { file });
124
+ await safeDestination(workspace.directory, file);
125
+ await lease.download(posix.join(lease.root, file), await safeDestination(join(transfer, "incoming"), file));
126
+ }
127
+ if (head !== synchronized) {
128
+ await run(["bundle", "create", remoteBundle, "HEAD"]);
129
+ await lease.download(remoteBundle, join(transfer, "commits.bundle"));
130
+ }
131
+ if (protectedFiles.length) {
132
+ const changed = new Set([
133
+ ...(await run(["diff", "--name-only", "-z", originalHead]))
134
+ .split("\0")
135
+ .filter(Boolean),
136
+ ...incoming,
137
+ ]);
138
+ const overlaps = protectedFiles.filter((file) => [...changed].some((path) => path === file ||
139
+ path.startsWith(`${file}/`) ||
140
+ file.startsWith(`${path}/`)));
141
+ if (overlaps.length)
142
+ throw new OutpostError("conflict", "Remote changes overlap uncommitted host files", { files: overlaps, recovery: transfer });
143
+ }
144
+ if ((await digest(workspace.directory, recovery)) !== expected)
145
+ throw new OutpostError("conflict", "Host workspace changed while the remote sandbox was active", { recovery });
146
+ if (head !== synchronized) {
147
+ await git(workspace.directory, [
148
+ "fetch",
149
+ join(transfer, "commits.bundle"),
150
+ "HEAD",
151
+ ]);
152
+ await git(workspace.directory, [
153
+ "merge-base",
154
+ "--is-ancestor",
155
+ "HEAD",
156
+ "FETCH_HEAD",
157
+ ]);
158
+ }
159
+ const validation = join(transfer, "validation");
160
+ await git(workspace.directory, [
161
+ "worktree",
162
+ "add",
163
+ "--detach",
164
+ validation,
165
+ head,
166
+ ]);
167
+ try {
168
+ if ((await readFile(patch)).length)
169
+ await git(validation, ["apply", "--binary", patch]);
170
+ if (!options.includeUncommitted &&
171
+ (await readFile(initialPatch)).length)
172
+ await git(validation, ["apply", "--binary", initialPatch]);
173
+ if (!options.includeUncommitted &&
174
+ (await readFile(initialIndex)).length)
175
+ await git(validation, [
176
+ "apply",
177
+ "--cached",
178
+ "--binary",
179
+ initialIndex,
180
+ ]);
181
+ }
182
+ finally {
183
+ await git(workspace.directory, [
184
+ "worktree",
185
+ "remove",
186
+ "--force",
187
+ validation,
188
+ ]);
189
+ }
190
+ const previousPatch = join(transfer, "previous.patch");
191
+ await git(workspace.directory, [
192
+ "diff",
193
+ "--binary",
194
+ "HEAD",
195
+ `--output=${previousPatch}`,
196
+ ]);
197
+ await git(workspace.directory, [
198
+ "diff",
199
+ "--cached",
200
+ "--binary",
201
+ `--output=${join(transfer, "previous-index.patch")}`,
202
+ ]);
203
+ const previousExtras = await extras(workspace.directory);
204
+ for (const file of previousExtras) {
205
+ const backup = await safeDestination(join(transfer, "previous-files"), file);
206
+ await mkdir(dirname(backup), { recursive: true });
207
+ await cp(await safeDestination(workspace.directory, file), backup, {
208
+ dereference: false,
209
+ });
210
+ }
211
+ await writeFile(join(transfer, "state.json"), JSON.stringify({
212
+ previous: synchronized,
213
+ next: head,
214
+ previousExtras,
215
+ incoming,
216
+ }));
217
+ if ((await digest(workspace.directory, recovery)) !== expected)
218
+ throw new OutpostError("conflict", "Host workspace changed during synchronization", { recovery });
219
+ if ((await readFile(previousPatch)).length)
220
+ await git(workspace.directory, [
221
+ "apply",
222
+ "--reverse",
223
+ "--binary",
224
+ previousPatch,
225
+ ]);
226
+ await git(workspace.directory, ["reset", "--mixed", "HEAD"]);
227
+ for (const file of previousExtras.filter((file) => !protectedFiles.includes(file)))
228
+ await rm(await safeDestination(workspace.directory, file), {
229
+ force: true,
230
+ });
231
+ if (head !== synchronized)
232
+ await git(workspace.directory, ["merge", "--ff-only", "FETCH_HEAD"]);
233
+ if ((await readFile(patch)).length)
234
+ await git(workspace.directory, ["apply", "--binary", patch]);
235
+ if (!options.includeUncommitted &&
236
+ (await readFile(initialPatch)).length)
237
+ await git(workspace.directory, ["apply", "--binary", initialPatch]);
238
+ if (!options.includeUncommitted &&
239
+ (await readFile(initialIndex)).length)
240
+ await git(workspace.directory, [
241
+ "apply",
242
+ "--cached",
243
+ "--binary",
244
+ initialIndex,
245
+ ]);
246
+ for (const file of incoming) {
247
+ const target = await safeDestination(workspace.directory, file);
248
+ await mkdir(dirname(target), { recursive: true });
249
+ await cp(join(transfer, "incoming", file), target, {
250
+ dereference: false,
251
+ });
252
+ }
253
+ synchronized = head;
254
+ expected = await digest(workspace.directory, recovery);
255
+ await rm(transfer, { recursive: true, force: true });
256
+ }
257
+ catch (cause) {
258
+ failed = true;
259
+ throw new OutpostError("workspace", "Remote changes could not be fully synchronized; recovery files retained", { recovery: transfer, directory: workspace.directory }, cause);
260
+ }
261
+ },
262
+ };
263
+ }
264
+ //# sourceMappingURL=remote-workspace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-workspace.js","sourceRoot":"","sources":["../../src/application/remote-workspace.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n cp,\n lstat,\n mkdir,\n readFile,\n readlink,\n rm,\n writeFile,\n} from \"node:fs/promises\";\nimport { dirname, join, posix } from \"node:path\";\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { OutpostError } from \"../domain/errors.ts\";\nimport type {\n SandboxLease,\n StageLimits,\n WorkspaceRecord,\n} from \"../domain/ports.ts\";\nimport { git } from \"../infrastructure/git.ts\";\nimport { safeDestination } from \"../infrastructure/files.ts\";\n\nexport interface RemoteSync {\n pull(): Promise<void>;\n close(): Promise<void>;\n}\n\nexport interface RemoteSyncOptions {\n readonly includeUncommitted?: boolean;\n readonly signal?: AbortSignal;\n readonly limits?: StageLimits;\n}\n\nasync function extras(directory: string): Promise<string[]> {\n return (\n await git(directory, [\"ls-files\", \"--others\", \"--exclude-standard\", \"-z\"])\n )\n .split(\"\\0\")\n .filter((file) => file && !file.startsWith(\".outpost/\"));\n}\n\nasync function digest(directory: string, recovery: string): Promise<string> {\n const hash = createHash(\"sha256\");\n hash.update(await git(directory, [\"rev-parse\", \"HEAD\"]));\n const patch = join(recovery, \"fingerprint.patch\");\n await git(directory, [\"diff\", \"--binary\", \"HEAD\", `--output=${patch}`]);\n hash.update(await readFile(patch));\n hash.update(await git(directory, [\"diff\", \"--cached\", \"--binary\"]));\n for (const file of await extras(directory)) {\n const path = await safeDestination(directory, file),\n info = await lstat(path);\n hash.update(file).update(String(info.mode));\n hash.update(\n info.isSymbolicLink() ? await readlink(path) : await readFile(path),\n );\n }\n return hash.digest(\"hex\");\n}\n\nexport async function seedRemote(\n workspace: WorkspaceRecord,\n lease: SandboxLease,\n options: RemoteSyncOptions = {},\n): Promise<RemoteSync> {\n options.signal?.throwIfAborted();\n const recovery = join(\n workspace.repository,\n \".outpost\",\n \"recovery\",\n randomUUID(),\n );\n await mkdir(recovery, { recursive: true });\n const bundle = join(recovery, \"initial.bundle\");\n await git(workspace.directory, [\"bundle\", \"create\", bundle, \"--all\", \"HEAD\"]);\n const remoteBundle = posix.join(\n lease.root.replaceAll(\"\\\\\", \"/\"),\n \"..\",\n `outpost-${randomUUID()}.bundle`,\n );\n await lease.upload(bundle, remoteBundle);\n let initializing = true,\n failed = false;\n const run = async (args: readonly string[]) => {\n let result;\n for (let attempt = 0; attempt < 3; attempt++) {\n result = await lease.invoke({\n executable: \"git\",\n arguments: args,\n directory: lease.root,\n retain: 16_777_216,\n ...(initializing && options.signal ? { signal: options.signal } : {}),\n ...(options.limits?.gitMs ? { deadlineMs: options.limits.gitMs } : {}),\n });\n if (!initializing || result.status !== 126) break;\n }\n if (!result)\n throw new OutpostError(\"workspace\", \"Remote Git did not start\");\n if (result.status !== 0)\n throw new OutpostError(\"workspace\", \"Remote Git operation failed\", {\n ...result,\n recovery,\n });\n return result.stdout;\n };\n await run([\"init\"]);\n await run([\"config\", \"core.autocrlf\", \"false\"]);\n await run([\"fetch\", remoteBundle, \"HEAD\"]);\n await run([\"checkout\", \"-B\", workspace.branch, \"FETCH_HEAD\"]);\n for (const key of [\"user.name\", \"user.email\"] as const) {\n const fallback = key === \"user.name\" ? \"Outpost\" : \"outpost@localhost\";\n const value =\n (\n await git(workspace.repository, [\"config\", \"--get\", key]).catch(\n () => fallback,\n )\n ).trim() || fallback;\n await run([\"config\", key, value]);\n }\n const initialPatch = join(recovery, \"initial.patch\");\n await git(workspace.directory, [\n \"diff\",\n \"--binary\",\n \"HEAD\",\n `--output=${initialPatch}`,\n ]);\n const initialIndex = join(recovery, \"initial-index.patch\");\n await git(workspace.directory, [\n \"diff\",\n \"--cached\",\n \"--binary\",\n `--output=${initialIndex}`,\n ]);\n const protectedFiles = options.includeUncommitted\n ? []\n : [\n ...(\n await git(workspace.directory, [\"diff\", \"--name-only\", \"-z\", \"HEAD\"])\n )\n .split(\"\\0\")\n .filter(Boolean),\n ...(await extras(workspace.directory)),\n ];\n const originalHead = (\n await git(workspace.directory, [\"rev-parse\", \"HEAD\"])\n ).trim();\n if (options.includeUncommitted && (await readFile(initialPatch)).length) {\n await lease.upload(initialPatch, `${remoteBundle}.patch`);\n await run([\"apply\", \"--binary\", `${remoteBundle}.patch`]);\n }\n for (const file of options.includeUncommitted\n ? await extras(workspace.directory)\n : [])\n await lease.upload(\n await safeDestination(workspace.directory, file),\n posix.join(lease.root, file),\n );\n let synchronized = (await run([\"rev-parse\", \"HEAD\"])).trim();\n initializing = false;\n let expected = await digest(workspace.directory, recovery);\n return {\n async close() {\n if (!failed) await rm(recovery, { recursive: true, force: true });\n },\n async pull() {\n const transfer = join(recovery, randomUUID());\n await mkdir(transfer, { recursive: true });\n try {\n const head = (await run([\"rev-parse\", \"HEAD\"])).trim(),\n patch = join(transfer, \"remote.patch\");\n await run([\n \"diff\",\n \"--binary\",\n \"HEAD\",\n `--output=${remoteBundle}.patch`,\n ]);\n await lease.download(`${remoteBundle}.patch`, patch);\n const incoming = (\n await run([\"ls-files\", \"--others\", \"--exclude-standard\", \"-z\"])\n )\n .split(\"\\0\")\n .filter(Boolean);\n for (const file of incoming) {\n if (/^\\.outpost\\/(locks|recovery|workspaces|logs)(\\/|$)/i.test(file))\n throw new OutpostError(\n \"workspace\",\n \"Remote file overlaps Outpost runtime state\",\n { file },\n );\n await safeDestination(workspace.directory, file);\n await lease.download(\n posix.join(lease.root, file),\n await safeDestination(join(transfer, \"incoming\"), file),\n );\n }\n if (head !== synchronized) {\n await run([\"bundle\", \"create\", remoteBundle, \"HEAD\"]);\n await lease.download(remoteBundle, join(transfer, \"commits.bundle\"));\n }\n if (protectedFiles.length) {\n const changed = new Set([\n ...(await run([\"diff\", \"--name-only\", \"-z\", originalHead]))\n .split(\"\\0\")\n .filter(Boolean),\n ...incoming,\n ]);\n const overlaps = protectedFiles.filter((file) =>\n [...changed].some(\n (path) =>\n path === file ||\n path.startsWith(`${file}/`) ||\n file.startsWith(`${path}/`),\n ),\n );\n if (overlaps.length)\n throw new OutpostError(\n \"conflict\",\n \"Remote changes overlap uncommitted host files\",\n { files: overlaps, recovery: transfer },\n );\n }\n if ((await digest(workspace.directory, recovery)) !== expected)\n throw new OutpostError(\n \"conflict\",\n \"Host workspace changed while the remote sandbox was active\",\n { recovery },\n );\n if (head !== synchronized) {\n await git(workspace.directory, [\n \"fetch\",\n join(transfer, \"commits.bundle\"),\n \"HEAD\",\n ]);\n await git(workspace.directory, [\n \"merge-base\",\n \"--is-ancestor\",\n \"HEAD\",\n \"FETCH_HEAD\",\n ]);\n }\n const validation = join(transfer, \"validation\");\n await git(workspace.directory, [\n \"worktree\",\n \"add\",\n \"--detach\",\n validation,\n head,\n ]);\n try {\n if ((await readFile(patch)).length)\n await git(validation, [\"apply\", \"--binary\", patch]);\n if (\n !options.includeUncommitted &&\n (await readFile(initialPatch)).length\n )\n await git(validation, [\"apply\", \"--binary\", initialPatch]);\n if (\n !options.includeUncommitted &&\n (await readFile(initialIndex)).length\n )\n await git(validation, [\n \"apply\",\n \"--cached\",\n \"--binary\",\n initialIndex,\n ]);\n } finally {\n await git(workspace.directory, [\n \"worktree\",\n \"remove\",\n \"--force\",\n validation,\n ]);\n }\n const previousPatch = join(transfer, \"previous.patch\");\n await git(workspace.directory, [\n \"diff\",\n \"--binary\",\n \"HEAD\",\n `--output=${previousPatch}`,\n ]);\n await git(workspace.directory, [\n \"diff\",\n \"--cached\",\n \"--binary\",\n `--output=${join(transfer, \"previous-index.patch\")}`,\n ]);\n const previousExtras = await extras(workspace.directory);\n for (const file of previousExtras) {\n const backup = await safeDestination(\n join(transfer, \"previous-files\"),\n file,\n );\n await mkdir(dirname(backup), { recursive: true });\n await cp(await safeDestination(workspace.directory, file), backup, {\n dereference: false,\n });\n }\n await writeFile(\n join(transfer, \"state.json\"),\n JSON.stringify({\n previous: synchronized,\n next: head,\n previousExtras,\n incoming,\n }),\n );\n if ((await digest(workspace.directory, recovery)) !== expected)\n throw new OutpostError(\n \"conflict\",\n \"Host workspace changed during synchronization\",\n { recovery },\n );\n if ((await readFile(previousPatch)).length)\n await git(workspace.directory, [\n \"apply\",\n \"--reverse\",\n \"--binary\",\n previousPatch,\n ]);\n await git(workspace.directory, [\"reset\", \"--mixed\", \"HEAD\"]);\n for (const file of previousExtras.filter(\n (file) => !protectedFiles.includes(file),\n ))\n await rm(await safeDestination(workspace.directory, file), {\n force: true,\n });\n if (head !== synchronized)\n await git(workspace.directory, [\"merge\", \"--ff-only\", \"FETCH_HEAD\"]);\n if ((await readFile(patch)).length)\n await git(workspace.directory, [\"apply\", \"--binary\", patch]);\n if (\n !options.includeUncommitted &&\n (await readFile(initialPatch)).length\n )\n await git(workspace.directory, [\"apply\", \"--binary\", initialPatch]);\n if (\n !options.includeUncommitted &&\n (await readFile(initialIndex)).length\n )\n await git(workspace.directory, [\n \"apply\",\n \"--cached\",\n \"--binary\",\n initialIndex,\n ]);\n for (const file of incoming) {\n const target = await safeDestination(workspace.directory, file);\n await mkdir(dirname(target), { recursive: true });\n await cp(join(transfer, \"incoming\", file), target, {\n dereference: false,\n });\n }\n synchronized = head;\n expected = await digest(workspace.directory, recovery);\n await rm(transfer, { recursive: true, force: true });\n } catch (cause) {\n failed = true;\n throw new OutpostError(\n \"workspace\",\n \"Remote changes could not be fully synchronized; recovery files retained\",\n { recovery: transfer, directory: workspace.directory },\n cause,\n );\n }\n },\n };\n}\n"]}
@@ -0,0 +1,17 @@
1
+ import { type Task, type TaskContext, type TaskOptions } from "../domain/workflow.ts";
2
+ import type { AgentAdapter, Command, CommandResult } from "../domain/ports.ts";
3
+ import type { DispatchOptions } from "./execution.ts";
4
+ import type { DispatchResult, Sandbox, SandboxOptions } from "./outpost.ts";
5
+ export declare function agentTask<T>(options: Omit<TaskOptions<DispatchResult<T>>, "perform"> & {
6
+ sandbox: Sandbox;
7
+ request: (context: TaskContext) => DispatchOptions<T>;
8
+ }): Task<DispatchResult<T>>;
9
+ export declare function isolatedTask<T>(options: Omit<TaskOptions<DispatchResult<T>>, "perform"> & {
10
+ request: (context: TaskContext) => SandboxOptions & DispatchOptions<T> & {
11
+ readonly agent: AgentAdapter;
12
+ };
13
+ }): Task<DispatchResult<T>>;
14
+ export declare function commandTask(options: Omit<TaskOptions<CommandResult>, "perform"> & {
15
+ sandbox: Sandbox;
16
+ command: Command | ((context: TaskContext) => Command);
17
+ }): Task<CommandResult>;
@@ -0,0 +1,36 @@
1
+ import { task, } from "../domain/workflow.js";
2
+ import { OutpostError } from "../domain/errors.js";
3
+ import { dispatch } from "./outpost.js";
4
+ export function agentTask(options) {
5
+ const { sandbox, request, ...definition } = options;
6
+ return task({
7
+ ...definition,
8
+ perform: (context) => sandbox.dispatch({ ...request(context), signal: context.signal }),
9
+ });
10
+ }
11
+ export function isolatedTask(options) {
12
+ const { request, ...definition } = options;
13
+ return task({
14
+ ...definition,
15
+ perform: (context) => dispatch({ ...request(context), signal: context.signal }),
16
+ });
17
+ }
18
+ export function commandTask(options) {
19
+ const { sandbox, command, ...definition } = options;
20
+ return task({
21
+ ...definition,
22
+ async perform(context) {
23
+ const invocation = typeof command === "function" ? command(context) : command;
24
+ const result = await sandbox.command({
25
+ ...invocation,
26
+ signal: context.signal,
27
+ });
28
+ if (result.status !== 0)
29
+ throw new OutpostError("process", "Workflow command failed", {
30
+ ...result,
31
+ });
32
+ return result;
33
+ },
34
+ });
35
+ }
36
+ //# sourceMappingURL=tasks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/application/tasks.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,GAIL,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,MAAM,UAAU,SAAS,CACvB,OAGC;IAED,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,GAAG,OAAO,CAAC;IACpD,OAAO,IAAI,CAAC;QACV,GAAG,UAAU;QACb,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE,CACnB,OAAO,CAAC,QAAQ,CAAC,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;KACpE,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,OAIC;IAED,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,GAAG,OAAO,CAAC;IAC3C,OAAO,IAAI,CAAC;QACV,GAAG,UAAU;QACb,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE,CACnB,QAAQ,CAAC,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;KAC5D,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,OAGC;IAED,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,GAAG,OAAO,CAAC;IACpD,OAAO,IAAI,CAAC;QACV,GAAG,UAAU;QACb,KAAK,CAAC,OAAO,CAAC,OAAO;YACnB,MAAM,UAAU,GACd,OAAO,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YAC7D,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC;gBACnC,GAAG,UAAU;gBACb,MAAM,EAAE,OAAO,CAAC,MAAM;aACvB,CAAC,CAAC;YACH,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;gBACrB,MAAM,IAAI,YAAY,CAAC,SAAS,EAAE,yBAAyB,EAAE;oBAC3D,GAAG,MAAM;iBACV,CAAC,CAAC;YACL,OAAO,MAAM,CAAC;QAChB,CAAC;KACF,CAAC,CAAC;AACL,CAAC","sourcesContent":["import {\n task,\n type Task,\n type TaskContext,\n type TaskOptions,\n} from \"../domain/workflow.ts\";\nimport type { AgentAdapter, Command, CommandResult } from \"../domain/ports.ts\";\nimport { OutpostError } from \"../domain/errors.ts\";\nimport type { DispatchOptions } from \"./execution.ts\";\nimport type { DispatchResult, Sandbox, SandboxOptions } from \"./outpost.ts\";\nimport { dispatch } from \"./outpost.ts\";\n\nexport function agentTask<T>(\n options: Omit<TaskOptions<DispatchResult<T>>, \"perform\"> & {\n sandbox: Sandbox;\n request: (context: TaskContext) => DispatchOptions<T>;\n },\n): Task<DispatchResult<T>> {\n const { sandbox, request, ...definition } = options;\n return task({\n ...definition,\n perform: (context) =>\n sandbox.dispatch({ ...request(context), signal: context.signal }),\n });\n}\n\nexport function isolatedTask<T>(\n options: Omit<TaskOptions<DispatchResult<T>>, \"perform\"> & {\n request: (\n context: TaskContext,\n ) => SandboxOptions & DispatchOptions<T> & { readonly agent: AgentAdapter };\n },\n): Task<DispatchResult<T>> {\n const { request, ...definition } = options;\n return task({\n ...definition,\n perform: (context) =>\n dispatch({ ...request(context), signal: context.signal }),\n });\n}\n\nexport function commandTask(\n options: Omit<TaskOptions<CommandResult>, \"perform\"> & {\n sandbox: Sandbox;\n command: Command | ((context: TaskContext) => Command);\n },\n): Task<CommandResult> {\n const { sandbox, command, ...definition } = options;\n return task({\n ...definition,\n async perform(context) {\n const invocation =\n typeof command === \"function\" ? command(context) : command;\n const result = await sandbox.command({\n ...invocation,\n signal: context.signal,\n });\n if (result.status !== 0)\n throw new OutpostError(\"process\", \"Workflow command failed\", {\n ...result,\n });\n return result;\n },\n });\n}\n"]}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env node
2
+ import { parseArgs } from "node:util";
3
+ import { createInterface } from "node:readline/promises";
4
+ import { initialize, manageImage } from "./scaffold.js";
5
+ const help = `Outpost — sandboxed coding agents and workflows
6
+
7
+ outpost init [--yes] [--agent codex|claude] [--provider docker|podman|vercel|daytona|local]
8
+ [--template blank|iterate|review|plan|plan-review] [--tracker github|beads|custom]
9
+ [--manager npm|pnpm|yarn|bun] [--model NAME] [--install] [--build] [--image NAME] [--label NAME] [--directory PATH]
10
+ outpost image build|remove [--engine docker|podman] [--file PATH] [--image NAME] [--uid ID] [--gid ID]
11
+
12
+ Node.js 24+ and Git are required. Run generated scripts with Node.js.
13
+ `;
14
+ try {
15
+ const { values, positionals } = parseArgs({
16
+ allowPositionals: true,
17
+ options: {
18
+ help: { type: "boolean", short: "h" },
19
+ yes: { type: "boolean", short: "y" },
20
+ install: { type: "boolean" },
21
+ build: { type: "boolean" },
22
+ agent: { type: "string" },
23
+ provider: { type: "string" },
24
+ template: { type: "string" },
25
+ tracker: { type: "string" },
26
+ manager: { type: "string" },
27
+ model: { type: "string" },
28
+ label: { type: "string" },
29
+ directory: { type: "string" },
30
+ engine: { type: "string" },
31
+ file: { type: "string" },
32
+ image: { type: "string" },
33
+ uid: { type: "string" },
34
+ gid: { type: "string" },
35
+ },
36
+ });
37
+ if (values.help || !positionals.length)
38
+ process.stdout.write(help);
39
+ else if (positionals[0] === "init") {
40
+ const options = Object.fromEntries(Object.entries(values).filter(([key]) => !["help", "yes"].includes(key)));
41
+ if (!values.yes &&
42
+ !process.stdin.isTTY &&
43
+ (!values.agent || !values.provider || !values.template || !values.tracker))
44
+ throw new Error("Headless initialization requires --yes for defaults, or --agent, --provider, --template and --tracker.");
45
+ if (!values.yes && process.stdin.isTTY) {
46
+ const terminal = createInterface({
47
+ input: process.stdin,
48
+ output: process.stdout,
49
+ });
50
+ try {
51
+ for (const [key, label, fallback] of [
52
+ ["agent", "Agent (codex/claude)", "codex"],
53
+ [
54
+ "provider",
55
+ "Sandbox (docker/podman/vercel/daytona/local)",
56
+ "docker",
57
+ ],
58
+ [
59
+ "template",
60
+ "Template (blank/iterate/review/plan/plan-review)",
61
+ "blank",
62
+ ],
63
+ ["tracker", "Issue tracker (github/beads/custom)", "github"],
64
+ ]) {
65
+ options[key] ??=
66
+ (await terminal.question(`${label} [${fallback}]: `)).trim() ||
67
+ fallback;
68
+ }
69
+ }
70
+ finally {
71
+ terminal.close();
72
+ }
73
+ }
74
+ const result = await initialize(options);
75
+ process.stdout.write(`Created ${result.files.length} files.\nRun: ${result.run}\n`);
76
+ }
77
+ else if (positionals[0] === "image" &&
78
+ ["build", "remove"].includes(positionals[1] ?? "")) {
79
+ const options = Object.fromEntries(Object.entries(values).filter(([key]) => ["directory", "engine", "file", "image"].includes(key)));
80
+ const image = await manageImage(positionals[1], {
81
+ ...options,
82
+ ...(values.uid ? { uid: Number(values.uid) } : {}),
83
+ ...(values.gid ? { gid: Number(values.gid) } : {}),
84
+ });
85
+ process.stdout.write(`${positionals[1]}: ${image}\n`);
86
+ }
87
+ else
88
+ throw new Error("Unknown command. Run outpost --help.");
89
+ }
90
+ catch (error) {
91
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
92
+ process.exitCode = 1;
93
+ }
94
+ //# sourceMappingURL=main.js.map