@everywheredev/cli 0.0.5 → 0.0.7

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 (307) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +274 -59
  3. package/package.json +3 -2
  4. package/scripts/build.mjs +68 -0
  5. package/dist/agent/agent-loop.d.ts +0 -40
  6. package/dist/agent/agent-loop.d.ts.map +0 -1
  7. package/dist/agent/agent-loop.js +0 -162
  8. package/dist/agent/agent-loop.js.map +0 -1
  9. package/dist/agent/approval.d.ts +0 -38
  10. package/dist/agent/approval.d.ts.map +0 -1
  11. package/dist/agent/approval.js +0 -55
  12. package/dist/agent/approval.js.map +0 -1
  13. package/dist/agent/run-tracker.d.ts +0 -26
  14. package/dist/agent/run-tracker.d.ts.map +0 -1
  15. package/dist/agent/run-tracker.js +0 -43
  16. package/dist/agent/run-tracker.js.map +0 -1
  17. package/dist/auth/device-flow.d.ts +0 -61
  18. package/dist/auth/device-flow.d.ts.map +0 -1
  19. package/dist/auth/device-flow.js +0 -141
  20. package/dist/auth/device-flow.js.map +0 -1
  21. package/dist/auth/hydra-oauth-auth-provider.d.ts +0 -35
  22. package/dist/auth/hydra-oauth-auth-provider.d.ts.map +0 -1
  23. package/dist/auth/hydra-oauth-auth-provider.js +0 -153
  24. package/dist/auth/hydra-oauth-auth-provider.js.map +0 -1
  25. package/dist/auth/keychain.d.ts +0 -42
  26. package/dist/auth/keychain.d.ts.map +0 -1
  27. package/dist/auth/keychain.js +0 -138
  28. package/dist/auth/keychain.js.map +0 -1
  29. package/dist/auth/pkce.d.ts +0 -20
  30. package/dist/auth/pkce.d.ts.map +0 -1
  31. package/dist/auth/pkce.js +0 -44
  32. package/dist/auth/pkce.js.map +0 -1
  33. package/dist/auth/ports.d.ts +0 -25
  34. package/dist/auth/ports.d.ts.map +0 -1
  35. package/dist/auth/ports.js +0 -8
  36. package/dist/auth/ports.js.map +0 -1
  37. package/dist/commands/activity.d.ts +0 -17
  38. package/dist/commands/activity.d.ts.map +0 -1
  39. package/dist/commands/activity.js +0 -54
  40. package/dist/commands/activity.js.map +0 -1
  41. package/dist/commands/agent.d.ts +0 -25
  42. package/dist/commands/agent.d.ts.map +0 -1
  43. package/dist/commands/agent.js +0 -80
  44. package/dist/commands/agent.js.map +0 -1
  45. package/dist/commands/agents.d.ts +0 -9
  46. package/dist/commands/agents.d.ts.map +0 -1
  47. package/dist/commands/agents.js +0 -28
  48. package/dist/commands/agents.js.map +0 -1
  49. package/dist/commands/commits.d.ts +0 -16
  50. package/dist/commands/commits.d.ts.map +0 -1
  51. package/dist/commands/commits.js +0 -39
  52. package/dist/commands/commits.js.map +0 -1
  53. package/dist/commands/diff.d.ts +0 -15
  54. package/dist/commands/diff.d.ts.map +0 -1
  55. package/dist/commands/diff.js +0 -27
  56. package/dist/commands/diff.js.map +0 -1
  57. package/dist/commands/expose.d.ts +0 -15
  58. package/dist/commands/expose.d.ts.map +0 -1
  59. package/dist/commands/expose.js +0 -39
  60. package/dist/commands/expose.js.map +0 -1
  61. package/dist/commands/index.d.ts +0 -7
  62. package/dist/commands/index.d.ts.map +0 -1
  63. package/dist/commands/index.js +0 -12
  64. package/dist/commands/index.js.map +0 -1
  65. package/dist/commands/login.d.ts +0 -9
  66. package/dist/commands/login.d.ts.map +0 -1
  67. package/dist/commands/login.js +0 -27
  68. package/dist/commands/login.js.map +0 -1
  69. package/dist/commands/logout.d.ts +0 -9
  70. package/dist/commands/logout.d.ts.map +0 -1
  71. package/dist/commands/logout.js +0 -24
  72. package/dist/commands/logout.js.map +0 -1
  73. package/dist/commands/me.d.ts +0 -10
  74. package/dist/commands/me.d.ts.map +0 -1
  75. package/dist/commands/me.js +0 -25
  76. package/dist/commands/me.js.map +0 -1
  77. package/dist/commands/open.d.ts +0 -16
  78. package/dist/commands/open.d.ts.map +0 -1
  79. package/dist/commands/open.js +0 -34
  80. package/dist/commands/open.js.map +0 -1
  81. package/dist/commands/ports.d.ts +0 -75
  82. package/dist/commands/ports.d.ts.map +0 -1
  83. package/dist/commands/ports.js +0 -78
  84. package/dist/commands/ports.js.map +0 -1
  85. package/dist/commands/profile.d.ts +0 -21
  86. package/dist/commands/profile.d.ts.map +0 -1
  87. package/dist/commands/profile.js +0 -93
  88. package/dist/commands/profile.js.map +0 -1
  89. package/dist/commands/push.d.ts +0 -18
  90. package/dist/commands/push.d.ts.map +0 -1
  91. package/dist/commands/push.js +0 -116
  92. package/dist/commands/push.js.map +0 -1
  93. package/dist/commands/registry.d.ts +0 -15
  94. package/dist/commands/registry.d.ts.map +0 -1
  95. package/dist/commands/registry.js +0 -45
  96. package/dist/commands/registry.js.map +0 -1
  97. package/dist/commands/request.d.ts +0 -25
  98. package/dist/commands/request.d.ts.map +0 -1
  99. package/dist/commands/request.js +0 -58
  100. package/dist/commands/request.js.map +0 -1
  101. package/dist/commands/resume.d.ts +0 -22
  102. package/dist/commands/resume.d.ts.map +0 -1
  103. package/dist/commands/resume.js +0 -69
  104. package/dist/commands/resume.js.map +0 -1
  105. package/dist/commands/save.d.ts +0 -34
  106. package/dist/commands/save.d.ts.map +0 -1
  107. package/dist/commands/save.js +0 -141
  108. package/dist/commands/save.js.map +0 -1
  109. package/dist/commands/session.d.ts +0 -9
  110. package/dist/commands/session.d.ts.map +0 -1
  111. package/dist/commands/session.js +0 -282
  112. package/dist/commands/session.js.map +0 -1
  113. package/dist/commands/skills/markdown-loader.d.ts +0 -19
  114. package/dist/commands/skills/markdown-loader.d.ts.map +0 -1
  115. package/dist/commands/skills/markdown-loader.js +0 -108
  116. package/dist/commands/skills/markdown-loader.js.map +0 -1
  117. package/dist/commands/skills/registry.d.ts +0 -23
  118. package/dist/commands/skills/registry.d.ts.map +0 -1
  119. package/dist/commands/skills/registry.js +0 -45
  120. package/dist/commands/skills/registry.js.map +0 -1
  121. package/dist/commands/terminal.d.ts +0 -19
  122. package/dist/commands/terminal.d.ts.map +0 -1
  123. package/dist/commands/terminal.js +0 -39
  124. package/dist/commands/terminal.js.map +0 -1
  125. package/dist/commands/tree.d.ts +0 -16
  126. package/dist/commands/tree.d.ts.map +0 -1
  127. package/dist/commands/tree.js +0 -44
  128. package/dist/commands/tree.js.map +0 -1
  129. package/dist/commands/undo.d.ts +0 -18
  130. package/dist/commands/undo.d.ts.map +0 -1
  131. package/dist/commands/undo.js +0 -46
  132. package/dist/commands/undo.js.map +0 -1
  133. package/dist/config/config-store.d.ts +0 -19
  134. package/dist/config/config-store.d.ts.map +0 -1
  135. package/dist/config/config-store.js +0 -199
  136. package/dist/config/config-store.js.map +0 -1
  137. package/dist/config/defaults.d.ts +0 -22
  138. package/dist/config/defaults.d.ts.map +0 -1
  139. package/dist/config/defaults.js +0 -38
  140. package/dist/config/defaults.js.map +0 -1
  141. package/dist/config/ports.d.ts +0 -60
  142. package/dist/config/ports.d.ts.map +0 -1
  143. package/dist/config/ports.js +0 -8
  144. package/dist/config/ports.js.map +0 -1
  145. package/dist/config/profile-constants.d.ts +0 -4
  146. package/dist/config/profile-constants.d.ts.map +0 -1
  147. package/dist/config/profile-constants.js +0 -10
  148. package/dist/config/profile-constants.js.map +0 -1
  149. package/dist/config/profile.d.ts +0 -84
  150. package/dist/config/profile.d.ts.map +0 -1
  151. package/dist/config/profile.js +0 -66
  152. package/dist/config/profile.js.map +0 -1
  153. package/dist/contract/index.d.ts +0 -193
  154. package/dist/contract/index.d.ts.map +0 -1
  155. package/dist/contract/index.js +0 -14
  156. package/dist/contract/index.js.map +0 -1
  157. package/dist/core/app.d.ts +0 -35
  158. package/dist/core/app.d.ts.map +0 -1
  159. package/dist/core/app.js +0 -86
  160. package/dist/core/app.js.map +0 -1
  161. package/dist/core/command-router.d.ts +0 -29
  162. package/dist/core/command-router.d.ts.map +0 -1
  163. package/dist/core/command-router.js +0 -61
  164. package/dist/core/command-router.js.map +0 -1
  165. package/dist/core/errors.d.ts +0 -39
  166. package/dist/core/errors.d.ts.map +0 -1
  167. package/dist/core/errors.js +0 -106
  168. package/dist/core/errors.js.map +0 -1
  169. package/dist/core/preflight.d.ts +0 -16
  170. package/dist/core/preflight.d.ts.map +0 -1
  171. package/dist/core/preflight.js +0 -38
  172. package/dist/core/preflight.js.map +0 -1
  173. package/dist/core/repl.d.ts +0 -18
  174. package/dist/core/repl.d.ts.map +0 -1
  175. package/dist/core/repl.js +0 -128
  176. package/dist/core/repl.js.map +0 -1
  177. package/dist/di/container.d.ts +0 -13
  178. package/dist/di/container.d.ts.map +0 -1
  179. package/dist/di/container.js +0 -160
  180. package/dist/di/container.js.map +0 -1
  181. package/dist/di/tokens.d.ts +0 -20
  182. package/dist/di/tokens.d.ts.map +0 -1
  183. package/dist/di/tokens.js +0 -22
  184. package/dist/di/tokens.js.map +0 -1
  185. package/dist/index.d.ts +0 -9
  186. package/dist/index.d.ts.map +0 -1
  187. package/dist/index.js.map +0 -1
  188. package/dist/render/ink-renderer.d.ts +0 -28
  189. package/dist/render/ink-renderer.d.ts.map +0 -1
  190. package/dist/render/ink-renderer.js +0 -174
  191. package/dist/render/ink-renderer.js.map +0 -1
  192. package/dist/render/plain-renderer.d.ts +0 -16
  193. package/dist/render/plain-renderer.d.ts.map +0 -1
  194. package/dist/render/plain-renderer.js +0 -38
  195. package/dist/render/plain-renderer.js.map +0 -1
  196. package/dist/render/ports.d.ts +0 -12
  197. package/dist/render/ports.d.ts.map +0 -1
  198. package/dist/render/ports.js +0 -10
  199. package/dist/render/ports.js.map +0 -1
  200. package/dist/render/raw-renderer.d.ts +0 -11
  201. package/dist/render/raw-renderer.d.ts.map +0 -1
  202. package/dist/render/raw-renderer.js +0 -68
  203. package/dist/render/raw-renderer.js.map +0 -1
  204. package/dist/render/repl-input.d.ts +0 -15
  205. package/dist/render/repl-input.d.ts.map +0 -1
  206. package/dist/render/repl-input.js +0 -102
  207. package/dist/render/repl-input.js.map +0 -1
  208. package/dist/session/file-session-store.d.ts +0 -26
  209. package/dist/session/file-session-store.d.ts.map +0 -1
  210. package/dist/session/file-session-store.js +0 -174
  211. package/dist/session/file-session-store.js.map +0 -1
  212. package/dist/session/ports.d.ts +0 -50
  213. package/dist/session/ports.d.ts.map +0 -1
  214. package/dist/session/ports.js +0 -6
  215. package/dist/session/ports.js.map +0 -1
  216. package/dist/sync/git-sync.d.ts +0 -16
  217. package/dist/sync/git-sync.d.ts.map +0 -1
  218. package/dist/sync/git-sync.js +0 -28
  219. package/dist/sync/git-sync.js.map +0 -1
  220. package/dist/sync/git.d.ts +0 -12
  221. package/dist/sync/git.d.ts.map +0 -1
  222. package/dist/sync/git.js +0 -100
  223. package/dist/sync/git.js.map +0 -1
  224. package/dist/sync/reconciler.d.ts +0 -36
  225. package/dist/sync/reconciler.d.ts.map +0 -1
  226. package/dist/sync/reconciler.js +0 -143
  227. package/dist/sync/reconciler.js.map +0 -1
  228. package/dist/sync/walk.d.ts +0 -23
  229. package/dist/sync/walk.d.ts.map +0 -1
  230. package/dist/sync/walk.js +0 -81
  231. package/dist/sync/walk.js.map +0 -1
  232. package/dist/sync/watch.d.ts +0 -13
  233. package/dist/sync/watch.d.ts.map +0 -1
  234. package/dist/sync/watch.js +0 -75
  235. package/dist/sync/watch.js.map +0 -1
  236. package/dist/tools/git-diff.d.ts +0 -16
  237. package/dist/tools/git-diff.d.ts.map +0 -1
  238. package/dist/tools/git-diff.js +0 -25
  239. package/dist/tools/git-diff.js.map +0 -1
  240. package/dist/tools/http-request.d.ts +0 -25
  241. package/dist/tools/http-request.d.ts.map +0 -1
  242. package/dist/tools/http-request.js +0 -41
  243. package/dist/tools/http-request.js.map +0 -1
  244. package/dist/tools/index.d.ts +0 -7
  245. package/dist/tools/index.d.ts.map +0 -1
  246. package/dist/tools/index.js +0 -22
  247. package/dist/tools/index.js.map +0 -1
  248. package/dist/tools/ports.d.ts +0 -58
  249. package/dist/tools/ports.d.ts.map +0 -1
  250. package/dist/tools/ports.js +0 -17
  251. package/dist/tools/ports.js.map +0 -1
  252. package/dist/tools/read-file.d.ts +0 -16
  253. package/dist/tools/read-file.d.ts.map +0 -1
  254. package/dist/tools/read-file.js +0 -24
  255. package/dist/tools/read-file.js.map +0 -1
  256. package/dist/tools/registry.d.ts +0 -10
  257. package/dist/tools/registry.d.ts.map +0 -1
  258. package/dist/tools/registry.js +0 -28
  259. package/dist/tools/registry.js.map +0 -1
  260. package/dist/tools/run-command.d.ts +0 -20
  261. package/dist/tools/run-command.d.ts.map +0 -1
  262. package/dist/tools/run-command.js +0 -65
  263. package/dist/tools/run-command.js.map +0 -1
  264. package/dist/tools/write-file.d.ts +0 -24
  265. package/dist/tools/write-file.d.ts.map +0 -1
  266. package/dist/tools/write-file.js +0 -60
  267. package/dist/tools/write-file.js.map +0 -1
  268. package/dist/transport/composite-transport.d.ts +0 -30
  269. package/dist/transport/composite-transport.d.ts.map +0 -1
  270. package/dist/transport/composite-transport.js +0 -71
  271. package/dist/transport/composite-transport.js.map +0 -1
  272. package/dist/transport/device-browser.d.ts +0 -19
  273. package/dist/transport/device-browser.d.ts.map +0 -1
  274. package/dist/transport/device-browser.js +0 -243
  275. package/dist/transport/device-browser.js.map +0 -1
  276. package/dist/transport/device-git.d.ts +0 -14
  277. package/dist/transport/device-git.d.ts.map +0 -1
  278. package/dist/transport/device-git.js +0 -107
  279. package/dist/transport/device-git.js.map +0 -1
  280. package/dist/transport/device-http.d.ts +0 -10
  281. package/dist/transport/device-http.d.ts.map +0 -1
  282. package/dist/transport/device-http.js +0 -96
  283. package/dist/transport/device-http.js.map +0 -1
  284. package/dist/transport/device-terminal.d.ts +0 -44
  285. package/dist/transport/device-terminal.d.ts.map +0 -1
  286. package/dist/transport/device-terminal.js +0 -140
  287. package/dist/transport/device-terminal.js.map +0 -1
  288. package/dist/transport/http-transport.d.ts +0 -26
  289. package/dist/transport/http-transport.d.ts.map +0 -1
  290. package/dist/transport/http-transport.js +0 -125
  291. package/dist/transport/http-transport.js.map +0 -1
  292. package/dist/transport/ports.d.ts +0 -67
  293. package/dist/transport/ports.d.ts.map +0 -1
  294. package/dist/transport/ports.js +0 -11
  295. package/dist/transport/ports.js.map +0 -1
  296. package/dist/transport/reconnect.d.ts +0 -44
  297. package/dist/transport/reconnect.d.ts.map +0 -1
  298. package/dist/transport/reconnect.js +0 -69
  299. package/dist/transport/reconnect.js.map +0 -1
  300. package/dist/transport/terminal-transport.d.ts +0 -28
  301. package/dist/transport/terminal-transport.d.ts.map +0 -1
  302. package/dist/transport/terminal-transport.js +0 -63
  303. package/dist/transport/terminal-transport.js.map +0 -1
  304. package/dist/transport/ws-stream-transport.d.ts +0 -66
  305. package/dist/transport/ws-stream-transport.d.ts.map +0 -1
  306. package/dist/transport/ws-stream-transport.js +0 -246
  307. package/dist/transport/ws-stream-transport.js.map +0 -1
@@ -1,174 +0,0 @@
1
- // FileSessionStore — JSONL transcript persistence + host /api/sessions sync.
2
- //
3
- // SRP: this class only persists/loads transcripts and reconciles them with the host. It depends on
4
- // `ConfigStore` (for profile/subject context) and `HttpPort` (for sync) via constructor injection —
5
- // DIP, no direct fs-vs-network policy leaks into the agent loop.
6
- //
7
- // Layout: ~/.pocketdev/sessions/<id>.jsonl — first line is the SessionMeta header, subsequent lines
8
- // are Turn records appended atomically. JSONL is crash-safe: a torn final line is simply dropped on
9
- // read without corrupting earlier turns.
10
- import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
11
- import { homedir } from "node:os";
12
- import { join } from "node:path";
13
- import { USER_DIR_NAME } from "../config/defaults.js";
14
- import { CliError } from "../core/errors.js";
15
- export class FileSessionStore {
16
- config;
17
- http;
18
- dir;
19
- constructor(config, http) {
20
- this.config = config;
21
- this.http = http;
22
- this.dir = join(homedir(), USER_DIR_NAME, "sessions");
23
- }
24
- async list() {
25
- if (!existsSync(this.dir))
26
- return [];
27
- const metas = [];
28
- for (const file of readdirSync(this.dir)) {
29
- if (!file.endsWith(".jsonl"))
30
- continue;
31
- const meta = this.readHeader(join(this.dir, file));
32
- if (meta)
33
- metas.push(meta);
34
- }
35
- return metas.sort((a, b) => b.updatedAt - a.updatedAt);
36
- }
37
- async create(meta) {
38
- this.ensureDir();
39
- const full = { ...meta, updatedAt: meta.startedAt };
40
- const path = this.pathFor(meta.id);
41
- if (existsSync(path)) {
42
- throw CliError.config(`Session "${meta.id}" already exists.`);
43
- }
44
- writeFileSync(path, `${JSON.stringify({ type: "meta", meta: full })}\n`, {
45
- encoding: "utf8",
46
- mode: 0o600,
47
- });
48
- return { meta: full, turns: [] };
49
- }
50
- async resume(id) {
51
- const path = this.pathFor(id);
52
- if (!existsSync(path)) {
53
- throw CliError.config(`No local session "${id}".`, "List sessions with `pocketdev resume`.");
54
- }
55
- return this.readTranscript(path);
56
- }
57
- async append(id, turn) {
58
- const path = this.pathFor(id);
59
- if (!existsSync(path)) {
60
- throw CliError.config(`No local session "${id}" to append to.`);
61
- }
62
- appendFileSync(path, `${JSON.stringify({ type: "turn", turn })}\n`, "utf8");
63
- // Touch the header's updatedAt by rewriting only the first line is costly; instead the header's
64
- // updatedAt is recomputed from the last turn at read time (see readHeader/readTranscript).
65
- }
66
- /**
67
- * Reconcile local transcripts with the host. The host persists an opaque `sessions[]` array, so we
68
- * push a compacted view (id/title/updatedAt + turn count summary) and adopt any server sessions we
69
- * do not have locally as headers (their full transcript is fetched lazily on resume).
70
- */
71
- async sync() {
72
- const locals = await this.list();
73
- const compacted = locals.map((m) => ({
74
- id: m.id,
75
- title: m.title,
76
- updatedAt: m.updatedAt,
77
- }));
78
- // PUT our view, then GET the merged authoritative list back.
79
- await this.http.put("/api/sessions", { sessions: compacted });
80
- const remote = await this.http.get("/api/sessions");
81
- const localIds = new Set(locals.map((m) => m.id));
82
- const subject = this.subject();
83
- const profile = this.config.profile().name;
84
- for (const s of remote.sessions ?? []) {
85
- if (localIds.has(s.id))
86
- continue;
87
- // Create a header-only local stub for a session that exists remotely but not locally.
88
- this.ensureDir();
89
- const meta = {
90
- id: s.id,
91
- profile,
92
- subject,
93
- startedAt: s.updatedAt,
94
- title: s.title,
95
- updatedAt: s.updatedAt,
96
- };
97
- const path = this.pathFor(s.id);
98
- if (!existsSync(path)) {
99
- writeFileSync(path, `${JSON.stringify({ type: "meta", meta })}\n`, {
100
- encoding: "utf8",
101
- mode: 0o600,
102
- });
103
- }
104
- }
105
- }
106
- // ── internals ───────────────────────────────────────────────────────────────
107
- pathFor(id) {
108
- if (!/^[A-Za-z0-9._-]+$/.test(id)) {
109
- throw CliError.config(`Invalid session id "${id}".`);
110
- }
111
- return join(this.dir, `${id}.jsonl`);
112
- }
113
- ensureDir() {
114
- if (!existsSync(this.dir))
115
- mkdirSync(this.dir, { recursive: true, mode: 0o700 });
116
- }
117
- subject() {
118
- // Subject attribution is owned by AuthProvider at runtime; for the file header we fall back to a
119
- // stable per-profile placeholder when no provider context is threaded through here.
120
- return "local";
121
- }
122
- readHeader(path) {
123
- const first = firstLine(path);
124
- if (!first)
125
- return undefined;
126
- const rec = safeParse(first);
127
- if (rec?.type === "meta" && rec.meta) {
128
- const meta = rec.meta;
129
- return { ...meta, updatedAt: this.lastTurnAt(path) ?? meta.updatedAt };
130
- }
131
- return undefined;
132
- }
133
- readTranscript(path) {
134
- const lines = readFileSync(path, "utf8").split("\n").filter(Boolean);
135
- let meta;
136
- const turns = [];
137
- for (const line of lines) {
138
- const rec = safeParse(line);
139
- if (!rec)
140
- continue; // tolerate a torn final line (crash-safety)
141
- if (rec.type === "meta" && rec.meta)
142
- meta = rec.meta;
143
- else if (rec.type === "turn" && rec.turn)
144
- turns.push(rec.turn);
145
- }
146
- if (!meta)
147
- throw CliError.config(`Session file ${path} has no header.`);
148
- const updatedAt = turns.length ? turns[turns.length - 1].at : meta.updatedAt;
149
- return { meta: { ...meta, updatedAt }, turns };
150
- }
151
- lastTurnAt(path) {
152
- const lines = readFileSync(path, "utf8").split("\n").filter(Boolean);
153
- for (let i = lines.length - 1; i >= 0; i--) {
154
- const rec = safeParse(lines[i]);
155
- if (rec?.type === "turn" && rec.turn)
156
- return rec.turn.at;
157
- }
158
- return undefined;
159
- }
160
- }
161
- function firstLine(path) {
162
- const text = readFileSync(path, "utf8");
163
- const nl = text.indexOf("\n");
164
- return nl === -1 ? text || undefined : text.slice(0, nl) || undefined;
165
- }
166
- function safeParse(line) {
167
- try {
168
- return JSON.parse(line);
169
- }
170
- catch {
171
- return undefined;
172
- }
173
- }
174
- //# sourceMappingURL=file-session-store.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"file-session-store.js","sourceRoot":"","sources":["../../src/session/file-session-store.ts"],"names":[],"mappings":"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"}
@@ -1,50 +0,0 @@
1
- /** A tool invocation captured in a turn (mirrors the host's agent:tool kinds). */
2
- export interface ToolCall {
3
- kind: "file" | "cmd" | "read" | "http";
4
- action?: "create" | "modify" | "delete";
5
- path?: string;
6
- }
7
- /** A user approval decision recorded against a turn (UX-only; host Casbin is authoritative). */
8
- export interface Approval {
9
- decision: "allow" | "deny" | "always";
10
- at: number;
11
- }
12
- /** One conversational turn in a session transcript. */
13
- export interface Turn {
14
- id: string;
15
- role: "user" | "agent" | "system";
16
- text: string;
17
- at: number;
18
- /** Links a turn to the host run from POST /api/agent/prompt, for resume/undo. */
19
- runId?: string;
20
- toolCalls?: ToolCall[];
21
- approvals?: Approval[];
22
- }
23
- /** Lightweight session header used for listing/resume. */
24
- export interface SessionMeta {
25
- id: string;
26
- profile: string;
27
- subject: string;
28
- startedAt: number;
29
- title?: string;
30
- updatedAt: number;
31
- }
32
- /** A full transcript = header + ordered turns. */
33
- export interface Transcript {
34
- meta: SessionMeta;
35
- turns: Turn[];
36
- }
37
- /**
38
- * SessionStore persists transcripts locally (crash-safe JSONL) and reconciles a compacted view with
39
- * the host via GET/PUT /api/sessions so chat history survives device changes and is shared with the
40
- * mobile app (docs §9).
41
- */
42
- export interface SessionStore {
43
- list(): Promise<SessionMeta[]>;
44
- create(meta: Omit<SessionMeta, "updatedAt">): Promise<Transcript>;
45
- resume(id: string): Promise<Transcript>;
46
- append(id: string, turn: Turn): Promise<void>;
47
- /** Reconcile local transcripts with the host's opaque sessions[] array. */
48
- sync(): Promise<void>;
49
- }
50
- //# sourceMappingURL=ports.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../../src/session/ports.ts"],"names":[],"mappings":"AAKA,kFAAkF;AAClF,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;IACvC,MAAM,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,gGAAgG;AAChG,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IACtC,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,uDAAuD;AACvD,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,iFAAiF;IACjF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;CACxB;AAED,0DAA0D;AAC1D,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,kDAAkD;AAClD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,IAAI,EAAE,CAAC;CACf;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC/B,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAClE,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACxC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,2EAA2E;IAC3E,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB"}
@@ -1,6 +0,0 @@
1
- // Session / transcript ports.
2
- //
3
- // SRP: describes the transcript model and the store contract; the concrete FileSessionStore owns
4
- // JSONL persistence and host /api/sessions sync. The AgentLoop depends on `SessionStore` only.
5
- export {};
6
- //# sourceMappingURL=ports.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ports.js","sourceRoot":"","sources":["../../src/session/ports.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,EAAE;AACF,iGAAiG;AACjG,+FAA+F"}
@@ -1,16 +0,0 @@
1
- import type { HttpPort } from "../transport/ports.js";
2
- export interface GitSyncSummary {
3
- branch: string;
4
- commits: number;
5
- changes: number;
6
- bundle: boolean;
7
- }
8
- /**
9
- * Read local git under `cwd` and push it to `projectId`. Returns null when `cwd` is not a git repo.
10
- * `skipBundle` posts only the metadata (branch/commits/status/diffs) — used for the live in-session
11
- * refresh so the host's per-file diffs track the working tree without re-uploading the heavy bundle.
12
- */
13
- export declare function uploadGit(http: HttpPort, cwd: string, projectId: string, opts?: {
14
- skipBundle?: boolean;
15
- }): Promise<GitSyncSummary | null>;
16
- //# sourceMappingURL=git-sync.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"git-sync.d.ts","sourceRoot":"","sources":["../../src/sync/git-sync.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGtD,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAC7B,IAAI,EAAE,QAAQ,EACd,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GAClC,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAgBhC"}
@@ -1,28 +0,0 @@
1
- // Upload the local git state to a project: metadata (branch/commits/status/diffs) via POST /api/git,
2
- // and the raw .git bundle via POST /api/git/bundle. Best-effort — callers ignore failures (the file
3
- // sync already succeeded).
4
- import { readLocalGit } from "./git.js";
5
- /**
6
- * Read local git under `cwd` and push it to `projectId`. Returns null when `cwd` is not a git repo.
7
- * `skipBundle` posts only the metadata (branch/commits/status/diffs) — used for the live in-session
8
- * refresh so the host's per-file diffs track the working tree without re-uploading the heavy bundle.
9
- */
10
- export async function uploadGit(http, cwd, projectId, opts = {}) {
11
- const local = await readLocalGit(cwd);
12
- if (!local)
13
- return null;
14
- const header = { "X-Pocketdev-Project": projectId };
15
- await http.post("/api/git", local.meta, header);
16
- let bundle = false;
17
- if (!opts.skipBundle && local.bundle) {
18
- await http.postRaw("/api/git/bundle", local.bundle, header);
19
- bundle = true;
20
- }
21
- return {
22
- branch: local.meta.branch,
23
- commits: local.meta.commits.length,
24
- changes: local.meta.changes.length,
25
- bundle,
26
- };
27
- }
28
- //# sourceMappingURL=git-sync.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"git-sync.js","sourceRoot":"","sources":["../../src/sync/git-sync.ts"],"names":[],"mappings":"AAAA,qGAAqG;AACrG,oGAAoG;AACpG,2BAA2B;AAG3B,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AASxC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,IAAc,EACd,GAAW,EACX,SAAiB,EACjB,OAAiC,EAAE;IAEnC,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,MAAM,GAAG,EAAE,qBAAqB,EAAE,SAAS,EAAE,CAAC;IACpD,MAAM,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAChD,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACrC,MAAM,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC5D,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC;IACD,OAAO;QACL,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM;QACzB,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM;QAClC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM;QAClC,MAAM;KACP,CAAC;AACJ,CAAC"}
@@ -1,12 +0,0 @@
1
- import type { GitMeta } from "../contract/index.js";
2
- export interface LocalGit {
3
- meta: GitMeta;
4
- /** Full `git bundle --all` (undefined for an empty repo or one larger than the cap). */
5
- bundle?: Buffer;
6
- }
7
- /** Read the local git state under `cwd`, or null if it isn't a git working tree (or git is absent). */
8
- export declare function readLocalGit(cwd: string, maxBundleBytes?: number): Promise<LocalGit | null>;
9
- /** Run a git command under `cwd`, returning stdout (rejects with the ExecFileException — incl. stderr —
10
- * on a non-zero exit). Exported so the device git responder can reuse the same invocation. */
11
- export declare function git(cwd: string, args: string[]): Promise<string>;
12
- //# sourceMappingURL=git.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/sync/git.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAA8B,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAOhF,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,OAAO,CAAC;IACd,wFAAwF;IACxF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,uGAAuG;AACvG,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,cAAc,SAAmB,GAChC,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAc1B;AAED;+FAC+F;AAC/F,wBAAsB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAGtE"}
package/dist/sync/git.js DELETED
@@ -1,100 +0,0 @@
1
- // Read the LOCAL git state of a folder for the hybrid git sync: branch, recent commits, `git status`,
2
- // per-file diffs, and a full `.git` bundle. The host has no git binary, so the CLI does the reading and
3
- // ships the result as metadata (+ the bundle as a downloadable artifact). Everything is best-effort:
4
- // no git / not a repo / empty repo → the caller skips the git step silently.
5
- import { execFile } from "node:child_process";
6
- import { promises as fs } from "node:fs";
7
- import { tmpdir } from "node:os";
8
- import { join } from "node:path";
9
- import { promisify } from "node:util";
10
- const exec = promisify(execFile);
11
- const US = "\x1f"; // unit separator (between commit fields)
12
- const RS = "\x1e"; // record separator (between commits)
13
- /** Read the local git state under `cwd`, or null if it isn't a git working tree (or git is absent). */
14
- export async function readLocalGit(cwd, maxBundleBytes = 50 * 1024 * 1024) {
15
- try {
16
- if ((await git(cwd, ["rev-parse", "--is-inside-work-tree"])).trim() !== "true")
17
- return null;
18
- }
19
- catch {
20
- return null; // git not installed, or not a repo
21
- }
22
- const branch = (await safe(() => git(cwd, ["rev-parse", "--abbrev-ref", "HEAD"]), "")).trim();
23
- const commits = await readCommits(cwd);
24
- const changes = await readChanges(cwd);
25
- const diffs = await readDiffs(cwd, changes);
26
- const meta = { branch, commits, changes, diffs };
27
- const bundle = await makeBundle(cwd, maxBundleBytes);
28
- return { meta, bundle };
29
- }
30
- /** Run a git command under `cwd`, returning stdout (rejects with the ExecFileException — incl. stderr —
31
- * on a non-zero exit). Exported so the device git responder can reuse the same invocation. */
32
- export async function git(cwd, args) {
33
- const { stdout } = await exec("git", args, { cwd, maxBuffer: 64 * 1024 * 1024 });
34
- return stdout;
35
- }
36
- async function safe(fn, fallback) {
37
- try {
38
- return await fn();
39
- }
40
- catch {
41
- return fallback;
42
- }
43
- }
44
- async function readCommits(cwd) {
45
- const fmt = `%H${US}%s${US}%an${US}%aI${RS}`;
46
- const out = await safe(() => git(cwd, ["log", "-n", "50", `--pretty=format:${fmt}`]), "");
47
- return out
48
- .split(RS)
49
- .map((r) => r.trim())
50
- .filter(Boolean)
51
- .map((r) => {
52
- const [hash, subject, author, date] = r.split(US);
53
- return { hash, subject, author, date };
54
- });
55
- }
56
- async function readChanges(cwd) {
57
- const out = await safe(() => git(cwd, ["status", "--porcelain"]), "");
58
- return out
59
- .split("\n")
60
- .map((l) => l.replace(/\r$/, ""))
61
- .filter(Boolean)
62
- .map((l) => {
63
- // Keep the raw 2-char porcelain code "XY" (X=index/staged, Y=worktree/unstaged) — the dashboard
64
- // splits Staged vs Changes from it. (Trimming here would collapse "M " and " M" into "M".)
65
- const status = l.slice(0, 2);
66
- let path = l.slice(3);
67
- const arrow = path.indexOf(" -> "); // rename: keep the new path
68
- if (arrow >= 0)
69
- path = path.slice(arrow + 4);
70
- return { path, status };
71
- });
72
- }
73
- async function readDiffs(cwd, changes) {
74
- const diffs = [];
75
- for (const c of changes) {
76
- if (c.status === "??")
77
- continue; // untracked has no diff (status already lists it)
78
- const patch = await safe(() => git(cwd, ["diff", "HEAD", "--", c.path]), "");
79
- if (patch.trim())
80
- diffs.push({ path: c.path, patch });
81
- }
82
- return diffs;
83
- }
84
- async function makeBundle(cwd, maxBytes) {
85
- const tmp = join(tmpdir(), `pd-${Date.now()}-${Math.random().toString(36).slice(2)}.bundle`);
86
- try {
87
- await git(cwd, ["bundle", "create", tmp, "--all"]);
88
- const stat = await fs.stat(tmp);
89
- if (stat.size > maxBytes)
90
- return undefined;
91
- return await fs.readFile(tmp);
92
- }
93
- catch {
94
- return undefined; // empty repo (no commits) → `bundle --all` fails
95
- }
96
- finally {
97
- await fs.rm(tmp, { force: true }).catch(() => { });
98
- }
99
- }
100
- //# sourceMappingURL=git.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/sync/git.ts"],"names":[],"mappings":"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"}
@@ -1,36 +0,0 @@
1
- import type { FileChange } from "../contract/index.js";
2
- import type { HttpPort } from "../transport/ports.js";
3
- export declare class SyncReconciler {
4
- private readonly cwd;
5
- private readonly http;
6
- private readonly projectHeader;
7
- private readonly log?;
8
- private readonly synced;
9
- constructor(cwd: string, http: HttpPort, projectHeader: Record<string, string>, log?: ((line: string) => void) | undefined);
10
- /** Record the baseline after the initial upload, so we don't re-apply what we just pushed. */
11
- seed(files: ReadonlyArray<{
12
- relPath: string;
13
- content: string;
14
- }>): void;
15
- /** True when a local upsert is a genuine change to push up (false = an echo of a just-applied remote write). */
16
- upsertShouldPush(rel: string, content: string): boolean;
17
- /** True when a local delete should be pushed up (false = the path was already removed by a remote apply). */
18
- deleteShouldPush(rel: string): boolean;
19
- /**
20
- * After a BULK working-tree change (e.g. a `git checkout` the dashboard triggered), re-walk and
21
- * push the full delta: PUT changed/new files, DELETE paths that no longer exist locally. The live
22
- * chokidar watcher reliably MISSES bulk git operations (especially whole-directory deletions on
23
- * macOS/fsevents), which leaves old-branch files lingering in the host's copy and mixes two
24
- * branches in the file tree — so we reconcile deterministically instead of trusting the watcher.
25
- * Hash-gated via the shared `synced` map, so unchanged files are never re-uploaded.
26
- */
27
- resyncWorkingTree(files: ReadonlyArray<{
28
- relPath: string;
29
- content: string;
30
- }>): Promise<void>;
31
- /** Shallowest segment of `rel` that no longer exists on disk, so deleting it on the host removes
32
- * the whole vanished subtree (incl. now-empty dirs). Falls back to `rel` if every segment exists. */
33
- private topMissingAncestor;
34
- applyRemote(change: FileChange): Promise<void>;
35
- }
36
- //# sourceMappingURL=reconciler.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reconciler.d.ts","sourceRoot":"","sources":["../../src/sync/reconciler.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,sBAAsB,CAAC;AACpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAMtD,qBAAa,cAAc;IAIvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;IANvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;gBAGjC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,QAAQ,EACd,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,GAAG,CAAC,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,aAAA;IAG/C,8FAA8F;IAC9F,IAAI,CAAC,KAAK,EAAE,aAAa,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI;IAMtE,gHAAgH;IAChH,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO;IAOvD,6GAA6G;IAC7G,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAQtC;;;;;;;OAOG;IACG,iBAAiB,CAAC,KAAK,EAAE,aAAa,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAgClG;0GACsG;YACxF,kBAAkB;IAe1B,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;CAiCrD"}
@@ -1,143 +0,0 @@
1
- // SyncReconciler — the two-way sync arbiter.
2
- //
3
- // The session watcher pushes LOCAL edits UP (PUT/DELETE /api/file). This adds the reverse: host changes
4
- // (e.g. a file created/edited/deleted in the dashboard) are pulled DOWN and applied to the local folder.
5
- // A single content-hash map (`synced: relPath → sha256`) is the source of truth both directions consult,
6
- // so a change can never bounce forever: after a round trip the hashes match and the echo is dropped.
7
- import { createHash } from "node:crypto";
8
- import { promises as fs } from "node:fs";
9
- import { dirname, join } from "node:path";
10
- function hash(content) {
11
- return createHash("sha256").update(content).digest("hex");
12
- }
13
- export class SyncReconciler {
14
- cwd;
15
- http;
16
- projectHeader;
17
- log;
18
- synced = new Map(); // relPath → hash of the last in-sync content
19
- constructor(cwd, http, projectHeader, log) {
20
- this.cwd = cwd;
21
- this.http = http;
22
- this.projectHeader = projectHeader;
23
- this.log = log;
24
- }
25
- /** Record the baseline after the initial upload, so we don't re-apply what we just pushed. */
26
- seed(files) {
27
- for (const f of files)
28
- this.synced.set(f.relPath, hash(f.content));
29
- }
30
- // ── upward gates (called by the watcher before it PUTs/DELETEs) ───────────────
31
- /** True when a local upsert is a genuine change to push up (false = an echo of a just-applied remote write). */
32
- upsertShouldPush(rel, content) {
33
- const h = hash(content);
34
- if (this.synced.get(rel) === h)
35
- return false;
36
- this.synced.set(rel, h);
37
- return true;
38
- }
39
- /** True when a local delete should be pushed up (false = the path was already removed by a remote apply). */
40
- deleteShouldPush(rel) {
41
- if (!this.synced.has(rel))
42
- return false;
43
- this.synced.delete(rel);
44
- return true;
45
- }
46
- // ── bulk reconcile (called after a dashboard-triggered git checkout) ──────────
47
- /**
48
- * After a BULK working-tree change (e.g. a `git checkout` the dashboard triggered), re-walk and
49
- * push the full delta: PUT changed/new files, DELETE paths that no longer exist locally. The live
50
- * chokidar watcher reliably MISSES bulk git operations (especially whole-directory deletions on
51
- * macOS/fsevents), which leaves old-branch files lingering in the host's copy and mixes two
52
- * branches in the file tree — so we reconcile deterministically instead of trusting the watcher.
53
- * Hash-gated via the shared `synced` map, so unchanged files are never re-uploaded.
54
- */
55
- async resyncWorkingTree(files) {
56
- const present = new Set();
57
- for (const f of files) {
58
- present.add(f.relPath);
59
- if (this.upsertShouldPush(f.relPath, f.content)) {
60
- try {
61
- await this.http.put("/api/file", { path: f.relPath, content: f.content }, this.projectHeader);
62
- this.log?.(` ↑ ${f.relPath}\n`);
63
- }
64
- catch {
65
- /* transient (offline blip); the watcher or next checkout re-syncs */
66
- }
67
- }
68
- }
69
- // Deletions: any previously-synced path no longer present locally. Delete the TOPMOST missing
70
- // ancestor so an emptied old-branch directory is removed as one subtree (backend Remove =
71
- // os.RemoveAll, idempotent) instead of being left behind as an empty folder.
72
- const targets = new Set();
73
- for (const rel of [...this.synced.keys()]) {
74
- if (present.has(rel))
75
- continue;
76
- this.synced.delete(rel);
77
- targets.add(await this.topMissingAncestor(rel));
78
- }
79
- for (const t of targets) {
80
- try {
81
- await this.http.del(`/api/file?path=${encodeURIComponent(t)}`, this.projectHeader);
82
- this.log?.(` ✗ ${t}\n`);
83
- }
84
- catch {
85
- /* idempotent on the backend; self-heals on the next checkout */
86
- }
87
- }
88
- }
89
- /** Shallowest segment of `rel` that no longer exists on disk, so deleting it on the host removes
90
- * the whole vanished subtree (incl. now-empty dirs). Falls back to `rel` if every segment exists. */
91
- async topMissingAncestor(rel) {
92
- let path = "";
93
- for (const seg of rel.split("/")) {
94
- path = path ? `${path}/${seg}` : seg;
95
- try {
96
- await fs.stat(join(this.cwd, path));
97
- }
98
- catch {
99
- return path;
100
- }
101
- }
102
- return rel;
103
- }
104
- // ── downward apply (called on the host's files:changed event) ─────────────────
105
- async applyRemote(change) {
106
- try {
107
- if (change.event === "unlink") {
108
- this.synced.delete(change.path);
109
- await fs.rm(join(this.cwd, change.path), { force: true, recursive: true });
110
- this.log?.(` ↓ ${change.path} (deleted)\n`);
111
- return;
112
- }
113
- // add | change → fetch the host's content and mirror it locally.
114
- let file;
115
- try {
116
- file = await this.http.get("/api/file", { path: change.path }, this.projectHeader);
117
- }
118
- catch {
119
- // /api/file can't read a directory — a host mkdir broadcasts files:changed{add} for the dir, so
120
- // a failed read on an "add" means it's a folder: create it locally, best-effort.
121
- if (change.event === "add") {
122
- await fs.mkdir(join(this.cwd, change.path), { recursive: true });
123
- this.log?.(` ↓ ${change.path}/\n`);
124
- }
125
- return;
126
- }
127
- if (file.truncated)
128
- return; // never clobber a local file with a partial (host-truncated) read
129
- const h = hash(file.content);
130
- if (this.synced.get(change.path) === h)
131
- return; // already in sync (our own push echoing back)
132
- this.synced.set(change.path, h);
133
- const abs = join(this.cwd, change.path);
134
- await fs.mkdir(dirname(abs), { recursive: true });
135
- await fs.writeFile(abs, file.content, "utf8");
136
- this.log?.(` ↓ ${change.path}\n`);
137
- }
138
- catch {
139
- /* best-effort; a transient failure self-heals on the next change or reconnect */
140
- }
141
- }
142
- }
143
- //# sourceMappingURL=reconciler.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reconciler.js","sourceRoot":"","sources":["../../src/sync/reconciler.ts"],"names":[],"mappings":"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"}