@corenel/harness 0.2.0 → 0.4.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 (163) hide show
  1. package/dist/acp/agentMap.d.ts +34 -0
  2. package/dist/acp/agentMap.d.ts.map +1 -0
  3. package/dist/acp/agentMap.js +110 -0
  4. package/dist/acp/agentMap.js.map +1 -0
  5. package/dist/acp/index.d.ts +4 -0
  6. package/dist/acp/index.d.ts.map +1 -0
  7. package/dist/acp/index.js +6 -0
  8. package/dist/acp/index.js.map +1 -0
  9. package/dist/acp/policyMap.d.ts +55 -0
  10. package/dist/acp/policyMap.d.ts.map +1 -0
  11. package/dist/acp/policyMap.js +121 -0
  12. package/dist/acp/policyMap.js.map +1 -0
  13. package/dist/acp/types.d.ts +41 -0
  14. package/dist/acp/types.d.ts.map +1 -0
  15. package/dist/acp/types.js +14 -0
  16. package/dist/acp/types.js.map +1 -0
  17. package/dist/api/backend.d.ts +39 -0
  18. package/dist/api/backend.d.ts.map +1 -0
  19. package/dist/api/backend.js +126 -0
  20. package/dist/api/backend.js.map +1 -0
  21. package/dist/api/client.d.ts +95 -0
  22. package/dist/api/client.d.ts.map +1 -0
  23. package/dist/api/client.js +212 -0
  24. package/dist/api/client.js.map +1 -0
  25. package/dist/api/fileMirrorSource.d.ts +24 -0
  26. package/dist/api/fileMirrorSource.d.ts.map +1 -0
  27. package/dist/api/fileMirrorSource.js +59 -0
  28. package/dist/api/fileMirrorSource.js.map +1 -0
  29. package/dist/api/mirror.d.ts +102 -0
  30. package/dist/api/mirror.d.ts.map +1 -0
  31. package/dist/api/mirror.js +204 -0
  32. package/dist/api/mirror.js.map +1 -0
  33. package/dist/api/mirrorScheduler.d.ts +56 -0
  34. package/dist/api/mirrorScheduler.d.ts.map +1 -0
  35. package/dist/api/mirrorScheduler.js +167 -0
  36. package/dist/api/mirrorScheduler.js.map +1 -0
  37. package/dist/compression.d.ts +15 -1
  38. package/dist/compression.d.ts.map +1 -1
  39. package/dist/compression.js +32 -1
  40. package/dist/compression.js.map +1 -1
  41. package/dist/core/loop.d.ts +12 -0
  42. package/dist/core/loop.d.ts.map +1 -1
  43. package/dist/core/loop.js +138 -14
  44. package/dist/core/loop.js.map +1 -1
  45. package/dist/core/spawn.d.ts +54 -0
  46. package/dist/core/spawn.d.ts.map +1 -0
  47. package/dist/core/spawn.js +58 -0
  48. package/dist/core/spawn.js.map +1 -0
  49. package/dist/dag/executeNode.js +2 -2
  50. package/dist/fileSchema.js +1 -1
  51. package/dist/guardrail/guardrail.js +1 -1
  52. package/dist/guardrail/index.js +7 -7
  53. package/dist/guardrail/permission-service.js +1 -1
  54. package/dist/guardrail/serialize.js +1 -1
  55. package/dist/guardrail/store.js +2 -2
  56. package/dist/install/lockfile.d.ts +79 -0
  57. package/dist/install/lockfile.d.ts.map +1 -0
  58. package/dist/install/lockfile.js +155 -0
  59. package/dist/install/lockfile.js.map +1 -0
  60. package/dist/install/store.d.ts +13 -0
  61. package/dist/install/store.d.ts.map +1 -0
  62. package/dist/install/store.js +38 -0
  63. package/dist/install/store.js.map +1 -0
  64. package/dist/log.d.ts.map +1 -1
  65. package/dist/log.js +6 -1
  66. package/dist/log.js.map +1 -1
  67. package/dist/prompts/config.js +2 -2
  68. package/dist/prompts/host.d.ts +4 -0
  69. package/dist/prompts/host.d.ts.map +1 -1
  70. package/dist/prompts/host.js.map +1 -1
  71. package/dist/prompts/index.d.ts.map +1 -1
  72. package/dist/prompts/index.js +13 -6
  73. package/dist/prompts/index.js.map +1 -1
  74. package/dist/prompts/library/defaults.generated.js +2 -2
  75. package/dist/prompts/library/defaults.generated.js.map +1 -1
  76. package/dist/prompts/library/index.js +1 -1
  77. package/dist/providers/contextWindow.d.ts +19 -0
  78. package/dist/providers/contextWindow.d.ts.map +1 -0
  79. package/dist/providers/contextWindow.js +68 -0
  80. package/dist/providers/contextWindow.js.map +1 -0
  81. package/dist/providers/gateway.d.ts +3 -0
  82. package/dist/providers/gateway.d.ts.map +1 -1
  83. package/dist/providers/gateway.js +4 -1
  84. package/dist/providers/gateway.js.map +1 -1
  85. package/dist/sessions/apiLeaseStore.d.ts +10 -0
  86. package/dist/sessions/apiLeaseStore.d.ts.map +1 -0
  87. package/dist/sessions/apiLeaseStore.js +41 -0
  88. package/dist/sessions/apiLeaseStore.js.map +1 -0
  89. package/dist/sessions/blobGc.d.ts +62 -0
  90. package/dist/sessions/blobGc.d.ts.map +1 -0
  91. package/dist/sessions/blobGc.js +154 -0
  92. package/dist/sessions/blobGc.js.map +1 -0
  93. package/dist/sessions/fileRecallStore.js +1 -1
  94. package/dist/sessions/fileSessionStore.js +1 -1
  95. package/dist/sessions/head.d.ts +90 -0
  96. package/dist/sessions/head.d.ts.map +1 -0
  97. package/dist/sessions/head.js +82 -0
  98. package/dist/sessions/head.js.map +1 -0
  99. package/dist/sessions/inflight.d.ts +58 -0
  100. package/dist/sessions/inflight.d.ts.map +1 -0
  101. package/dist/sessions/inflight.js +0 -0
  102. package/dist/sessions/inflight.js.map +1 -0
  103. package/dist/sessions/lease.d.ts +59 -0
  104. package/dist/sessions/lease.d.ts.map +1 -0
  105. package/dist/sessions/lease.js +115 -0
  106. package/dist/sessions/lease.js.map +1 -0
  107. package/dist/sessions/leaseStore.d.ts +46 -0
  108. package/dist/sessions/leaseStore.d.ts.map +1 -0
  109. package/dist/sessions/leaseStore.js +58 -0
  110. package/dist/sessions/leaseStore.js.map +1 -0
  111. package/dist/sessions/timeline.d.ts +134 -0
  112. package/dist/sessions/timeline.d.ts.map +1 -0
  113. package/dist/sessions/timeline.js +127 -0
  114. package/dist/sessions/timeline.js.map +1 -0
  115. package/dist/sidecar/host.d.ts +241 -5
  116. package/dist/sidecar/host.d.ts.map +1 -1
  117. package/dist/sidecar/host.js +630 -5
  118. package/dist/sidecar/host.js.map +1 -1
  119. package/dist/sidecar/server.d.ts +124 -2
  120. package/dist/sidecar/server.d.ts.map +1 -1
  121. package/dist/sidecar/server.js +620 -9
  122. package/dist/sidecar/server.js.map +1 -1
  123. package/dist/sidecar/wsChannel.d.ts +4 -0
  124. package/dist/sidecar/wsChannel.d.ts.map +1 -0
  125. package/dist/sidecar/wsChannel.js +62 -0
  126. package/dist/sidecar/wsChannel.js.map +1 -0
  127. package/dist/skills.js +2 -2
  128. package/dist/snapshot/effects.d.ts +69 -0
  129. package/dist/snapshot/effects.d.ts.map +1 -0
  130. package/dist/snapshot/effects.js +67 -0
  131. package/dist/snapshot/effects.js.map +1 -0
  132. package/dist/snapshot/manifest.d.ts +73 -0
  133. package/dist/snapshot/manifest.d.ts.map +1 -0
  134. package/dist/snapshot/manifest.js +141 -0
  135. package/dist/snapshot/manifest.js.map +1 -0
  136. package/dist/snapshot/tree.d.ts +62 -0
  137. package/dist/snapshot/tree.d.ts.map +1 -0
  138. package/dist/snapshot/tree.js +147 -0
  139. package/dist/snapshot/tree.js.map +1 -0
  140. package/dist/tools/builtins.d.ts.map +1 -1
  141. package/dist/tools/builtins.js +67 -8
  142. package/dist/tools/builtins.js.map +1 -1
  143. package/dist/tools/callAgent.d.ts +16 -0
  144. package/dist/tools/callAgent.d.ts.map +1 -0
  145. package/dist/tools/callAgent.js +53 -0
  146. package/dist/tools/callAgent.js.map +1 -0
  147. package/dist/tools/files.d.ts +10 -0
  148. package/dist/tools/files.d.ts.map +1 -1
  149. package/dist/tools/files.js +159 -8
  150. package/dist/tools/files.js.map +1 -1
  151. package/dist/tools/http.js +1 -1
  152. package/dist/tools/namespaces.d.ts +1 -1
  153. package/dist/tools/namespaces.d.ts.map +1 -1
  154. package/dist/tools/namespaces.js +40 -2
  155. package/dist/tools/namespaces.js.map +1 -1
  156. package/dist/tools/procs.d.ts +18 -0
  157. package/dist/tools/procs.d.ts.map +1 -0
  158. package/dist/tools/procs.js +281 -0
  159. package/dist/tools/procs.js.map +1 -0
  160. package/dist/tools/todo.d.ts.map +1 -1
  161. package/dist/tools/todo.js +12 -0
  162. package/dist/tools/todo.js.map +1 -1
  163. package/package.json +18 -7
@@ -0,0 +1,204 @@
1
+ import { LeaseConflict } from './client.js';
2
+ const blank = () => ({
3
+ pushedIndex: 0, lastPushedAt: 0, lastError: '', authoritative: false, epoch: 0,
4
+ });
5
+ export class SessionMirror {
6
+ constructor(deps) {
7
+ Object.defineProperty(this, "deps", {
8
+ enumerable: true,
9
+ configurable: true,
10
+ writable: true,
11
+ value: deps
12
+ });
13
+ Object.defineProperty(this, "state", {
14
+ enumerable: true,
15
+ configurable: true,
16
+ writable: true,
17
+ value: new Map()
18
+ });
19
+ /** local session id -> the id this backend knows it by. Two namespaces, and
20
+ * assuming they are one is a silent 404 on every push. */
21
+ Object.defineProperty(this, "remoteIds", {
22
+ enumerable: true,
23
+ configurable: true,
24
+ writable: true,
25
+ value: new Map()
26
+ });
27
+ Object.defineProperty(this, "now", {
28
+ enumerable: true,
29
+ configurable: true,
30
+ writable: true,
31
+ value: void 0
32
+ });
33
+ this.now = deps.now ?? Date.now;
34
+ }
35
+ /**
36
+ * The backend's id for a local session, creating the record if this is the
37
+ * first time it has been mentioned.
38
+ *
39
+ * Idempotent on the server, so a reconnect finds the session it was already
40
+ * pushing to rather than opening a second one beside it and splitting the log.
41
+ */
42
+ async remoteId(sessionId) {
43
+ const known = this.remoteIds.get(sessionId);
44
+ if (known)
45
+ return known;
46
+ const found = await this.deps.client.findByLocalId(sessionId);
47
+ if (found) {
48
+ this.remoteIds.set(sessionId, found._id);
49
+ return found._id;
50
+ }
51
+ try {
52
+ const created = await this.deps.client.createSession({ localId: sessionId, location: 'local' });
53
+ this.remoteIds.set(sessionId, created._id);
54
+ return created._id;
55
+ }
56
+ catch (err) {
57
+ // A SANDBOX credential cannot create sessions, on purpose: the user
58
+ // provisions the session and the credential together, and the machine
59
+ // finds them. Saying that plainly beats reporting the raw 401, which reads
60
+ // like a broken credential rather than a missing session.
61
+ const status = err.status;
62
+ if (status === 401 || status === 403) {
63
+ throw new Error(`no session on the backend for "${sessionId}", and this credential may not create one — `
64
+ + 'provision the session first, or use a user credential');
65
+ }
66
+ throw err;
67
+ }
68
+ }
69
+ status(sessionId) {
70
+ return { ...(this.state.get(sessionId) ?? blank()) };
71
+ }
72
+ set(sessionId, patch) {
73
+ const next = { ...(this.state.get(sessionId) ?? blank()), ...patch };
74
+ this.state.set(sessionId, next);
75
+ return { ...next };
76
+ }
77
+ /**
78
+ * Claim authority for this machine.
79
+ *
80
+ * Reads the current epoch and takes the next one. Losing the race is a normal
81
+ * answer, not an error: another machine holds the session, and what this one
82
+ * does about that is a decision for the caller (usually: stop, and offer the
83
+ * user a demote).
84
+ */
85
+ async claim(sessionId) {
86
+ try {
87
+ const remote = await this.remoteId(sessionId);
88
+ const current = await this.deps.client.getSession(remote);
89
+ const lease = await this.deps.client.acquireLease(remote, current.epoch, this.deps.holder);
90
+ this.deps.log?.(`mirror: took authority for ${sessionId} at epoch ${lease.epoch}`);
91
+ return { ok: true, status: this.set(sessionId, { authoritative: true, epoch: lease.epoch, lastError: '' }) };
92
+ }
93
+ catch (err) {
94
+ const lost = err instanceof LeaseConflict;
95
+ const message = err instanceof Error ? err.message : String(err);
96
+ this.deps.log?.(`mirror: could not take authority for ${sessionId}: ${message}`);
97
+ return {
98
+ ok: false,
99
+ status: this.set(sessionId, {
100
+ authoritative: false,
101
+ ...(lost ? { epoch: err.currentEpoch } : {}),
102
+ lastError: message,
103
+ }),
104
+ };
105
+ }
106
+ }
107
+ /** Give authority up, so another machine can take it without waiting for an
108
+ * expiry that does not exist. Best-effort like everything else here. */
109
+ async release(sessionId) {
110
+ const s = this.status(sessionId);
111
+ if (!s.authoritative)
112
+ return;
113
+ try {
114
+ const epoch = await this.deps.client.releaseLease(await this.remoteId(sessionId), s.epoch);
115
+ this.set(sessionId, { authoritative: false, epoch });
116
+ }
117
+ catch (err) {
118
+ // A failed release is not worth surfacing: the next holder's acquire will
119
+ // supersede this epoch anyway. That is the whole point of a monotonic
120
+ // counter over a flag.
121
+ this.set(sessionId, { authoritative: false, lastError: err instanceof Error ? err.message : String(err) });
122
+ }
123
+ }
124
+ /**
125
+ * Push everything the mirror has not seen.
126
+ *
127
+ * Resumes from the recorded cursor, so an interrupted push costs a retry rather
128
+ * than a re-upload of the whole log. Resolves either way — a caller in the
129
+ * middle of an agent turn must never have to handle this throwing.
130
+ */
131
+ async push(sessionId) {
132
+ const before = this.status(sessionId);
133
+ if (!before.authoritative) {
134
+ // Pushing without authority would overwrite whichever machine is actually
135
+ // running the session. Refusing is the correct behaviour, not a limitation.
136
+ return { ok: false, pushed: 0, status: this.set(sessionId, { lastError: 'not the authoritative holder' }) };
137
+ }
138
+ try {
139
+ const remote = await this.remoteId(sessionId);
140
+ const { entries, nextIndex } = await this.deps.local.entriesSince(sessionId, before.pushedIndex);
141
+ if (entries.length) {
142
+ await this.deps.client.appendTimeline(remote, before.epoch, entries);
143
+ }
144
+ const head = await this.deps.local.head(sessionId);
145
+ if (head)
146
+ await this.deps.client.putHead(remote, before.epoch, head);
147
+ return {
148
+ ok: true,
149
+ pushed: entries.length,
150
+ status: this.set(sessionId, {
151
+ pushedIndex: Math.max(before.pushedIndex, nextIndex),
152
+ lastPushedAt: this.now(),
153
+ lastError: '',
154
+ }),
155
+ };
156
+ }
157
+ catch (err) {
158
+ const message = err instanceof Error ? err.message : String(err);
159
+ const lostAuthority = err instanceof LeaseConflict;
160
+ if (lostAuthority) {
161
+ // Someone else took the session. This machine's copy is a stale branch
162
+ // now, and continuing to push would be fighting over a session it no
163
+ // longer holds. Stop, and let the caller decide what to tell the user.
164
+ this.deps.log?.(`mirror: lost authority for ${sessionId}; stopping`);
165
+ return {
166
+ ok: false,
167
+ pushed: 0,
168
+ lostAuthority: true,
169
+ status: this.set(sessionId, {
170
+ authoritative: false,
171
+ epoch: err.currentEpoch,
172
+ lastError: 'another machine took this session',
173
+ }),
174
+ };
175
+ }
176
+ this.deps.log?.(`mirror: push failed for ${sessionId}: ${message}`);
177
+ return { ok: false, pushed: 0, status: this.set(sessionId, { lastError: message }) };
178
+ }
179
+ }
180
+ /**
181
+ * Read the mirror.
182
+ *
183
+ * RETURNS the remote state; it does not write anything locally. What to do with
184
+ * a remote copy — restore it, merge it, show it read-only — belongs to whoever
185
+ * owns the local store, and a mirror that silently overwrote local state would
186
+ * have made itself the original.
187
+ */
188
+ async pull(sessionId, since = 0) {
189
+ try {
190
+ const { entries, nextIndex } = await this.deps.client.readTimeline(await this.remoteId(sessionId), since);
191
+ return { ok: true, entries, nextIndex, error: '' };
192
+ }
193
+ catch (err) {
194
+ return { ok: false, entries: [], nextIndex: 0, error: err instanceof Error ? err.message : String(err) };
195
+ }
196
+ }
197
+ /** Forget local bookkeeping for a session — after a destroy, or when this
198
+ * machine stops caring about it. Does not touch the remote copy. */
199
+ forget(sessionId) {
200
+ this.state.delete(sessionId);
201
+ this.remoteIds.delete(sessionId);
202
+ }
203
+ }
204
+ //# sourceMappingURL=mirror.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mirror.js","sourceRoot":"","sources":["../../api/mirror.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ import type { PushResult } from './mirror';
2
+ /** Just enough of SessionMirror to schedule against — so a test needs no client. */
3
+ export interface SchedulableMirror {
4
+ push(sessionId: string): Promise<PushResult>;
5
+ }
6
+ export interface MirrorSchedulerDeps {
7
+ mirror: SchedulableMirror;
8
+ /** Quiet period after the last write before pushing. */
9
+ debounceMs?: number;
10
+ /** How far behind the mirror may fall while writes keep coming. */
11
+ maxWaitMs?: number;
12
+ /** Wait after a failed push before trying again. Doubles, to a cap. */
13
+ retryMs?: number;
14
+ maxRetryMs?: number;
15
+ setTimer?: (fn: () => void, ms: number) => unknown;
16
+ clearTimer?: (handle: unknown) => void;
17
+ now?: () => number;
18
+ log?: (line: string) => void;
19
+ }
20
+ export declare class MirrorScheduler {
21
+ private readonly deps;
22
+ private readonly pending;
23
+ private readonly cfg;
24
+ private readonly setTimer;
25
+ private readonly clearTimer;
26
+ private readonly now;
27
+ constructor(deps: MirrorSchedulerDeps);
28
+ private slot;
29
+ private disarm;
30
+ /**
31
+ * Work happened; push soon.
32
+ *
33
+ * Cheap and synchronous — this is called from the write path, and the write
34
+ * path must never wait on the mirror.
35
+ */
36
+ touch(sessionId: string): void;
37
+ /**
38
+ * Push now and wait for the result.
39
+ *
40
+ * For pause, handoff and shutdown — the moments where "shortly" is not good
41
+ * enough because the machine may be about to stop being the one that has the
42
+ * session.
43
+ */
44
+ flush(sessionId: string): Promise<PushResult>;
45
+ /** Flush every session with work outstanding — shutdown, or a demote of the
46
+ * whole machine. Runs them together; one failure does not stop the others. */
47
+ flushAll(): Promise<Record<string, PushResult>>;
48
+ private run;
49
+ /** Whether a push is scheduled or in flight. */
50
+ pending_(sessionId: string): boolean;
51
+ /** Stop scheduling for a session and forget it — a destroy, or a handoff that
52
+ * has already flushed. */
53
+ stop(sessionId: string): void;
54
+ dispose(): void;
55
+ }
56
+ //# sourceMappingURL=mirrorScheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mirrorScheduler.d.ts","sourceRoot":"","sources":["../../api/mirrorScheduler.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,oFAAoF;AACpF,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC9C;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;IACnD,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AAgBD,qBAAa,eAAe;IAOd,OAAO,CAAC,QAAQ,CAAC,IAAI;IANjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8B;IACtD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAkB;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0C;IACnE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA4B;IACvD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;gBAEN,IAAI,EAAE,mBAAmB;IAYtD,OAAO,CAAC,IAAI;IASZ,OAAO,CAAC,MAAM;IAOd;;;;;OAKG;IACH,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAqB9B;;;;;;OAMG;IACG,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAMnD;kFAC8E;IACxE,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YAMvC,GAAG;IA2CjB,gDAAgD;IAChD,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAKpC;8BAC0B;IAC1B,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAO7B,OAAO,IAAI,IAAI;CAIhB"}
@@ -0,0 +1,167 @@
1
+ const DEFAULTS = { debounceMs: 2000, maxWaitMs: 15000, retryMs: 5000, maxRetryMs: 60000 };
2
+ export class MirrorScheduler {
3
+ constructor(deps) {
4
+ Object.defineProperty(this, "deps", {
5
+ enumerable: true,
6
+ configurable: true,
7
+ writable: true,
8
+ value: deps
9
+ });
10
+ Object.defineProperty(this, "pending", {
11
+ enumerable: true,
12
+ configurable: true,
13
+ writable: true,
14
+ value: new Map()
15
+ });
16
+ Object.defineProperty(this, "cfg", {
17
+ enumerable: true,
18
+ configurable: true,
19
+ writable: true,
20
+ value: void 0
21
+ });
22
+ Object.defineProperty(this, "setTimer", {
23
+ enumerable: true,
24
+ configurable: true,
25
+ writable: true,
26
+ value: void 0
27
+ });
28
+ Object.defineProperty(this, "clearTimer", {
29
+ enumerable: true,
30
+ configurable: true,
31
+ writable: true,
32
+ value: void 0
33
+ });
34
+ Object.defineProperty(this, "now", {
35
+ enumerable: true,
36
+ configurable: true,
37
+ writable: true,
38
+ value: void 0
39
+ });
40
+ this.cfg = {
41
+ debounceMs: deps.debounceMs ?? DEFAULTS.debounceMs,
42
+ maxWaitMs: deps.maxWaitMs ?? DEFAULTS.maxWaitMs,
43
+ retryMs: deps.retryMs ?? DEFAULTS.retryMs,
44
+ maxRetryMs: deps.maxRetryMs ?? DEFAULTS.maxRetryMs,
45
+ };
46
+ this.setTimer = deps.setTimer ?? ((fn, ms) => setTimeout(fn, ms));
47
+ this.clearTimer = deps.clearTimer ?? ((h) => clearTimeout(h));
48
+ this.now = deps.now ?? Date.now;
49
+ }
50
+ slot(sessionId) {
51
+ let p = this.pending.get(sessionId);
52
+ if (!p) {
53
+ p = { handle: null, firstDirtyAt: 0, running: false, dirtyAgain: false, retryMs: this.cfg.retryMs, stopped: false };
54
+ this.pending.set(sessionId, p);
55
+ }
56
+ return p;
57
+ }
58
+ disarm(p) {
59
+ if (p.handle !== null) {
60
+ this.clearTimer(p.handle);
61
+ p.handle = null;
62
+ }
63
+ }
64
+ /**
65
+ * Work happened; push soon.
66
+ *
67
+ * Cheap and synchronous — this is called from the write path, and the write
68
+ * path must never wait on the mirror.
69
+ */
70
+ touch(sessionId) {
71
+ const p = this.slot(sessionId);
72
+ if (p.stopped)
73
+ return;
74
+ if (p.running) {
75
+ // Do not overlap pushes for one session: the second would race the first's
76
+ // cursor advance and could re-send or skip entries.
77
+ p.dirtyAgain = true;
78
+ return;
79
+ }
80
+ if (!p.firstDirtyAt)
81
+ p.firstDirtyAt = this.now();
82
+ this.disarm(p);
83
+ // The ceiling wins over the quiet period: a busy session must not defer its
84
+ // push forever just because it never goes quiet.
85
+ const elapsed = this.now() - p.firstDirtyAt;
86
+ const wait = Math.max(0, Math.min(this.cfg.debounceMs, this.cfg.maxWaitMs - elapsed));
87
+ p.handle = this.setTimer(() => { void this.run(sessionId); }, wait);
88
+ }
89
+ /**
90
+ * Push now and wait for the result.
91
+ *
92
+ * For pause, handoff and shutdown — the moments where "shortly" is not good
93
+ * enough because the machine may be about to stop being the one that has the
94
+ * session.
95
+ */
96
+ async flush(sessionId) {
97
+ const p = this.slot(sessionId);
98
+ this.disarm(p);
99
+ return this.run(sessionId, { force: true });
100
+ }
101
+ /** Flush every session with work outstanding — shutdown, or a demote of the
102
+ * whole machine. Runs them together; one failure does not stop the others. */
103
+ async flushAll() {
104
+ const ids = [...this.pending.keys()];
105
+ const results = await Promise.all(ids.map(async (id) => [id, await this.flush(id)]));
106
+ return Object.fromEntries(results);
107
+ }
108
+ async run(sessionId, opts = {}) {
109
+ const p = this.slot(sessionId);
110
+ if (p.stopped && !opts.force) {
111
+ return { ok: false, pushed: 0, status: { pushedIndex: 0, lastPushedAt: 0, lastError: 'stopped', authoritative: false, epoch: 0 } };
112
+ }
113
+ p.running = true;
114
+ this.disarm(p);
115
+ try {
116
+ const result = await this.deps.mirror.push(sessionId);
117
+ if (result.lostAuthority) {
118
+ // Another machine has the session. Stop — do not retry, do not re-arm.
119
+ this.deps.log?.(`mirror: authority lost for ${sessionId}; scheduler stopped`);
120
+ p.stopped = true;
121
+ p.dirtyAgain = false;
122
+ p.firstDirtyAt = 0;
123
+ return result;
124
+ }
125
+ if (result.ok) {
126
+ p.retryMs = this.cfg.retryMs;
127
+ p.firstDirtyAt = 0;
128
+ // Work that arrived mid-push has not been sent; schedule another round.
129
+ if (p.dirtyAgain) {
130
+ p.dirtyAgain = false;
131
+ p.running = false;
132
+ this.touch(sessionId);
133
+ return result;
134
+ }
135
+ return result;
136
+ }
137
+ // A transient failure. Back off rather than hammering a server that is
138
+ // already unhappy, and keep the dirty state so nothing is dropped.
139
+ p.handle = this.setTimer(() => { void this.run(sessionId); }, p.retryMs);
140
+ p.retryMs = Math.min(p.retryMs * 2, this.cfg.maxRetryMs);
141
+ return result;
142
+ }
143
+ finally {
144
+ p.running = false;
145
+ }
146
+ }
147
+ /** Whether a push is scheduled or in flight. */
148
+ pending_(sessionId) {
149
+ const p = this.pending.get(sessionId);
150
+ return !!p && (p.handle !== null || p.running || p.dirtyAgain);
151
+ }
152
+ /** Stop scheduling for a session and forget it — a destroy, or a handoff that
153
+ * has already flushed. */
154
+ stop(sessionId) {
155
+ const p = this.pending.get(sessionId);
156
+ if (!p)
157
+ return;
158
+ this.disarm(p);
159
+ this.pending.delete(sessionId);
160
+ }
161
+ dispose() {
162
+ for (const [, p] of this.pending)
163
+ this.disarm(p);
164
+ this.pending.clear();
165
+ }
166
+ }
167
+ //# sourceMappingURL=mirrorScheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mirrorScheduler.js","sourceRoot":"","sources":["../../api/mirrorScheduler.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,23 @@
1
1
  import type { CompressionMode, OffloadRef } from '@corenel/protocol';
2
- export type { CompressionMode, CompressionConfig, OffloadRef } from '@corenel/protocol';
2
+ export type { CompressionMode, CompressionConfig, CompressionStrategy, OffloadRef } from '@corenel/protocol';
3
3
  /** How much of an offloaded output to keep inline as a preview. */
4
4
  export declare const PREVIEW_BYTES = 800;
5
5
  /** Threshold for a given fill ratio (0–1). As the window fills, offload sooner. */
6
6
  export declare function effectiveThreshold(mode: CompressionMode, fill?: number): number;
7
+ export declare const OFFLOAD_MARKER_PREFIX = "[offloaded tool result \u00B7 ";
8
+ /** True if `content` is already a formatOffloadRef() pointer — i.e. this
9
+ * result was already offloaded and must not be recorded/rewritten again. */
10
+ export declare function isOffloadPointer(content: string): boolean;
11
+ /** The blob id (and recorded byte count) a formatOffloadRef() pointer carries,
12
+ * for a caller that needs to read the real content back — e.g. a restored
13
+ * transcript row recognizing a persisted pointer as still-offloaded (see
14
+ * @corenel/term's persist.ts). Returns `null` for anything that isn't a
15
+ * pointer, or a pointer whose tail doesn't parse (never thrown on — this can
16
+ * be read back out of a session log written by an older/different format). */
17
+ export declare function parseOffloadPointer(content: string): {
18
+ id: string;
19
+ bytes: number;
20
+ } | null;
7
21
  /** The self-describing reference that replaces a large output in the history.
8
22
  * Carries enough (tool, size, preview, recall instruction) for the model to
9
23
  * decide whether to pull the full content back. */
@@ -1 +1 @@
1
- {"version":3,"file":"compression.d.ts","sourceRoot":"","sources":["../compression.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACrE,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAExF,mEAAmE;AACnE,eAAO,MAAM,aAAa,MAAM,CAAC;AAOjC,mFAAmF;AACnF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,EAAE,IAAI,SAAI,GAAG,MAAM,CAI1E;AAED;;mDAEmD;AACnD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CAGxD"}
1
+ {"version":3,"file":"compression.d.ts","sourceRoot":"","sources":["../compression.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACrE,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE7G,mEAAmE;AACnE,eAAO,MAAM,aAAa,MAAM,CAAC;AAOjC,mFAAmF;AACnF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,EAAE,IAAI,SAAI,GAAG,MAAM,CAI1E;AAQD,eAAO,MAAM,qBAAqB,mCAA8B,CAAC;AAEjE;4EAC4E;AAC5E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEzD;AAOD;;;;;8EAK8E;AAC9E,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAMzF;AAED;;mDAEmD;AACnD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CAGxD"}
@@ -17,11 +17,42 @@ export function effectiveThreshold(mode, fill = 0) {
17
17
  const factor = fill < 0.5 ? 1 : fill < 0.7 ? 0.7 : fill < 0.85 ? 0.5 : 0.35;
18
18
  return Math.max(FLOOR[mode], Math.round(BASE[mode] * factor));
19
19
  }
20
+ // The stable, load-bearing prefix every formatOffloadRef() output starts with.
21
+ // Exported (not just used internally) so any pass that needs to recognize an
22
+ // ALREADY-offloaded message — the deferred strategy's history-compaction pass
23
+ // in loop.ts is the first caller — checks this instead of re-deriving it or
24
+ // loose-matching a substring that could coincidentally appear in real tool
25
+ // output. Keep formatOffloadRef's head in sync with this if either changes.
26
+ export const OFFLOAD_MARKER_PREFIX = '[offloaded tool result · ';
27
+ /** True if `content` is already a formatOffloadRef() pointer — i.e. this
28
+ * result was already offloaded and must not be recorded/rewritten again. */
29
+ export function isOffloadPointer(content) {
30
+ return content.startsWith(OFFLOAD_MARKER_PREFIX);
31
+ }
32
+ // Matches the `{bytes} bytes · recall the full content with recall_result({ id: "{id}" })`
33
+ // tail formatOffloadRef() writes. Kept beside it so there is exactly one place
34
+ // that knows both directions of the pointer format.
35
+ const POINTER_TAIL_RE = /· ([\d,]+) bytes · recall the full content with recall_result\(\{ id: "([^"]+)" \}\)/;
36
+ /** The blob id (and recorded byte count) a formatOffloadRef() pointer carries,
37
+ * for a caller that needs to read the real content back — e.g. a restored
38
+ * transcript row recognizing a persisted pointer as still-offloaded (see
39
+ * @corenel/term's persist.ts). Returns `null` for anything that isn't a
40
+ * pointer, or a pointer whose tail doesn't parse (never thrown on — this can
41
+ * be read back out of a session log written by an older/different format). */
42
+ export function parseOffloadPointer(content) {
43
+ if (!isOffloadPointer(content))
44
+ return null;
45
+ const m = POINTER_TAIL_RE.exec(content);
46
+ if (!m)
47
+ return null;
48
+ const bytes = Number(m[1].replace(/,/g, ''));
49
+ return { id: m[2], bytes: Number.isFinite(bytes) ? bytes : 0 };
50
+ }
20
51
  /** The self-describing reference that replaces a large output in the history.
21
52
  * Carries enough (tool, size, preview, recall instruction) for the model to
22
53
  * decide whether to pull the full content back. */
23
54
  export function formatOffloadRef(ref) {
24
- const head = `[offloaded tool result · ${ref.toolName} · ${ref.bytes.toLocaleString()} bytes · recall the full content with recall_result({ id: "${ref.id}" })]`;
55
+ const head = `${OFFLOAD_MARKER_PREFIX}${ref.toolName} · ${ref.bytes.toLocaleString()} bytes · recall the full content with recall_result({ id: "${ref.id}" })]`;
25
56
  return ref.preview ? `${head}\n--- preview ---\n${ref.preview}${ref.bytes > ref.preview.length ? '\n…(truncated)' : ''}` : head;
26
57
  }
27
58
  //# sourceMappingURL=compression.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"compression.js","sourceRoot":"","sources":["../compression.ts"],"names":[],"mappings":"AAAA;;;;;yFAKyF;AAOzF,mEAAmE;AACnE,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAC;AAEjC,+EAA+E;AAC/E,8BAA8B;AAC9B,MAAM,IAAI,GAAoC,EAAE,GAAG,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAM,EAAE,QAAQ,EAAE,KAAM,EAAE,UAAU,EAAE,IAAK,EAAE,CAAC;AAC3H,MAAM,KAAK,GAAoC,EAAE,GAAG,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAK,EAAE,QAAQ,EAAE,IAAK,EAAE,UAAU,EAAE,IAAK,EAAE,CAAC;AAE1H,mFAAmF;AACnF,MAAM,UAAU,kBAAkB,CAAC,IAAqB,EAAE,IAAI,GAAG,CAAC;IAChE,IAAI,IAAI,KAAK,KAAK;QAAE,OAAO,QAAQ,CAAC;IACpC,MAAM,MAAM,GAAG,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5E,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;AAChE,CAAC;AAED;;mDAEmD;AACnD,MAAM,UAAU,gBAAgB,CAAC,GAAe;IAC9C,MAAM,IAAI,GAAG,4BAA4B,GAAG,CAAC,QAAQ,MAAM,GAAG,CAAC,KAAK,CAAC,cAAc,EAAE,8DAA8D,GAAG,CAAC,EAAE,OAAO,CAAC;IACjK,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,sBAAsB,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAClI,CAAC"}
1
+ {"version":3,"file":"compression.js","sourceRoot":"","sources":["../compression.ts"],"names":[],"mappings":"AAAA;;;;;yFAKyF;AAOzF,mEAAmE;AACnE,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAC;AAEjC,+EAA+E;AAC/E,8BAA8B;AAC9B,MAAM,IAAI,GAAoC,EAAE,GAAG,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAM,EAAE,QAAQ,EAAE,KAAM,EAAE,UAAU,EAAE,IAAK,EAAE,CAAC;AAC3H,MAAM,KAAK,GAAoC,EAAE,GAAG,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAK,EAAE,QAAQ,EAAE,IAAK,EAAE,UAAU,EAAE,IAAK,EAAE,CAAC;AAE1H,mFAAmF;AACnF,MAAM,UAAU,kBAAkB,CAAC,IAAqB,EAAE,IAAI,GAAG,CAAC;IAChE,IAAI,IAAI,KAAK,KAAK;QAAE,OAAO,QAAQ,CAAC;IACpC,MAAM,MAAM,GAAG,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5E,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,+EAA+E;AAC/E,6EAA6E;AAC7E,8EAA8E;AAC9E,4EAA4E;AAC5E,2EAA2E;AAC3E,4EAA4E;AAC5E,MAAM,CAAC,MAAM,qBAAqB,GAAG,2BAA2B,CAAC;AAEjE;4EAC4E;AAC5E,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,OAAO,OAAO,CAAC,UAAU,CAAC,qBAAqB,CAAC,CAAC;AACnD,CAAC;AAED,2FAA2F;AAC3F,+EAA+E;AAC/E,oDAAoD;AACpD,MAAM,eAAe,GAAG,sFAAsF,CAAC;AAE/G;;;;;8EAK8E;AAC9E,MAAM,UAAU,mBAAmB,CAAC,OAAe;IACjD,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5C,MAAM,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACxC,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;IAC7C,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACjE,CAAC;AAED;;mDAEmD;AACnD,MAAM,UAAU,gBAAgB,CAAC,GAAe;IAC9C,MAAM,IAAI,GAAG,GAAG,qBAAqB,GAAG,GAAG,CAAC,QAAQ,MAAM,GAAG,CAAC,KAAK,CAAC,cAAc,EAAE,8DAA8D,GAAG,CAAC,EAAE,OAAO,CAAC;IAChK,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,sBAAsB,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAClI,CAAC"}
@@ -20,6 +20,16 @@ export interface RunAgentArgs {
20
20
  policy?: Policy;
21
21
  /** Per-tool permission resolver. When omitted, tools run without an approval gate. */
22
22
  permission?: PermissionService;
23
+ /** Customize the tool-result text a refused tool call gets. The kernel is
24
+ * host-agnostic and cannot know WHY a decision came back "deny" — a real
25
+ * person declining an interactive prompt, and a non-interactive host that
26
+ * has nobody to ask, are both just "deny" by the time they reach here. The
27
+ * default wording ("denied by the user") is only honest for the former;
28
+ * a host that fails closed with no prompt at all (see `run`/`run-agent` in
29
+ * @corenel/cli) should supply this so the model — and whoever reads the
30
+ * transcript — hears the actual cause and the actual remedy, not a claim
31
+ * that a person was asked and said no when nobody was asked anything. */
32
+ describePermissionDenial?: (toolName: string) => string;
23
33
  /** Context-compression config (rung-1 offload). Omit to disable. */
24
34
  compression?: CompressionConfig;
25
35
  /** Intra-run self-healing budget (stream-retry + tool-steer). Omit for defaults. */
@@ -27,6 +37,8 @@ export interface RunAgentArgs {
27
37
  /** Optional output-token ceiling forwarded to the model on every turn (reasoning
28
38
  * + visible output combined for reasoning models). Omit to leave output unbounded. */
29
39
  maxCompletionTokens?: number;
40
+ /** Sampling temperature, already vetted by the caller for model support. */
41
+ temperature?: number;
30
42
  signal?: AbortSignal;
31
43
  onEvent?: (e: AgentEvent) => void;
32
44
  }
@@ -1 +1 @@
1
- {"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../core/loop.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,KAAK,EAAE,0BAA0B,EAAsB,MAAM,mCAAmC,CAAC;AACxG,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAEnF,OAAO,EACY,KAAK,cAAc,EAErC,MAAM,YAAY,CAAC;AAMpB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAwC,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAG9F,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd;kDAC8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,0BAA0B,EAAE,CAAC;IACvC,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sFAAsF;IACtF,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,oEAAoE;IACpE,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,oFAAoF;IACpF,QAAQ,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACnC;0FACsF;IACtF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,0BAA0B,EAAE,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,KAAK,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,CAsQ1E"}
1
+ {"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../core/loop.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,KAAK,EAAE,0BAA0B,EAAsB,MAAM,mCAAmC,CAAC;AACxG,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,KAAK,EAA4B,MAAM,mBAAmB,CAAC;AAE7G,OAAO,EACY,KAAK,cAAc,EAErC,MAAM,YAAY,CAAC;AAMpB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAA0D,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGhH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd;kDAC8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,0BAA0B,EAAE,CAAC;IACvC,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sFAAsF;IACtF,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B;;;;;;;;6EAQyE;IACzE,wBAAwB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;IACxD,oEAAoE;IACpE,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,oFAAoF;IACpF,QAAQ,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACnC;0FACsF;IACtF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,0BAA0B,EAAE,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,KAAK,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,CA2U1E"}