veryfront 0.1.615 → 0.1.617

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 (55) hide show
  1. package/esm/deno.d.ts +3 -0
  2. package/esm/deno.js +4 -1
  3. package/esm/src/agent/hosted/child-stream-watchdog.d.ts.map +1 -1
  4. package/esm/src/agent/hosted/child-stream-watchdog.js +47 -29
  5. package/esm/src/agent/hosted/cloud-prepared-chat-execution-runtime.d.ts +9 -0
  6. package/esm/src/agent/hosted/cloud-prepared-chat-execution-runtime.d.ts.map +1 -1
  7. package/esm/src/agent/hosted/cloud-prepared-chat-execution-runtime.js +26 -1
  8. package/esm/src/agent/hosted/stream-terminal-error.d.ts.map +1 -1
  9. package/esm/src/agent/hosted/stream-terminal-error.js +44 -0
  10. package/esm/src/agent/identity-contracts.d.ts +59 -0
  11. package/esm/src/agent/identity-contracts.d.ts.map +1 -0
  12. package/esm/src/agent/identity-contracts.js +41 -0
  13. package/esm/src/agent/index.d.ts +1 -0
  14. package/esm/src/agent/index.d.ts.map +1 -1
  15. package/esm/src/agent/index.js +1 -0
  16. package/esm/src/oauth/providers/base.d.ts +9 -0
  17. package/esm/src/oauth/providers/base.d.ts.map +1 -1
  18. package/esm/src/oauth/providers/base.js +23 -3
  19. package/esm/src/platform/adapters/redis/deno.d.ts +1 -0
  20. package/esm/src/platform/adapters/redis/deno.d.ts.map +1 -1
  21. package/esm/src/platform/adapters/redis/deno.js +5 -0
  22. package/esm/src/platform/adapters/redis/interface.d.ts +5 -0
  23. package/esm/src/platform/adapters/redis/interface.d.ts.map +1 -1
  24. package/esm/src/platform/adapters/redis/node.d.ts +1 -0
  25. package/esm/src/platform/adapters/redis/node.d.ts.map +1 -1
  26. package/esm/src/platform/adapters/redis/node.js +5 -0
  27. package/esm/src/platform/adapters/redis/types.d.ts +5 -0
  28. package/esm/src/platform/adapters/redis/types.d.ts.map +1 -1
  29. package/esm/src/provider/local/local-engine.d.ts +32 -0
  30. package/esm/src/provider/local/local-engine.d.ts.map +1 -1
  31. package/esm/src/provider/local/local-engine.js +66 -9
  32. package/esm/src/provider/runtime-loader/provider-usage.d.ts.map +1 -1
  33. package/esm/src/provider/runtime-loader/provider-usage.js +12 -1
  34. package/esm/src/rendering/rsc/server-renderer/tree-processor.js +5 -5
  35. package/esm/src/routing/api/api-route-matcher.d.ts.map +1 -1
  36. package/esm/src/routing/api/api-route-matcher.js +3 -2
  37. package/esm/src/routing/matchers/decode-param.d.ts +9 -0
  38. package/esm/src/routing/matchers/decode-param.d.ts.map +1 -0
  39. package/esm/src/routing/matchers/decode-param.js +17 -0
  40. package/esm/src/routing/matchers/route-matcher.d.ts.map +1 -1
  41. package/esm/src/routing/matchers/route-matcher.js +3 -4
  42. package/esm/src/routing/slug-mapper/dynamic-route-matcher.d.ts.map +1 -1
  43. package/esm/src/routing/slug-mapper/dynamic-route-matcher.js +8 -2
  44. package/esm/src/server/node-handler.d.ts.map +1 -1
  45. package/esm/src/server/node-handler.js +40 -5
  46. package/esm/src/tool/factory.d.ts.map +1 -1
  47. package/esm/src/tool/factory.js +4 -3
  48. package/esm/src/utils/version-constant.d.ts +1 -1
  49. package/esm/src/utils/version-constant.js +1 -1
  50. package/esm/src/workflow/backends/redis/index.d.ts +2 -0
  51. package/esm/src/workflow/backends/redis/index.d.ts.map +1 -1
  52. package/esm/src/workflow/backends/redis/index.js +39 -6
  53. package/esm/src/workflow/executor/dag/index.d.ts.map +1 -1
  54. package/esm/src/workflow/executor/dag/index.js +30 -5
  55. package/package.json +5 -1
@@ -1 +1 @@
1
- {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/src/tool/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,KAAK,EAAE,UAAU,EAAU,MAAM,+BAA+B,CAAC;AAyJxE,sCAAsC;AACtC,wBAAgB,IAAI,CAAC,MAAM,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,EACtD,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CA+CvB;AAED,0CAA0C;AAC1C,MAAM,WAAW,iBAAiB;IAChC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,UAAU,CAAC;IAC7B,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,oBAAoB,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IACxF,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;IAC7C,GAAG,CAAC,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;CACzB;AAED,wCAAwC;AACxC,wBAAgB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CA4B7E"}
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/src/tool/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,KAAK,EAAE,UAAU,EAAU,MAAM,+BAA+B,CAAC;AAyJxE,sCAAsC;AACtC,wBAAgB,IAAI,CAAC,MAAM,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,EACtD,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAgDvB;AAED,0CAA0C;AAC1C,MAAM,WAAW,iBAAiB;IAChC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,UAAU,CAAC;IAC7B,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,oBAAoB,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IACxF,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;IAC7C,GAAG,CAAC,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;CACzB;AAED,wCAAwC;AACxC,wBAAgB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CA4B7E"}
@@ -102,9 +102,10 @@ export function tool(config) {
102
102
  outputSchema: config.outputSchema,
103
103
  outputSchemaJson,
104
104
  execute: async (input, context) => {
105
+ let validated = input;
105
106
  if (hasSchemaParse(config.inputSchema)) {
106
107
  try {
107
- config.inputSchema.parse(input);
108
+ validated = config.inputSchema.parse(input);
108
109
  }
109
110
  catch (error) {
110
111
  throw toError(createError({
@@ -113,7 +114,7 @@ export function tool(config) {
113
114
  }));
114
115
  }
115
116
  }
116
- return await config.execute(input, context);
117
+ return await config.execute(validated, context);
117
118
  },
118
119
  mcp: config.mcp,
119
120
  };
@@ -133,7 +134,7 @@ export function dynamicTool(config) {
133
134
  inputSchemaJson,
134
135
  execute: async (input, context) => {
135
136
  if (hasSchemaParse(config.inputSchema)) {
136
- config.inputSchema.parse(input);
137
+ input = config.inputSchema.parse(input);
137
138
  }
138
139
  else if (input === undefined) {
139
140
  input = {};
@@ -1,3 +1,3 @@
1
1
  /** Shared version value. */
2
- export declare const VERSION = "0.1.615";
2
+ export declare const VERSION = "0.1.617";
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.615";
4
+ export const VERSION = "0.1.617";
@@ -9,6 +9,8 @@ export declare class RedisBackend implements WorkflowBackend {
9
9
  private connectionPromise;
10
10
  private config;
11
11
  private initialized;
12
+ /** Per-run lock tokens for ownership-checked release/extend (Redlock pattern). */
13
+ private lockValues;
12
14
  constructor(config?: RedisBackendConfig);
13
15
  private runKey;
14
16
  private checkpointsKey;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/src/workflow/backends/redis/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/src/workflow/backends/redis/index.ts"],"names":[],"mappings":"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"}
@@ -12,12 +12,25 @@ import { requeueRun } from "../shared/requeue-run.js";
12
12
  import { INITIALIZATION_ERROR, INVALID_ARGUMENT, RESOURCE_NOT_FOUND } from "../../../errors/index.js";
13
13
  import { DenoRedisAdapter, getRedisModule, NodeRedisAdapter, } from "../../../platform/adapters/redis/index.js";
14
14
  const logger = agentLogger.component("redis-backend");
15
+ /**
16
+ * Atomic compare-and-delete: delete the lock only if it still holds our token.
17
+ * Server-side Lua (Redis EVAL) so the GET and DEL are one indivisible step,
18
+ * preventing a stale owner from deleting another worker's reacquired lock.
19
+ */
20
+ const RELEASE_LOCK_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
21
+ /**
22
+ * Atomic compare-and-pexpire: extend the lock TTL only if it still holds our
23
+ * token. Same TOCTOU protection as the release script.
24
+ */
25
+ const EXTEND_LOCK_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('pexpire', KEYS[1], ARGV[2]) else return 0 end";
15
26
  /** Implement redis backend. */
16
27
  export class RedisBackend {
17
28
  client = null;
18
29
  connectionPromise = null;
19
30
  config;
20
31
  initialized = false;
32
+ /** Per-run lock tokens for ownership-checked release/extend (Redlock pattern). */
33
+ lockValues = new Map();
21
34
  constructor(config = {}) {
22
35
  this.config = {
23
36
  prefix: "vf:workflow:",
@@ -442,20 +455,40 @@ export class RedisBackend {
442
455
  const client = await this.ensureClient();
443
456
  const lockValue = dntShim.crypto.randomUUID();
444
457
  const result = await client.set(this.lockKey(runId), lockValue, { nx: true, px: duration });
445
- return result === "OK";
458
+ if (result === "OK") {
459
+ // Remember our token so release/extend can verify ownership (Redlock).
460
+ this.lockValues.set(runId, lockValue);
461
+ return true;
462
+ }
463
+ return false;
446
464
  }
447
465
  async releaseLock(runId) {
448
466
  const client = await this.ensureClient();
449
- await client.del(this.lockKey(runId));
467
+ const key = this.lockKey(runId);
468
+ const ourValue = this.lockValues.get(runId);
469
+ // Only release if we still own the lock (compare-and-delete). Without a
470
+ // known token we never owned it, so do nothing.
471
+ if (ourValue === undefined)
472
+ return;
473
+ // Atomic GET + DEL via Lua so a stale owner cannot delete a lock that was
474
+ // reacquired by another worker between the check and the delete (TOCTOU).
475
+ await client.eval(RELEASE_LOCK_SCRIPT, [key], [ourValue]);
476
+ this.lockValues.delete(runId);
450
477
  }
451
478
  async extendLock(runId, duration) {
452
479
  const client = await this.ensureClient();
453
480
  const key = this.lockKey(runId);
454
- const exists = await client.exists(key);
455
- if (exists === 0)
481
+ const ourValue = this.lockValues.get(runId);
482
+ // Only extend if we still own the lock (compare-and-pexpire).
483
+ if (ourValue === undefined)
456
484
  return false;
457
- await client.expire(key, Math.ceil(duration / 1000));
458
- return true;
485
+ // Atomic GET + PEXPIRE via Lua. PEXPIRE returns 1 when the key existed and
486
+ // the TTL was set, 0 otherwise (e.g. our token no longer owns the lock).
487
+ const result = await client.eval(EXTEND_LOCK_SCRIPT, [key], [
488
+ ourValue,
489
+ String(duration),
490
+ ]);
491
+ return Number(result) === 1;
459
492
  }
460
493
  async isLocked(runId) {
461
494
  const client = await this.ensureClient();
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/src/workflow/executor/dag/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAYV,YAAY,EAEZ,WAAW,EACZ,MAAM,gBAAgB,CAAC;AAIxB,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE7F,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EAGlB,MAAM,YAAY,CAAC;AAIpB,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAA4B;gBAE9B,MAAM,EAAE,iBAAiB;IAQ/B,OAAO,CACX,KAAK,EAAE,YAAY,EAAE,EACrB,GAAG,EAAE,WAAW,EAChB,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,kBAAkB,CAAC;YAsGhB,WAAW;YA8CX,eAAe;YA0Bf,mBAAmB;YA0CnB,cAAc;YAmGd,iBAAiB;YA6DjB,eAAe;YA8Bf,sBAAsB;YA+DtB,eAAe;YA6If,UAAU;CAoBzB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/src/workflow/executor/dag/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAYV,YAAY,EAEZ,WAAW,EACZ,MAAM,gBAAgB,CAAC;AAIxB,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE7F,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EAGlB,MAAM,YAAY,CAAC;AAIpB,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAA4B;gBAE9B,MAAM,EAAE,iBAAiB;IAQ/B,OAAO,CACX,KAAK,EAAE,YAAY,EAAE,EACrB,GAAG,EAAE,WAAW,EAChB,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,kBAAkB,CAAC;YAsGhB,WAAW;YA8CX,eAAe;YA0Bf,mBAAmB;YA4CnB,cAAc;YAqGd,iBAAiB;YA+DjB,eAAe;YA8Bf,sBAAsB;YA+DtB,eAAe;YAsKf,UAAU;CAoBzB"}
@@ -160,7 +160,9 @@ export class DAGExecutor {
160
160
  workflowId: "",
161
161
  status: "running",
162
162
  input: context.input,
163
- nodeStates: {},
163
+ // Carry already-accumulated child states so completed children are
164
+ // skipped on resume instead of re-executing (H8).
165
+ nodeStates,
164
166
  currentNodes: [],
165
167
  context,
166
168
  checkpoints: [],
@@ -232,7 +234,9 @@ export class DAGExecutor {
232
234
  workflowId: "",
233
235
  status: "running",
234
236
  input: context.input,
235
- nodeStates: {},
237
+ // Carry already-accumulated child states so completed children are
238
+ // skipped on resume instead of re-executing (H8).
239
+ nodeStates,
236
240
  currentNodes: [],
237
241
  context: { ...context },
238
242
  checkpoints: [],
@@ -281,7 +285,9 @@ export class DAGExecutor {
281
285
  workflowId: "",
282
286
  status: "running",
283
287
  input: context.input,
284
- nodeStates: {},
288
+ // Carry already-accumulated child states so completed children are
289
+ // skipped on resume instead of re-executing (H8).
290
+ nodeStates,
285
291
  currentNodes: [],
286
292
  context,
287
293
  checkpoints: [],
@@ -384,9 +390,15 @@ export class DAGExecutor {
384
390
  let exitReason = "condition";
385
391
  let lastError;
386
392
  const existingLoopState = context[`${node.id}_loop_state`];
393
+ // Child node states for the in-flight (resumed) iteration, so its already
394
+ // completed steps are not re-executed on resume (H9).
395
+ let resumeIterationNodeStates;
396
+ let resumeIteration;
387
397
  if (existingLoopState) {
388
398
  iteration = existingLoopState.iteration;
389
399
  previousResults.push(...existingLoopState.previousResults);
400
+ resumeIterationNodeStates = existingLoopState.iterationNodeStates;
401
+ resumeIteration = existingLoopState.iteration;
390
402
  }
391
403
  while (iteration < config.maxIterations) {
392
404
  const loopContext = {
@@ -403,12 +415,19 @@ export class DAGExecutor {
403
415
  const steps = typeof config.steps === "function"
404
416
  ? config.steps(context, loopContext)
405
417
  : config.steps;
418
+ // On resume, rehydrate the in-flight iteration's child node states so its
419
+ // already-completed steps are skipped instead of re-executed (H9).
420
+ const iterationNodeStates = resumeIteration === iteration && resumeIterationNodeStates
421
+ ? { ...resumeIterationNodeStates }
422
+ : {};
423
+ // Only rehydrate once; subsequent iterations start fresh.
424
+ resumeIterationNodeStates = undefined;
406
425
  const result = await this.execute(steps, {
407
426
  id: `${node.id}_iter_${iteration}`,
408
427
  workflowId: "",
409
428
  status: "running",
410
429
  input: context.input,
411
- nodeStates: {},
430
+ nodeStates: iterationNodeStates,
412
431
  currentNodes: [],
413
432
  context: { ...context, _loop: loopContext },
414
433
  checkpoints: [],
@@ -428,7 +447,13 @@ export class DAGExecutor {
428
447
  state,
429
448
  contextUpdates: {
430
449
  ...result.context,
431
- [`${node.id}_loop_state`]: { iteration, previousResults },
450
+ [`${node.id}_loop_state`]: {
451
+ iteration,
452
+ previousResults,
453
+ // Persist the in-flight iteration's child states so completed
454
+ // steps are not re-executed when this iteration resumes (H9).
455
+ iterationNodeStates: result.nodeStates,
456
+ },
432
457
  },
433
458
  waiting: true,
434
459
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veryfront",
3
- "version": "0.1.615",
3
+ "version": "0.1.617",
4
4
  "description": "The simplest way to build AI-powered apps",
5
5
  "keywords": [
6
6
  "react",
@@ -73,6 +73,10 @@
73
73
  "import": "./esm/src/agent/index.js",
74
74
  "types": "./esm/src/agent/index.d.ts"
75
75
  },
76
+ "./agent/identity": {
77
+ "import": "./esm/src/agent/identity-contracts.js",
78
+ "types": "./esm/src/agent/identity-contracts.d.ts"
79
+ },
76
80
  "./agent/testing": {
77
81
  "import": "./esm/src/agent/testing/index.js",
78
82
  "types": "./esm/src/agent/testing/index.d.ts"