@oharness/engine 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/dist/agent/agent.d.ts +196 -0
  2. package/dist/agent/agent.js +758 -0
  3. package/dist/agent/agent.js.map +1 -0
  4. package/dist/agent/compaction.d.ts +68 -0
  5. package/dist/agent/compaction.js +179 -0
  6. package/dist/agent/compaction.js.map +1 -0
  7. package/dist/agent/hooks.d.ts +77 -0
  8. package/dist/agent/hooks.js +152 -0
  9. package/dist/agent/hooks.js.map +1 -0
  10. package/dist/agent/memory.d.ts +45 -0
  11. package/dist/agent/memory.js +147 -0
  12. package/dist/agent/memory.js.map +1 -0
  13. package/dist/agent/overflow.d.ts +35 -0
  14. package/dist/agent/overflow.js +69 -0
  15. package/dist/agent/overflow.js.map +1 -0
  16. package/dist/agent/permissions.d.ts +181 -0
  17. package/dist/agent/permissions.js +289 -0
  18. package/dist/agent/permissions.js.map +1 -0
  19. package/dist/agent/prompt.d.ts +25 -0
  20. package/dist/agent/prompt.js +63 -0
  21. package/dist/agent/prompt.js.map +1 -0
  22. package/dist/agent/session.d.ts +108 -0
  23. package/dist/agent/session.js +231 -0
  24. package/dist/agent/session.js.map +1 -0
  25. package/dist/agent/settings.d.ts +37 -0
  26. package/dist/agent/settings.js +113 -0
  27. package/dist/agent/settings.js.map +1 -0
  28. package/dist/agent/skills.d.ts +58 -0
  29. package/dist/agent/skills.js +225 -0
  30. package/dist/agent/skills.js.map +1 -0
  31. package/dist/agent/store.d.ts +308 -0
  32. package/dist/agent/store.js +596 -0
  33. package/dist/agent/store.js.map +1 -0
  34. package/dist/agent/subagent.d.ts +44 -0
  35. package/dist/agent/subagent.js +138 -0
  36. package/dist/agent/subagent.js.map +1 -0
  37. package/dist/agent/titles.d.ts +8 -0
  38. package/dist/agent/titles.js +23 -0
  39. package/dist/agent/titles.js.map +1 -0
  40. package/dist/agent/workspace.d.ts +60 -0
  41. package/dist/agent/workspace.js +156 -0
  42. package/dist/agent/workspace.js.map +1 -0
  43. package/dist/artifacts/publish.d.ts +94 -0
  44. package/dist/artifacts/publish.js +104 -0
  45. package/dist/artifacts/publish.js.map +1 -0
  46. package/dist/artifacts/store.d.ts +324 -0
  47. package/dist/artifacts/store.js +500 -0
  48. package/dist/artifacts/store.js.map +1 -0
  49. package/dist/auth/index.d.ts +13 -0
  50. package/dist/auth/index.js +10 -0
  51. package/dist/auth/index.js.map +1 -0
  52. package/dist/auth/manager.d.ts +83 -0
  53. package/dist/auth/manager.js +266 -0
  54. package/dist/auth/manager.js.map +1 -0
  55. package/dist/auth/oauth.d.ts +83 -0
  56. package/dist/auth/oauth.js +327 -0
  57. package/dist/auth/oauth.js.map +1 -0
  58. package/dist/auth/providers/account.d.ts +59 -0
  59. package/dist/auth/providers/account.js +282 -0
  60. package/dist/auth/providers/account.js.map +1 -0
  61. package/dist/auth/providers/anthropic.d.ts +24 -0
  62. package/dist/auth/providers/anthropic.js +209 -0
  63. package/dist/auth/providers/anthropic.js.map +1 -0
  64. package/dist/auth/providers/generic.d.ts +57 -0
  65. package/dist/auth/providers/generic.js +155 -0
  66. package/dist/auth/providers/generic.js.map +1 -0
  67. package/dist/auth/providers/official.d.ts +3 -0
  68. package/dist/auth/providers/official.js +90 -0
  69. package/dist/auth/providers/official.js.map +1 -0
  70. package/dist/auth/providers/ottoport.d.ts +3 -0
  71. package/dist/auth/providers/ottoport.js +60 -0
  72. package/dist/auth/providers/ottoport.js.map +1 -0
  73. package/dist/auth/store.d.ts +22 -0
  74. package/dist/auth/store.js +138 -0
  75. package/dist/auth/store.js.map +1 -0
  76. package/dist/auth/types.d.ts +167 -0
  77. package/dist/auth/types.js +16 -0
  78. package/dist/auth/types.js.map +1 -0
  79. package/dist/config.d.ts +197 -0
  80. package/dist/config.js +195 -0
  81. package/dist/config.js.map +1 -0
  82. package/dist/core/errors.d.ts +46 -0
  83. package/dist/core/errors.js +83 -0
  84. package/dist/core/errors.js.map +1 -0
  85. package/dist/core/tokens.d.ts +12 -0
  86. package/dist/core/tokens.js +56 -0
  87. package/dist/core/tokens.js.map +1 -0
  88. package/dist/core/types.d.ts +91 -0
  89. package/dist/core/types.js +49 -0
  90. package/dist/core/types.js.map +1 -0
  91. package/dist/harness.d.ts +302 -0
  92. package/dist/harness.js +695 -0
  93. package/dist/harness.js.map +1 -0
  94. package/dist/index.d.ts +32 -0
  95. package/dist/index.js +21 -0
  96. package/dist/index.js.map +1 -0
  97. package/dist/mcp/client.d.ts +55 -0
  98. package/dist/mcp/client.js +199 -0
  99. package/dist/mcp/client.js.map +1 -0
  100. package/dist/mcp/index.d.ts +13 -0
  101. package/dist/mcp/index.js +8 -0
  102. package/dist/mcp/index.js.map +1 -0
  103. package/dist/mcp/manager.d.ts +77 -0
  104. package/dist/mcp/manager.js +325 -0
  105. package/dist/mcp/manager.js.map +1 -0
  106. package/dist/mcp/oauth.d.ts +63 -0
  107. package/dist/mcp/oauth.js +302 -0
  108. package/dist/mcp/oauth.js.map +1 -0
  109. package/dist/mcp/protocol.d.ts +130 -0
  110. package/dist/mcp/protocol.js +14 -0
  111. package/dist/mcp/protocol.js.map +1 -0
  112. package/dist/mcp/registry.d.ts +52 -0
  113. package/dist/mcp/registry.js +100 -0
  114. package/dist/mcp/registry.js.map +1 -0
  115. package/dist/mcp/registry.json +293 -0
  116. package/dist/mcp/secrets.d.ts +20 -0
  117. package/dist/mcp/secrets.js +75 -0
  118. package/dist/mcp/secrets.js.map +1 -0
  119. package/dist/mcp/transport.d.ts +51 -0
  120. package/dist/mcp/transport.js +158 -0
  121. package/dist/mcp/transport.js.map +1 -0
  122. package/dist/paths.d.ts +37 -0
  123. package/dist/paths.js +63 -0
  124. package/dist/paths.js.map +1 -0
  125. package/dist/plugins.d.ts +55 -0
  126. package/dist/plugins.js +201 -0
  127. package/dist/plugins.js.map +1 -0
  128. package/dist/providers/builtin.d.ts +23 -0
  129. package/dist/providers/builtin.js +141 -0
  130. package/dist/providers/builtin.js.map +1 -0
  131. package/dist/providers/catalog.d.ts +129 -0
  132. package/dist/providers/catalog.js +254 -0
  133. package/dist/providers/catalog.js.map +1 -0
  134. package/dist/providers/catalog.json +472 -0
  135. package/dist/providers/discovery.d.ts +16 -0
  136. package/dist/providers/discovery.js +161 -0
  137. package/dist/providers/discovery.js.map +1 -0
  138. package/dist/providers/http.d.ts +24 -0
  139. package/dist/providers/http.js +139 -0
  140. package/dist/providers/http.js.map +1 -0
  141. package/dist/providers/index.d.ts +10 -0
  142. package/dist/providers/index.js +8 -0
  143. package/dist/providers/index.js.map +1 -0
  144. package/dist/providers/piai.d.ts +124 -0
  145. package/dist/providers/piai.js +551 -0
  146. package/dist/providers/piai.js.map +1 -0
  147. package/dist/providers/registry.d.ts +65 -0
  148. package/dist/providers/registry.js +195 -0
  149. package/dist/providers/registry.js.map +1 -0
  150. package/dist/providers/resilient.d.ts +46 -0
  151. package/dist/providers/resilient.js +117 -0
  152. package/dist/providers/resilient.js.map +1 -0
  153. package/dist/providers/types.d.ts +182 -0
  154. package/dist/providers/types.js +50 -0
  155. package/dist/providers/types.js.map +1 -0
  156. package/dist/schedule/cron.d.ts +35 -0
  157. package/dist/schedule/cron.js +125 -0
  158. package/dist/schedule/cron.js.map +1 -0
  159. package/dist/schedule/scheduler.d.ts +87 -0
  160. package/dist/schedule/scheduler.js +237 -0
  161. package/dist/schedule/scheduler.js.map +1 -0
  162. package/dist/storage/kv.d.ts +56 -0
  163. package/dist/storage/kv.js +173 -0
  164. package/dist/storage/kv.js.map +1 -0
  165. package/dist/storage/migrate.d.ts +11 -0
  166. package/dist/storage/migrate.js +93 -0
  167. package/dist/storage/migrate.js.map +1 -0
  168. package/dist/storage/project.d.ts +9 -0
  169. package/dist/storage/project.js +57 -0
  170. package/dist/storage/project.js.map +1 -0
  171. package/dist/storage/records.d.ts +32 -0
  172. package/dist/storage/records.js +48 -0
  173. package/dist/storage/records.js.map +1 -0
  174. package/dist/sync/client.d.ts +79 -0
  175. package/dist/sync/client.js +118 -0
  176. package/dist/sync/client.js.map +1 -0
  177. package/dist/sync/mirror.d.ts +85 -0
  178. package/dist/sync/mirror.js +389 -0
  179. package/dist/sync/mirror.js.map +1 -0
  180. package/dist/sync/protocol.d.ts +67 -0
  181. package/dist/sync/protocol.js +16 -0
  182. package/dist/sync/protocol.js.map +1 -0
  183. package/dist/sync/settings.d.ts +56 -0
  184. package/dist/sync/settings.js +60 -0
  185. package/dist/sync/settings.js.map +1 -0
  186. package/dist/tools/builtin/artifact.d.ts +16 -0
  187. package/dist/tools/builtin/artifact.js +134 -0
  188. package/dist/tools/builtin/artifact.js.map +1 -0
  189. package/dist/tools/builtin/bash.d.ts +3 -0
  190. package/dist/tools/builtin/bash.js +142 -0
  191. package/dist/tools/builtin/bash.js.map +1 -0
  192. package/dist/tools/builtin/fs.d.ts +19 -0
  193. package/dist/tools/builtin/fs.js +280 -0
  194. package/dist/tools/builtin/fs.js.map +1 -0
  195. package/dist/tools/builtin/index.d.ts +22 -0
  196. package/dist/tools/builtin/index.js +42 -0
  197. package/dist/tools/builtin/index.js.map +1 -0
  198. package/dist/tools/builtin/mcp-resource.d.ts +3 -0
  199. package/dist/tools/builtin/mcp-resource.js +220 -0
  200. package/dist/tools/builtin/mcp-resource.js.map +1 -0
  201. package/dist/tools/builtin/memory.d.ts +10 -0
  202. package/dist/tools/builtin/memory.js +76 -0
  203. package/dist/tools/builtin/memory.js.map +1 -0
  204. package/dist/tools/builtin/recall.d.ts +13 -0
  205. package/dist/tools/builtin/recall.js +163 -0
  206. package/dist/tools/builtin/recall.js.map +1 -0
  207. package/dist/tools/builtin/search.d.ts +3 -0
  208. package/dist/tools/builtin/search.js +240 -0
  209. package/dist/tools/builtin/search.js.map +1 -0
  210. package/dist/tools/builtin/skill.d.ts +10 -0
  211. package/dist/tools/builtin/skill.js +46 -0
  212. package/dist/tools/builtin/skill.js.map +1 -0
  213. package/dist/tools/builtin/task.d.ts +9 -0
  214. package/dist/tools/builtin/task.js +68 -0
  215. package/dist/tools/builtin/task.js.map +1 -0
  216. package/dist/tools/builtin/todo.d.ts +20 -0
  217. package/dist/tools/builtin/todo.js +63 -0
  218. package/dist/tools/builtin/todo.js.map +1 -0
  219. package/dist/tools/define.d.ts +19 -0
  220. package/dist/tools/define.js +39 -0
  221. package/dist/tools/define.js.map +1 -0
  222. package/dist/tools/index.d.ts +7 -0
  223. package/dist/tools/index.js +5 -0
  224. package/dist/tools/index.js.map +1 -0
  225. package/dist/tools/registry.d.ts +39 -0
  226. package/dist/tools/registry.js +101 -0
  227. package/dist/tools/registry.js.map +1 -0
  228. package/dist/tools/types.d.ts +112 -0
  229. package/dist/tools/types.js +22 -0
  230. package/dist/tools/types.js.map +1 -0
  231. package/dist/util/id.d.ts +9 -0
  232. package/dist/util/id.js +19 -0
  233. package/dist/util/id.js.map +1 -0
  234. package/dist/util/json.d.ts +25 -0
  235. package/dist/util/json.js +100 -0
  236. package/dist/util/json.js.map +1 -0
  237. package/dist/util/jwt.d.ts +74 -0
  238. package/dist/util/jwt.js +177 -0
  239. package/dist/util/jwt.js.map +1 -0
  240. package/dist/util/logger.d.ts +13 -0
  241. package/dist/util/logger.js +59 -0
  242. package/dist/util/logger.js.map +1 -0
  243. package/dist/util/queue.d.ts +26 -0
  244. package/dist/util/queue.js +106 -0
  245. package/dist/util/queue.js.map +1 -0
  246. package/dist/util/schema.d.ts +17 -0
  247. package/dist/util/schema.js +98 -0
  248. package/dist/util/schema.js.map +1 -0
  249. package/dist/util/shell.d.ts +20 -0
  250. package/dist/util/shell.js +24 -0
  251. package/dist/util/shell.js.map +1 -0
  252. package/official.json +4 -0
  253. package/package.json +38 -0
  254. package/skills/artifact-authoring/SKILL.md +81 -0
  255. package/skills/canvas/SKILL.md +85 -0
  256. package/skills/skill-authoring/SKILL.md +85 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/sync/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ import type { SessionStore } from "../agent/store.ts";
2
+ import { JsonStore } from "../storage/kv.ts";
3
+ import { SyncClient } from "./client.ts";
4
+ export interface MirrorOptions {
5
+ store: SessionStore;
6
+ client: SyncClient;
7
+ /** The feed this mirror is bound to — a repository, not a path. */
8
+ projectId: string;
9
+ /** Where the cursor is kept. Defaults to the store's own root. */
10
+ state?: JsonStore;
11
+ /** Told about failures. Sync problems are worth a log line, never a throw. */
12
+ onError?: (message: string) => void;
13
+ /**
14
+ * Seconds to hold a poll open, capped by the protocol.
15
+ *
16
+ * The maximum is the right answer for a harness someone is working in, and
17
+ * the wrong one for anything short-lived: a held connection keeps the
18
+ * process alive, so a scheduled run or a test would sit waiting on a server
19
+ * that has nothing to say.
20
+ */
21
+ pollSeconds?: number;
22
+ /** Overridable for tests, which should not wait in real seconds. */
23
+ timers?: {
24
+ setTimeout: (fn: () => void, ms: number) => unknown;
25
+ clearTimeout: (handle: unknown) => void;
26
+ };
27
+ }
28
+ export declare class SessionMirror {
29
+ private readonly store;
30
+ private readonly client;
31
+ private readonly projectId;
32
+ private readonly state;
33
+ private readonly onError;
34
+ private readonly pollSeconds;
35
+ private readonly timers;
36
+ private unwatch?;
37
+ private aborter?;
38
+ private pushTimer?;
39
+ private pulling?;
40
+ private running;
41
+ /** Sessions with local writes not known to be pushed. */
42
+ private readonly dirty;
43
+ /** Deletions waiting to travel, kept because the metadata is already gone. */
44
+ private readonly tombstones;
45
+ private held?;
46
+ constructor(opts: MirrorOptions);
47
+ get active(): boolean;
48
+ /**
49
+ * Begin mirroring.
50
+ *
51
+ * Subscribing comes before the first pull so a write that lands during the
52
+ * opening round trip is not missed — it would otherwise sit unpushed until
53
+ * something else in that session changed, which for a finished session is
54
+ * never.
55
+ */
56
+ start(): void;
57
+ /**
58
+ * Stop, and stay stopped.
59
+ *
60
+ * The in-flight long poll is aborted rather than waited out: a user who
61
+ * switches sync off should not have a connection to the server outliving the
62
+ * decision by up to thirty seconds.
63
+ */
64
+ stop(): void;
65
+ /** Push whatever is pending now, rather than on the debounce. */
66
+ flush(): Promise<void>;
67
+ private onChange;
68
+ private schedulePush;
69
+ /** Offer every session in this project, for a device that has never pushed. */
70
+ private sweep;
71
+ private push;
72
+ /**
73
+ * Read the feed forward, forever.
74
+ *
75
+ * A long poll returns either when something arrives or when the server gives
76
+ * up holding it, so the loop is not a poll with a delay in it — the delay
77
+ * only appears after a failure.
78
+ */
79
+ private loop;
80
+ private pull;
81
+ private report;
82
+ private wait;
83
+ private read;
84
+ private write;
85
+ }
@@ -0,0 +1,389 @@
1
+ import { asArtifactRevision } from "../artifacts/store.js";
2
+ import { JsonStore } from "../storage/kv.js";
3
+ import { errorMessage } from "../core/errors.js";
4
+ import { SyncClient, SyncHttpError, chunk } from "./client.js";
5
+ import { MAX_WAIT_SECONDS } from "./protocol.js";
6
+ /**
7
+ * The line between the session store and a sync server.
8
+ *
9
+ * One mirror serves one project, because a feed is scoped to one and a cursor
10
+ * into someone else's is meaningless. It pushes what the store reports and
11
+ * pulls in a loop, and it is allowed to fail at every step: the local store is
12
+ * complete on its own, so a mirror that cannot reach anything must leave the
13
+ * harness working exactly as it would with sync switched off. Nothing here
14
+ * throws outward, and nothing here is awaited by a write path.
15
+ *
16
+ * Two asymmetries worth knowing, both of them the protocol's doing:
17
+ *
18
+ * Pushing again is free. The server deduplicates on record id, so the
19
+ * bookkeeping below only has to be approximately right — it exists to keep
20
+ * pushes small, not to keep them correct. On any doubt it re-sends.
21
+ *
22
+ * Pulling twice is free for the same reason, one layer down: `mergeRecords`
23
+ * drops what the log already holds. So a cursor lost to a crash costs
24
+ * bandwidth and nothing else.
25
+ */
26
+ /** How long to gather writes before pushing. A turn writes many records. */
27
+ const PUSH_DEBOUNCE_MS = 750;
28
+ /** Backoff after a failure, doubling to the ceiling. */
29
+ const RETRY_FLOOR_MS = 2_000;
30
+ const RETRY_CEILING_MS = 60_000;
31
+ export class SessionMirror {
32
+ store;
33
+ client;
34
+ projectId;
35
+ state;
36
+ onError;
37
+ pollSeconds;
38
+ timers;
39
+ unwatch;
40
+ aborter;
41
+ pushTimer;
42
+ pulling;
43
+ running = false;
44
+ /** Sessions with local writes not known to be pushed. */
45
+ dirty = new Set();
46
+ /** Deletions waiting to travel, kept because the metadata is already gone. */
47
+ tombstones = new Map();
48
+ held;
49
+ constructor(opts) {
50
+ this.store = opts.store;
51
+ this.client = opts.client;
52
+ this.projectId = opts.projectId;
53
+ this.state = opts.state ?? new JsonStore(opts.store.root);
54
+ this.onError = opts.onError ?? (() => { });
55
+ this.pollSeconds = Math.min(opts.pollSeconds ?? MAX_WAIT_SECONDS, MAX_WAIT_SECONDS);
56
+ this.timers = opts.timers ?? {
57
+ setTimeout: (fn, ms) => setTimeout(fn, ms),
58
+ clearTimeout: (handle) => clearTimeout(handle),
59
+ };
60
+ }
61
+ get active() {
62
+ return this.running;
63
+ }
64
+ /**
65
+ * Begin mirroring.
66
+ *
67
+ * Subscribing comes before the first pull so a write that lands during the
68
+ * opening round trip is not missed — it would otherwise sit unpushed until
69
+ * something else in that session changed, which for a finished session is
70
+ * never.
71
+ */
72
+ start() {
73
+ if (this.running)
74
+ return;
75
+ this.running = true;
76
+ this.aborter = new AbortController();
77
+ this.unwatch = this.store.watch((change) => this.onChange(change));
78
+ // Everything already on disk may predate this device having a server at
79
+ // all, so the first pass offers the whole project rather than only what
80
+ // changes from here.
81
+ void this.sweep();
82
+ void this.loop();
83
+ }
84
+ /**
85
+ * Stop, and stay stopped.
86
+ *
87
+ * The in-flight long poll is aborted rather than waited out: a user who
88
+ * switches sync off should not have a connection to the server outliving the
89
+ * decision by up to thirty seconds.
90
+ */
91
+ stop() {
92
+ if (!this.running)
93
+ return;
94
+ this.running = false;
95
+ this.unwatch?.();
96
+ this.unwatch = undefined;
97
+ if (this.pushTimer !== undefined) {
98
+ this.timers.clearTimeout(this.pushTimer);
99
+ this.pushTimer = undefined;
100
+ }
101
+ this.aborter?.abort();
102
+ this.aborter = undefined;
103
+ }
104
+ /** Push whatever is pending now, rather than on the debounce. */
105
+ async flush() {
106
+ if (this.pushTimer !== undefined) {
107
+ this.timers.clearTimeout(this.pushTimer);
108
+ this.pushTimer = undefined;
109
+ }
110
+ await this.push();
111
+ }
112
+ onChange(change) {
113
+ if (change.projectId !== this.projectId)
114
+ return;
115
+ if (change.kind === "delete") {
116
+ this.tombstones.set(change.id, change.meta);
117
+ this.dirty.delete(change.id);
118
+ }
119
+ else {
120
+ this.dirty.add(change.id);
121
+ }
122
+ this.schedulePush();
123
+ }
124
+ schedulePush() {
125
+ if (!this.running || this.pushTimer !== undefined)
126
+ return;
127
+ this.pushTimer = this.timers.setTimeout(() => {
128
+ this.pushTimer = undefined;
129
+ void this.push();
130
+ }, PUSH_DEBOUNCE_MS);
131
+ }
132
+ /** Offer every session in this project, for a device that has never pushed. */
133
+ async sweep() {
134
+ try {
135
+ const sessions = await this.store.list(Number.MAX_SAFE_INTEGER, {
136
+ projectId: this.projectId,
137
+ });
138
+ for (const meta of sessions)
139
+ this.dirty.add(meta.id);
140
+ if (sessions.length > 0)
141
+ this.schedulePush();
142
+ }
143
+ catch (err) {
144
+ this.onError(`sync sweep failed: ${errorMessage(err)}`);
145
+ }
146
+ }
147
+ async push() {
148
+ if (!this.running)
149
+ return;
150
+ const ids = [...this.dirty];
151
+ const graves = [...this.tombstones.entries()];
152
+ if (ids.length === 0 && graves.length === 0)
153
+ return;
154
+ // Cleared before the work, not after: a write that lands mid-push marks the
155
+ // session dirty again and earns its own round rather than being folded into
156
+ // one whose records were already read.
157
+ this.dirty.clear();
158
+ this.tombstones.clear();
159
+ const state = await this.read();
160
+ const records = [];
161
+ const sessions = [];
162
+ try {
163
+ for (const id of ids) {
164
+ const meta = await this.store.readMeta(id);
165
+ if (!meta)
166
+ continue;
167
+ const from = state.pushed[id] ?? 0;
168
+ const pending = (await this.store.recordsOf(id)).filter((record) => record.seq > from);
169
+ for (const record of pending)
170
+ records.push(toWire(id, record));
171
+ // Artifact revisions ride the same lane and the same watermark. They
172
+ // are not messages, so they travel in an envelope the reader can tell
173
+ // apart, and a client that predates them skips what it cannot read
174
+ // rather than mistaking a revision for a turn.
175
+ const revisions = (await this.store.artifactRevisions(id)).filter((revision) => (revision.seq ?? 0) > from);
176
+ for (const revision of revisions)
177
+ records.push(artifactToWire(id, revision));
178
+ sessions.push({
179
+ id,
180
+ gen: meta.gen ?? 0,
181
+ updatedAt: meta.updatedAt,
182
+ body: meta,
183
+ });
184
+ state.pushed[id] = Math.max(from, ...pending.map((record) => record.seq), ...revisions.map((revision) => revision.seq ?? 0), from);
185
+ }
186
+ for (const [id, meta] of graves) {
187
+ sessions.push({ id, gen: meta.gen ?? 0, updatedAt: meta.updatedAt, deleted: true });
188
+ delete state.pushed[id];
189
+ }
190
+ // Batched to the protocol's cap. A first sync of a long project is many
191
+ // more records than one push may carry, and the server refuses an
192
+ // oversized batch outright rather than taking half of it.
193
+ const recordBatches = chunk(records);
194
+ const sessionBatches = chunk(sessions);
195
+ const rounds = Math.max(recordBatches.length, sessionBatches.length, 1);
196
+ for (let round = 0; round < rounds; round++) {
197
+ await this.client.push(this.projectId, recordBatches[round] ?? [], sessionBatches[round] ?? [], this.aborter?.signal);
198
+ }
199
+ await this.write(state);
200
+ }
201
+ catch (err) {
202
+ // Put them back. The next change, or the next loop turn, tries again.
203
+ for (const id of ids)
204
+ this.dirty.add(id);
205
+ for (const [id, meta] of graves)
206
+ this.tombstones.set(id, meta);
207
+ this.report(err, "push");
208
+ }
209
+ }
210
+ /**
211
+ * Read the feed forward, forever.
212
+ *
213
+ * A long poll returns either when something arrives or when the server gives
214
+ * up holding it, so the loop is not a poll with a delay in it — the delay
215
+ * only appears after a failure.
216
+ */
217
+ async loop() {
218
+ if (this.pulling)
219
+ return this.pulling;
220
+ const run = (async () => {
221
+ let backoff = RETRY_FLOOR_MS;
222
+ while (this.running) {
223
+ try {
224
+ const moved = await this.pull();
225
+ backoff = RETRY_FLOOR_MS;
226
+ // `more` means the page was cut short, so come straight back rather
227
+ // than holding a poll open while the rest is already waiting.
228
+ if (!moved)
229
+ continue;
230
+ }
231
+ catch (err) {
232
+ if (!this.running)
233
+ break;
234
+ this.report(err, "pull");
235
+ await this.wait(backoff);
236
+ backoff = Math.min(backoff * 2, RETRY_CEILING_MS);
237
+ }
238
+ }
239
+ })();
240
+ this.pulling = run.finally(() => {
241
+ this.pulling = undefined;
242
+ // A stop that landed while the poll was in flight leaves `running`
243
+ // false; a stop followed by a start leaves it true and wants the loop
244
+ // back, which the finished promise can no longer provide.
245
+ if (this.running)
246
+ void this.loop();
247
+ });
248
+ return this.pulling;
249
+ }
250
+ async pull() {
251
+ const state = await this.read();
252
+ const answer = await this.client.pull(this.projectId, state.cursor, {
253
+ wait: this.pollSeconds,
254
+ ...(this.aborter?.signal ? { signal: this.aborter.signal } : {}),
255
+ });
256
+ for (const wire of answer.sessions) {
257
+ if (wire.deleted) {
258
+ await this.store.delete(wire.id).catch(() => false);
259
+ continue;
260
+ }
261
+ const meta = wire.body;
262
+ if (meta && typeof meta.id === "string") {
263
+ await this.store.mergeMeta({ ...meta, projectId: this.projectId }).catch(() => false);
264
+ }
265
+ }
266
+ // Grouped as wire records rather than messages, because the two kinds are
267
+ // only told apart once the envelope is opened.
268
+ const bySession = new Map();
269
+ for (const wire of answer.records) {
270
+ const list = bySession.get(wire.session) ?? [];
271
+ list.push(wire);
272
+ bySession.set(wire.session, list);
273
+ }
274
+ for (const [id, incoming] of bySession) {
275
+ const messages = [];
276
+ const revisions = [];
277
+ for (const wire of incoming) {
278
+ const revision = artifactFromWire(wire);
279
+ if (revision)
280
+ revisions.push(revision);
281
+ else
282
+ messages.push(fromWire(wire));
283
+ }
284
+ await this.store.mergeRecords(id, messages).catch(() => 0);
285
+ await this.store.mergeArtifactRevisions(id, revisions).catch(() => 0);
286
+ }
287
+ if (answer.cursor !== state.cursor) {
288
+ state.cursor = answer.cursor;
289
+ await this.write(state);
290
+ }
291
+ return !answer.more;
292
+ }
293
+ report(err, what) {
294
+ // An aborted request is this mirror being stopped, not a problem.
295
+ if (err instanceof Error && err.name === "AbortError")
296
+ return;
297
+ if (!this.running)
298
+ return;
299
+ if (err instanceof SyncHttpError && err.status === 401) {
300
+ this.onError(`sync ${what}: the token was rejected; sign in again to resume`);
301
+ // A bad token will not fix itself, and retrying it every few seconds is
302
+ // how an expired credential becomes a log nobody reads.
303
+ this.stop();
304
+ return;
305
+ }
306
+ this.onError(`sync ${what}: ${errorMessage(err)}`);
307
+ }
308
+ wait(ms) {
309
+ return new Promise((resolve) => {
310
+ this.timers.setTimeout(resolve, ms);
311
+ });
312
+ }
313
+ async read() {
314
+ if (this.held)
315
+ return this.held;
316
+ const stored = await this.state.read(["sync", this.projectId]);
317
+ this.held = {
318
+ cursor: typeof stored?.cursor === "number" ? stored.cursor : 0,
319
+ pushed: stored?.pushed && typeof stored.pushed === "object" ? { ...stored.pushed } : {},
320
+ };
321
+ return this.held;
322
+ }
323
+ async write(state) {
324
+ this.held = state;
325
+ await this.state.write(["sync", this.projectId], state).catch(() => { });
326
+ }
327
+ }
328
+ /**
329
+ * The envelope an artifact revision travels in.
330
+ *
331
+ * A record body is opaque to the server, so this needs no server change at
332
+ * all — but it does need to be unmistakable to a reader, because the same feed
333
+ * carries turns. `{ artifact: … }` is that mark: `asRecord` returns undefined
334
+ * for it, so a client that has never heard of artifacts skips the line instead
335
+ * of writing a malformed message into a transcript.
336
+ */
337
+ const ARTIFACT_ENVELOPE = "artifact";
338
+ function artifactToWire(session, revision) {
339
+ return {
340
+ session,
341
+ id: revision.id ?? `art_${revision.artifact}_v${revision.version}`,
342
+ seq: revision.seq ?? 0,
343
+ device: revision.device ?? "unknown",
344
+ at: revision.at,
345
+ body: { [ARTIFACT_ENVELOPE]: revision },
346
+ };
347
+ }
348
+ /** The revision inside an envelope, or undefined for anything else on the feed. */
349
+ function artifactFromWire(wire) {
350
+ const body = wire.body;
351
+ if (!body || typeof body !== "object")
352
+ return undefined;
353
+ const inner = body[ARTIFACT_ENVELOPE];
354
+ if (!inner)
355
+ return undefined;
356
+ const revision = asArtifactRevision(inner);
357
+ if (!revision)
358
+ return undefined;
359
+ // The wire fields win: they are what the other device recorded, and what
360
+ // dedupe on both sides is keyed on.
361
+ return { ...revision, id: wire.id, seq: wire.seq, device: wire.device };
362
+ }
363
+ function toWire(session, record) {
364
+ return {
365
+ session,
366
+ id: record.id,
367
+ seq: record.seq,
368
+ device: record.device,
369
+ at: record.at,
370
+ body: record.message,
371
+ };
372
+ }
373
+ /**
374
+ * A record as it came back.
375
+ *
376
+ * The three identity fields are taken as given — that is the entire point of
377
+ * sending them — while `body` is trusted only as far as being an object,
378
+ * because the server never looked inside it and neither did anything between.
379
+ */
380
+ function fromWire(wire) {
381
+ return {
382
+ id: wire.id,
383
+ seq: wire.seq,
384
+ device: wire.device,
385
+ at: wire.at,
386
+ message: wire.body,
387
+ };
388
+ }
389
+ //# sourceMappingURL=mirror.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mirror.js","sourceRoot":"","sources":["../../src/sync/mirror.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * The wire between a harness and a sync server.
3
+ *
4
+ * The server never looks inside `body`. It stores an opaque blob against an
5
+ * id, a sequence and a cursor, and hands it back in order — which is what makes
6
+ * it safe to change the message format without redeploying anything, and what
7
+ * would make an end-to-end encrypted mode a client-side change alone.
8
+ */
9
+ /** One transcript line, as it crosses the network. */
10
+ export interface WireRecord {
11
+ /** Session it belongs to. */
12
+ session: string;
13
+ /** Stable across devices — the server dedupes on it, so a retry is free. */
14
+ id: string;
15
+ /** Lamport counter within the session. Ordering, not arrival. */
16
+ seq: number;
17
+ device: string;
18
+ at: number;
19
+ /** The message. Opaque to the server. */
20
+ body: unknown;
21
+ }
22
+ /** Session metadata, resolved last-writer-wins rather than merged. */
23
+ export interface WireSession {
24
+ id: string;
25
+ /** Bumped by a rewrite (compaction). Higher generations win outright. */
26
+ gen: number;
27
+ updatedAt: number;
28
+ /** Tombstone: a deletion has to travel, or the other device restores it. */
29
+ deleted?: boolean;
30
+ /** The metadata. Opaque to the server. */
31
+ body?: unknown;
32
+ }
33
+ export interface PushRequest {
34
+ project: string;
35
+ device: string;
36
+ records?: WireRecord[];
37
+ sessions?: WireSession[];
38
+ /**
39
+ * Push into a team's feed rather than your own.
40
+ *
41
+ * Absent means the person, which is what a single-user install always wants
42
+ * and what every client sent before teams existed. Named, the server checks
43
+ * the token holds that team — a client cannot reach a feed by guessing an
44
+ * id, and there is no scope string that could be pointed at another person.
45
+ */
46
+ team?: string;
47
+ }
48
+ export interface PushResponse {
49
+ /** Where the caller now stands in this project's feed. */
50
+ cursor: number;
51
+ /** How many were new; the rest were already held. */
52
+ accepted: number;
53
+ }
54
+ export interface PullResponse {
55
+ cursor: number;
56
+ records: WireRecord[];
57
+ sessions: WireSession[];
58
+ /** True when the response was cut short by `limit` and more is waiting. */
59
+ more: boolean;
60
+ }
61
+ /** Refused rather than truncated: a silently dropped record is a lost turn. */
62
+ export declare const MAX_PUSH_RECORDS = 500;
63
+ export declare const MAX_BODY_BYTES: number;
64
+ /** Cap on one pull, so a first sync arrives in pages instead of one gulp. */
65
+ export declare const DEFAULT_PULL_LIMIT = 500;
66
+ /** Longest a long-poll is held open. Below any sensible proxy idle timeout. */
67
+ export declare const MAX_WAIT_SECONDS = 30;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The wire between a harness and a sync server.
3
+ *
4
+ * The server never looks inside `body`. It stores an opaque blob against an
5
+ * id, a sequence and a cursor, and hands it back in order — which is what makes
6
+ * it safe to change the message format without redeploying anything, and what
7
+ * would make an end-to-end encrypted mode a client-side change alone.
8
+ */
9
+ /** Refused rather than truncated: a silently dropped record is a lost turn. */
10
+ export const MAX_PUSH_RECORDS = 500;
11
+ export const MAX_BODY_BYTES = 8 * 1024 * 1024;
12
+ /** Cap on one pull, so a first sync arrives in pages instead of one gulp. */
13
+ export const DEFAULT_PULL_LIMIT = 500;
14
+ /** Longest a long-poll is held open. Below any sensible proxy idle timeout. */
15
+ export const MAX_WAIT_SECONDS = 30;
16
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/sync/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA2DH,+EAA+E;AAC/E,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,CAAC;AACpC,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAC9C,6EAA6E;AAC7E,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AACtC,+EAA+E;AAC/E,MAAM,CAAC,MAAM,gBAAgB,GAAG,EAAE,CAAC"}
@@ -0,0 +1,56 @@
1
+ import type { SyncConfig } from "../config.ts";
2
+ /**
3
+ * Whether to mirror, and where to.
4
+ *
5
+ * Sync is on by default, which is a decision about defaults rather than about
6
+ * consent: it cannot do anything until there is a destination and a token, and
7
+ * the token comes from signing in. So the honest reading of "on" is "as soon
8
+ * as you have an account", and a machine that never signs in never sends
9
+ * anything.
10
+ *
11
+ * Three ways to stop it, in the order they are checked. Each exists because
12
+ * the others do not cover its case:
13
+ *
14
+ * `OHARNESS_SYNC=0` one run, or every run in CI, without editing a file.
15
+ * `sync.enabled` this machine, or this repository (off only — see
16
+ * `mergeSync` on why a project cannot switch it on).
17
+ * `sync.exclude` one project, while everything else keeps mirroring.
18
+ */
19
+ /** The official service. Overridden by `sync.url` for self-hosted servers. */
20
+ export declare const DEFAULT_SYNC_URL = "https://sync.oharness.ai";
21
+ export interface ResolvedSync {
22
+ url: string;
23
+ token: string;
24
+ }
25
+ export interface SyncInputs {
26
+ config: SyncConfig | undefined;
27
+ /** The account credential, when signed in. Used when no token is configured. */
28
+ accountToken?: string | undefined;
29
+ env?: NodeJS.ProcessEnv;
30
+ }
31
+ /**
32
+ * Off, and why.
33
+ *
34
+ * The reason is carried rather than collapsed to a boolean so a UI can tell
35
+ * "you turned this off" from "you are not signed in" — two states that look
36
+ * identical from the outside and need opposite advice.
37
+ */
38
+ export type SyncDecision = {
39
+ on: true;
40
+ target: ResolvedSync;
41
+ } | {
42
+ on: false;
43
+ reason: "disabled" | "no-credential";
44
+ };
45
+ export declare function resolveSync(inputs: SyncInputs): SyncDecision;
46
+ /**
47
+ * Whether one project is excluded.
48
+ *
49
+ * Matched against both the project id and the worktree path, because neither
50
+ * alone is what a person reaches for: the id is a commit hash nobody has
51
+ * memorised, and the path is what they would type.
52
+ */
53
+ export declare function isExcluded(config: SyncConfig | undefined, project: {
54
+ id: string;
55
+ cwd?: string;
56
+ }): boolean;