@elie-laloum/outpost 1.1.2 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/README.md +19 -191
- package/package.json +9 -6
- package/README.fr.md +0 -251
- package/ROADMAP.md +0 -34
- package/docs/api.md +0 -147
- package/docs/architecture.fr.md +0 -37
- package/docs/architecture.md +0 -57
- package/docs/migration-1.1.fr.md +0 -44
- package/docs/migration-1.1.md +0 -38
- package/docs/operations.md +0 -101
- package/docs/providers.md +0 -119
- package/docs/workflows.md +0 -101
package/docs/api.md
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
# API reference
|
|
2
|
-
|
|
3
|
-
## Domain and ownership
|
|
4
|
-
|
|
5
|
-
`Workspace` owns a Git checkout and its lock. `Sandbox` owns a running environment attached to exactly one workspace. `dispatch` is one agent job, potentially containing several turns. `Task<T>` is one typed workflow node. A native conversation belongs to an agent and can outlive both workspace and sandbox.
|
|
6
|
-
|
|
7
|
-
| Entry point | Lifetime |
|
|
8
|
-
| ------------------------ | -------------------------------------------------------------------------------------- |
|
|
9
|
-
| `dispatch(options)` | Creates and closes its own sandbox; closes its workspace unless supplied. |
|
|
10
|
-
| `attach(options)` | Opens a terminal session, synchronizes changes and closes owned resources. |
|
|
11
|
-
| `createSandbox(options)` | Returns a warm handle with `dispatch`, `resume`, `fork`, `attach`, `command`, `close`. |
|
|
12
|
-
| `openWorkspace(options)` | Returns a workspace with `dispatch`, `sandbox`, `attach`, `integrate`, `close`. |
|
|
13
|
-
|
|
14
|
-
Sandbox and workspace handles implement `Symbol.asyncDispose` for `await using`. Explicit `close()` is supported and idempotent. Close the sandbox before closing a separately owned workspace. A warm sandbox rejects overlapping operations. Separate workspaces hold separate locks; automatic merges hold a host-branch merge lock.
|
|
15
|
-
|
|
16
|
-
## WorkspaceOptions
|
|
17
|
-
|
|
18
|
-
| Field | Type / default | Meaning |
|
|
19
|
-
| ------------------ | ------------------------------------- | ---------------------------------------------------------- |
|
|
20
|
-
| `repository` | `string`, current directory | Repository root or a directory inside it. |
|
|
21
|
-
| `branch` | `BranchPolicy`, `{ mode: "current" }` | Checkout, named worktree, or temporary integration branch. |
|
|
22
|
-
| `copies` | `readonly string[]` | Repository-relative inputs copied before workspace hooks. |
|
|
23
|
-
| `limits.copyMs` | `number`, 60000 | Copy deadline. |
|
|
24
|
-
| `limits.gitMs` | `number`, 30000 | Git setup operation deadline. |
|
|
25
|
-
| `limits.collectMs` | `number`, 30000 | Commit collection deadline. |
|
|
26
|
-
| `limits.mergeMs` | `number`, 30000 | Host merge deadline. |
|
|
27
|
-
|
|
28
|
-
Branch variants:
|
|
29
|
-
|
|
30
|
-
```ts
|
|
31
|
-
type BranchPolicy =
|
|
32
|
-
| { mode: "current" }
|
|
33
|
-
| { mode: "named"; name: string; from?: string }
|
|
34
|
-
| { mode: "integrate"; from?: string };
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
`from` accepts a Git commit-ish and is resolved before branch creation. An existing named branch is reused. Managed worktrees live under `.outpost/workspaces`. A branch checked out outside its managed location is not moved. Integration requires an attached host branch and never switches the host checkout. Dirty worktrees survive close; `close({ preserve: true })` also retains clean ones. Inspect the returned `retainedDirectory`.
|
|
38
|
-
|
|
39
|
-
## SandboxOptions
|
|
40
|
-
|
|
41
|
-
Includes `WorkspaceOptions`, plus:
|
|
42
|
-
|
|
43
|
-
| Field | Meaning |
|
|
44
|
-
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
45
|
-
| `agent` | Default `AgentAdapter` for warm operations; optional on `createSandbox`, required on one-shot `dispatch`/`attach`. Use `codex()` or `claude()`. |
|
|
46
|
-
| `provider` | `SandboxProvider`; defaults to `docker()`. |
|
|
47
|
-
| `workspace` | Existing workspace. Cannot be combined with `repository`, `branch` or `copies`. |
|
|
48
|
-
| `hooks` | `workspaceReady`, `hostReady`, `sandboxReady` command arrays. |
|
|
49
|
-
| `signal` | Cancels provisioning. In one-shot calls, also cancels execution. |
|
|
50
|
-
| `logging` | `false`, `"stdout"`, or `{ file?, verbose? }`; default generated JSONL file. |
|
|
51
|
-
| `bootstrap` | Remote agent installation when absent; defaults to `true`. |
|
|
52
|
-
| `conversationHome` | Host directory containing `.claude`/`.codex`; defaults to OS home. |
|
|
53
|
-
|
|
54
|
-
Hook order is copies → `workspaceReady` on host → provider acquisition/synchronization → concurrent `hostReady` and `sandboxReady`. Host commands run sequentially. Sandbox commands run concurrently. Failure aborts sibling hooks and waits for their cleanup. `openWorkspace({ hooks })` runs `workspaceReady` immediately and passes the remaining hooks to later sandboxes without repeating it. Commands may choose a directory, environment and timeout. Sandbox commands can request `elevated: true` on providers supporting elevation. Host execution does not elevate privileges.
|
|
55
|
-
|
|
56
|
-
## DispatchOptions
|
|
57
|
-
|
|
58
|
-
| Field | Default / meaning |
|
|
59
|
-
| -------------- | --------------------------------------------------------------------------------------------- |
|
|
60
|
-
| `brief` | Required `{ text }` or `{ file, values? }`. |
|
|
61
|
-
| `agent` | Overrides the warm sandbox's default adapter for this job, including its model and variables. |
|
|
62
|
-
| `logging` | Overrides the sandbox's logging policy for this job. |
|
|
63
|
-
| `label` | Optional label included in journal records and generated log filenames. |
|
|
64
|
-
| `passes` | Positive integer, default 1. Maximum agent turns when no response validator is supplied. |
|
|
65
|
-
| `until` | String or strings; default `<outpost>done</outpost>`. Empty array disables markers. |
|
|
66
|
-
| `idleMs` | 600000; maximum silence before completion. Any output refreshes it. |
|
|
67
|
-
| `settleMs` | 60000; grace period after completion, refreshed by output. |
|
|
68
|
-
| `deadlineMs` | 3600000; hard deadline for each agent command. |
|
|
69
|
-
| `expansionMs` | 30000; deadline for each embedded prompt command. |
|
|
70
|
-
| `signal` | Cancels this operation, preserving a warm sandbox. |
|
|
71
|
-
| `continuation` | `{ id, fork? }`; native resume or conversation fork. |
|
|
72
|
-
| `response` | A `ResponseSpec<T>` produced by `response.text/json`. |
|
|
73
|
-
| `observe` | Receives normalized events; exceptions cannot fail the job. |
|
|
74
|
-
| `warn` | Receives nonfatal warnings; exceptions cannot fail the job. |
|
|
75
|
-
|
|
76
|
-
Resume and structured output require `passes: 1`. A one-shot continuation validates the host transcript before allocating an environment. Warm continuations reuse sessions already present, otherwise importing the host transcript.
|
|
77
|
-
|
|
78
|
-
`DispatchResult<T>` contains `text`, `value`, `turns`, `usage`, `completed`, optional `completion`, `conversation`, `transcript`, `log`, `branch`, `directory`, `commits`, optional `retainedDirectory`, and `resume`/`fork` methods. `value` is inferred from the response validator. Without a validator it is `undefined`. Usage contains raw `input`, `cached` (cache read), optional `cacheCreated` (cache creation) and `output` token counts. Claude transcript usage takes the final assistant message, independently from streamed totals. Costs are not estimated.
|
|
79
|
-
|
|
80
|
-
Each turn contains `text`, `status`, `durationMs`, `usage`, and optional `conversation` and `transcript`. Commits contain their original `oid` and `subject`. A budget exhausted without a completion marker returns `completed: false`; process failures throw.
|
|
81
|
-
|
|
82
|
-
## Agent settings
|
|
83
|
-
|
|
84
|
-
```ts
|
|
85
|
-
codex({
|
|
86
|
-
model: "your-model",
|
|
87
|
-
reasoning: "high",
|
|
88
|
-
approvalReviewer: "auto_review",
|
|
89
|
-
saveConversations: true,
|
|
90
|
-
variables: {},
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
claude({
|
|
94
|
-
model: "sonnet",
|
|
95
|
-
reasoning: "high",
|
|
96
|
-
permissions: "acceptEdits",
|
|
97
|
-
saveConversations: true,
|
|
98
|
-
variables: {},
|
|
99
|
-
});
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
Model is optional; the installed CLI chooses its default. Codex reasoning accepts `low`, `medium`, `high`, `xhigh`. Claude also accepts `max`. Actual model support is determined by the CLI/provider. Claude permission modes are `default`, `acceptEdits`, `plan`, `auto`, `dontAsk`, `bypassPermissions`.
|
|
103
|
-
|
|
104
|
-
Noninteractive defaults avoid permission prompts because the outer sandbox is responsible for isolation. Codex can instead use the auto-review approval reviewer. Interactive commands use native terminal behavior and native session resume/fork commands.
|
|
105
|
-
|
|
106
|
-
Events are a discriminated union with `kind`: `phase`, `prompt`, `text`, `result`, `tool`, `conversation`, `usage`, `summary`, `warning`, `failure`, `finished`, `raw`. Every public observation adds a one-based `pass` and ISO timestamp `at`. Protocol noise is retained as `raw`. Adapters implement `request(input): Command` and `events(line): AgentEvent[]`; a custom adapter can omit native conversation support.
|
|
107
|
-
|
|
108
|
-
## Command and attachment
|
|
109
|
-
|
|
110
|
-
```ts
|
|
111
|
-
const result = await sandbox.command({
|
|
112
|
-
executable: "npm",
|
|
113
|
-
arguments: ["test"],
|
|
114
|
-
directory: "/workspace",
|
|
115
|
-
variables: { CI: "true" },
|
|
116
|
-
deadlineMs: 120_000,
|
|
117
|
-
retain: 65_536,
|
|
118
|
-
observe(channel, text) {
|
|
119
|
-
process.stdout.write(text);
|
|
120
|
-
},
|
|
121
|
-
});
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
Arguments are passed directly, without implicit shell expansion. For shell syntax, explicitly invoke `sh -c` (inside Linux sandboxes) or the host shell. Default directory is the sandbox workspace. `stdin` supplies a string. `interactive` inherits terminal input/output by default; `terminal: { input?, output?, error? }` supplies caller-owned streams. Raw mode and cursor visibility are restored after attachment. `retain` bounds the captured tail of each stream; observers receive all output. `CommandResult` contains `status`, `stdout`, `stderr`.
|
|
125
|
-
|
|
126
|
-
`attach({ agent?, brief?, continuation?, signal?, ask?, terminal? })` uses the adapter's terminal mode. Missing file-prompt variables are requested once per variable through the TTY or the optional async `ask(name)` callback. Existing values are preserved. Docker, Podman and host support attachment. Remote cloud adapters reject it explicitly. Both warm and one-shot results include commits, branch and workspace directory. The top-level result additionally returns disposal information.
|
|
127
|
-
|
|
128
|
-
## Errors and recovery
|
|
129
|
-
|
|
130
|
-
`OutpostError` has a machine-readable `code`, frozen `details`, `recovery`, and optional `cause`. `recoveryDetails(error)` retrieves recovery metadata for native errors and cancellation reasons as well, preserving their original identity. Codes: `configuration`, `process`, `timeout`, `aborted`, `workspace`, `conflict`, `prompt`, `response`, `session`, `provider`. Multiple failures can surface as `AggregateError` without losing the original causes.
|
|
131
|
-
|
|
132
|
-
`ResponseError` adds `tag`, optional `raw` and `recovery`. Recovery records include the conversation and workspace; after collection they also include commits, transcript and log. Native main-transcript capture failure fails the dispatch. Child transcript capture errors only warn.
|
|
133
|
-
|
|
134
|
-
Remote recovery directories contain Git bundles, binary patches and copied untracked files. A failed synchronization reports its recovery path. Do not delete it before inspecting the failure. See [Operations](operations.md).
|
|
135
|
-
|
|
136
|
-
## Additional 1.1 contracts
|
|
137
|
-
|
|
138
|
-
- `WorkspaceOptions.label` names generated branches and workspace directories; `hooks` and `signal` are available on standalone workspaces.
|
|
139
|
-
- `SandboxOptions.includeUncommitted` explicitly seeds remote patches and untracked files; the default is committed history only.
|
|
140
|
-
- `DispatchOptions.idleWarningMs` defaults to 60000; `diagnostic(message)` receives expansion-size estimates. Relative file briefs use the caller's cwd.
|
|
141
|
-
- `AgentAdapter.resumable` declares repair capability. `storage?: ConversationStore` supplies locate/capture/restore; `transcriptUsage?(text)` extracts authoritative usage.
|
|
142
|
-
- `conversations.native(format)` returns a store. Helpers include `locate`, `capture`, `restore`, `rewrite`, `projectKey`, `claudePath`, `directory` and `destination`.
|
|
143
|
-
- Cold `DispatchResult.resume/fork` accepts `ContinuationOptions`, including a new branch, provider and lifecycle hooks. `WarmDispatchResult` accepts dispatch settings only.
|
|
144
|
-
- `TransferOptions` contains optional `signal` and `deadlineMs`. `SandboxLease.upload/download` accept it as a third argument. Orchestration uses `limits.copyMs`, with a 120000 ms transfer default.
|
|
145
|
-
- `reporter` renders observations with label, verbose, quiet and custom writer settings.
|
|
146
|
-
- `campaign`, `CampaignOptions`, `CampaignResult`, `CampaignEvent`, `IssueOutcome`, `Issue`, `Assignment` and `Backlog` define issue delivery. See the [workflow guide](workflows.md#issue-campaigns).
|
|
147
|
-
- `githubBacklog` and `beadsBacklog` accept `directory`, `label` and `deadlineMs`. Their commands receive declared project environment values.
|
package/docs/architecture.fr.md
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# Architecture
|
|
2
|
-
|
|
3
|
-
[English](architecture.md)
|
|
4
|
-
|
|
5
|
-
Outpost utilise des ports et des adapters. Le domaine décrit les capacités ; les services applicatifs coordonnent leur utilisation. Les agents et les providers de sandbox implémentent des contrats indépendants.
|
|
6
|
-
|
|
7
|
-
| Couche | Responsabilité |
|
|
8
|
-
| ------------------- | ----------------------------------------------------------------------- |
|
|
9
|
-
| `domain` | Contrats, règles, prompts, réponses, graphes et exécution des workflows |
|
|
10
|
-
| `adapters/agents` | Commandes et protocoles propres à Claude et Codex |
|
|
11
|
-
| `adapters/backlogs` | Accès aux issues GitHub et Beads |
|
|
12
|
-
| `providers` | Allocation, commandes, transferts et libération des sandboxes |
|
|
13
|
-
| `infrastructure` | Git, processus, fichiers, conversations et journaux |
|
|
14
|
-
| `application` | Cycle de vie, dispatch, campagnes et synchronisation distante |
|
|
15
|
-
| `cli` | Commandes, initialisation et images |
|
|
16
|
-
|
|
17
|
-
Les contrats nommés et les types objets sont placés dans des fichiers `*.types.ts`, sans initialisation à l’exécution. Les paramètres par défaut, options reconnues, recettes et limites partagées sont placés dans des fichiers `*.constants.ts`. Les variables locales et valeurs calculées restent dans leur opération.
|
|
18
|
-
|
|
19
|
-
Les points d’entrée publics sont conservés. Les façades `providers/agents.ts`, `application/outpost.ts` et `domain/ports.ts` réexportent les implémentations et contrats ; les services internes importent directement leurs dépendances.
|
|
20
|
-
|
|
21
|
-
## Responsabilités
|
|
22
|
-
|
|
23
|
-
- Chaque agent possède un adapter, un constructeur de commande et un décodeur d’événements. Des registres de handlers remplacent le dispatch conditionnel des protocoles. Un événement inconnu reste une observation brute.
|
|
24
|
-
- Les conversations constituent un port distinct. Les stratégies Claude et Codex portent leurs conventions de stockage ; capture, restauration, recherche et réécriture sont séparées.
|
|
25
|
-
- Le workspace possède son état Git. La préparation du sandbox, les opérations exclusives, le dispatch, le terminal et la fermeture ont chacun un service dédié.
|
|
26
|
-
- L’exécution d’un tour, l’accumulation des événements et la surveillance des délais sont séparées. L’agrégation de consommation est une règle commune du domaine.
|
|
27
|
-
- Les providers composent leurs services de préparation, commandes et transferts. Docker et Podman partagent la mécanique du moteur de conteneurs.
|
|
28
|
-
- La synchronisation distante suit quatre étapes : téléchargement, validation, sauvegarde puis application. Le coordinateur conserve la révision synchronisée et les informations de récupération.
|
|
29
|
-
- Les workflows séparent validation du graphe, état d’exécution, tentatives d’une tâche et ordonnancement. Les campagnes composent planification, traitement d’une issue et intégration vérifiée avant clôture.
|
|
30
|
-
|
|
31
|
-
## Extension et vérification
|
|
32
|
-
|
|
33
|
-
Un nouvel agent implémente `AgentAdapter` dans son propre module. Un nouveau backend implémente `SandboxProvider` et `SandboxLease`, avec annulation, délais de transfert et libération idempotente. Les contrats existants restent compatibles.
|
|
34
|
-
|
|
35
|
-
`npm run check` vérifie l’architecture, les types, les tests unitaires et fonctionnels et la compilation. `npm run coverage` impose 80 % sur les lignes, branches et fonctions. Les modules de types, effacés à l’exécution, sont contrôlés par TypeScript et le test consommateur du package. Les handlers CLI entrent dans la couverture ; seul le point d’entrée du processus est exclu.
|
|
36
|
-
|
|
37
|
-
La CI refuse les dépendances entre couches dans le mauvais sens, les contrats déclarés hors des fichiers de types, l’initialisation à l’exécution dans ces fichiers, les chaînes de branches alternatives et les déclarations inutilisées. Elle vérifie aussi les trois systèmes, Docker, Podman et le package installé. Le respect du SRP reste également un travail de revue.
|
package/docs/architecture.md
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
# Architecture
|
|
2
|
-
|
|
3
|
-
[Français](architecture.fr.md)
|
|
4
|
-
|
|
5
|
-
Outpost uses ports and adapters. Domain contracts describe capabilities; application services coordinate their use. Concrete agents and sandbox providers implement independent ports. A new agent does not require changes to sandbox allocation, and a new provider does not require changes to agent protocols.
|
|
6
|
-
|
|
7
|
-
| Layer | Owns | Dependencies |
|
|
8
|
-
| ------------------- | ----------------------------------------------------------------------------------- | ---------------------------------------------- |
|
|
9
|
-
| `domain` | Contracts, validation, prompts, responses, task graphs and workflow execution rules | Domain and Node primitives |
|
|
10
|
-
| `adapters/agents` | Claude/Codex command construction and event translation | Domain and infrastructure |
|
|
11
|
-
| `adapters/backlogs` | GitHub/Beads issue access | Domain and infrastructure |
|
|
12
|
-
| `providers` | Sandbox allocation, commands, transfers and disposal | Domain, infrastructure and provider services |
|
|
13
|
-
| `infrastructure` | Git, processes, files, native transcript storage and logging | Domain and infrastructure |
|
|
14
|
-
| `application` | Resource ownership, use cases, campaigns and remote synchronization | Domain, adapters, providers and infrastructure |
|
|
15
|
-
| `cli` | Argument handling, onboarding and image commands | Application and adapters |
|
|
16
|
-
|
|
17
|
-
## Contracts and configuration
|
|
18
|
-
|
|
19
|
-
Named contracts and object type declarations live in dedicated `*.types.ts` files next to their owner. These modules have no runtime initialization. Configuration defaults, supported options, recipes and shared limits belong in `*.constants.ts` files. Local variables and computed values stay with their operation.
|
|
20
|
-
|
|
21
|
-
The public facade remains `src/index.ts`, with the existing `providers/*` package subpaths. Compatibility facades such as `providers/agents.ts`, `application/outpost.ts` and `domain/ports.ts` re-export implementations or contracts. Internal services import their dependencies directly.
|
|
22
|
-
|
|
23
|
-
## Agents and conversations
|
|
24
|
-
|
|
25
|
-
Each agent has its own factory, request builder and event decoder in `adapters/agents`. The factory composes these capabilities into `AgentAdapter`. Protocol decoding uses event-handler registries; unknown events remain raw observations.
|
|
26
|
-
|
|
27
|
-
`ConversationStore` is a separate port. Native stores delegate filesystem conventions to Claude and Codex layout strategies. Capture, restore, discovery and structural transcript rewriting have separate services. A custom store can be supplied without changing the execution pipeline.
|
|
28
|
-
|
|
29
|
-
## Resource lifecycle
|
|
30
|
-
|
|
31
|
-
`application/workspace.ts` owns the host workspace. `sandbox-provision.ts` acquires and prepares a provider lease. `sandbox.ts` composes dispatch, attachment and command operations; `operation-gate.ts` enforces exclusive ownership and waits for active work during closure.
|
|
32
|
-
|
|
33
|
-
`sandbox-dispatch.ts` owns the dispatch transaction: execution, transcript capture, synchronization, journal closure and recovery metadata. `agent-turn.ts` supervises one process; `agent-output.ts` accumulates protocol output; `activity-watchdog.ts` owns timers. Usage aggregation is a domain operation shared by warm and cold execution.
|
|
34
|
-
|
|
35
|
-
Workspaces and sandboxes retain separate lifetimes. Cold passes allocate separate environments; warm operations reuse a lease. Cancellation, continuation, hook ordering and recovery remain part of the contract.
|
|
36
|
-
|
|
37
|
-
## Providers and Git
|
|
38
|
-
|
|
39
|
-
Docker and Podman share the container adapter while preflight, allocation arguments, mounts, invocation and file transfers have separate modules. Vercel and Daytona compose dedicated command and transfer services. Optional SDK loading stays in the corresponding provider entry point.
|
|
40
|
-
|
|
41
|
-
Git infrastructure separates repository preparation, locking, managed worktree allocation, remote refresh, history collection and lease disposal. Dirty or detached worktrees remain recoverable.
|
|
42
|
-
|
|
43
|
-
Remote synchronization follows explicit stages: download changes, validate them, back up host state, then apply changes. These services retain overlap checks, concurrent-edit detection and recovery artifacts. The coordinator owns the last synchronized revision and decides whether cleanup is safe.
|
|
44
|
-
|
|
45
|
-
## Workflows and campaigns
|
|
46
|
-
|
|
47
|
-
Workflow graph validation, execution state, task retries and dependency scheduling are separate domain services. Task identity controls access to dependency values. Observer errors cannot alter execution outcomes.
|
|
48
|
-
|
|
49
|
-
Campaign orchestration composes a planner, an issue worker and an integration service. A worker implements and reviews one issue; integration verifies commits before tracker closure. The campaign owns cycle limits and outcome aggregation.
|
|
50
|
-
|
|
51
|
-
## Extending and validating
|
|
52
|
-
|
|
53
|
-
To add an agent, implement `AgentAdapter` in its own module, with request and event contracts tested independently. Add a conversation layout or custom store when native continuation is supported. To add a sandbox backend, implement `SandboxProvider` and `SandboxLease`, including cancellation, transfer deadlines and idempotent disposal.
|
|
54
|
-
|
|
55
|
-
Run `npm run check` for architecture checks, type checking, unit/functional tests and the build. `npm run coverage` enforces 80% lines, branches and functions. Type-only modules are excluded from runtime coverage because TypeScript erases them; type checking and the packed consumer test validate their contracts. CLI command handlers are covered; only the process entry wrapper is excluded.
|
|
56
|
-
|
|
57
|
-
CI rejects reversed layer dependencies, inline contract declarations, runtime initialization in type modules, chained alternative branches and unused implementation declarations. Multi-platform checks, real Docker/Podman tests and a packed-package consumer exercise the supported boundaries. These checks support architectural review; they do not mechanically prove SRP.
|
package/docs/migration-1.1.fr.md
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# Migrer vers la version 1.1
|
|
2
|
-
|
|
3
|
-
La version 1.1 complète les campagnes par issue et corrige plusieurs contrats d’exécution. Voici les changements visibles depuis la version 1.0.
|
|
4
|
-
|
|
5
|
-
| Domaine | Comportement en 1.1 |
|
|
6
|
-
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
7
|
-
| Boucle ponctuelle | Chaque passe de `dispatch` acquiert une nouvelle sandbox. Utilisez `createSandbox()` pour conserver un environnement entre les passes. |
|
|
8
|
-
| Variables | Seul `.outpost/.env` est lu. Une valeur non vide du fichier est prioritaire ; une déclaration vide reprend la valeur du processus. |
|
|
9
|
-
| Prompts | Les chemins relatifs partent du répertoire de l’appelant, même lorsque `repository` désigne un autre dossier. |
|
|
10
|
-
| Hooks | `workspaceReady` intervient dès l’ouverture du workspace. Les hooks hôte sont séquentiels ; ceux de la sandbox sont concurrents. |
|
|
11
|
-
| Copies | Une entrée absente est ignorée. Les autres erreurs de copie restent bloquantes. |
|
|
12
|
-
| Cloud | Les commits sont envoyés par défaut. `includeUncommitted: true` ajoute les modifications et fichiers non suivis. Les copies demandées explicitement sont transférées. |
|
|
13
|
-
| Branche distante | Sans politique explicite, un workspace d’intégration est créé. |
|
|
14
|
-
| Tokens Claude | `input`, `cached` et `cacheCreated` distinguent entrée non cachée, lecture et création du cache. |
|
|
15
|
-
| Événements | `pass` et `at` identifient chaque observation. Les lignes brutes accompagnent les événements normalisés. |
|
|
16
|
-
| Journaux | Un fichier explicite est complété sans écrasement. `logging: "stdout"` affiche une progression lisible. |
|
|
17
|
-
| Reprise | Un résultat ponctuel accepte une nouvelle branche, un fournisseur et des hooks. Un résultat chaud conserve sa sandbox. |
|
|
18
|
-
| Réponse structurée | La balise et la capacité de réparation sont validées avant allocation. Un bloc Markdown JSON peut apparaître dans la balise. |
|
|
19
|
-
|
|
20
|
-
Le marqueur par défaut reste `<outpost>done</outpost>`. Les adaptateurs natifs restent Codex et Claude Code.
|
|
21
|
-
|
|
22
|
-
## Campagnes et starters
|
|
23
|
-
|
|
24
|
-
`campaign` utilise `Backlog.list/get/close`, recharge les issues à chaque cycle et ne les ferme qu’après intégration des commits dans la branche hôte. Le connecteur GitHub pagine les résultats et applique son label. Beads doit être installé sur l’hôte ; sa recette de conteneur générée inclut aussi `bd`.
|
|
25
|
-
|
|
26
|
-
Les paramètres du starter sont `cycles`, `concurrency`, `implementationPasses` et `reviewPasses`. `planner: false` traite les issues disponibles dans l’ordre ; `reviewer: false` désactive la revue. Les rôles `planner`, `reviewer` et `merger` acceptent des adaptateurs distincts pour choisir les modèles. Les règles de développement se trouvent dans `.outpost/STANDARDS.md`.
|
|
27
|
-
|
|
28
|
-
Un échec d’implémentation est enregistré sans interrompre les issues indépendantes. Un cycle sans commit s’arrête. Un échec de fusion conserve le travail et ne ferme aucune issue concernée. Si la fermeture chez le tracker échoue après une fusion réussie, vérifiez son état avant de relancer la campagne.
|
|
29
|
-
|
|
30
|
-
`init` ne remplace jamais les fichiers existants : adoptez le nouveau starter manuellement ou générez-le dans un autre dossier.
|
|
31
|
-
|
|
32
|
-
## Diagnostic et récupération
|
|
33
|
-
|
|
34
|
-
`recoveryDetails(error)` fournit les chemins, commits et journaux disponibles sans remplacer la raison d’annulation. Un échec de préparation nettoie le workspace s’il est propre ; le travail modifié et les artefacts d’une synchronisation échouée sont conservés. Les transferts réussis sont nettoyés à la fermeture.
|
|
35
|
-
|
|
36
|
-
`reporter({ label, verbose, quiet, write })` produit un observateur lisible. `idleWarningMs` règle les avertissements d’inactivité ; `diagnostic` reçoit l’estimation de taille des expansions de prompt. Cette estimation n’est pas un compteur de facturation.
|
|
37
|
-
|
|
38
|
-
## Extensions
|
|
39
|
-
|
|
40
|
-
Un adaptateur peut fournir `storage: ConversationStore`, `resumable` et `transcriptUsage`. Le service `conversations` expose chemins, recherche, capture, restauration et réécriture sélective. Chaque tour expose son propre chemin `transcript`.
|
|
41
|
-
|
|
42
|
-
Les transferts acceptent `{ signal, deadlineMs }` ; `limits.copyMs` borne leur attente. Un fournisseur personnalisé doit réellement respecter l’annulation pour empêcher des écritures tardives. `Command.terminal` accepte les flux de l’appelant et `attach.ask` complète les variables de prompt manquantes sans terminal interactif.
|
|
43
|
-
|
|
44
|
-
La CI vérifie Linux, Windows, macOS, Docker et Podman. Les contrats Vercel/Daytona sont testés avec des doubles SDK. Une authentification modèle et des comptes cloud distincts restent nécessaires pour les essais réels correspondants.
|
package/docs/migration-1.1.md
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# Migrating to 1.1
|
|
2
|
-
|
|
3
|
-
Version 1.1 completes the issue campaign layer and corrects execution contracts. Review these observable changes when upgrading from 1.0.
|
|
4
|
-
|
|
5
|
-
| Area | 1.1 behavior |
|
|
6
|
-
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
7
|
-
| Cold loops | Each pass acquires a fresh sandbox. Use an explicit `createSandbox()` for warm multi-pass execution. |
|
|
8
|
-
| Environment | Only `.outpost/.env` is loaded. Nonempty file values win; empty declarations inherit the process. Declare every key needed inside a sandbox. |
|
|
9
|
-
| Prompt files | Relative paths resolve from the caller's working directory, even if `repository` points elsewhere. |
|
|
10
|
-
| Hooks | `workspaceReady` runs at workspace creation. Host hooks are sequential; sandbox hooks run concurrently. |
|
|
11
|
-
| Optional inputs | Missing `copies` entries are skipped. Other copy errors still fail. |
|
|
12
|
-
| Remote input | Only commits are seeded by default. `includeUncommitted: true` opts into patch/untracked transfer. Selected `copies` are always explicit inputs. |
|
|
13
|
-
| Remote default | An omitted branch policy creates an integration workspace. |
|
|
14
|
-
| Claude usage | `input` contains uncached input; `cached` and `cacheCreated` remain separate counters. |
|
|
15
|
-
| Observations | Every public event has `pass` and `at`. Raw lines accompany normalized events. New phase, summary, result and warning events are available. |
|
|
16
|
-
| Journals | Explicit files append across runs. `logging: "stdout"` renders human-readable progress. |
|
|
17
|
-
| Continuations | Cold result methods accept branch/provider/hook overrides. Warm result methods retain their existing sandbox and reject sandbox reconfiguration. |
|
|
18
|
-
| Structured output | Opening tags and repair capability are checked before provisioning. JSON can use a Markdown code fence inside its tag. |
|
|
19
|
-
|
|
20
|
-
The default completion marker remains `<outpost>done</outpost>`. Native adapters remain Codex and Claude Code.
|
|
21
|
-
|
|
22
|
-
## Campaigns
|
|
23
|
-
|
|
24
|
-
Regenerate starters in a new directory or manually adopt `campaign`; `init` never overwrites existing files. Campaigns use `Backlog.list/get/close`, refresh the backlog every cycle and close issues only after their commits reach the host branch. The GitHub connector paginates and applies its configured label. Beads runs on the host and must be installed there; its generated container recipe also includes `bd`.
|
|
25
|
-
|
|
26
|
-
Set `cycles`, `concurrency`, `implementationPasses` and `reviewPasses` in the starter. `planner: false` takes ready issues in order. `reviewer: false` skips review. Set separate adapters for `planner`, `reviewer` and `merger` to choose different models.
|
|
27
|
-
|
|
28
|
-
## Recovery and observability
|
|
29
|
-
|
|
30
|
-
`recoveryDetails(error)` returns available branch, directory, commits, transcript and log information. It preserves cancellation reason identity. A preparation failure removes a clean owned workspace; changed workspaces and failed remote recovery files survive. Successful remote transfer staging is cleaned at close.
|
|
31
|
-
|
|
32
|
-
`reporter({ label, verbose, quiet, write })` creates a public observation callback. `idleWarningMs` controls periodic inactivity messages; `diagnostic` receives estimated token sizes of prompt command expansions. Estimates are not billing counts.
|
|
33
|
-
|
|
34
|
-
## Extension ports
|
|
35
|
-
|
|
36
|
-
Custom agents can provide `storage: ConversationStore`, `resumable`, and `transcriptUsage`. `conversations` exposes native path, search, capture, restore and selective rewrite helpers. Per-turn results expose their own `transcript` path.
|
|
37
|
-
|
|
38
|
-
Transfers accept optional `{ signal, deadlineMs }`. `limits.copyMs` bounds orchestration transfers. A custom provider must honor cancellation itself to prevent background side effects. `Command.terminal` accepts caller-owned input/output/error streams; `attach.ask` supplies missing file-prompt variables without a TTY.
|
package/docs/operations.md
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
# Operations and releases
|
|
2
|
-
|
|
3
|
-
## Repository topology
|
|
4
|
-
|
|
5
|
-
GitLab is the writable source of truth:
|
|
6
|
-
|
|
7
|
-
```text
|
|
8
|
-
https://gitlab.elielaloum.com/elielaloum/outpost.git
|
|
9
|
-
push mirror → https://github.com/elie-laloum/outpost.git
|
|
10
|
-
GitHub Actions → packages and releases
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Create commits and tags on GitLab. The push mirror includes branches and tags and preserves divergent refs rather than silently overwriting them. Do not merge changes directly on GitHub; bring contributions back to GitLab. Mirror credentials belong in GitLab's protected mirror configuration, never in tracked files or local remote URLs.
|
|
14
|
-
|
|
15
|
-
## Install a released archive
|
|
16
|
-
|
|
17
|
-
Download the `.tgz` from [GitHub Releases](https://github.com/elie-laloum/outpost/releases), then:
|
|
18
|
-
|
|
19
|
-
```sh
|
|
20
|
-
npm install --save-dev ./elie-laloum-outpost-1.1.2.tgz
|
|
21
|
-
npx outpost --help
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
The archive includes JavaScript, declarations, source maps, EN/FR READMEs and the license. Main imports and local/container providers have no mandatory runtime npm dependencies. Cloud SDK peers are optional and installed only when needed.
|
|
25
|
-
|
|
26
|
-
For GitHub Packages, configure the scope in your project's `.npmrc`:
|
|
27
|
-
|
|
28
|
-
```ini
|
|
29
|
-
@elie-laloum:registry=https://npm.pkg.github.com
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
Authenticate to that registry using an appropriate package-read token or your organization's supported authentication flow, then install `@elie-laloum/outpost`. GitHub Packages can require authentication even for public packages. Do not commit authentication tokens. The public release archive avoids registry authentication.
|
|
33
|
-
|
|
34
|
-
## Local development
|
|
35
|
-
|
|
36
|
-
```sh
|
|
37
|
-
npm ci
|
|
38
|
-
npm run typecheck
|
|
39
|
-
npm test
|
|
40
|
-
npm run coverage
|
|
41
|
-
npm run build
|
|
42
|
-
npm run test:package
|
|
43
|
-
npm run format:check
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
Tests use temporary Git repositories and fixture agents, so unit/functional tests require no paid model access. `test:package` installs the actual archive in a separate temporary project and checks imports and initialization. `test:container` requires `OUTPOST_CONTAINER_ENGINE=docker` or `podman` and an `outpost-ci:latest` image generated by the CLI.
|
|
47
|
-
|
|
48
|
-
The CI matrix covers Linux, Windows and macOS. Docker and Podman jobs build the generated image, verify both native CLIs, edit/commit through mounted Git, round-trip binary files and nested directories, verify file-mount parent permissions, test output/environment handling and verify cancellation does not destroy the warm sandbox or leave a delayed writer alive. SDK contract tests cover Vercel and Daytona without provisioning cloud resources.
|
|
49
|
-
|
|
50
|
-
Live model/cloud tests require separate provider credentials. Contract tests and CLI compatibility checks do not prove availability or model behavior in a specific paid account. Pin custom images and use account-specific smoke tests before broad deployment.
|
|
51
|
-
|
|
52
|
-
## Release procedure
|
|
53
|
-
|
|
54
|
-
1. Change `package.json` and `package-lock.json` to the intended stable version and update `CHANGELOG.md` on GitLab.
|
|
55
|
-
2. Wait for GitHub CI on that mirrored commit to pass.
|
|
56
|
-
3. Create `v<version>` on GitLab at that exact commit.
|
|
57
|
-
4. The mirrored tag starts `Release`. It verifies the version, runs the complete reusable CI workflow, builds the package and publishes to GitHub Packages using its short-lived `GITHUB_TOKEN`.
|
|
58
|
-
5. The workflow creates a GitHub release with the installable tarball. Confirm the package and release point to the expected version.
|
|
59
|
-
|
|
60
|
-
The publishing job has `packages: write` and `contents: write`; ordinary CI only has `contents: read`. Checkout does not persist credentials. No long-lived package-publishing token is needed for GitHub Packages.
|
|
61
|
-
|
|
62
|
-
For GitHub Packages, the release job sets the archive's repository metadata to the GitHub mirror so package permissions attach to that workflow repository. The tracked source manifest, writable repository and tag creation remain on GitLab.
|
|
63
|
-
|
|
64
|
-
Optional npm publication is disabled until repository variable `NPM_PUBLISH` is `true`. Before enabling it, configure the npm package's trusted publisher for GitHub owner `elie-laloum`, repository `outpost`, workflow `release.yml`. The job uses OIDC and provenance. Account/namespace ownership and the registry's initial package setup must be completed by an authorized npm account. Enabling a variable alone does not establish that trust.
|
|
65
|
-
|
|
66
|
-
Published package versions are immutable. If a release fails after publication, inspect the registry before rerunning to avoid duplicate publication errors; use a new patch version for changed content. Never move a released tag.
|
|
67
|
-
|
|
68
|
-
## Recovery
|
|
69
|
-
|
|
70
|
-
Every failure should retain enough context to inspect the workspace. `OutpostError.details` includes available paths; `recoveryDetails(error)` includes collected conversation, commit, log and workspace information without changing the error identity. Clean workspaces are removed after startup failure; dirty ones are retained. Dirty managed worktrees remain under `.outpost/workspaces`, and named branches remain after clean worktree removal.
|
|
71
|
-
|
|
72
|
-
Remote transfer folders under `.outpost/recovery` may contain:
|
|
73
|
-
|
|
74
|
-
- `initial.bundle` / `commits.bundle`: Git objects with original history.
|
|
75
|
-
- `initial.patch` / `remote.patch` / `previous.patch`: binary-capable worktree changes.
|
|
76
|
-
- `previous-index.patch`: the prior staged changes.
|
|
77
|
-
- `incoming/` / `previous-files/`: untracked file copies.
|
|
78
|
-
- `state.json`: synchronization endpoints and file lists.
|
|
79
|
-
|
|
80
|
-
Inspect these before attempting recovery. Fetch a bundle into a separate recovery clone and review the patch there before applying it to valuable work. An incomplete network transfer is not guaranteed to contain every remote file; the original error identifies the failed stage. Keep the cloud sandbox accessible when performing custom manual recovery.
|
|
81
|
-
|
|
82
|
-
Lock files record their owner PID. Active locks reject conflicting workspace use; dead owners can be recovered automatically. If a PID has been reused, verify ownership before manually deleting a lock. Avoid editing a local workspace while its remote sandbox is active.
|
|
83
|
-
|
|
84
|
-
## Logs and credentials
|
|
85
|
-
|
|
86
|
-
Logs are JSONL under `.outpost/logs`; prompts, text, tool events, conversation IDs and usage are recorded. Verbose mode additionally retains raw protocol events. Native transcripts use the agent's own host storage. Files can contain private data; choose retention and backup policies accordingly. Runtime folders are ignored by Git. Successful remote transfer staging is removed at closure; failed recovery artifacts and native transcripts are retained. Explicit `await sandbox.close()` is the reliable shutdown path. SIGINT/SIGTERM await registered cleanup; `process.exit()` can only perform synchronous cleanup, including container removal. Asynchronous cloud cleanup cannot be guaranteed during a forced process exit.
|
|
87
|
-
|
|
88
|
-
Use `.outpost/.env` for task-specific secrets and `.env.example` for names only. Explicitly mount authentication files only when needed, preferably read-only. Container environment values are transported through per-command aliases, preserving the engine's own host environment and keeping values out of command arguments.
|
|
89
|
-
|
|
90
|
-
## Troubleshooting
|
|
91
|
-
|
|
92
|
-
| Symptom | Check |
|
|
93
|
-
| ------------------------------------------ | ------------------------------------------------------------------------------------------ |
|
|
94
|
-
| Image not found or UID mismatch | Build with the same engine, image name and UID/GID used by the provider. |
|
|
95
|
-
| Podman cannot write the worktree | Verify rootless user namespaces, host permissions and SELinux labels. |
|
|
96
|
-
| Agent not authenticated | Check the agent API key/OAuth variable or its explicitly mounted native auth file. |
|
|
97
|
-
| Cold resume cannot find a transcript | Confirm agent, conversation ID and `conversationHome`; capture must have succeeded. |
|
|
98
|
-
| Host changed during remote execution | Preserve the recovery folder, resolve local edits and inspect incoming history separately. |
|
|
99
|
-
| Workflow never finishes after cancellation | Ensure custom task callbacks and custom providers honor their `AbortSignal`. |
|
|
100
|
-
| Native CLI rejects a flag | Compare installed versions with exported `agentVersions`; rebuild a stale image. |
|
|
101
|
-
| No GitHub CI after a GitLab push | Inspect the GitLab push mirror status and its token permissions. |
|
package/docs/providers.md
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
# Sandbox providers
|
|
2
|
-
|
|
3
|
-
| Provider | Placement | Terminal | File transfer | Requirement |
|
|
4
|
-
| -------------- | ------------- | -------- | ----------------- | ------------------------------------- |
|
|
5
|
-
| Docker | Mounted | Yes | Files/directories | Running Docker daemon |
|
|
6
|
-
| Podman | Mounted | Yes | Files/directories | Running Podman engine |
|
|
7
|
-
| Host `local()` | Host checkout | Yes | Files/directories | Native agent installed |
|
|
8
|
-
| Vercel | Remote | No | Files/directories | `@vercel/sandbox`, Vercel credentials |
|
|
9
|
-
| Daytona | Remote | No | Files/directories | `@daytona/sdk`, Daytona credentials |
|
|
10
|
-
|
|
11
|
-
## Docker and Podman
|
|
12
|
-
|
|
13
|
-
```ts
|
|
14
|
-
import { docker } from "@elie-laloum/outpost/providers/docker";
|
|
15
|
-
|
|
16
|
-
const provider = docker({
|
|
17
|
-
image: "outpost:my-repository",
|
|
18
|
-
user: { uid: 1000, gid: 1000 },
|
|
19
|
-
volumes: [
|
|
20
|
-
{
|
|
21
|
-
source: "~/.config/example",
|
|
22
|
-
target: "/home/agent/.config/example",
|
|
23
|
-
readOnly: true,
|
|
24
|
-
},
|
|
25
|
-
],
|
|
26
|
-
networks: ["development"],
|
|
27
|
-
groups: [1000],
|
|
28
|
-
devices: [],
|
|
29
|
-
cpus: 2,
|
|
30
|
-
memoryMb: 4096,
|
|
31
|
-
label: "z",
|
|
32
|
-
retain: 65_536,
|
|
33
|
-
variables: {},
|
|
34
|
-
});
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
`podman()` accepts the same options. Default image is `outpost:<normalized-repository-directory>`. Build it with the CLI. Default UID/GID match the host on POSIX and use 1000 on Windows. The image preflight reports numeric UID mismatches when the user was not explicitly overridden. Podman supports `userns: "keep-id" | false` and maps explicit UIDs/GIDs. macOS checks that Podman Machine is running. Mount sources support `~`, relative and absolute paths, and files. Relative targets resolve under `/workspace`; `~` and `~/...` resolve under the agent home. Individual file mounts must target the home: mount a directory for other destinations. Their parents are prepared for the agent UID/GID. Linux mounts use SELinux `z` by default; choose `Z` for a private label or `false` to omit labels. Windows/macOS use bind-mount syntax.
|
|
38
|
-
|
|
39
|
-
Containers have a private ephemeral home, dropped capabilities, no-new-privileges and an init process. Only selected mounts and Git metadata are exposed. Git paths are remapped so Windows worktree pointers remain usable inside Linux. Credentials are passed through environment names rather than command-line values. A command-specific process group allows cancellation without destroying the warm environment.
|
|
40
|
-
|
|
41
|
-
The generated image contains Git, Node.js, Python, shell utilities and both agent CLIs. Modify the Dockerfile/Containerfile to install project tools. `outpost image build --file custom.Dockerfile --image custom:tag --uid 1000 --gid 1000` selects an alternative recipe. `outpost image remove` removes only the selected image.
|
|
42
|
-
|
|
43
|
-
## Explicit host execution
|
|
44
|
-
|
|
45
|
-
```ts
|
|
46
|
-
import { local } from "@elie-laloum/outpost/providers/local";
|
|
47
|
-
const result = await dispatch({
|
|
48
|
-
agent: codex(),
|
|
49
|
-
provider: local(),
|
|
50
|
-
brief: { text: "Inspect the project." },
|
|
51
|
-
});
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
This is unisolated execution using your OS account and environment. Install/authenticate the CLI on the host. Outpost never silently falls back to host execution if a container fails. The host adapter does not elevate privileges.
|
|
55
|
-
|
|
56
|
-
## Vercel
|
|
57
|
-
|
|
58
|
-
```sh
|
|
59
|
-
npm install @vercel/sandbox
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
```ts
|
|
63
|
-
import { vercel } from "@elie-laloum/outpost/providers/vercel";
|
|
64
|
-
|
|
65
|
-
const provider = vercel({
|
|
66
|
-
create: { timeout: 30 * 60 * 1000 },
|
|
67
|
-
variables: { OPENAI_API_KEY: process.env.OPENAI_API_KEY! },
|
|
68
|
-
});
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
`create` accepts the installed SDK's sandbox-creation options, including credentials, runtime/image, networking and resources. Credential discovery follows the SDK. `root` can override the remote workspace directory; `retain` controls captured output tails. The provider discovers the actual remote home. Outpost installs the chosen agent in a user-writable prefix if it is missing; set `bootstrap: false` on `createSandbox`/`dispatch` when managing tools yourself.
|
|
72
|
-
|
|
73
|
-
## Daytona
|
|
74
|
-
|
|
75
|
-
```sh
|
|
76
|
-
npm install @daytona/sdk
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
```ts
|
|
80
|
-
import { daytona } from "@elie-laloum/outpost/providers/daytona";
|
|
81
|
-
|
|
82
|
-
const provider = daytona({
|
|
83
|
-
connection: { apiKey: process.env.DAYTONA_API_KEY },
|
|
84
|
-
create: { language: "typescript" },
|
|
85
|
-
});
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
`connection` is the SDK client configuration. `create` accepts an image/snapshot sandbox configuration. The remote environment must provide Node.js, npm, Git, `sh` and `setsid`. `root`, `variables`, and `retain` are available. Native process sessions stream both output channels and are cleaned up after each invocation. Cancellation terminates only the command process group.
|
|
89
|
-
|
|
90
|
-
## Remote Git transport
|
|
91
|
-
|
|
92
|
-
Remote workspaces default to temporary integration branches and start from committed Git history. `includeUncommitted: true` explicitly sends the host patch and untracked files. Otherwise pre-existing host edits are preserved and overlapping remote edits are rejected before local mutation. Selected copied inputs are uploaded too. Each dispatch, command or terminal completion synchronizes back. New commits retain their object IDs, authors, timestamps and parent relationships. Repeated synchronization handles uncommitted work later becoming committed without duplicating commits.
|
|
93
|
-
|
|
94
|
-
Outpost compares host state with its last synchronized state. Concurrent local edits cause a recovery error. Before applying remote changes it saves patches, untracked files and incoming commits in `.outpost/recovery`. Rewritten/non-fast-forward remote history is rejected. Relative transfer paths are validated, and local symlink-parent traversal is rejected.
|
|
95
|
-
|
|
96
|
-
## Custom providers
|
|
97
|
-
|
|
98
|
-
`mountedProvider({ name, variables?, acquire })` and `remoteProvider({ name, variables?, acquire })` wrap your own backend. `acquire(context)` receives repository/workspace paths, Git metadata directories, resolved variables and a signal. Return a `SandboxLease`:
|
|
99
|
-
|
|
100
|
-
```ts
|
|
101
|
-
interface SandboxLease {
|
|
102
|
-
root: string;
|
|
103
|
-
home: string;
|
|
104
|
-
invoke(command: Command): Promise<CommandResult>;
|
|
105
|
-
upload(
|
|
106
|
-
source: string,
|
|
107
|
-
destination: string,
|
|
108
|
-
options?: TransferOptions,
|
|
109
|
-
): Promise<void>;
|
|
110
|
-
download(
|
|
111
|
-
source: string,
|
|
112
|
-
destination: string,
|
|
113
|
-
options?: TransferOptions,
|
|
114
|
-
): Promise<void>;
|
|
115
|
-
release(): Promise<void>;
|
|
116
|
-
}
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
`invoke` must stream output to `observe`, respect abort/deadline, and leave the lease reusable after cancellation. `release` must be idempotent. Transfer options contain `signal` and `deadlineMs`; custom transfers must stop writing after cancellation. Outpost bounds the wait, but cannot forcibly cancel arbitrary user callbacks. Cloud SDK requests already sent may finish remotely; built-in downloads check cancellation before writing returned bytes. Remote providers must support Git and file transfer; Outpost performs synchronization through those capabilities. Interactive support is optional but unsupported calls must fail clearly. Cloud factories also accept an optional connection factory for contract tests or custom SDK wiring.
|