@intentic/machine 1.317.0 → 1.319.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 (125) hide show
  1. package/README.md +186 -11
  2. package/dist/commands.d.ts.map +1 -1
  3. package/dist/commands.js +2 -2
  4. package/dist/commands.js.map +1 -1
  5. package/dist/device/commands.d.ts +3 -1
  6. package/dist/device/commands.d.ts.map +1 -1
  7. package/dist/device/commands.js +2 -2
  8. package/dist/device/commands.js.map +1 -1
  9. package/dist/device/connection.d.ts +1 -0
  10. package/dist/device/connection.d.ts.map +1 -1
  11. package/dist/device/connection.js +5 -0
  12. package/dist/device/connection.js.map +1 -1
  13. package/dist/device/grant.d.ts +38 -0
  14. package/dist/device/grant.d.ts.map +1 -1
  15. package/dist/device/loopback-catch.d.ts +3 -0
  16. package/dist/device/loopback-catch.d.ts.map +1 -0
  17. package/dist/device/loopback-catch.js +103 -0
  18. package/dist/device/loopback-catch.js.map +1 -0
  19. package/dist/device/mcp.d.ts.map +1 -1
  20. package/dist/device/mcp.js +8 -1
  21. package/dist/device/mcp.js.map +1 -1
  22. package/dist/device/router.d.ts +38 -0
  23. package/dist/device/router.d.ts.map +1 -1
  24. package/dist/device/router.js +3 -1
  25. package/dist/device/router.js.map +1 -1
  26. package/dist/device/sandbox-cli.d.ts +3 -0
  27. package/dist/device/sandbox-cli.d.ts.map +1 -1
  28. package/dist/device/sandbox-cli.js +42 -0
  29. package/dist/device/sandbox-cli.js.map +1 -1
  30. package/dist/device/sandbox-rounds/ic-rounds.d.ts +3 -4
  31. package/dist/device/sandbox-rounds/ic-rounds.d.ts.map +1 -1
  32. package/dist/device/sandbox-rounds/ic-rounds.js +9 -3
  33. package/dist/device/sandbox-rounds/ic-rounds.js.map +1 -1
  34. package/dist/device/sandbox-rounds/keeper.d.ts +95 -0
  35. package/dist/device/sandbox-rounds/keeper.d.ts.map +1 -0
  36. package/dist/device/sandbox-rounds/keeper.js +277 -0
  37. package/dist/device/sandbox-rounds/keeper.js.map +1 -0
  38. package/dist/device/sandbox-rounds/swap-records.d.ts +1 -0
  39. package/dist/device/sandbox-rounds/swap-records.d.ts.map +1 -1
  40. package/dist/device/sandbox-rounds/swap-records.js +7 -0
  41. package/dist/device/sandbox-rounds/swap-records.js.map +1 -1
  42. package/dist/device/tools/agent.d.ts +2 -2
  43. package/dist/device/tools/agent.d.ts.map +1 -1
  44. package/dist/device/tools/agent.js +1 -3
  45. package/dist/device/tools/agent.js.map +1 -1
  46. package/dist/device/tools/describe.d.ts +1 -1
  47. package/dist/device/tools/describe.d.ts.map +1 -1
  48. package/dist/device/tools/describe.js +2 -1
  49. package/dist/device/tools/describe.js.map +1 -1
  50. package/dist/device/tools/in-flight.d.ts +6 -0
  51. package/dist/device/tools/in-flight.d.ts.map +1 -0
  52. package/dist/device/tools/in-flight.js +26 -0
  53. package/dist/device/tools/in-flight.js.map +1 -0
  54. package/dist/device/tools/sandboxes.d.ts +19 -7
  55. package/dist/device/tools/sandboxes.d.ts.map +1 -1
  56. package/dist/device/tools/sandboxes.js +90 -20
  57. package/dist/device/tools/sandboxes.js.map +1 -1
  58. package/dist/environments/machine.d.ts +1 -0
  59. package/dist/environments/machine.d.ts.map +1 -1
  60. package/dist/environments/machine.js.map +1 -1
  61. package/dist/resident.d.ts +12 -1
  62. package/dist/resident.d.ts.map +1 -1
  63. package/dist/resident.js +45 -14
  64. package/dist/resident.js.map +1 -1
  65. package/dist/status.d.ts.map +1 -1
  66. package/dist/status.js +9 -4
  67. package/dist/status.js.map +1 -1
  68. package/dist/sync/commands.d.ts +21 -1
  69. package/dist/sync/commands.d.ts.map +1 -1
  70. package/dist/sync/commands.js +91 -20
  71. package/dist/sync/commands.js.map +1 -1
  72. package/dist/sync/config.d.ts +10 -1
  73. package/dist/sync/config.d.ts.map +1 -1
  74. package/dist/sync/config.js +42 -1
  75. package/dist/sync/config.js.map +1 -1
  76. package/dist/sync/folders.d.ts +8 -0
  77. package/dist/sync/folders.d.ts.map +1 -0
  78. package/dist/sync/folders.js +34 -0
  79. package/dist/sync/folders.js.map +1 -0
  80. package/dist/sync/git-bridge.d.ts +1 -1
  81. package/dist/sync/git-bridge.d.ts.map +1 -1
  82. package/dist/sync/git-bridge.js +2 -1
  83. package/dist/sync/git-bridge.js.map +1 -1
  84. package/dist/sync/mirror.d.ts.map +1 -1
  85. package/dist/sync/mirror.js +3 -3
  86. package/dist/sync/mirror.js.map +1 -1
  87. package/dist/sync/mutagen.d.ts +16 -3
  88. package/dist/sync/mutagen.d.ts.map +1 -1
  89. package/dist/sync/mutagen.js +40 -22
  90. package/dist/sync/mutagen.js.map +1 -1
  91. package/dist/sync/project-commands.d.ts +23 -0
  92. package/dist/sync/project-commands.d.ts.map +1 -0
  93. package/dist/sync/project-commands.js +212 -0
  94. package/dist/sync/project-commands.js.map +1 -0
  95. package/dist/sync/project-files.d.ts +42 -0
  96. package/dist/sync/project-files.d.ts.map +1 -0
  97. package/dist/sync/project-files.js +110 -0
  98. package/dist/sync/project-files.js.map +1 -0
  99. package/dist/sync/project-local.d.ts +46 -0
  100. package/dist/sync/project-local.d.ts.map +1 -0
  101. package/dist/sync/project-local.js +217 -0
  102. package/dist/sync/project-local.js.map +1 -0
  103. package/dist/sync/project-remote.d.ts +55 -0
  104. package/dist/sync/project-remote.d.ts.map +1 -0
  105. package/dist/sync/project-remote.js +261 -0
  106. package/dist/sync/project-remote.js.map +1 -0
  107. package/dist/sync/project-transfer.d.ts +52 -0
  108. package/dist/sync/project-transfer.d.ts.map +1 -0
  109. package/dist/sync/project-transfer.js +278 -0
  110. package/dist/sync/project-transfer.js.map +1 -0
  111. package/dist/sync/report.d.ts.map +1 -1
  112. package/dist/sync/report.js +6 -4
  113. package/dist/sync/report.js.map +1 -1
  114. package/dist/sync/residue.d.ts.map +1 -1
  115. package/dist/sync/residue.js +2 -1
  116. package/dist/sync/residue.js.map +1 -1
  117. package/dist/sync/restore-points.d.ts +72 -0
  118. package/dist/sync/restore-points.d.ts.map +1 -0
  119. package/dist/sync/restore-points.js +154 -0
  120. package/dist/sync/restore-points.js.map +1 -0
  121. package/dist/sync/ssh.d.ts +3 -0
  122. package/dist/sync/ssh.d.ts.map +1 -1
  123. package/dist/sync/ssh.js +13 -4
  124. package/dist/sync/ssh.js.map +1 -1
  125. package/package.json +8 -8
package/README.md CHANGED
@@ -21,7 +21,10 @@ flowchart LR
21
21
  the intentic sandboxes on this machine through the `ic` CLI.
22
22
  - The sandbox tools are thin callers of `ic` ([`tools/sandboxes.ts`](src/device/tools/sandboxes.ts)): the listing is
23
23
  `ic sandbox list --json` passed through, and start, stop, restart, the swaps, `set-shape`, `forget-shape` and the
24
- logs are ic's own verbs, argv spelled by the contract (`icShapeArgs`, `icPowerArgs`). The shape reaches ic as the
24
+ logs are ic's own verbs, argv spelled by the contract (`icShapeArgs`, `icPowerArgs`). `diagnose_sandbox` is
25
+ `ic sandbox doctor <slug> --json`, read-only and gated like the logs (`shell` or `sandboxes`), so an agent in another
26
+ sandbox can find out why one on this device is unreachable; it skips the listing, which cannot answer while Docker is
27
+ down, and refuses a slug ic would read as a flag. The shape reaches ic as the
25
28
  contract's own object (`--set memoryGib=12`), so no flag of ic's is spelled here; the old `reshape` op is carried
26
29
  out through the same verb. A rollback's `to` becomes `ic sandbox rollback <slug> --to <version>`. A sandbox an
27
30
  interrupted swap left parked is listed under its own slug and found like any other, so start, rollback and update
@@ -33,14 +36,25 @@ flowchart LR
33
36
  A fetch that fails is logged with its reason and reported in the device's facts (`icOutOfDate`, beside `features`),
34
37
  so a stale `ic` explains why logs and saving a shape are missing; the next sandbox action tries again.
35
38
  - **sync** (`src/sync/`): `sync setup` enrolls an SSH key and runs Mutagen against the sandbox's sshd, reached
36
- through a loopback port tunnelled over a WebSocket. It keeps a folder two-way synced, forwards every workspace
37
- port to the same localhost port, and fast-forwards local git clones from the sandbox.
39
+ through a loopback port tunnelled over a WebSocket. It keeps a folder two-way synced (a project copy-first, below),
40
+ forwards every workspace port to the same localhost port, and fast-forwards local git clones from the sandbox.
41
+ - A **project pairing** (`sync setup --remote-dir /work/<name> --project`, what the desktop app asks for when it
42
+ makes a sandbox for a folder the owner picked) syncs that folder with `/work/<name>` rather than `/work`, and nothing
43
+ of the sandbox's is written into it: no state backup session, no git bridge, and an ignore list that keeps a
44
+ project's own `.intentic/` and `refs/` ([`sync/config.ts`](src/sync/config.ts) holds a remote dir to those two
45
+ shapes, and refuses `sync.json` whole otherwise). `setup` refuses a folder that is, holds or sits inside another
46
+ sandbox's, and a set-up-again that would change where a paired sandbox's folder syncs. It is **copy-first** unless
47
+ its owner opted into two-way: see [Copy-first projects](#copy-first-projects).
38
48
  - Only the resident agent creates Mutagen sessions: `setup` records the pairing and waits for the session to
39
49
  appear, since two creators racing left one name holding two identical sessions. The agent keeps one session per
40
- name, terminating any extras, and recreates a session whose rules drifted once there are no conflicts left.
50
+ name, terminating any extras, and recreates a session whose rules drifted (its ignores, its folders, its sync mode,
51
+ its symlink mode). A two-way session replaced by another waits until no conflicts are left and has its derived
52
+ residue swept first; every other replacement happens as soon as the sandbox answers (`settlesFirst` in
53
+ [`sync/mutagen.ts`](src/sync/mutagen.ts) says why for each).
41
54
  - `setup` replaces what this agent's `known_hosts` holds for the pairing's alias (hashed entries included): with the
42
- host key the enrollment carries when it carries one, else with nothing, so `accept-new` records the key the sandbox
43
- presents now. Outside an enrollment a changed key is still refused. A sandbox whose ports poll has failed for ten
55
+ host key the enrollment carries when it carries one (a sandbox reads its sshd's public key off its history volume and
56
+ answers with it, `SyncEnrollmentAnswerSchema` in the contract), else with nothing, so `accept-new` records the key
57
+ the sandbox presents now, as it does for an older sandbox. Outside an enrollment a changed key is still refused. A sandbox whose ports poll has failed for ten
44
58
  minutes has its forwards taken off localhost, and they come back with its first answer. `sync uninstall` stops and
45
59
  unregisters Mutagen's daemon only when it is this agent's own copy, never a Mutagen the user installed.
46
60
  - Symbolic links travel only where the device can create them ([`sync/symlinks.ts`](src/sync/symlinks.ts)). A
@@ -63,18 +77,135 @@ flowchart LR
63
77
  - Scopes are enforced here and nowhere else: the sandbox only asks, and a refusal names the switch that is off.
64
78
  Files stay inside the configured roots, writes need their own switch, and every call is appended to
65
79
  `~/.intentic/machine/audit.jsonl`. While an agent drives input on Windows, a notice shows on screen and
66
- `PAUSE_HOTKEY` pauses every link.
67
- - Every connection dials out; the only listeners are on loopback.
80
+ `PAUSE_HOTKEY` pauses every link. The one door behind no switch is this agent's own Update and Restart
81
+ (`runAgentFlow`, [`device/tools/agent.ts`](src/device/tools/agent.ts)): no agent tool reaches it, and the sandbox
82
+ admits only a maintainer to it, so the owner's maintenance does not wait on the agents' "Run commands" (2026-09-29;
83
+ it rode that switch before, and an owner had to widen what agents may do to update the agent).
84
+ - Every connection dials out; the only listeners are on loopback. One of them is short-lived: while a sandbox's
85
+ sign-in is open, [`device/loopback-catch.ts`](src/device/loopback-catch.ts) listens on the
86
+ `http://localhost:<port>/…` address the provider redirects to, the one a CLI running here would have held, and
87
+ streams each landing back (`catchLoopback`, advertised as the `loopback-catch` feature). It checks nothing: the state
88
+ and the PKCE verifier stay in the sandbox, which alone can tell the sign-in from anything else that hits the port. A
89
+ taken port answers `busy`, and the sandbox leaves the paste to the person.
68
90
  - On Windows the Windows side is the root of the PC (`src/environments/`): it holds one `wsl.exe` session per
69
91
  distro with an agent, and `upgrade` brings every environment to the same release. The root also updates itself
70
92
  on a timer and pre-downloads sandbox updates with `ic sandbox prepare --auto`.
71
93
  - The install shims only put a first binary down and run `setup`; `install.ts` decides the rest. `status --json`
72
94
  is what the desktop app's tray reads.
73
95
 
96
+ ### Copy-first projects
97
+
98
+ A project's folder flows **one way**, this device to the sandbox, so nothing an agent does in `/work/<name>` (an
99
+ `rm -rf` included) reaches the owner's files. What an agent changed comes back only when the owner asks, through
100
+ `sync bring-back`, which keeps a restore point first. Two-way stays one switch away.
101
+
102
+ - **Direction** is the pairing's `direction` in `sync.json`: `"to-sandbox"` (Mutagen's `one-way-safe`, this device as
103
+ alpha) or `"both"` (`two-way-safe`, as every workspace pairing). Absent, as on every project paired before it existed,
104
+ means `"to-sandbox"`, and so does a value this build has no word for; it means nothing on a workspace pairing
105
+ ([`sync/config.ts`](src/sync/config.ts) `projectDirection`). An older agent keeps the field through every write but a
106
+ `setup` (which resets it, with the pairing's other switches), and keeps the copy-first session it finds, since it never
107
+ compared sync modes. `sync direction` rewrites the field; the watcher sees the new mode on its next tick and recreates
108
+ the session (`sessionMatchesSpec` compares the live session's `mode`).
109
+ - **Replacements** into copy-first happen at once, conflicts or not, with no flush and no residue sweep: a last flush
110
+ of a two-way session would carry the sandbox's latest changes into the folder, and the new session never writes here.
111
+ Out of copy-first too: a one-way session's conflicts are the agent's kept edits, which differ whoever holds them. This
112
+ is how every existing project becomes copy-first on its first start of this build.
113
+
114
+ **What one-way-safe does**, measured with Mutagen 0.18.1 over ssh against an sshd whose `/work` was a scratch folder,
115
+ driving this agent's own session code and CLI (alpha is this device, beta the sandbox):
116
+
117
+ | The sandbox (an agent)… | Mutagen one-way-safe |
118
+ |---|---|
119
+ | edits a file this folder has | keeps the sandbox's version and reports it as a conflict; this folder is untouched |
120
+ | creates a file | keeps it in the sandbox, no conflict; nothing reaches this folder |
121
+ | deletes a file or a folder | puts it back from this folder on the next cycle |
122
+ | runs `rm -rf /work/<name>/*`, or removes `/work/<name>` | refills the sandbox's copy from this folder; this folder is untouched |
123
+
124
+ | This device… | Mutagen one-way-safe |
125
+ |---|---|
126
+ | edits, creates or deletes a file | carries it to the sandbox, except over a file the sandbox changed, which is kept |
127
+ | deletes a file the sandbox changed | the sandbox keeps its version, and the conflict clears |
128
+
129
+ A fresh session over two copies that already differ (what any replacement starts from) deletes nothing on either side.
130
+ One-way-safe copies what only this folder has into the sandbox and keeps every sandbox file that differs, as a conflict.
131
+ Two-way-safe also copies what only the sandbox has into this folder, and reports what differs on both as a conflict.
132
+ `mutagen sync list --template '{{json .}}'` prints the mode as a top-level `mode`, absent on a session created without
133
+ `--sync-mode`, which Mutagen runs two-way-safe.
134
+
135
+ **The commands**, all under `intentic-machine sync`, name the project by `--dir <its folder>` (links resolved, case
136
+ folded where the platform folds it). With `--json` each prints exactly one JSON object on stdout, and on failure
137
+ `{ "ok": false, "error": "<sentence>" }` with exit code 1. The desktop app parses these, so fields are only ever added.
138
+
139
+ | Command | Success output |
140
+ |---|---|
141
+ | `sync changes` | `{ "ok": true, "pairing": "<id>", "direction": "to-sandbox"\|"both", "changes": [{ "path", "kind": "added"\|"modified"\|"deleted", "size"?, "conflict"?: true }], "truncated"?: true }` |
142
+ | `sync bring-back [--path <p>]... [--paths-file <file>]` | `{ "ok": true, "point": "<id>", "applied": [{ "path", "kind" }], "skipped": [{ "path", "reason" }] }` |
143
+ | `sync restore-points` | `{ "ok": true, "points": [{ "id", "createdAt", "entries": n }] }` |
144
+ | `sync restore --point <id>` | `{ "ok": true, "restored": n, "skipped": [{ "path", "reason" }] }` |
145
+ | `sync direction <to-sandbox\|both>` | `{ "ok": true, "direction": "…" }` |
146
+
147
+ - **`sync changes`** lists what the sandbox did, relative paths with `/`, sorted, the first 5,000 (`truncated` when
148
+ there were more): `added` exists only in the sandbox's copy, `modified` on both with different content (`size` is the
149
+ sandbox copy's), `deleted` was removed there. The sandbox is listed by ONE command over the pairing's ssh alias, a
150
+ node program that walks `/work/<name>` and prints path, size and sha256 NUL-separated, so any name survives. This
151
+ device is walked the same way, reading a file only where its size matches the sandbox's, through a hash cache keyed
152
+ by path, size and times in `~/.intentic/machine/hashes/<pairing>.json`. Both walks prune by the pairing's ignore list
153
+ read as Mutagen reads it: a name, `*` within it, at any depth (or at the root with a leading `/`), taking a matched
154
+ folder's contents along; any other spelling is refused rather than approximated. Mutagen's `.mutagen-temporary-*`
155
+ scratch files are left out too, and so are links and anything else that is not a regular file, on either side.
156
+ - **Whose change it is, and never over a newer edit.** The same cache file records each path's content when both
157
+ copies were last seen equal. A difference the sandbox did not move away from (an edit made here, still on its way) is
158
+ not listed at all. A file only this device holds is offered as `deleted` only when that record shows the sandbox had
159
+ exactly this copy. A `modified` file is written over here only when this device's copy is still what the two last
160
+ agreed on, which only a session that was running and whose flush just finished a whole cycle can show. Mutagen's own
161
+ record says so for the files it reports in conflict (ten at most, each with SHA-1 digests of what the two last agreed
162
+ on and of this device's copy, the latter checked against the file here now); the listing record says so for the rest.
163
+ Anything else is listed with `conflict: true` and skipped by bring-back with its reason, even when named by `--path`:
164
+ both copies moved (a record gone stale while the sync was paused, say, with the owner's own older version in the
165
+ sandbox), no record of the two ever agreeing on it, or a session that was paused, absent, or whose flush did not
166
+ finish. Since one-way-safe puts an agent's deletions back, `deleted` shows up mainly while the session is paused, and
167
+ a rename in the sandbox comes back as an addition (the old name is put back there). The record is written only by
168
+ whoever holds the folder's lock, so a listing beside a running bring-back never undoes what that one recorded.
169
+ - **`sync bring-back`** runs with the session paused (after a flush) if it was running, and leaves one somebody paused
170
+ as it is. It lists both sides and fetches the `added` and `modified` files in ONE ssh stream into a private staging
171
+ folder, each checked against the listing's sha256 (a file that changed since is skipped with the reason). Then it
172
+ writes the restore point, and only then touches the folder: each file renamed into place from a copy beside it, only
173
+ where the folder still holds what the point kept of it. `deleted` files are removed with the folders they leave
174
+ empty. `--path` takes a file or a folder, repeatable; `--paths-file` names a UTF-8 file holding a JSON array of such
175
+ paths (a Windows command line holds 32,767 characters, fewer than a long selection), taken together with any
176
+ `--path`. An unreadable file, one that is not such an array, or an empty one (which would otherwise mean every change)
177
+ is refused before anything is listed. A new file gets the sandbox copy's executable bit. Nothing is written through a
178
+ link: every folder on the way is checked.
179
+ - **Why the session pushes nothing stale back.** Paused, it runs no cycle between the listing, the fetch and the writes,
180
+ and on resume it rescans both sides. What was written here is byte for byte the sandbox's, so both sides moved from
181
+ their last agreement to the same content: Mutagen records that and transfers nothing. A sandbox file that changed
182
+ again meanwhile is a sandbox modification one-way-safe keeps, as a conflict. The e2e run checked all of it: no
183
+ conflicts after resume, the sandbox still holding the agent's content, and a later edit here carried over as usual.
184
+ - **Restore points** live in `~/.intentic/machine/restore/<pairing>/<id>/`, the id being the creation time in ISO 8601
185
+ basic format (`20260928T213000.123Z`, a folder name on every system). Each holds `manifest.json`, which is
186
+ `{ id, createdAt, dir, entries: [{ path, kind, backedUp, applied, backup?, mode? }] }` (`applied` is the sha256
187
+ bring-back left, null for a deletion), and `files/<path>`, a copy of every file bring-back overwrote or deleted. Only
188
+ what was actually written stays in the manifest. All of it is on the disk before the first write here: each copy is
189
+ flushed as it is made, the manifest by a durable write, then every folder of the point up to `restore/<pairing>`, so a
190
+ crash right after a bring-back never finds the folder rewritten and the copies empty. Files put in the folder are
191
+ flushed before the rename that places them.
192
+ - **Retention**, after each bring-back and under its lock: a pairing keeps its newest 20 points that hold files, plus
193
+ every such point younger than 30 days. A point that holds nothing (a bring-back that wrote nothing, or one cut off
194
+ before its manifest) never counts toward the 20, is never listed, and goes at the next bring-back. Until then it is
195
+ the `point` that bring-back answered with, so that answer always names a real point, as the desktop app expects.
196
+ - **`sync restore --point <id>`** puts each backed-up file back and removes each file bring-back added, where the
197
+ folder still holds exactly what bring-back left (by sha256). Anything else is skipped and reported, one already put
198
+ back included. Copy-first then carries the restored files to the sandbox, as it does any edit here, so the agent's
199
+ versions they replace are gone from there too.
200
+ - One bring-back or restore runs per folder at a time (`restore/<pairing>/.operation.pid`, a pid of this boot, checked
201
+ alive). A pause an operation made and never lifted (the process killed in between) is recorded in
202
+ `restore/<pairing>/.paused`, and the next command about that folder resumes the session.
203
+
74
204
  ### Upgrades that can be undone
75
205
 
76
206
  - **A swap is never cut short by this agent.** `ic` runs in a process group of its own on POSIX, keeps its pipes, and
77
- is never killed when the link or request that asked for it goes away. Every restart of the agent (the auto-upgrade
207
+ is never killed when the link or request that asked for it goes away. The one run it ever stops is the keeper's
208
+ `sandbox fix` past its deadline (below), which is not a swap. Every restart of the agent (the auto-upgrade
78
209
  tick, `upgrade`, `run`, the browser's Update and Restart) waits while any channel record in this environment's ic
79
210
  home (`INTENTIC_HOME`, else `~/.intentic`) says `swap_phase=cutover` with `swap_at` in the last 30 minutes, or while
80
211
  this process runs a flow that moves a container ([`device/sandbox-rounds/swap-records.ts`](src/device/sandbox-rounds/swap-records.ts)); the tick
@@ -111,8 +242,52 @@ flowchart LR
111
242
  ([`tools/command-ledger.ts`](src/device/tools/command-ledger.ts)). The login entries of the two agents this one
112
243
  replaced on 2026-08-29 (`intentic-host`, the sync mirror) are removed once, at start.
113
244
  - `intentic-machine sandbox <verb> [slug]` passes `list`, `start`, `stop`, `restart`, `update`, `rollback [--to]`,
114
- `versions`, `logs`, `doctor`, `watch`, `backup` and `backups` straight to ic, in this terminal, with ic's exit code:
115
- a sandbox can be looked at and repaired from here when no browser reaches it.
245
+ `versions`, `logs`, `doctor`, `watch`, `backup`, `backups` and `fix [--code] [--auto] [--yes] [--accept] [--json]
246
+ [--source]` straight to ic, in this terminal, with ic's exit code: a sandbox can be looked at and repaired from here
247
+ when no browser reaches it, and `fix` asks here for the yes the keeper never gives.
248
+
249
+ ### The keeper
250
+
251
+ When a sandbox on this machine stops answering (Docker Desktop not started after a reboot, a stopped container, a
252
+ daemon whose registration gave up, a full disk), the agent heals what is safe to heal by itself and reports the rest
253
+ ([`device/sandbox-rounds/keeper.ts`](src/device/sandbox-rounds/keeper.ts)). ic does every fix; the keeper keeps the
254
+ clock.
255
+
256
+ - **When.** `ic sandbox fix --auto --json --source agent` over every sandbox half a minute after the agent starts (the
257
+ logon case: Docker Desktop is off by default after a reboot) and every five minutes, and `ic sandbox fix <slug> …` as
258
+ soon as the agent's link to a sandbox that runs on this machine has failed for a minute. A link's sandbox runs here
259
+ when this environment's ic has a record of it or listed it (by its hostname's first label or the id in it, as sync's
260
+ swap pause maps them), or when the agent has reached it over loopback.
261
+ - **What ic does by itself** under `--auto`: starts Docker Desktop and waits for it, starts a sandbox its owner did not
262
+ stop on purpose, restarts one whose registration gave up, tidies when the disk is low. It posts its report to the
263
+ platform itself; nothing comes back down to the device (there is no platform-to-device relay).
264
+ - **What the keeper never does**: apply a fix that needs a yes (each is logged with `intentic-machine sandbox fix
265
+ <slug>`, which asks in a terminal, as the desktop app's buttons and the recovery panel's command do), run two fixes at
266
+ once, run while the probation watch is running ic, fix a sandbox a swap is moving or one a flow of this agent holds,
267
+ or start the sweep while any flow runs. Each run holds the sandboxes it may touch as a flow that moves a container,
268
+ so the other rounds leave them alone and the agent does not restart under it.
269
+ - **Bounded.** A run is stopped after eight minutes (starting Docker Desktop alone can take five), with its process
270
+ group on POSIX and its process tree on Windows.
271
+ - **Waiting.** A sandbox whose run left something (needs-you, failed, no verdict) waits 3 minutes, then 6, 12, 24 and
272
+ 30 at most, and the wait ends when its link comes back. One ic found healthy or fixed while its link stays down is
273
+ asked about again after five minutes, not every ten seconds. The sweep's own cadence stretches on the same ladder
274
+ (never under five minutes) while a sweep leaves something. An ic that cannot fix (one from before `sandbox fix`,
275
+ which clap refuses with no JSON, or no ic at all) is said once and asked again on the same ladder.
276
+ - **The log** (`~/.intentic/machine/machine.log`, like every round): what ic is doing as it does it, and each
277
+ sandbox's verdict when it changes (a standing `healthy` or `needs-you` is said once per stretch; `fixed` always).
278
+ - **Where.** Every environment runs its own keeper, since `ic sandbox fix` knows only the sandboxes its own ic keeps
279
+ records of; a WSL distro's shares the Windows side's Docker Desktop.
280
+ - **The switch** is this environment's `sandboxKeeper` in `machine.json` (absent means on), set by
281
+ `intentic-machine sandbox keeper on|off` and read by `keeper status`. It is re-read every round.
282
+ - **It keeps the agent resident.** An agent with no link, no pairing and no distro to serve used to take its login
283
+ entry away and exit, and then nothing started Docker Desktop after the next reboot. It now stays while the keeper is
284
+ on and this machine hosts a sandbox other than a runner: the ones `ic sandbox list --json` names when Docker answers,
285
+ else the ones ic keeps a record of (a removed sandbox's record lasts until `ic sandbox tidy` archives it, so the
286
+ listing wins whenever it answers). The resident asks at start and then every five minutes, and only while it has
287
+ nothing else to serve. `keeper off` lets it go; `intentic-machine uninstall` retires it whatever this machine hosts,
288
+ while `device uninstall` and `sync uninstall` leave it running for the sandboxes here and say so (2026-09-30:
289
+ retiring as before was rejected, since a machine whose last link was revoked kept its sandbox down after every
290
+ reboot).
116
291
 
117
292
  ## Key files
118
293
 
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAoGjF,eAAO,MAAM,QAAQ,kDAoBnB,CAAC"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAqGjF,eAAO,MAAM,QAAQ,kDAoBnB,CAAC"}
package/dist/commands.js CHANGED
@@ -64,8 +64,8 @@ const uninstall = buildCommand({
64
64
  parameters: {},
65
65
  async func() {
66
66
  const out = (message) => void this.process.stdout.write(`${message}\n`);
67
- await syncUninstall(out);
68
- await deviceUninstall(out);
67
+ await syncUninstall(out, undefined, { forGood: true });
68
+ await deviceUninstall(out, undefined, { forGood: true });
69
69
  const still = await readResident();
70
70
  out(still === undefined
71
71
  ? "Nothing intentic stays resident here."
@@ -1 +1 @@
1
- {"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,8 @@
1
1
  import { type Log } from "@intentic/local-agent";
2
2
  import { type CommandContext } from "@stricli/core";
3
- export declare const deviceUninstall: (out: Log, sandbox?: string) => Promise<void>;
3
+ export declare const deviceUninstall: (out: Log, sandbox?: string, { forGood }?: {
4
+ readonly forGood?: boolean;
5
+ }) => Promise<void>;
4
6
  export declare const dropUnreachableLinks: (out: Log) => Promise<void>;
5
7
  export declare const deviceCommands: {
6
8
  setup: import("@stricli/core").Command<CommandContext>;
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/device/commands.ts"],"names":[],"mappings":"AAGA,OAAO,EAAY,KAAK,GAAG,EAA0B,MAAM,uBAAuB,CAAC;AACnF,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAsHlE,eAAO,MAAM,eAAe,QAAe,GAAG,YAAY,MAAM,KAAG,OAAO,CAAC,IAAI,CAyB9E,CAAC;AAgBF,eAAO,MAAM,oBAAoB,QAAe,GAAG,KAAG,OAAO,CAAC,IAAI,CA0BjE,CAAC;AAEF,eAAO,MAAM,cAAc;;;;CAAgE,CAAC"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/device/commands.ts"],"names":[],"mappings":"AAGA,OAAO,EAAY,KAAK,GAAG,EAA0B,MAAM,uBAAuB,CAAC;AACnF,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAsHlE,eAAO,MAAM,eAAe,QAAe,GAAG,YAAY,MAAM,gBAAuB;IAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,KAAQ,OAAO,CAAC,IAAI,CAyBxI,CAAC;AAgBF,eAAO,MAAM,oBAAoB,QAAe,GAAG,KAAG,OAAO,CAAC,IAAI,CA0BjE,CAAC;AAEF,eAAO,MAAM,cAAc;;;;CAAgE,CAAC"}
@@ -79,7 +79,7 @@ const uninstall = buildCommand({
79
79
  await deviceUninstall(out, flags.sandbox);
80
80
  },
81
81
  });
82
- export const deviceUninstall = async (out, sandbox) => {
82
+ export const deviceUninstall = async (out, sandbox, { forGood = false } = {}) => {
83
83
  const only = sandbox === undefined || sandbox === "" ? undefined : sandbox;
84
84
  const dropped = await removeLinks(only);
85
85
  const left = await readLinks();
@@ -90,7 +90,7 @@ export const deviceUninstall = async (out, sandbox) => {
90
90
  if (left.length === 0) {
91
91
  await rm(configPath, { force: true });
92
92
  }
93
- await ensureResident(out);
93
+ await ensureResident(out, { forGood });
94
94
  if (left.length > 0) {
95
95
  out(`Disconnected from ${dropped.map((link) => link.sandboxUrl).join(", ")}. Still connected to ${left.length} sandbox${left.length === 1 ? "" : "es"}.`);
96
96
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/device/commands.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/device/commands.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,7 @@ export interface Dial {
7
7
  readonly resolveBase: (sandboxUrl: string) => Promise<DaemonBase>;
8
8
  readonly socket: (url: string) => WebSocket;
9
9
  }
10
+ export declare const reachedOverLoopback: ReadonlySet<string>;
10
11
  declare const forgetLink: (sandboxUrl: string) => Promise<void>;
11
12
  export declare const connect: (config: HostLink, version: string, log: Log, dial?: Dial, forget?: typeof forgetLink, indicator?: Indicator) => PeerLink;
12
13
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/device/connection.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAkD,KAAK,QAAQ,EAAE,MAAM,sCAAsC,CAAC;AAErH,OAAO,EAAE,KAAK,UAAU,EAAqB,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,KAAK,QAAQ,EAA+B,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,KAAK,SAAS,EAAoB,MAAM,gBAAgB,CAAC;AASlE,MAAM,WAAW,IAAI;IACjB,QAAQ,CAAC,WAAW,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAClE,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,SAAS,CAAC;CAC/C;AAKD,QAAA,MAAM,UAAU,eAAsB,MAAM,KAAG,OAAO,CAAC,IAAI,CAAyC,CAAC;AAErG,eAAO,MAAM,OAAO,WACR,QAAQ,WACP,MAAM,OACV,GAAG,SACF,IAAI,0CAEC,SAAS,KACrB,QA4DF,CAAC"}
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/device/connection.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAkD,KAAK,QAAQ,EAAE,MAAM,sCAAsC,CAAC;AAErH,OAAO,EAAE,KAAK,UAAU,EAAqB,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,KAAK,QAAQ,EAA+B,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,KAAK,SAAS,EAAoB,MAAM,gBAAgB,CAAC;AASlE,MAAM,WAAW,IAAI;IACjB,QAAQ,CAAC,WAAW,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAClE,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,SAAS,CAAC;CAC/C;AAQD,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAAgB,CAAC;AAGrE,QAAA,MAAM,UAAU,eAAsB,MAAM,KAAG,OAAO,CAAC,IAAI,CAAyC,CAAC;AAErG,eAAO,MAAM,OAAO,WACR,QAAQ,WACP,MAAM,OACV,GAAG,SACF,IAAI,0CAEC,SAAS,KACrB,QA+DF,CAAC"}
@@ -8,6 +8,8 @@ import { rememberScopes, removeLinks } from "./config.js";
8
8
  import { machineIndicator } from "./indicator.js";
9
9
  import { createHostRouter } from "./router.js";
10
10
  const realDial = { resolveBase: resolveDaemonBase, socket: (url) => new WebSocket(url) };
11
+ const loopbackUrls = new Set();
12
+ export const reachedOverLoopback = loopbackUrls;
11
13
  const forgetLink = async (sandboxUrl) => void (await removeLinks(sandboxUrl));
12
14
  export const connect = (config, version, log, dial = realDial, forget = forgetLink, indicator = machineIndicator()) => {
13
15
  const linkLog = (message) => log(`${config.sandboxUrl}: ${message}`);
@@ -28,6 +30,9 @@ export const connect = (config, version, log, dial = realDial, forget = forgetLi
28
30
  if (signal.aborted) {
29
31
  return undefined;
30
32
  }
33
+ if (local) {
34
+ loopbackUrls.add(config.sandboxUrl);
35
+ }
31
36
  return {
32
37
  socket: dial.socket(hostConnectUrl(base)),
33
38
  said: `connected${local ? ` over loopback (${base})` : ""} as "${config.id}"`,
@@ -1 +1 @@
1
- {"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/device/connection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/device/connection.ts"],"names":[],"mappings":"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"}
@@ -73,6 +73,7 @@ export declare const tolerantDeviceContract: {
73
73
  sync: "sync";
74
74
  }>;
75
75
  localDir: z.ZodOptional<z.ZodString>;
76
+ remoteDir: z.ZodOptional<z.ZodString>;
76
77
  mirroring: z.ZodOptional<z.ZodEnum<{
77
78
  off: "off";
78
79
  on: "on";
@@ -242,6 +243,43 @@ export declare const tolerantDeviceContract: {
242
243
  message: z.ZodString;
243
244
  }, z.core.$strip>], "kind">;
244
245
  }, Record<never, never>, Record<never, never>>;
246
+ catchLoopback: import("@orpc/contract").ContractProcedureBuilderWithInputOutput<z.ZodObject<{
247
+ id: z.ZodString;
248
+ host: z.ZodEnum<{
249
+ "127.0.0.1": "127.0.0.1";
250
+ localhost: "localhost";
251
+ }>;
252
+ port: z.ZodNumber;
253
+ path: z.ZodString;
254
+ expiresAt: z.ZodNumber;
255
+ title: z.ZodString;
256
+ }, z.core.$strict>, import("@orpc/contract").Schema<AsyncIteratorObject<{
257
+ type: "listening";
258
+ } | {
259
+ type: "busy";
260
+ reason: string;
261
+ } | {
262
+ type: "landed";
263
+ url: string;
264
+ }, unknown, void>, import("@orpc/contract").AsyncIteratorClass<{
265
+ type: "listening";
266
+ } | {
267
+ type: "busy";
268
+ reason: string;
269
+ } | {
270
+ type: "landed";
271
+ url: string;
272
+ }, unknown, void>> & {
273
+ [x: symbol]: z.ZodDiscriminatedUnion<[z.ZodObject<{
274
+ type: z.ZodLiteral<"listening">;
275
+ }, z.core.$strip>, z.ZodObject<{
276
+ type: z.ZodLiteral<"busy">;
277
+ reason: z.ZodString;
278
+ }, z.core.$strip>, z.ZodObject<{
279
+ type: z.ZodLiteral<"landed">;
280
+ url: z.ZodString;
281
+ }, z.core.$strip>], "type">;
282
+ }, Record<never, never>, Record<never, never>>;
245
283
  setScopes: {
246
284
  "~orpc": {
247
285
  meta: Record<never, never>;
@@ -1 +1 @@
1
- {"version":3,"file":"grant.d.ts","sourceRoot":"","sources":["../../src/device/grant.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,YAAY,EAAkB,MAAM,4BAA4B,CAAC;AACnG,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAyE,CAAC;AACvG,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAM1D,MAAM,WAAW,KAAK;IAClB,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAED,eAAO,MAAM,SAAS,UAAW,UAAU,KAAG,KAK5C,CAAC;AAIH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAGlC,CAAC"}
1
+ {"version":3,"file":"grant.d.ts","sourceRoot":"","sources":["../../src/device/grant.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,YAAY,EAAkB,MAAM,4BAA4B,CAAC;AACnG,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAyE,CAAC;AACvG,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAM1D,MAAM,WAAW,KAAK;IAClB,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAED,eAAO,MAAM,SAAS,UAAW,UAAU,KAAG,KAK5C,CAAC;AAIH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAGlC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { LoopbackCatch, LoopbackCatchEvent } from "@intentic/sandbox-contract";
2
+ export declare function catchLoopback(spec: LoopbackCatch, signal: AbortSignal | undefined, log: (message: string) => void): AsyncGenerator<LoopbackCatchEvent>;
3
+ //# sourceMappingURL=loopback-catch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loopback-catch.d.ts","sourceRoot":"","sources":["../../src/device/loopback-catch.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AA6EpF,wBAAuB,aAAa,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,WAAW,GAAG,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,cAAc,CAAC,kBAAkB,CAAC,CAqD7J"}
@@ -0,0 +1,103 @@
1
+ import { createServer } from "node:http";
2
+ const LONGEST_WATCH_MS = 30 * 60_000;
3
+ const escapeHtml = (text) => text.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
4
+ const landedPage = (title) => `<!doctype html>
5
+ <html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <title>Signed in to ${escapeHtml(title)}</title>
7
+ <style>body{font:16px/1.5 system-ui,sans-serif;margin:0;min-height:100vh;display:grid;place-items:center;background:#0f1115;color:#e6e6e6}main{max-width:28rem;padding:2rem;text-align:center}h1{font-size:1.25rem;margin:0 0 .5rem}p{margin:0;color:#a0a4ab}</style>
8
+ </head><body><main><h1>Signed in to ${escapeHtml(title)}</h1><p>Intentic is finishing the connection. You can close this tab and go back to it.</p></main></body></html>`;
9
+ const listen = (server, port, address) => new Promise((resolve) => {
10
+ const onError = (error) => resolve({ ok: false, code: error.code, message: error.message });
11
+ server.once("error", onError);
12
+ server.listen({ port, host: address, exclusive: true }, () => {
13
+ server.off("error", onError);
14
+ resolve({ ok: true });
15
+ });
16
+ });
17
+ const bind = async (spec, onRequest) => {
18
+ const addresses = spec.host === "localhost" ? ["127.0.0.1", "::1"] : ["127.0.0.1"];
19
+ const servers = [];
20
+ const sockets = new Set();
21
+ const close = async () => {
22
+ for (const socket of sockets) {
23
+ socket.destroy();
24
+ }
25
+ await Promise.all(servers.map((server) => new Promise((resolve) => server.close(() => resolve()))));
26
+ };
27
+ for (const [index, address] of addresses.entries()) {
28
+ const server = createServer(onRequest);
29
+ server.on("connection", (socket) => {
30
+ sockets.add(socket);
31
+ socket.on("close", () => sockets.delete(socket));
32
+ });
33
+ const bound = await listen(server, spec.port, address);
34
+ if (bound.ok) {
35
+ servers.push(server);
36
+ continue;
37
+ }
38
+ if (index === 0) {
39
+ await close();
40
+ return {
41
+ ok: false,
42
+ reason: bound.code === "EADDRINUSE" ? `port ${spec.port} is already taken on this machine` : `could not listen on ${address}:${spec.port}: ${bound.message}`,
43
+ };
44
+ }
45
+ }
46
+ return { ok: true, close };
47
+ };
48
+ const landingUrl = (spec, request) => new URL(request.url ?? "/", `http://${spec.host}:${spec.port}`);
49
+ export async function* catchLoopback(spec, signal, log) {
50
+ const queue = [];
51
+ let wake;
52
+ let over = false;
53
+ const nudge = () => {
54
+ const resume = wake;
55
+ wake = undefined;
56
+ resume?.();
57
+ };
58
+ const end = () => {
59
+ over = true;
60
+ nudge();
61
+ };
62
+ const bound = await bind(spec, (request, response) => {
63
+ const url = landingUrl(spec, request);
64
+ if (request.method !== "GET" || url.pathname !== spec.path) {
65
+ response.writeHead(404, { "content-type": "text/plain; charset=utf-8" }).end("Not found");
66
+ return;
67
+ }
68
+ queue.push({ type: "landed", url: url.toString() });
69
+ nudge();
70
+ response
71
+ .writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store", "referrer-policy": "no-referrer" })
72
+ .end(landedPage(spec.title));
73
+ });
74
+ if (!bound.ok) {
75
+ log(`could not watch for the ${spec.title} sign-in: ${bound.reason}`);
76
+ yield { type: "busy", reason: bound.reason };
77
+ return;
78
+ }
79
+ log(`watching ${spec.host}:${spec.port}${spec.path} for the ${spec.title} sign-in`);
80
+ const deadline = setTimeout(end, Math.max(0, Math.min(spec.expiresAt - Date.now(), LONGEST_WATCH_MS)));
81
+ signal?.addEventListener("abort", end, { once: true });
82
+ try {
83
+ yield { type: "listening" };
84
+ for (;;) {
85
+ const next = queue.shift();
86
+ if (next !== undefined) {
87
+ yield next;
88
+ continue;
89
+ }
90
+ if (over || signal?.aborted === true) {
91
+ break;
92
+ }
93
+ await new Promise((resolve) => (wake = resolve));
94
+ }
95
+ }
96
+ finally {
97
+ clearTimeout(deadline);
98
+ signal?.removeEventListener("abort", end);
99
+ await bound.close();
100
+ log(`stopped watching ${spec.host}:${spec.port} for the ${spec.title} sign-in`);
101
+ }
102
+ }
103
+ //# sourceMappingURL=loopback-catch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loopback-catch.js","sourceRoot":"","sources":["../../src/device/loopback-catch.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/device/mcp.ts"],"names":[],"mappings":"AA6aA,eAAO,MAAM,gBAAgB;;;;;;;;kDAQ3B,CAAC"}
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/device/mcp.ts"],"names":[],"mappings":"AAsbA,eAAO,MAAM,gBAAgB;;;;;;;;kDAQ3B,CAAC"}
@@ -11,7 +11,7 @@ import { editTextFile, listDirectory, readTextFile, trashFile, writeTextFile } f
11
11
  import { focusWindow, listWindows, openTarget, readClipboard, writeClipboard } from "./tools/apps.js";
12
12
  import { clickElement, fillElement, listTabs, openPage, pressKey, readPage, selectTab, snapshotPage } from "./tools/browser.js";
13
13
  import { act, describeAction, settle } from "./tools/device.js";
14
- import { DEFAULT_LOG_LINES, forgetShape, listSandboxes, manageSandbox, MAX_LOG_LINES, removeSandbox, SandboxOpSchema, SandboxSwapSchema, sandboxLogs, shapeSandbox, swapSandbox, } from "./tools/sandboxes.js";
14
+ import { DEFAULT_LOG_LINES, diagnoseSandbox, forgetShape, listSandboxes, manageSandbox, MAX_LOG_LINES, removeSandbox, SandboxOpSchema, SandboxSwapSchema, sandboxLogs, shapeSandbox, swapSandbox, } from "./tools/sandboxes.js";
15
15
  import { DEFAULT_TIMEOUT_MS, describeResult, MAX_TIMEOUT_MS, runCommand } from "./tools/shell.js";
16
16
  import { MACHINE_VERSION } from "../version.js";
17
17
  const NO_ARGS = z.object({});
@@ -326,6 +326,13 @@ const TOOLS = [
326
326
  }),
327
327
  run: async ({ slug, lines }, scopes) => textResult(await sandboxLogs(slug, lines, scopes)),
328
328
  }),
329
+ tool({
330
+ name: "diagnose_sandbox",
331
+ description: "Check every link of one Intentic sandbox's reachability chain on this device (Docker, its container, its daemon, its registration with the platform, the network, the tunnel) and say what is broken and what fixes it, as JSON from the device's `ic sandbox doctor`. Changes nothing, and answers while Docker is down, when list_sandboxes cannot: how you find out why a sandbox on this device cannot be reached. Requires 'Run commands' or 'Manage sandboxes on this device'.",
332
+ effect: "read",
333
+ input: z.object({ slug: required.describe("The sandbox's slug, from list_sandboxes, or the first label of its address.") }),
334
+ run: async ({ slug }, scopes) => textResult(await diagnoseSandbox(slug, scopes)),
335
+ }),
329
336
  ];
330
337
  const auditDetail = (name, args) => {
331
338
  const redact = (name === "device" && args["action"] === "type") || (name === "clipboard" && args["action"] === "write") || name === "browser_fill";