@agentfield/sdk 0.1.110 → 0.1.111-rc.1

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.
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import fs, { promises } from 'fs';
1
+ import fs, { promises, readFileSync } from 'fs';
2
2
  import * as path2 from 'path';
3
- import path2__default, { resolve } from 'path';
3
+ import path2__default, { resolve, dirname } from 'path';
4
4
  import { createRequire } from 'module';
5
5
  import { spawn } from 'child_process';
6
6
  import express from 'express';
@@ -25,6 +25,7 @@ import { Buffer as Buffer$1 } from 'buffer';
25
25
  import { zodToJsonSchema } from 'zod-to-json-schema';
26
26
  import { generateKeyPair, exportJWK, importJWK, CompactEncrypt, compactDecrypt } from 'jose';
27
27
  import { readFile } from 'fs/promises';
28
+ import { fileURLToPath } from 'url';
28
29
 
29
30
  var __defProp = Object.defineProperty;
30
31
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -454,7 +455,7 @@ function resolveIdleMs(idleSeconds) {
454
455
  return seconds > 0 ? seconds * 1e3 : void 0;
455
456
  }
456
457
  function runCli(cmd, options) {
457
- return new Promise((resolve2, reject) => {
458
+ return new Promise((resolve3, reject) => {
458
459
  const [bin, ...args] = cmd;
459
460
  const env = { ...process.env, ...options?.env };
460
461
  applyOpenRouterAttributionEnv(env);
@@ -514,7 +515,7 @@ function runCli(cmd, options) {
514
515
  }
515
516
  settled = true;
516
517
  cleanup();
517
- resolve2({ stdout, stderr, exitCode: code ?? 0 });
518
+ resolve3({ stdout, stderr, exitCode: code ?? 0 });
518
519
  });
519
520
  proc.on("error", (err) => {
520
521
  if (settled) {
@@ -1008,8 +1009,8 @@ var init_runner = __esm({
1008
1009
  return base + jitter;
1009
1010
  }
1010
1011
  sleep(delaySeconds) {
1011
- return new Promise((resolve2) => {
1012
- setTimeout(resolve2, Math.max(0, delaySeconds) * 1e3);
1012
+ return new Promise((resolve3) => {
1013
+ setTimeout(resolve3, Math.max(0, delaySeconds) * 1e3);
1013
1014
  });
1014
1015
  }
1015
1016
  };
@@ -1200,8 +1201,8 @@ var PauseManager = class {
1200
1201
  return existing.promise;
1201
1202
  }
1202
1203
  let resolveFn;
1203
- const promise = new Promise((resolve2) => {
1204
- resolveFn = resolve2;
1204
+ const promise = new Promise((resolve3) => {
1205
+ resolveFn = resolve3;
1205
1206
  });
1206
1207
  this.pending.set(approvalRequestId, { resolve: resolveFn, promise });
1207
1208
  if (executionId) {
@@ -1423,7 +1424,7 @@ var ApprovalClient = class {
1423
1424
  }
1424
1425
  };
1425
1426
  function sleep(ms) {
1426
- return new Promise((resolve2) => setTimeout(resolve2, ms));
1427
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
1427
1428
  }
1428
1429
 
1429
1430
  // src/triggers/factories.ts
@@ -1481,6 +1482,77 @@ function triggerToPayload(trigger) {
1481
1482
  const _exhaustive = trigger;
1482
1483
  throw new TypeError(`Unknown trigger kind: ${_exhaustive}`);
1483
1484
  }
1485
+
1486
+ // src/triggers/dispatch.ts
1487
+ function isTriggerEnvelope(body) {
1488
+ if (!body || typeof body !== "object" || Array.isArray(body)) return false;
1489
+ const obj = body;
1490
+ if (!("event" in obj && "_meta" in obj)) return false;
1491
+ const meta = obj._meta;
1492
+ if (!meta || typeof meta !== "object" || Array.isArray(meta)) return false;
1493
+ return "trigger_id" in meta;
1494
+ }
1495
+ function unwrapEnvelope(body) {
1496
+ if (!isTriggerEnvelope(body)) {
1497
+ return { input: body };
1498
+ }
1499
+ const meta = body._meta;
1500
+ let receivedAt;
1501
+ try {
1502
+ receivedAt = new Date(meta.received_at);
1503
+ if (isNaN(receivedAt.getTime())) {
1504
+ receivedAt = /* @__PURE__ */ new Date();
1505
+ }
1506
+ } catch {
1507
+ receivedAt = /* @__PURE__ */ new Date();
1508
+ }
1509
+ const triggerContext = {
1510
+ triggerId: meta.trigger_id,
1511
+ source: meta.source,
1512
+ eventType: meta.event_type,
1513
+ eventId: meta.event_id,
1514
+ idempotencyKey: meta.idempotency_key,
1515
+ receivedAt,
1516
+ vcId: meta.vc_id
1517
+ };
1518
+ return {
1519
+ input: body.event,
1520
+ triggerContext
1521
+ };
1522
+ }
1523
+ function applyTriggerTransform(triggerContext, bindings, input) {
1524
+ if (!bindings || bindings.length === 0) return input;
1525
+ let bestMatch;
1526
+ let bestSpecificity = -1;
1527
+ for (const binding of bindings) {
1528
+ if (binding.kind !== "event") continue;
1529
+ if (binding.spec.source !== triggerContext.source) continue;
1530
+ const types = binding.spec.types ?? [];
1531
+ if (types.length > 0) {
1532
+ const matched = types.some(
1533
+ (t) => triggerContext.eventType === t || triggerContext.eventType.startsWith(t + ".")
1534
+ );
1535
+ if (!matched) continue;
1536
+ if (1 > bestSpecificity) {
1537
+ bestMatch = binding;
1538
+ bestSpecificity = 1;
1539
+ }
1540
+ } else {
1541
+ if (0 > bestSpecificity) {
1542
+ bestMatch = binding;
1543
+ bestSpecificity = 0;
1544
+ }
1545
+ }
1546
+ }
1547
+ if (bestMatch?.spec.transform) {
1548
+ try {
1549
+ return bestMatch.spec.transform(input);
1550
+ } catch {
1551
+ return input;
1552
+ }
1553
+ }
1554
+ return input;
1555
+ }
1484
1556
  var store = new AsyncLocalStorage();
1485
1557
  var ExecutionContext = class {
1486
1558
  input;
@@ -1830,6 +1902,12 @@ var ReasonerContext = class {
1830
1902
  * CPU loops, check `ctx.signal.aborted` periodically and throw.
1831
1903
  */
1832
1904
  signal;
1905
+ /**
1906
+ * Trigger context populated when the reasoner was invoked by an inbound
1907
+ * webhook event or cron schedule. `undefined` for direct calls via
1908
+ * `app.call(...)` or HTTP POST without a dispatcher envelope.
1909
+ */
1910
+ trigger;
1833
1911
  constructor(params) {
1834
1912
  this.input = params.input;
1835
1913
  this.executionId = params.executionId;
@@ -1852,6 +1930,7 @@ var ReasonerContext = class {
1852
1930
  this.workflow = params.workflow;
1853
1931
  this.did = params.did;
1854
1932
  this.signal = params.signal ?? new AbortController().signal;
1933
+ this.trigger = params.trigger;
1855
1934
  }
1856
1935
  ai(prompt, options) {
1857
1936
  if (options?.tools) {
@@ -2165,7 +2244,7 @@ var StatelessRateLimiter = class {
2165
2244
  }
2166
2245
  }
2167
2246
  async _sleep(delaySeconds) {
2168
- await new Promise((resolve2) => setTimeout(resolve2, delaySeconds * 1e3));
2247
+ await new Promise((resolve3) => setTimeout(resolve3, delaySeconds * 1e3));
2169
2248
  }
2170
2249
  _now() {
2171
2250
  return Date.now() / 1e3;
@@ -3289,7 +3368,7 @@ var AgentFieldClient = class {
3289
3368
  }
3290
3369
  };
3291
3370
  function sleep2(ms) {
3292
- return new Promise((resolve2) => setTimeout(resolve2, ms));
3371
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
3293
3372
  }
3294
3373
  async function safePauseCallback(cb) {
3295
3374
  if (!cb) return;
@@ -4748,6 +4827,44 @@ var Agent = class {
4748
4827
  }
4749
4828
  return this;
4750
4829
  }
4830
+ /**
4831
+ * Sugar for registering an event-triggered reasoner.
4832
+ *
4833
+ * Equivalent to:
4834
+ * ```ts
4835
+ * app.reasoner(name, handler, { triggers: [eventTrigger(spec)] });
4836
+ * ```
4837
+ *
4838
+ * The reasoner name defaults to `handler.name` when not provided.
4839
+ */
4840
+ onEvent(spec, handler, options) {
4841
+ const name = spec.name || handler.name || `on_${spec.source}`;
4842
+ const { name: _discarded, ...triggerSpec } = spec;
4843
+ const binding = eventTrigger(triggerSpec);
4844
+ return this.reasoner(name, handler, {
4845
+ ...options,
4846
+ triggers: [...options?.triggers ?? [], binding]
4847
+ });
4848
+ }
4849
+ /**
4850
+ * Sugar for registering a schedule-triggered (cron) reasoner.
4851
+ *
4852
+ * Equivalent to:
4853
+ * ```ts
4854
+ * app.reasoner(name, handler, { triggers: [scheduleTrigger({ cron })] });
4855
+ * ```
4856
+ *
4857
+ * The reasoner name defaults to `handler.name` when not provided.
4858
+ */
4859
+ onSchedule(cron, handler, options) {
4860
+ const name = options?.name || handler.name || "on_schedule";
4861
+ const binding = scheduleTrigger({ cron, timezone: options?.timezone });
4862
+ const { name: _discarded, timezone: _tz, ...restOptions } = options ?? {};
4863
+ return this.reasoner(name, handler, {
4864
+ ...restOptions,
4865
+ triggers: [...restOptions?.triggers ?? [], binding]
4866
+ });
4867
+ }
4751
4868
  skill(name, handler, options) {
4752
4869
  this.skills.register(name, handler, options);
4753
4870
  if (options?.requireRealtimeValidation) {
@@ -4918,9 +5035,9 @@ var Agent = class {
4918
5035
  try {
4919
5036
  const result = await Promise.race([
4920
5037
  future,
4921
- new Promise((resolve2) => {
5038
+ new Promise((resolve3) => {
4922
5039
  timer = setTimeout(() => {
4923
- resolve2(
5040
+ resolve3(
4924
5041
  new ApprovalResult({
4925
5042
  decision: "expired",
4926
5043
  feedback: "timed out waiting for approval",
@@ -4973,8 +5090,8 @@ var Agent = class {
4973
5090
  const port = this.config.port ?? 8001;
4974
5091
  const host = this.config.host ?? "0.0.0.0";
4975
5092
  await this.agentFieldClient.heartbeat("starting");
4976
- await new Promise((resolve2, reject) => {
4977
- this.server = this.app.listen(port, host, () => resolve2()).on("error", reject);
5093
+ await new Promise((resolve3, reject) => {
5094
+ this.server = this.app.listen(port, host, () => resolve3()).on("error", reject);
4978
5095
  });
4979
5096
  this.memoryEventClient.start();
4980
5097
  this.startHeartbeat();
@@ -4984,10 +5101,10 @@ var Agent = class {
4984
5101
  clearInterval(this.heartbeatTimer);
4985
5102
  }
4986
5103
  this.pauseManager.cancelAll();
4987
- await new Promise((resolve2, reject) => {
5104
+ await new Promise((resolve3, reject) => {
4988
5105
  this.server?.close((err) => {
4989
5106
  if (err) reject(err);
4990
- else resolve2();
5107
+ else resolve3();
4991
5108
  });
4992
5109
  });
4993
5110
  this.memoryEventClient.stop();
@@ -4998,6 +5115,12 @@ var Agent = class {
4998
5115
  if (!agentId || agentId === this.config.nodeId) {
4999
5116
  const local = this.reasoners.get(name);
5000
5117
  if (!local) throw new Error(`Reasoner not found: ${name}`);
5118
+ const { input: unwrappedInput, triggerContext } = unwrapEnvelope(input);
5119
+ let resolvedInput = unwrappedInput;
5120
+ if (triggerContext) {
5121
+ const bindings = local.options?.triggers ?? [];
5122
+ resolvedInput = applyTriggerTransform(triggerContext, bindings, unwrappedInput);
5123
+ }
5001
5124
  const runId2 = parentMetadata?.runId ?? parentMetadata?.executionId ?? randomUUID();
5002
5125
  const rootWorkflowId2 = parentMetadata?.rootWorkflowId ?? parentMetadata?.workflowId ?? runId2;
5003
5126
  const metadata = {
@@ -5012,7 +5135,7 @@ var Agent = class {
5012
5135
  const dummyReq = {};
5013
5136
  const dummyRes = {};
5014
5137
  const execCtx = new ExecutionContext({
5015
- input,
5138
+ input: resolvedInput,
5016
5139
  metadata: {
5017
5140
  ...metadata,
5018
5141
  executionId: metadata.executionId ?? randomUUID()
@@ -5069,7 +5192,7 @@ var Agent = class {
5069
5192
  try {
5070
5193
  const result = await local.handler(
5071
5194
  new ReasonerContext({
5072
- input,
5195
+ input: resolvedInput,
5073
5196
  executionId: execCtx.metadata.executionId,
5074
5197
  runId: execCtx.metadata.runId,
5075
5198
  sessionId: execCtx.metadata.sessionId,
@@ -5088,7 +5211,8 @@ var Agent = class {
5088
5211
  aiClient: this.aiClient,
5089
5212
  memory: this.getMemoryInterface(execCtx.metadata),
5090
5213
  workflow: this.getWorkflowReporter(execCtx.metadata),
5091
- did: this.getDidInterface(execCtx.metadata, input, name)
5214
+ did: this.getDidInterface(execCtx.metadata, resolvedInput, name),
5215
+ trigger: triggerContext
5092
5216
  })
5093
5217
  );
5094
5218
  this.executionLogger.system("reasoner.completed", "Reasoner execution completed", {
@@ -5851,8 +5975,14 @@ var Agent = class {
5851
5975
  rootWorkflowId: params.metadata.rootWorkflowId ?? params.metadata.workflowId ?? params.metadata.runId ?? params.metadata.executionId,
5852
5976
  reasonerId: params.metadata.reasonerId ?? params.targetName
5853
5977
  };
5978
+ const { input: unwrappedInput, triggerContext } = unwrapEnvelope(params.input);
5979
+ let resolvedInput = unwrappedInput;
5980
+ if (triggerContext) {
5981
+ const bindings = reasoner.options?.triggers ?? [];
5982
+ resolvedInput = applyTriggerTransform(triggerContext, bindings, unwrappedInput);
5983
+ }
5854
5984
  const execCtx = new ExecutionContext({
5855
- input: params.input,
5985
+ input: resolvedInput,
5856
5986
  metadata: executionMetadata,
5857
5987
  req,
5858
5988
  res,
@@ -5881,7 +6011,7 @@ var Agent = class {
5881
6011
  });
5882
6012
  try {
5883
6013
  const ctx = new ReasonerContext({
5884
- input: params.input,
6014
+ input: resolvedInput,
5885
6015
  executionId: executionMetadata.executionId,
5886
6016
  runId: executionMetadata.runId,
5887
6017
  sessionId: executionMetadata.sessionId,
@@ -5900,8 +6030,9 @@ var Agent = class {
5900
6030
  aiClient: this.aiClient,
5901
6031
  memory: this.getMemoryInterface(executionMetadata),
5902
6032
  workflow: this.getWorkflowReporter(executionMetadata),
5903
- did: this.getDidInterface(executionMetadata, params.input, params.targetName),
5904
- signal: controller.signal
6033
+ did: this.getDidInterface(executionMetadata, resolvedInput, params.targetName),
6034
+ signal: controller.signal,
6035
+ trigger: triggerContext
5905
6036
  });
5906
6037
  const result = await reasoner.handler(ctx);
5907
6038
  this.executionLogger.system("reasoner.completed", "Reasoner execution completed", {
@@ -6146,7 +6277,7 @@ var Agent = class {
6146
6277
  const timeoutMs = 5 * 60 * 1e3;
6147
6278
  const deadline = Date.now() + timeoutMs;
6148
6279
  while (Date.now() < deadline) {
6149
- await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
6280
+ await new Promise((resolve3) => setTimeout(resolve3, pollInterval));
6150
6281
  try {
6151
6282
  const node = await this.agentFieldClient.getNode(this.config.nodeId);
6152
6283
  const status = node?.lifecycle_status;
@@ -7575,14 +7706,62 @@ var OpenRouterMediaProvider = class {
7575
7706
  }
7576
7707
  };
7577
7708
  function sleep3(ms) {
7578
- return new Promise((resolve2) => setTimeout(resolve2, ms));
7709
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
7579
7710
  }
7580
7711
 
7581
7712
  // src/harness/index.ts
7582
7713
  init_types();
7583
7714
  init_factory();
7584
7715
  init_runner();
7716
+ async function simulateTrigger(handler, options) {
7717
+ const body = options.body ?? {};
7718
+ const triggerContext = {
7719
+ triggerId: options.triggerId ?? `trg_sim_${randomUUID().slice(0, 12)}`,
7720
+ source: options.source,
7721
+ eventType: options.eventType ?? "",
7722
+ eventId: options.eventId ?? `evt_sim_${randomUUID().slice(0, 12)}`,
7723
+ idempotencyKey: options.idempotencyKey ?? `idem_sim_${randomUUID().slice(0, 12)}`,
7724
+ receivedAt: options.receivedAt ?? /* @__PURE__ */ new Date(),
7725
+ vcId: options.vcId
7726
+ };
7727
+ let resolvedInput = body;
7728
+ if (options.bindings && options.bindings.length > 0) {
7729
+ resolvedInput = applyTriggerTransform(triggerContext, options.bindings, body);
7730
+ }
7731
+ const ctx = {
7732
+ input: resolvedInput,
7733
+ trigger: triggerContext,
7734
+ executionId: `exec_sim_${randomUUID().slice(0, 12)}`
7735
+ };
7736
+ return handler(ctx);
7737
+ }
7738
+ async function simulateSchedule(handler, options) {
7739
+ return simulateTrigger(handler, {
7740
+ source: "cron",
7741
+ body: options?.cron ? { cron: options.cron } : {},
7742
+ eventType: "tick",
7743
+ receivedAt: options?.receivedAt,
7744
+ bindings: options?.bindings
7745
+ });
7746
+ }
7747
+ function loadFixture(source) {
7748
+ const dir = dirname(fileURLToPath(import.meta.url));
7749
+ const candidates = [
7750
+ resolve(dir, "fixtures", `${source}.json`),
7751
+ resolve(dir, "..", "src", "triggers", "fixtures", `${source}.json`)
7752
+ ];
7753
+ for (const fixturePath of candidates) {
7754
+ try {
7755
+ const content = readFileSync(fixturePath, "utf-8");
7756
+ return JSON.parse(content);
7757
+ } catch {
7758
+ }
7759
+ }
7760
+ throw new Error(
7761
+ `No fixture for source="${source}". Looked at ${candidates.join(", ")}`
7762
+ );
7763
+ }
7585
7764
 
7586
- export { ACTIVE_STATUSES, AIClient, Agent, AgentRouter, ApprovalClient, ApprovalResult, Audio, CANONICAL_STATUSES, DIDAuthenticator, DidClient, DidInterface, DidManager, ExecutionContext, ExecutionLogger, ExecutionStatus, File, HEADER_CALLER_DID, HEADER_DID_NONCE, HEADER_DID_SIGNATURE, HEADER_DID_TIMESTAMP, HarnessRunner, Image, JWE_ALG, JWE_ENC, KEY_AGREEMENT_TYPE, MediaProviderError, MediaRouter, MemoryClient, MemoryClientBase, MemoryEventClient, MemoryInterface, MultimodalResponse, OpenRouterMediaProvider, PauseClock, PauseManager, PayloadEncryptionError, RateLimitError, RealtimeSession, ReasonerContext, SUPPORTED_PROVIDERS, SUPPORTED_SESSION_TRANSPORTS, SessionTransportError, SkillContext, StatelessRateLimiter, TERMINAL_STATUSES, Text, Video, WorkflowReporter, audioFromBase64, audioFromBuffer, audioFromFile, audioFromUrl, buildProvider, buildSessionDefinition, buildToolConfig, capabilitiesToTools, capabilityToMetadataTool, capabilityToTool, createExecutionLogger, createHarnessResult, createMetrics, createMultimodalResponse, createRawResult, decrypt, decryptToString, encryptForDid, encryptToJwk, eventTrigger, executeToolCallLoop, extractKeyAgreementJwk, fileFromBase64, fileFromBuffer, fileFromPath, fileFromUrl, generateX25519KeyPair, getCurrentContext, getCurrentSkillContext, imageFromBase64, imageFromBuffer, imageFromFile, imageFromUrl, installApprovalWebhookRoute, isActive, isExecutionLogBatchPayload, isTerminal, normalizeExecutionLogEntry, normalizeSessionTransportValue, normalizeStatus, scheduleTrigger, serializeExecutionLogEntry, text, triggerToPayload, validateSessionTransport, videoFromBase64, videoFromBuffer, videoFromFile, videoFromUrl };
7765
+ export { ACTIVE_STATUSES, AIClient, Agent, AgentRouter, ApprovalClient, ApprovalResult, Audio, CANONICAL_STATUSES, DIDAuthenticator, DidClient, DidInterface, DidManager, ExecutionContext, ExecutionLogger, ExecutionStatus, File, HEADER_CALLER_DID, HEADER_DID_NONCE, HEADER_DID_SIGNATURE, HEADER_DID_TIMESTAMP, HarnessRunner, Image, JWE_ALG, JWE_ENC, KEY_AGREEMENT_TYPE, MediaProviderError, MediaRouter, MemoryClient, MemoryClientBase, MemoryEventClient, MemoryInterface, MultimodalResponse, OpenRouterMediaProvider, PauseClock, PauseManager, PayloadEncryptionError, RateLimitError, RealtimeSession, ReasonerContext, SUPPORTED_PROVIDERS, SUPPORTED_SESSION_TRANSPORTS, SessionTransportError, SkillContext, StatelessRateLimiter, TERMINAL_STATUSES, Text, Video, WorkflowReporter, applyTriggerTransform, audioFromBase64, audioFromBuffer, audioFromFile, audioFromUrl, buildProvider, buildSessionDefinition, buildToolConfig, capabilitiesToTools, capabilityToMetadataTool, capabilityToTool, createExecutionLogger, createHarnessResult, createMetrics, createMultimodalResponse, createRawResult, decrypt, decryptToString, encryptForDid, encryptToJwk, eventTrigger, executeToolCallLoop, extractKeyAgreementJwk, fileFromBase64, fileFromBuffer, fileFromPath, fileFromUrl, generateX25519KeyPair, getCurrentContext, getCurrentSkillContext, imageFromBase64, imageFromBuffer, imageFromFile, imageFromUrl, installApprovalWebhookRoute, isActive, isExecutionLogBatchPayload, isTerminal, isTriggerEnvelope, loadFixture, normalizeExecutionLogEntry, normalizeSessionTransportValue, normalizeStatus, scheduleTrigger, serializeExecutionLogEntry, simulateSchedule, simulateTrigger, text, triggerToPayload, unwrapEnvelope, validateSessionTransport, videoFromBase64, videoFromBuffer, videoFromFile, videoFromUrl };
7587
7766
  //# sourceMappingURL=index.js.map
7588
7767
  //# sourceMappingURL=index.js.map