veryfront 0.1.1071 → 0.1.1072

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.
@@ -109,6 +109,19 @@ interface ImportMetaPonyfill extends ImportMetaPonyfillCommonjs, ImportMetaPonyf
109
109
  export declare let import_meta_ponyfill_commonjs: ImportMetaPonyfillCommonjs;
110
110
  export declare let import_meta_ponyfill_esmodule: ImportMetaPonyfillEsmodule;
111
111
  export declare let import_meta_ponyfill: ImportMetaPonyfill;
112
+ declare global {
113
+ interface PromiseConstructor {
114
+ /**
115
+ * Creates a Promise that can be resolved or rejected using provided functions.
116
+ * @returns An object containing `promise` promise object, `resolve` and `reject` functions.
117
+ */
118
+ withResolvers<T>(): {
119
+ promise: Promise<T>;
120
+ resolve: (value: T | PromiseLike<T>) => void;
121
+ reject: (reason?: any) => void;
122
+ };
123
+ }
124
+ }
112
125
  declare global {
113
126
  interface Object {
114
127
  /**
@@ -169,17 +182,4 @@ declare global {
169
182
  }
170
183
  }
171
184
  export {};
172
- declare global {
173
- interface PromiseConstructor {
174
- /**
175
- * Creates a Promise that can be resolved or rejected using provided functions.
176
- * @returns An object containing `promise` promise object, `resolve` and `reject` functions.
177
- */
178
- withResolvers<T>(): {
179
- promise: Promise<T>;
180
- resolve: (value: T | PromiseLike<T>) => void;
181
- reject: (reason?: any) => void;
182
- };
183
- }
184
- }
185
185
  //# sourceMappingURL=_dnt.polyfills.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"_dnt.polyfills.d.ts","sourceRoot":"","sources":["../src/_dnt.polyfills.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"_dnt.polyfills.d.ts","sourceRoot":"","sources":["../src/_dnt.polyfills.ts"],"names":[],"mappings":"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"}
@@ -222,6 +222,17 @@ export let import_meta_ponyfill = ((...args) => {
222
222
  //@ts-ignore
223
223
  return import_meta_ponyfill(...args);
224
224
  });
225
+ // https://github.com/tc39/proposal-promise-with-resolvers/blob/3a78801e073e99217dbeb2c43ba7212f3bdc8b83/polyfills.js#L1C1-L9C2
226
+ if (Promise.withResolvers === undefined) {
227
+ Promise.withResolvers = () => {
228
+ const out = {};
229
+ out.promise = new Promise((resolve_, reject_) => {
230
+ out.resolve = resolve_;
231
+ out.reject = reject_;
232
+ });
233
+ return out;
234
+ };
235
+ }
225
236
  // https://github.com/tc39/proposal-accessible-object-hasownproperty/blob/main/polyfill.js
226
237
  if (!Object.hasOwn) {
227
238
  Object.defineProperty(Object, "hasOwn", {
@@ -272,14 +283,3 @@ if (!Uint8Array.prototype.findLast) {
272
283
  return findLast(this, callbackfn, that);
273
284
  };
274
285
  }
275
- // https://github.com/tc39/proposal-promise-with-resolvers/blob/3a78801e073e99217dbeb2c43ba7212f3bdc8b83/polyfills.js#L1C1-L9C2
276
- if (Promise.withResolvers === undefined) {
277
- Promise.withResolvers = () => {
278
- const out = {};
279
- out.promise = new Promise((resolve_, reject_) => {
280
- out.resolve = resolve_;
281
- out.reject = reject_;
282
- });
283
- return out;
284
- };
285
- }
package/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.1071",
3
+ "version": "0.1.1072",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "minimumDependencyAge": {
@@ -22,12 +22,18 @@
22
22
  *
23
23
  * @module
24
24
  */
25
+ interface ProjectScopedRegistryManagerOptions<T> {
26
+ /** Must be side-effect free; transaction preparation may invoke it again. */
27
+ validateRegistration?(id: string, existing: T, incoming: T): void;
28
+ }
25
29
  /**
26
30
  * Stage project-scoped registry mutations and publish them as one synchronous
27
31
  * commit after the callback succeeds. Reads inside the callback see staged
28
32
  * state; concurrent requests keep seeing the previous live state.
29
- * The commit is an authoritative replacement, so it linearizes after and may
30
- * supersede live writes made to the same scope while staging is in progress.
33
+ * Transactions for the same scope are serialized. Live writes made outside
34
+ * the transaction while discovery is in flight are journaled alongside staged
35
+ * mutations and replayed in call order, preserving the previous immediate-
36
+ * mutation semantics without exposing a partially discovered generation.
31
37
  * Use this for complete discovery generations, not incremental updates.
32
38
  *
33
39
  * Nested calls participate in the existing transaction. If a nested tenant
@@ -42,16 +48,22 @@ export declare function runWithRegistryTransaction<T>(fn: () => Promise<T>): Pro
42
48
  */
43
49
  export declare class ProjectScopedRegistryManager<T> {
44
50
  private registryName;
51
+ private options;
45
52
  private registriesByScope;
46
53
  private sharedRegistry;
47
- constructor(registryName: string);
54
+ private activeStagesByScope;
55
+ constructor(registryName: string, options?: ProjectScopedRegistryManagerOptions<T>);
56
+ private validateRegistration;
57
+ private applyMutation;
48
58
  /**
49
59
  * Get the current project ID from AsyncLocalStorage context.
50
60
  * Falls back to default for CLI/test scenarios.
51
61
  */
52
62
  private getCurrentScopeId;
53
- /** Return a transaction-local copy of the target registry when staging. */
54
- private getTransactionRegistry;
63
+ /** Return the transaction-local stage for this manager and scope. */
64
+ private getTransactionStage;
65
+ /** Record a live mutation in any in-flight transaction for this scope. */
66
+ private recordLiveMutation;
55
67
  /** Read the active registry, routing transaction access to its staged copy. */
56
68
  private getActiveScopeRegistry;
57
69
  /**
@@ -117,4 +129,5 @@ export declare class ProjectScopedRegistryManager<T> {
117
129
  currentProjectItems: number;
118
130
  };
119
131
  }
132
+ export {};
120
133
  //# sourceMappingURL=project-scoped-registry-manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"project-scoped-registry-manager.d.ts","sourceRoot":"","sources":["../../../src/src/registry/project-scoped-registry-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AA6BH;;;;;;;;;;;GAWG;AACH,wBAAsB,0BAA0B,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CA4BpF;AAED;;;;GAIG;AACH,qBAAa,4BAA4B,CAAC,CAAC;IAI7B,OAAO,CAAC,YAAY;IAHhC,OAAO,CAAC,iBAAiB,CAAqC;IAC9D,OAAO,CAAC,cAAc,CAAwB;gBAE1B,YAAY,EAAE,MAAM;IAExC;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAIzB,2EAA2E;IAC3E,OAAO,CAAC,sBAAsB;IAsC9B,+EAA+E;IAC/E,OAAO,CAAC,sBAAsB;IAI9B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAYxB;;OAEG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI;IAcnC;;;OAGG;IACH,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI;IAYzC;;;OAGG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAK9B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAKjC;;OAEG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAMxB;;OAEG;IACH,SAAS,IAAI,MAAM,EAAE;IAOrB;;OAEG;IACH,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAUxB;;OAEG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAU3B;;OAEG;IACH,KAAK,IAAI,IAAI;IASb;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAqBrC;;OAEG;IACH,QAAQ,IAAI,IAAI;IAahB;;OAEG;IACH,QAAQ,IAAI;QACV,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB,mBAAmB,EAAE,MAAM,CAAC;KAC7B;CAeF"}
1
+ {"version":3,"file":"project-scoped-registry-manager.d.ts","sourceRoot":"","sources":["../../../src/src/registry/project-scoped-registry-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AA4BH,UAAU,mCAAmC,CAAC,CAAC;IAC7C,6EAA6E;IAC7E,oBAAoB,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAC;CACnE;AAsCD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,0BAA0B,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAyCpF;AAED;;;;GAIG;AACH,qBAAa,4BAA4B,CAAC,CAAC;IAMvC,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,OAAO;IANjB,OAAO,CAAC,iBAAiB,CAAqC;IAC9D,OAAO,CAAC,cAAc,CAAwB;IAC9C,OAAO,CAAC,mBAAmB,CAA8D;gBAG/E,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,mCAAmC,CAAC,CAAC,CAAM;IAG9D,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,aAAa;IAqBrB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAIzB,qEAAqE;IACrE,OAAO,CAAC,mBAAmB;IA0E3B,0EAA0E;IAC1E,OAAO,CAAC,kBAAkB;IAM1B,+EAA+E;IAC/E,OAAO,CAAC,sBAAsB;IAI9B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IASxB;;OAEG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI;IAoBnC;;;OAGG;IACH,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI;IAYzC;;;OAGG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAK9B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAKjC;;OAEG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAMxB;;OAEG;IACH,SAAS,IAAI,MAAM,EAAE;IAOrB;;OAEG;IACH,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAUxB;;OAEG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAe3B;;OAEG;IACH,KAAK,IAAI,IAAI;IAWb;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAyBrC;;OAEG;IACH,QAAQ,IAAI,IAAI;IAoBhB;;OAEG;IACH,QAAQ,IAAI;QACV,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB,mBAAmB,EAAE,MAAM,CAAC;KAC7B;CAeF"}
@@ -27,6 +27,24 @@ import { agentLogger } from "../utils/logger/logger.js";
27
27
  import { AsyncLocalStorage } from "node:async_hooks";
28
28
  const DEFAULT_SCOPE_ID = "__default__";
29
29
  const registryTransactionStorage = new AsyncLocalStorage();
30
+ const registryTransactionLocks = new Map();
31
+ async function acquireRegistryTransactionLock(scopeId) {
32
+ const previous = registryTransactionLocks.get(scopeId) ?? Promise.resolve();
33
+ const gate = Promise.withResolvers();
34
+ const current = previous.then(() => gate.promise);
35
+ registryTransactionLocks.set(scopeId, current);
36
+ await previous;
37
+ let released = false;
38
+ return () => {
39
+ if (released)
40
+ return;
41
+ released = true;
42
+ gate.resolve();
43
+ if (registryTransactionLocks.get(scopeId) === current) {
44
+ registryTransactionLocks.delete(scopeId);
45
+ }
46
+ };
47
+ }
30
48
  function buildRegistryScopeId() {
31
49
  // tryGetRegistryScopeId() returns a project-isolated key even when
32
50
  // tryGetCacheKeyContext() would return null (e.g. control-plane runs for an
@@ -39,8 +57,10 @@ function buildRegistryScopeId() {
39
57
  * Stage project-scoped registry mutations and publish them as one synchronous
40
58
  * commit after the callback succeeds. Reads inside the callback see staged
41
59
  * state; concurrent requests keep seeing the previous live state.
42
- * The commit is an authoritative replacement, so it linearizes after and may
43
- * supersede live writes made to the same scope while staging is in progress.
60
+ * Transactions for the same scope are serialized. Live writes made outside
61
+ * the transaction while discovery is in flight are journaled alongside staged
62
+ * mutations and replayed in call order, preserving the previous immediate-
63
+ * mutation semantics without exposing a partially discovered generation.
44
64
  * Use this for complete discovery generations, not incremental updates.
45
65
  *
46
66
  * Nested calls participate in the existing transaction. If a nested tenant
@@ -51,29 +71,40 @@ export async function runWithRegistryTransaction(fn) {
51
71
  const existing = registryTransactionStorage.getStore();
52
72
  if (existing?.state === "active")
53
73
  return await fn();
74
+ const targetScopeId = buildRegistryScopeId();
75
+ const releaseLock = await acquireRegistryTransactionLock(targetScopeId);
54
76
  const transaction = {
55
- targetScopeId: buildRegistryScopeId(),
77
+ targetScopeId,
56
78
  stages: new Map(),
57
79
  state: "active",
58
80
  };
59
- return await registryTransactionStorage.run(transaction, async () => {
60
- try {
61
- const result = await fn();
62
- // Map replacement is synchronous. No other request can observe a partial
63
- // commit between managers in this JavaScript turn.
64
- for (const stage of transaction.stages.values()) {
65
- stage.commit();
81
+ try {
82
+ return await registryTransactionStorage.run(transaction, async () => {
83
+ try {
84
+ const result = await fn();
85
+ // Prepare every manager before publishing any of them. Publication is
86
+ // synchronous, so no request can observe a partial generation.
87
+ const publications = Array.from(transaction.stages.values(), (stage) => stage.prepare());
88
+ for (const publication of publications) {
89
+ publication.publish();
90
+ }
91
+ transaction.state = "committed";
92
+ transaction.stages.clear();
93
+ return result;
66
94
  }
67
- transaction.state = "committed";
68
- transaction.stages.clear();
69
- return result;
70
- }
71
- catch (error) {
72
- transaction.state = "aborted";
73
- transaction.stages.clear();
74
- throw error;
75
- }
76
- });
95
+ catch (error) {
96
+ transaction.state = "aborted";
97
+ for (const stage of transaction.stages.values()) {
98
+ stage.abort();
99
+ }
100
+ transaction.stages.clear();
101
+ throw error;
102
+ }
103
+ });
104
+ }
105
+ finally {
106
+ releaseLock();
107
+ }
77
108
  }
78
109
  /**
79
110
  * Base class for project-scoped registries.
@@ -82,10 +113,34 @@ export async function runWithRegistryTransaction(fn) {
82
113
  */
83
114
  export class ProjectScopedRegistryManager {
84
115
  registryName;
116
+ options;
85
117
  registriesByScope = new Map();
86
118
  sharedRegistry = new Map();
87
- constructor(registryName) {
119
+ activeStagesByScope = new Map();
120
+ constructor(registryName, options = {}) {
88
121
  this.registryName = registryName;
122
+ this.options = options;
123
+ }
124
+ validateRegistration(registry, id, incoming) {
125
+ if (!registry.has(id))
126
+ return;
127
+ this.options.validateRegistration?.(id, registry.get(id), incoming);
128
+ }
129
+ applyMutation(registry, mutation, validateRegistration = false) {
130
+ switch (mutation.type) {
131
+ case "clear":
132
+ registry.clear();
133
+ break;
134
+ case "delete":
135
+ registry.delete(mutation.id);
136
+ break;
137
+ case "set":
138
+ if (validateRegistration) {
139
+ this.validateRegistration(registry, mutation.id, mutation.item);
140
+ }
141
+ registry.set(mutation.id, mutation.item);
142
+ break;
143
+ }
89
144
  }
90
145
  /**
91
146
  * Get the current project ID from AsyncLocalStorage context.
@@ -94,8 +149,8 @@ export class ProjectScopedRegistryManager {
94
149
  getCurrentScopeId() {
95
150
  return buildRegistryScopeId();
96
151
  }
97
- /** Return a transaction-local copy of the target registry when staging. */
98
- getTransactionRegistry(scopeId) {
152
+ /** Return the transaction-local stage for this manager and scope. */
153
+ getTransactionStage(scopeId) {
99
154
  const transaction = registryTransactionStorage.getStore();
100
155
  if (!transaction)
101
156
  return undefined;
@@ -111,33 +166,69 @@ export class ProjectScopedRegistryManager {
111
166
  }
112
167
  const existing = transaction.stages.get(this);
113
168
  if (existing)
114
- return existing.registry;
115
- const registry = new Map(this.registriesByScope.get(scopeId));
169
+ return existing;
170
+ const baseRegistry = new Map(this.registriesByScope.get(scopeId));
171
+ const registry = new Map(baseRegistry);
172
+ const validationRegistry = new Map(baseRegistry);
173
+ const mutations = [];
174
+ let closed = false;
175
+ const close = () => {
176
+ if (closed)
177
+ return;
178
+ closed = true;
179
+ const activeStages = this.activeStagesByScope.get(scopeId);
180
+ activeStages?.delete(stage);
181
+ if (activeStages?.size === 0)
182
+ this.activeStagesByScope.delete(scopeId);
183
+ };
116
184
  const stage = {
117
185
  registry,
118
- commit: () => {
119
- if (registry.size === 0) {
120
- this.registriesByScope.delete(scopeId);
121
- }
122
- else {
123
- this.registriesByScope.set(scopeId, registry);
186
+ validateRegistration: (id, incoming) => {
187
+ this.validateRegistration(validationRegistry, id, incoming);
188
+ },
189
+ record: (mutation) => {
190
+ mutations.push(mutation);
191
+ this.applyMutation(validationRegistry, mutation);
192
+ },
193
+ prepare: () => {
194
+ const replacement = new Map(baseRegistry);
195
+ for (const mutation of mutations) {
196
+ this.applyMutation(replacement, mutation, true);
124
197
  }
198
+ return {
199
+ publish: () => {
200
+ close();
201
+ if (replacement.size === 0) {
202
+ this.registriesByScope.delete(scopeId);
203
+ }
204
+ else {
205
+ this.registriesByScope.set(scopeId, replacement);
206
+ }
207
+ },
208
+ };
125
209
  },
210
+ abort: close,
126
211
  };
127
212
  transaction.stages.set(this, stage);
128
- return registry;
213
+ const activeStages = this.activeStagesByScope.get(scopeId) ?? new Set();
214
+ activeStages.add(stage);
215
+ this.activeStagesByScope.set(scopeId, activeStages);
216
+ return stage;
217
+ }
218
+ /** Record a live mutation in any in-flight transaction for this scope. */
219
+ recordLiveMutation(scopeId, mutation) {
220
+ for (const stage of this.activeStagesByScope.get(scopeId) ?? []) {
221
+ stage.record(mutation);
222
+ }
129
223
  }
130
224
  /** Read the active registry, routing transaction access to its staged copy. */
131
225
  getActiveScopeRegistry(scopeId) {
132
- return this.getTransactionRegistry(scopeId) ?? this.registriesByScope.get(scopeId);
226
+ return this.getTransactionStage(scopeId)?.registry ?? this.registriesByScope.get(scopeId);
133
227
  }
134
228
  /**
135
229
  * Get or create registry for a specific project.
136
230
  */
137
231
  getScopeRegistry(scopeId) {
138
- const staged = this.getTransactionRegistry(scopeId);
139
- if (staged)
140
- return staged;
141
232
  const existing = this.registriesByScope.get(scopeId);
142
233
  if (existing)
143
234
  return existing;
@@ -150,11 +241,21 @@ export class ProjectScopedRegistryManager {
150
241
  */
151
242
  register(id, item) {
152
243
  const scopeId = this.getCurrentScopeId();
153
- const registry = this.getScopeRegistry(scopeId);
244
+ const stage = this.getTransactionStage(scopeId);
245
+ const registry = stage?.registry ?? this.getScopeRegistry(scopeId);
246
+ if (stage)
247
+ stage.validateRegistration(id, item);
248
+ else
249
+ this.validateRegistration(registry, id, item);
154
250
  if (registry.has(id)) {
155
251
  agentLogger.debug(`[${this.registryName}] "${id}" already registered for scope ${scopeId}. Overwriting.`);
156
252
  }
157
253
  registry.set(id, item);
254
+ const mutation = { type: "set", id, item };
255
+ if (stage)
256
+ stage.record(mutation);
257
+ else
258
+ this.recordLiveMutation(scopeId, mutation);
158
259
  agentLogger.debug(`[${this.registryName}] Registered "${id}" for scope ${scopeId}`);
159
260
  }
160
261
  /**
@@ -224,23 +325,32 @@ export class ProjectScopedRegistryManager {
224
325
  */
225
326
  delete(id) {
226
327
  const scopeId = this.getCurrentScopeId();
227
- const registry = this.getActiveScopeRegistry(scopeId);
228
- if (!registry?.has(id))
328
+ const stage = this.getTransactionStage(scopeId);
329
+ const registry = stage?.registry ?? this.registriesByScope.get(scopeId);
330
+ const existed = registry?.has(id) ?? false;
331
+ if (!existed && !stage && !this.activeStagesByScope.has(scopeId))
229
332
  return false;
230
- registry.delete(id);
333
+ registry?.delete(id);
334
+ const mutation = { type: "delete", id };
335
+ if (stage)
336
+ stage.record(mutation);
337
+ else
338
+ this.recordLiveMutation(scopeId, mutation);
231
339
  agentLogger.debug(`[${this.registryName}] Deleted "${id}" from scope ${scopeId}`);
232
- return true;
340
+ return existed;
233
341
  }
234
342
  /**
235
343
  * Clear all items for the current project.
236
344
  */
237
345
  clear() {
238
- const staged = this.getTransactionRegistry(this.getCurrentScopeId());
239
- if (staged) {
240
- staged.clear();
346
+ const scopeId = this.getCurrentScopeId();
347
+ const stage = this.getTransactionStage(scopeId);
348
+ if (stage) {
349
+ stage.registry.clear();
350
+ stage.record({ type: "clear" });
241
351
  return;
242
352
  }
243
- this.clearProject(this.getCurrentScopeId());
353
+ this.clearProject(scopeId);
244
354
  }
245
355
  /**
246
356
  * Clear a specific project's registry.
@@ -251,10 +361,14 @@ export class ProjectScopedRegistryManager {
251
361
  throw new Error(`[${this.registryName}] clearProject() is not supported during a registry transaction`);
252
362
  }
253
363
  let cleared = false;
254
- for (const scopeId of Array.from(this.registriesByScope.keys())) {
364
+ const scopeIds = new Set([
365
+ ...this.registriesByScope.keys(),
366
+ ...this.activeStagesByScope.keys(),
367
+ ]);
368
+ for (const scopeId of scopeIds) {
255
369
  if (scopeId === projectId || scopeId.startsWith(`${projectId}:`)) {
256
- this.registriesByScope.delete(scopeId);
257
- cleared = true;
370
+ cleared = this.registriesByScope.delete(scopeId) || cleared;
371
+ this.recordLiveMutation(scopeId, { type: "clear" });
258
372
  }
259
373
  }
260
374
  if (cleared) {
@@ -269,6 +383,13 @@ export class ProjectScopedRegistryManager {
269
383
  if (transaction && transaction.state !== "committed") {
270
384
  throw new Error(`[${this.registryName}] clearAll() is not supported during a registry transaction`);
271
385
  }
386
+ const scopeIds = new Set([
387
+ ...this.registriesByScope.keys(),
388
+ ...this.activeStagesByScope.keys(),
389
+ ]);
390
+ for (const scopeId of scopeIds) {
391
+ this.recordLiveMutation(scopeId, { type: "clear" });
392
+ }
272
393
  this.registriesByScope.clear();
273
394
  this.sharedRegistry.clear();
274
395
  agentLogger.debug(`[${this.registryName}] Cleared all registries`);
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/src/tool/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAiB7E,cAAM,iBAAkB,SAAQ,oBAAoB,CAAC,IAAI,CAAC;IAC/C,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI;IAgB/C,mBAAmB,IAAI,cAAc,EAAE;CAGxC;AAED,kCAAkC;AAClC,eAAO,MAAM,YAAY,mBAAqC,CAAC;AAE/D,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,IAAI,GAAG,cAAc,CAenE"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/src/tool/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AA2B7E,cAAM,iBAAkB,SAAQ,oBAAoB,CAAC,IAAI,CAAC;IAC/C,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI;IAW/C,mBAAmB,IAAI,cAAc,EAAE;CAGxC;AAED,kCAAkC;AAClC,eAAO,MAAM,YAAY,mBAAqC,CAAC;AAE/D,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,IAAI,GAAG,cAAc,CAenE"}
@@ -3,7 +3,6 @@ import { agentLogger } from "../utils/logger/logger.js";
3
3
  import { ScopedRegistryFacade } from "../registry/scoped-registry-facade.js";
4
4
  import { ProjectScopedRegistryManager } from "../registry/project-scoped-registry-manager.js";
5
5
  import { TOOL_ID_CONFLICT } from "../errors/error-registry/agent.js";
6
- const toolManager = new ProjectScopedRegistryManager("tool");
7
6
  /**
8
7
  * Returns true when `incoming` is considered the same definition as `existing`:
9
8
  * same object reference, or matching id + description. Equivalent definitions
@@ -14,17 +13,23 @@ function isSameToolDefinition(existing, incoming) {
14
13
  return existing === incoming ||
15
14
  (existing.id === incoming.id && existing.description === incoming.description);
16
15
  }
16
+ function validateToolRegistration(id, existing, incoming) {
17
+ if (isSameToolDefinition(existing, incoming))
18
+ return;
19
+ throw TOOL_ID_CONFLICT.create({
20
+ detail: `Tool "${id}" is already registered with a different definition. Use a unique tool ID or rename one of the conflicting tools.`,
21
+ });
22
+ }
23
+ const toolManager = new ProjectScopedRegistryManager("tool", {
24
+ validateRegistration: validateToolRegistration,
25
+ });
17
26
  class ToolRegistryClass extends ScopedRegistryFacade {
18
27
  register(id, item) {
19
- // Conflict-check against the project's own scope only: a project tool is
20
- // allowed to shadow a shared/framework tool with the same ID.
28
+ // Equivalent-registration diagnostics inspect the project scope only;
29
+ // the manager enforces conflicts here and again against journaled order.
30
+ // Shared/framework tools remain intentionally shadowable.
21
31
  const existing = this.getOwn(id);
22
- if (existing !== undefined && !isSameToolDefinition(existing, item)) {
23
- throw TOOL_ID_CONFLICT.create({
24
- detail: `Tool "${id}" is already registered with a different definition. Use a unique tool ID or rename one of the conflicting tools.`,
25
- });
26
- }
27
- if (existing !== undefined && existing !== item) {
32
+ if (existing !== undefined && existing !== item && isSameToolDefinition(existing, item)) {
28
33
  agentLogger.debug(`[tool] "${id}" re-registered with equivalent definition; replacing.`);
29
34
  }
30
35
  super.register(id, item);
@@ -1,3 +1,3 @@
1
1
  /** Shared version value. */
2
- export declare const VERSION = "0.1.1071";
2
+ export declare const VERSION = "0.1.1072";
3
3
  //# sourceMappingURL=version-constant.d.ts.map
@@ -1,4 +1,4 @@
1
1
  // Keep in sync with deno.json version.
2
2
  // scripts/release.ts updates this constant during releases.
3
3
  /** Shared version value. */
4
- export const VERSION = "0.1.1071";
4
+ export const VERSION = "0.1.1072";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veryfront",
3
- "version": "0.1.1071",
3
+ "version": "0.1.1072",
4
4
  "description": "The simplest way to build AI-powered apps",
5
5
  "keywords": [
6
6
  "react",
@@ -328,10 +328,10 @@
328
328
  "@types/react": "19.2.14",
329
329
  "@types/react-dom": "19.2.3",
330
330
  "ws": "8.21.0",
331
- "@veryfront/ext-bundler-esbuild": "0.1.1071",
332
- "@veryfront/ext-content-mdx": "0.1.1071",
333
- "@veryfront/ext-css-tailwind": "0.1.1071",
334
- "@veryfront/ext-parser-babel": "0.1.1071"
331
+ "@veryfront/ext-bundler-esbuild": "0.1.1072",
332
+ "@veryfront/ext-content-mdx": "0.1.1072",
333
+ "@veryfront/ext-css-tailwind": "0.1.1072",
334
+ "@veryfront/ext-parser-babel": "0.1.1072"
335
335
  },
336
336
  "devDependencies": {
337
337
  "@types/node": "20.9.0"