@stackbone/sdk 0.1.0-alpha.5 → 0.1.0-alpha.7

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/index.js CHANGED
@@ -3,7 +3,7 @@ export { z } from 'zod';
3
3
  import { drizzle } from 'drizzle-orm/postgres-js';
4
4
  import postgres from 'postgres';
5
5
  import { extractText } from 'unpdf';
6
- import { createHash } from 'crypto';
6
+ import { createHash, createHmac } from 'crypto';
7
7
  import OpenAI from 'openai';
8
8
  import { PutObjectCommand, GetObjectCommand, ListObjectsV2Command, DeleteObjectCommand, S3Client } from '@aws-sdk/client-s3';
9
9
  import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
@@ -2366,7 +2366,7 @@ var require_luxon = __commonJS({
2366
2366
  return new Formatter2(locale, opts);
2367
2367
  }
2368
2368
  static parseFormat(fmt) {
2369
- let current = null, currentFull = "", bracketed = false;
2369
+ let current3 = null, currentFull = "", bracketed = false;
2370
2370
  const splits = [];
2371
2371
  for (let i2 = 0; i2 < fmt.length; i2++) {
2372
2372
  const c2 = fmt.charAt(i2);
@@ -2377,12 +2377,12 @@ var require_luxon = __commonJS({
2377
2377
  val: currentFull === "" ? "'" : currentFull
2378
2378
  });
2379
2379
  }
2380
- current = null;
2380
+ current3 = null;
2381
2381
  currentFull = "";
2382
2382
  bracketed = !bracketed;
2383
2383
  } else if (bracketed) {
2384
2384
  currentFull += c2;
2385
- } else if (c2 === current) {
2385
+ } else if (c2 === current3) {
2386
2386
  currentFull += c2;
2387
2387
  } else {
2388
2388
  if (currentFull.length > 0) {
@@ -2392,7 +2392,7 @@ var require_luxon = __commonJS({
2392
2392
  });
2393
2393
  }
2394
2394
  currentFull = c2;
2395
- current = c2;
2395
+ current3 = c2;
2396
2396
  }
2397
2397
  }
2398
2398
  if (currentFull.length > 0) {
@@ -3122,28 +3122,28 @@ var require_luxon = __commonJS({
3122
3122
  __name(durationToMillis, "durationToMillis");
3123
3123
  function normalizeValues(matrix, vals) {
3124
3124
  const factor = durationToMillis(matrix, vals) < 0 ? -1 : 1;
3125
- orderedUnits$1.reduceRight((previous, current) => {
3126
- if (!isUndefined(vals[current])) {
3125
+ orderedUnits$1.reduceRight((previous, current3) => {
3126
+ if (!isUndefined(vals[current3])) {
3127
3127
  if (previous) {
3128
3128
  const previousVal = vals[previous] * factor;
3129
- const conv = matrix[current][previous];
3129
+ const conv = matrix[current3][previous];
3130
3130
  const rollUp = Math.floor(previousVal / conv);
3131
- vals[current] += rollUp * factor;
3131
+ vals[current3] += rollUp * factor;
3132
3132
  vals[previous] -= rollUp * conv * factor;
3133
3133
  }
3134
- return current;
3134
+ return current3;
3135
3135
  } else {
3136
3136
  return previous;
3137
3137
  }
3138
3138
  }, null);
3139
- orderedUnits$1.reduce((previous, current) => {
3140
- if (!isUndefined(vals[current])) {
3139
+ orderedUnits$1.reduce((previous, current3) => {
3140
+ if (!isUndefined(vals[current3])) {
3141
3141
  if (previous) {
3142
3142
  const fraction = vals[previous] % 1;
3143
3143
  vals[previous] -= fraction;
3144
- vals[current] += fraction * matrix[previous][current];
3144
+ vals[current3] += fraction * matrix[previous][current3];
3145
3145
  }
3146
- return current;
3146
+ return current3;
3147
3147
  } else {
3148
3148
  return previous;
3149
3149
  }
@@ -4256,21 +4256,21 @@ var require_luxon = __commonJS({
4256
4256
  * @return {Array}
4257
4257
  */
4258
4258
  static merge(intervals) {
4259
- const [found, final] = intervals.sort((a2, b2) => a2.s - b2.s).reduce(([sofar, current], item) => {
4260
- if (!current) {
4259
+ const [found, final] = intervals.sort((a2, b2) => a2.s - b2.s).reduce(([sofar, current3], item) => {
4260
+ if (!current3) {
4261
4261
  return [
4262
4262
  sofar,
4263
4263
  item
4264
4264
  ];
4265
- } else if (current.overlaps(item) || current.abutsStart(item)) {
4265
+ } else if (current3.overlaps(item) || current3.abutsStart(item)) {
4266
4266
  return [
4267
4267
  sofar,
4268
- current.union(item)
4268
+ current3.union(item)
4269
4269
  ];
4270
4270
  } else {
4271
4271
  return [
4272
4272
  sofar.concat([
4273
- current
4273
+ current3
4274
4274
  ]),
4275
4275
  item
4276
4276
  ];
@@ -5202,7 +5202,7 @@ var require_luxon = __commonJS({
5202
5202
  }
5203
5203
  __name(possiblyCachedLocalWeekData, "possiblyCachedLocalWeekData");
5204
5204
  function clone(inst, alts) {
5205
- const current = {
5205
+ const current3 = {
5206
5206
  ts: inst.ts,
5207
5207
  zone: inst.zone,
5208
5208
  c: inst.c,
@@ -5211,9 +5211,9 @@ var require_luxon = __commonJS({
5211
5211
  invalid: inst.invalid
5212
5212
  };
5213
5213
  return new DateTime({
5214
- ...current,
5214
+ ...current3,
5215
5215
  ...alts,
5216
- old: current
5216
+ old: current3
5217
5217
  });
5218
5218
  }
5219
5219
  __name(clone, "clone");
@@ -8218,7 +8218,7 @@ var require_expression = __commonJS({
8218
8218
  return schedule;
8219
8219
  }, "prev");
8220
8220
  CronExpression.prototype.hasNext = function() {
8221
- var current = this._currentDate;
8221
+ var current3 = this._currentDate;
8222
8222
  var hasIterated = this._hasIterated;
8223
8223
  try {
8224
8224
  this._findSchedule();
@@ -8226,12 +8226,12 @@ var require_expression = __commonJS({
8226
8226
  } catch (err3) {
8227
8227
  return false;
8228
8228
  } finally {
8229
- this._currentDate = current;
8229
+ this._currentDate = current3;
8230
8230
  this._hasIterated = hasIterated;
8231
8231
  }
8232
8232
  };
8233
8233
  CronExpression.prototype.hasPrev = function() {
8234
- var current = this._currentDate;
8234
+ var current3 = this._currentDate;
8235
8235
  var hasIterated = this._hasIterated;
8236
8236
  try {
8237
8237
  this._findSchedule(true);
@@ -8239,7 +8239,7 @@ var require_expression = __commonJS({
8239
8239
  } catch (err3) {
8240
8240
  return false;
8241
8241
  } finally {
8242
- this._currentDate = current;
8242
+ this._currentDate = current3;
8243
8243
  this._hasIterated = hasIterated;
8244
8244
  }
8245
8245
  };
@@ -8746,9 +8746,11 @@ var CAPABILITIES = [
8746
8746
  "prompts.basic",
8747
8747
  // `connections.actions`: the agent → control-plane connectors proxy
8748
8748
  // (feature connectors-connections-automations). Role-based naming per repo
8749
- // convention. `client.connections.list()` / `.invoke(connector, action, args)`
8749
+ // convention. `client.legacyConnections.list()` / `.invoke(connector, action, args)`
8750
8750
  // run against the proxy; the agent container never sees a credential. The
8751
- // v13 bump reintroduces this capability after v12 removed it.
8751
+ // v13 bump reintroduces this capability after v12 removed it. The capability
8752
+ // string stays `connections.actions` (it names the wire domain, not the
8753
+ // renamed SDK accessor).
8752
8754
  "connections.actions"
8753
8755
  ];
8754
8756
  var MODULE_CAPABILITIES = {
@@ -8765,10 +8767,11 @@ var MODULE_CAPABILITIES = {
8765
8767
  // row is still declared here because the table is shared with the cloud
8766
8768
  // contract / Studio capability advertisement.
8767
8769
  prompts: "prompts.basic",
8768
- // `client.connections` is a control-plane PROXY surface (like queues): the
8769
- // agent POSTs to `/api/v1/agent/connections/*` with its agent JWT and the
8770
+ // `client.legacyConnections` is a control-plane PROXY surface (like queues):
8771
+ // the agent POSTs to `/api/v1/agent/connections/*` with its agent JWT and the
8770
8772
  // control plane runs the connector action with credentials resolved in
8771
- // memory. Gated against `connections.actions`.
8773
+ // memory. Gated against `connections.actions`. The map key stays `connections`
8774
+ // (it is the module id shared with the cloud contract, not the SDK accessor).
8772
8775
  connections: "connections.actions"
8773
8776
  };
8774
8777
  var contractBuildNameSchema = z.enum([
@@ -8870,7 +8873,8 @@ var journalTerminalStatusSchema = z.enum([
8870
8873
  ]);
8871
8874
  var journalJobStatusSchema = z.enum([
8872
8875
  ...journalTerminalStatusSchema.options,
8873
- "running"
8876
+ "running",
8877
+ "lost"
8874
8878
  ]);
8875
8879
  var jobStatusSchema = z.enum([
8876
8880
  ...bullmqJobStatusSchema.options,
@@ -8972,6 +8976,27 @@ z.object({
8972
8976
  queue: z.string(),
8973
8977
  status: jobStatusSchema
8974
8978
  });
8979
+ z.object({
8980
+ items: z.array(bullmqJobSchema)
8981
+ });
8982
+ z.object({
8983
+ purged: z.number().int().nonnegative()
8984
+ });
8985
+ z.object({
8986
+ payload: jsonObject(),
8987
+ retries: z.number().int().nonnegative().optional(),
8988
+ delay: z.number().int().nonnegative().optional()
8989
+ });
8990
+ z.object({
8991
+ message_id: z.string(),
8992
+ queue: queueNameSchema
8993
+ });
8994
+ z.object({
8995
+ name: queueNameSchema
8996
+ });
8997
+ z.object({
8998
+ limit: z.coerce.number().int().min(1).max(50).default(10)
8999
+ });
8975
9000
 
8976
9001
  // ../shared/validators/src/lib/agents/queue-jobs.ts
8977
9002
  var MAX_JOB_ATTEMPTS = 20;
@@ -9165,9 +9190,9 @@ function createContractStore(resolved = resolveConfig({})) {
9165
9190
  function peek(baseUrl) {
9166
9191
  if (!baseUrl || baseUrl.trim() === "") return null;
9167
9192
  const key = normaliseBaseUrl(baseUrl);
9168
- const cached = lastResolved.get(key);
9169
- if (!cached || cached.error) return null;
9170
- return cached.data;
9193
+ const cached2 = lastResolved.get(key);
9194
+ if (!cached2 || cached2.error) return null;
9195
+ return cached2.data;
9171
9196
  }
9172
9197
  __name(peek, "peek");
9173
9198
  function gatingEnabled() {
@@ -9433,9 +9458,9 @@ var HttpClient = class {
9433
9458
  if (jwt && !requestHeaders.has("Authorization")) {
9434
9459
  requestHeaders.set("Authorization", `Bearer ${jwt}`);
9435
9460
  }
9436
- const installationId = resolveInstallationId(this.resolved);
9437
- if (installationId && !requestHeaders.has("X-Stackbone-Installation-Id")) {
9438
- requestHeaders.set("X-Stackbone-Installation-Id", installationId);
9461
+ const installationId2 = resolveInstallationId(this.resolved);
9462
+ if (installationId2 && !requestHeaders.has("X-Stackbone-Installation-Id")) {
9463
+ requestHeaders.set("X-Stackbone-Installation-Id", installationId2);
9439
9464
  }
9440
9465
  const body = serializeBody(method, options.body, requestHeaders);
9441
9466
  let lastError = null;
@@ -9930,10 +9955,10 @@ var ApprovalFacade = class {
9930
9955
  const fallback = onTimeoutToFallback(options.onTimeout);
9931
9956
  const callbackUrl = options.onDecide;
9932
9957
  try {
9933
- const rows = await sql.data`
9958
+ const rows = await this._getDatabase().runShared((db) => db`
9934
9959
  INSERT INTO stackbone_platform.approvals (
9935
9960
  topic, payload, callback_url, idempotency_key,
9936
- fallback, metadata, timeout_at
9961
+ fallback, metadata, run_id, requested_by_step_id, timeout_at
9937
9962
  ) VALUES (
9938
9963
  ${options.topic},
9939
9964
  ${JSON.stringify(options.payload ?? {})}::jsonb,
@@ -9941,6 +9966,8 @@ var ApprovalFacade = class {
9941
9966
  ${options.idempotencyKey ?? null},
9942
9967
  ${fallback},
9943
9968
  ${JSON.stringify(options.metadata ?? {})}::jsonb,
9969
+ ${options.runId ?? null}::uuid,
9970
+ ${options.requestedByStepId ?? null}::uuid,
9944
9971
  now() + (${timeoutMs}::int * interval '1 millisecond')
9945
9972
  )
9946
9973
  ON CONFLICT (workspace_id, topic, idempotency_key)
@@ -9949,7 +9976,7 @@ var ApprovalFacade = class {
9949
9976
  RETURNING id, callback_url,
9950
9977
  to_char(created_at AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') AS created_at,
9951
9978
  to_char(timeout_at AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') AS timeout_at
9952
- `;
9979
+ `);
9953
9980
  const row = rows[0];
9954
9981
  if (!row) {
9955
9982
  return err({
@@ -9984,13 +10011,13 @@ var ApprovalFacade = class {
9984
10011
  const patch = reason ? {
9985
10012
  cancelReason: reason
9986
10013
  } : {};
9987
- await sql.data`
10014
+ await this._getDatabase().runShared((db) => db`
9988
10015
  UPDATE stackbone_platform.approvals
9989
10016
  SET status = 'cancelled',
9990
10017
  decided_at = now(),
9991
10018
  metadata = metadata || ${JSON.stringify(patch)}::jsonb
9992
10019
  WHERE id = ${approvalId}::uuid AND status = 'pending'
9993
- `;
10020
+ `);
9994
10021
  return ok(void 0);
9995
10022
  } catch (cause) {
9996
10023
  return err({
@@ -10010,14 +10037,14 @@ var ApprovalFacade = class {
10010
10037
  const sql = this.sql();
10011
10038
  if (sql.error) return err(sql.error);
10012
10039
  try {
10013
- const rows = await sql.data`
10040
+ const rows = await this._getDatabase().runShared((db) => db`
10014
10041
  SELECT id, topic, status, payload, metadata,
10015
10042
  to_char(created_at AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') AS created_at,
10016
10043
  to_char(timeout_at AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') AS timeout_at
10017
10044
  FROM stackbone_platform.approvals
10018
10045
  WHERE id = ${approvalId}::uuid
10019
10046
  LIMIT 1
10020
- `;
10047
+ `);
10021
10048
  const row = rows[0];
10022
10049
  if (!row) {
10023
10050
  return err({
@@ -10042,7 +10069,7 @@ var ApprovalFacade = class {
10042
10069
  if (sql.error) return err(sql.error);
10043
10070
  const limit = clampLimit(options.limit);
10044
10071
  try {
10045
- const rows = await sql.data`
10072
+ const rows = await this._getDatabase().runShared((db) => db`
10046
10073
  SELECT id, topic, status, payload, metadata,
10047
10074
  to_char(created_at AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') AS created_at,
10048
10075
  to_char(timeout_at AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') AS timeout_at
@@ -10051,7 +10078,7 @@ var ApprovalFacade = class {
10051
10078
  AND (${options.topic ?? null}::text IS NULL OR topic = ${options.topic ?? null})
10052
10079
  ORDER BY created_at DESC, id DESC
10053
10080
  LIMIT ${limit}
10054
- `;
10081
+ `);
10055
10082
  return ok({
10056
10083
  items: rows.map((row) => toRecord(row))
10057
10084
  });
@@ -10173,7 +10200,7 @@ var ConfigFacade = class {
10173
10200
  void this._resolved;
10174
10201
  }
10175
10202
  async get(key) {
10176
- if (!key.trim()) {
10203
+ if (!String(key).trim()) {
10177
10204
  return err({
10178
10205
  code: "config_invalid_request",
10179
10206
  message: "`key` is required."
@@ -10184,7 +10211,7 @@ var ConfigFacade = class {
10184
10211
  if (!payload.data || !(key in payload.data)) {
10185
10212
  return err({
10186
10213
  code: "config_not_found",
10187
- message: `Config key \`${key}\` is not set for this agent.`,
10214
+ message: `Config key \`${String(key)}\` is not set for this agent.`,
10188
10215
  meta: {
10189
10216
  key
10190
10217
  }
@@ -10213,13 +10240,24 @@ var ConfigFacade = class {
10213
10240
  }
10214
10241
  return ok(out);
10215
10242
  }
10243
+ /**
10244
+ * Returns the agent's entire config payload as one typed object. An
10245
+ * absent/null `agent_config` row resolves to `ok({})` — an empty config is
10246
+ * "no config set", consistent with the facade reading the singleton row.
10247
+ * Reads stay an unvalidated SELECT (no AJV on the read path).
10248
+ */
10249
+ async getAll() {
10250
+ const payload = await this.loadPayload();
10251
+ if (payload.error) return err(payload.error);
10252
+ return ok(payload.data ?? {});
10253
+ }
10216
10254
  async loadPayload() {
10217
10255
  const sql = this.sql();
10218
10256
  if (sql.error) return err(sql.error);
10219
10257
  try {
10220
- const rows = await sql.data`
10258
+ const rows = await this._getDatabase().runShared((db) => db`
10221
10259
  SELECT payload FROM stackbone_platform.agent_config WHERE id = 1
10222
- `;
10260
+ `);
10223
10261
  return ok(rows[0]?.payload ?? null);
10224
10262
  } catch (cause) {
10225
10263
  return err({
@@ -10293,6 +10331,10 @@ function isPoolTerminatedError(error) {
10293
10331
  return typeof code === "string" && POOL_TERMINATED_ERROR_CODES.has(code);
10294
10332
  }
10295
10333
  __name(isPoolTerminatedError, "isPoolTerminatedError");
10334
+ function invalidatePoolHandle() {
10335
+ cachedHandle = null;
10336
+ }
10337
+ __name(invalidatePoolHandle, "invalidatePoolHandle");
10296
10338
  async function runWithColdStartRetry(firstAttempt, retryAttempt) {
10297
10339
  try {
10298
10340
  return await firstAttempt();
@@ -10394,21 +10436,21 @@ function buildProxy(steps, seed, rootCall, gate) {
10394
10436
  }
10395
10437
  __name(buildProxy, "buildProxy");
10396
10438
  function replayChain(seed, steps) {
10397
- let current = seed;
10439
+ let current3 = seed;
10398
10440
  for (const step of steps) {
10399
- if (current === null || current === void 0) return current;
10441
+ if (current3 === null || current3 === void 0) return current3;
10400
10442
  if (step.kind === "get") {
10401
- current = current[step.key];
10443
+ current3 = current3[step.key];
10402
10444
  continue;
10403
10445
  }
10404
- const parent = current;
10446
+ const parent = current3;
10405
10447
  const fn = parent[step.key];
10406
10448
  if (typeof fn !== "function") {
10407
10449
  throw new TypeError(`[stackbone/sdk] cold-start retry could not replay "${step.key}": not a function on the rebuilt handle`);
10408
10450
  }
10409
- current = fn.apply(parent, step.args);
10451
+ current3 = fn.apply(parent, step.args);
10410
10452
  }
10411
- return current;
10453
+ return current3;
10412
10454
  }
10413
10455
  __name(replayChain, "replayChain");
10414
10456
 
@@ -10461,6 +10503,48 @@ var DatabaseModule = class {
10461
10503
  // a half-baked tx. The contract gate fires before the first attempt.
10462
10504
  transaction = /* @__PURE__ */ __name((...args) => withColdStartRetry(() => getDatabaseHandle(this._databaseUrl).transaction(...args), this._gate), "transaction");
10463
10505
  /**
10506
+ * Cross-surface raw-SQL runner carrying the SAME cold-start resilience the
10507
+ * query-builder verbs above get. Sibling agent-local surfaces (`approval`,
10508
+ * `config`, `secrets`, `prompts`) that issue tagged-template queries over the
10509
+ * shared postgres-js `Sql` MUST execute them through this instead of caching
10510
+ * `shared().$client` once and calling it directly. Otherwise a dead pooled
10511
+ * socket — Fly Machines suspending the Machine between invokes, or a
10512
+ * WSL2/Docker localhost relay dropping an idle connection during a long LLM
10513
+ * step — surfaces as an unretried `CONNECTION_ENDED`/`ECONNRESET`. That is
10514
+ * exactly the asymmetry that let `client.approval.request` fail while the
10515
+ * `client.database.insert` right before it recovered.
10516
+ *
10517
+ * `fn` receives a FRESH `$client` on each attempt, so the single retry runs
10518
+ * against the rebuilt pool. Whole-operation granularity is replayed as a
10519
+ * unit — pass a multi-statement `sql.begin(...)` transaction or a helper that
10520
+ * fires several queries and the replay re-runs all of it; postgres-js never
10521
+ * commits a half-applied tx, so that is safe. SQLSTATE application errors
10522
+ * pass straight through without a retry. Like `shared()`/`raw()`, the
10523
+ * contract gate is intentionally NOT consulted here — gating surfaces gate at
10524
+ * their own call sites.
10525
+ */
10526
+ runShared(fn) {
10527
+ return withColdStartRetry(() => fn(getDatabaseHandle(this._databaseUrl).$client));
10528
+ }
10529
+ /**
10530
+ * `Result`-shaped sibling of `runShared` for surfaces whose driver swallows
10531
+ * the dead-socket error into a returned `Result.err.cause` instead of
10532
+ * throwing it — today only `client.rag`, whose `RagPipeline` returns a
10533
+ * `Result` rather than throwing. `attempt` runs once; if it comes back with a
10534
+ * pool-terminated `cause`, the pool is rebuilt and `attempt` replays exactly
10535
+ * once, then its result (success or the fresh error) is returned verbatim.
10536
+ * The `Result` contract is preserved end to end: a still-dead socket on the
10537
+ * replay surfaces as the surface's own `Result.err`, never as a raw throw.
10538
+ */
10539
+ async runSharedResult(attempt) {
10540
+ const first = await attempt();
10541
+ if (!first.error || !isPoolTerminatedError(first.error.cause)) return first;
10542
+ process.stderr.write(`[stackbone/sdk] database cold-start reconnect: rebuilding pool after ${first.error.cause.code ?? "unknown"}
10543
+ `);
10544
+ invalidatePoolHandle();
10545
+ return attempt();
10546
+ }
10547
+ /**
10464
10548
  * Canonical accessor for the **shared-handles pattern**. Returns the
10465
10549
  * process-wide Drizzle handle backing `client.database`. Cross-surface
10466
10550
  * SDK consumers (RAG today, memory / queues tomorrow) call this — never
@@ -10562,12 +10646,12 @@ var PromptsFacade = class {
10562
10646
  const sql = this.sql();
10563
10647
  if (sql.error) return err(sql.error);
10564
10648
  try {
10565
- const head = await fetchHead(sql.data, key);
10649
+ const head = await this._getDatabase().runShared((db) => fetchHead(db, key));
10566
10650
  if (!head) {
10567
10651
  return err(notFound(key));
10568
10652
  }
10569
10653
  if (options?.version !== void 0 && options.version !== head.current_version) {
10570
- const content = await fetchVersionContent(sql.data, key, options.version);
10654
+ const content = await this._getDatabase().runShared((db) => fetchVersionContent(db, key, options.version));
10571
10655
  if (content === null) {
10572
10656
  return err({
10573
10657
  code: "prompts_not_found",
@@ -10618,7 +10702,7 @@ var PromptsFacade = class {
10618
10702
  const sql = this.sql();
10619
10703
  if (sql.error) return err(sql.error);
10620
10704
  try {
10621
- const rows = await sql.data`
10705
+ const rows = await this._getDatabase().runShared((db) => db`
10622
10706
  SELECT p.key, p.name, p.description, p.current_version, p.metadata,
10623
10707
  p.created_at, p.updated_at, v.content
10624
10708
  FROM stackbone_platform.prompts p
@@ -10627,7 +10711,7 @@ var PromptsFacade = class {
10627
10711
  WHERE p.deleted_at IS NULL
10628
10712
  ORDER BY p.key
10629
10713
  LIMIT ${limit}
10630
- `;
10714
+ `);
10631
10715
  return ok({
10632
10716
  items: rows.map((row) => rowToPrompt(row, row.current_version, row.content))
10633
10717
  });
@@ -10654,7 +10738,7 @@ var PromptsFacade = class {
10654
10738
  if (sql.error) return err(sql.error);
10655
10739
  const variables = extractVars(request.template);
10656
10740
  try {
10657
- const head = await sql.data.begin(async (tx) => {
10741
+ const head = await this._getDatabase().runShared((db) => db.begin(async (tx) => {
10658
10742
  await tx`
10659
10743
  INSERT INTO stackbone_platform.prompts
10660
10744
  (key, name, description, current_version, metadata)
@@ -10682,7 +10766,7 @@ var PromptsFacade = class {
10682
10766
  WHERE p.key = ${request.key}
10683
10767
  `;
10684
10768
  return rows[0];
10685
- });
10769
+ }));
10686
10770
  if (!head) {
10687
10771
  return err({
10688
10772
  code: "prompts_unavailable",
@@ -10715,7 +10799,7 @@ var PromptsFacade = class {
10715
10799
  const sql = this.sql();
10716
10800
  if (sql.error) return err(sql.error);
10717
10801
  try {
10718
- const head = await sql.data.begin(async (tx) => {
10802
+ const head = await this._getDatabase().runShared((db) => db.begin(async (tx) => {
10719
10803
  await tx`SELECT pg_advisory_xact_lock(hashtext(${`prompts:${key}`}))`;
10720
10804
  const existing = await tx`
10721
10805
  SELECT p.key, p.name, p.description, p.current_version, p.metadata,
@@ -10726,11 +10810,11 @@ var PromptsFacade = class {
10726
10810
  WHERE p.key = ${key} AND p.deleted_at IS NULL
10727
10811
  LIMIT 1
10728
10812
  `;
10729
- const current = existing[0];
10730
- if (!current) return null;
10731
- let nextVersion = current.current_version;
10813
+ const current3 = existing[0];
10814
+ if (!current3) return null;
10815
+ let nextVersion = current3.current_version;
10732
10816
  if (options.template !== void 0) {
10733
- nextVersion = current.current_version + 1;
10817
+ nextVersion = current3.current_version + 1;
10734
10818
  const variables = extractVars(options.template);
10735
10819
  await tx`
10736
10820
  INSERT INTO stackbone_platform.prompt_versions
@@ -10744,8 +10828,8 @@ var PromptsFacade = class {
10744
10828
  await tx`
10745
10829
  UPDATE stackbone_platform.prompts
10746
10830
  SET current_version = ${nextVersion},
10747
- name = ${options.name ?? current.name},
10748
- description = ${options.description !== void 0 ? options.description : current.description},
10831
+ name = ${options.name ?? current3.name},
10832
+ description = ${options.description !== void 0 ? options.description : current3.description},
10749
10833
  metadata = COALESCE(${options.metadata !== void 0 ? JSON.stringify(options.metadata) : null}::jsonb, metadata),
10750
10834
  updated_at = now()
10751
10835
  WHERE key = ${key}
@@ -10759,7 +10843,7 @@ var PromptsFacade = class {
10759
10843
  WHERE p.key = ${key}
10760
10844
  `;
10761
10845
  return rows[0] ?? null;
10762
- });
10846
+ }));
10763
10847
  if (head === null) {
10764
10848
  return err(notFound(key));
10765
10849
  }
@@ -10774,12 +10858,12 @@ var PromptsFacade = class {
10774
10858
  const sql = this.sql();
10775
10859
  if (sql.error) return err(sql.error);
10776
10860
  try {
10777
- const rows = await sql.data`
10861
+ const rows = await this._getDatabase().runShared((db) => db`
10778
10862
  UPDATE stackbone_platform.prompts
10779
10863
  SET deleted_at = now(), updated_at = now()
10780
10864
  WHERE key = ${key} AND deleted_at IS NULL
10781
10865
  RETURNING key
10782
- `;
10866
+ `);
10783
10867
  const deleted = rows.length;
10784
10868
  if (deleted === 0) {
10785
10869
  return err(notFound(key));
@@ -11167,7 +11251,7 @@ async function createDocument(sql, args) {
11167
11251
  `;
11168
11252
  const insertedDoc = await tx`
11169
11253
  INSERT INTO stackbone_platform.rag_documents (collection_id, source, content_hash, metadata)
11170
- VALUES (${collectionId}, ${args.source}, ${args.contentHash}, ${tx.json(args.metadata)})
11254
+ VALUES (${collectionId}, ${args.source}, ${args.contentHash}, ${JSON.stringify(args.metadata)}::jsonb)
11171
11255
  RETURNING id
11172
11256
  `;
11173
11257
  const documentId = insertedDoc[0]?.id;
@@ -11863,8 +11947,10 @@ var RagModule = class {
11863
11947
  const sql = this.sql();
11864
11948
  if (sql.error) return err(sql.error);
11865
11949
  try {
11866
- await sql.data`DROP TABLE IF EXISTS rag_chunks`;
11867
- await sql.data`DROP TABLE IF EXISTS _rag_meta`;
11950
+ await this._getDatabase().runShared(async (db) => {
11951
+ await db`DROP TABLE IF EXISTS rag_chunks`;
11952
+ await db`DROP TABLE IF EXISTS _rag_meta`;
11953
+ });
11868
11954
  return ok(void 0);
11869
11955
  } catch (cause) {
11870
11956
  return err(toRagError(cause, "Reset failed"));
@@ -11914,13 +12000,15 @@ var RagModule = class {
11914
12000
  }
11915
12001
  }
11916
12002
  async withPipeline(embedder, run) {
11917
- const pipeline = new RagPipeline({
11918
- sqlProvider: /* @__PURE__ */ __name(() => this.sql(), "sqlProvider"),
11919
- ...embedder && {
11920
- embedder
11921
- }
12003
+ return this._getDatabase().runSharedResult(async () => {
12004
+ const pipeline = new RagPipeline({
12005
+ sqlProvider: /* @__PURE__ */ __name(() => this.sql(), "sqlProvider"),
12006
+ ...embedder && {
12007
+ embedder
12008
+ }
12009
+ });
12010
+ return await run(pipeline);
11922
12011
  });
11923
- return await run(pipeline);
11924
12012
  }
11925
12013
  };
11926
12014
  function countChunks(request) {
@@ -15803,12 +15891,12 @@ var SecretsFacade = class {
15803
15891
  if (sql.error) return err(sql.error);
15804
15892
  let rows;
15805
15893
  try {
15806
- rows = await sql.data`
15894
+ rows = await this._getDatabase().runShared((db) => db`
15807
15895
  SELECT version, nonce, ciphertext
15808
15896
  FROM stackbone_platform.secrets
15809
15897
  WHERE name = ${name}
15810
15898
  LIMIT 1
15811
- `;
15899
+ `);
15812
15900
  } catch (cause) {
15813
15901
  return err({
15814
15902
  code: "secrets_unavailable",
@@ -15854,11 +15942,11 @@ var SecretsFacade = class {
15854
15942
  if (sql.error) return err(sql.error);
15855
15943
  let rows;
15856
15944
  try {
15857
- rows = await sql.data`
15945
+ rows = await this._getDatabase().runShared((db) => db`
15858
15946
  SELECT name, version, nonce, ciphertext
15859
15947
  FROM stackbone_platform.secrets
15860
15948
  WHERE name = ANY(${names})
15861
- `;
15949
+ `);
15862
15950
  } catch (cause) {
15863
15951
  return err({
15864
15952
  code: "secrets_unavailable",
@@ -15922,6 +16010,99 @@ var SecretsFacade = class {
15922
16010
  }
15923
16011
  }
15924
16012
  };
16013
+ function agentRegistry() {
16014
+ const raw = process.env["AGENT_URLS"];
16015
+ if (!raw) {
16016
+ throw new Error("AGENT_URLS is not set. The emulator injects it; run this workflow through `stackbone dev`.");
16017
+ }
16018
+ return JSON.parse(raw);
16019
+ }
16020
+ __name(agentRegistry, "agentRegistry");
16021
+ function resolveAgentHost(name) {
16022
+ const registry = agentRegistry();
16023
+ const host = registry[name];
16024
+ if (!host) {
16025
+ throw new Error(`Unknown agent "${name}". Known agents: ${Object.keys(registry).join(", ")}`);
16026
+ }
16027
+ return host;
16028
+ }
16029
+ __name(resolveAgentHost, "resolveAgentHost");
16030
+ function signWorkflowHeaders() {
16031
+ const secret = process.env["HMAC_SECRET"] ?? "";
16032
+ const timestamp = String(Date.now());
16033
+ const signature = createHmac("sha256", secret).update(timestamp).digest("hex");
16034
+ return {
16035
+ "x-stackbone-timestamp": timestamp,
16036
+ "x-stackbone-workflow-signature": signature
16037
+ };
16038
+ }
16039
+ __name(signWorkflowHeaders, "signWorkflowHeaders");
16040
+
16041
+ // src/surfaces/external/agents/lazy-agent.ts
16042
+ var EVE_CLIENT_MODULE = "eve/client";
16043
+ async function buildEveClient(name) {
16044
+ const host = resolveAgentHost(name);
16045
+ const { Client } = await import(EVE_CLIENT_MODULE);
16046
+ return new Client({
16047
+ host,
16048
+ headers: /* @__PURE__ */ __name(() => signWorkflowHeaders(), "headers")
16049
+ });
16050
+ }
16051
+ __name(buildEveClient, "buildEveClient");
16052
+ function seedSessionState(seed) {
16053
+ if (typeof seed === "string") return {
16054
+ continuationToken: seed,
16055
+ streamIndex: 0
16056
+ };
16057
+ return seed ?? {
16058
+ streamIndex: 0
16059
+ };
16060
+ }
16061
+ __name(seedSessionState, "seedSessionState");
16062
+ function lazyAgentSession(getClient, seed) {
16063
+ const seededState = seedSessionState(seed);
16064
+ let real;
16065
+ let opened;
16066
+ const session = /* @__PURE__ */ __name(() => {
16067
+ real ??= getClient().then((client) => client.session(seed)).then((s2) => {
16068
+ opened = s2;
16069
+ return s2;
16070
+ }).catch((error) => {
16071
+ real = void 0;
16072
+ throw error;
16073
+ });
16074
+ return real;
16075
+ }, "session");
16076
+ return {
16077
+ get state() {
16078
+ return opened ? opened.state : seededState;
16079
+ },
16080
+ async send(input) {
16081
+ return (await session()).send(input);
16082
+ },
16083
+ async *stream(options) {
16084
+ yield* (await session()).stream(options);
16085
+ }
16086
+ };
16087
+ }
16088
+ __name(lazyAgentSession, "lazyAgentSession");
16089
+ function lazyAgent(name) {
16090
+ let client;
16091
+ const getClient = /* @__PURE__ */ __name(() => {
16092
+ client ??= buildEveClient(name).catch((error) => {
16093
+ client = void 0;
16094
+ throw error;
16095
+ });
16096
+ return client;
16097
+ }, "getClient");
16098
+ return {
16099
+ session(state) {
16100
+ return lazyAgentSession(getClient, state);
16101
+ }
16102
+ };
16103
+ }
16104
+ __name(lazyAgent, "lazyAgent");
16105
+ var agent = /* @__PURE__ */ __name((name) => lazyAgent(name), "agent");
15925
16106
  var AiModule = class {
15926
16107
  static {
15927
16108
  __name(this, "AiModule");
@@ -16252,6 +16433,95 @@ function mapApiError(raw, model) {
16252
16433
  };
16253
16434
  }
16254
16435
  __name(mapApiError, "mapApiError");
16436
+ var TIMESTAMP_HEADER = "x-stackbone-timestamp";
16437
+ var SIGNATURE_HEADER2 = "x-stackbone-workflow-signature";
16438
+ function signBrokerHeaders() {
16439
+ const secret = process.env["HMAC_SECRET"] ?? "";
16440
+ const timestamp = String(Date.now());
16441
+ const signature = createHmac("sha256", secret).update(timestamp).digest("hex");
16442
+ return {
16443
+ [TIMESTAMP_HEADER]: timestamp,
16444
+ [SIGNATURE_HEADER2]: signature
16445
+ };
16446
+ }
16447
+ __name(signBrokerHeaders, "signBrokerHeaders");
16448
+ function brokerBaseUrl() {
16449
+ const url = process.env["STACKBONE_API_URL"];
16450
+ if (!url) {
16451
+ throw new Error("STACKBONE_API_URL is not set. The Stackbone runtime injects the broker base URL; run this agent through `stackbone dev`.");
16452
+ }
16453
+ return url.replace(/\/+$/, "");
16454
+ }
16455
+ __name(brokerBaseUrl, "brokerBaseUrl");
16456
+ function installationId() {
16457
+ const id = process.env["STACKBONE_INSTALLATION_ID"];
16458
+ if (!id) {
16459
+ throw new Error("STACKBONE_INSTALLATION_ID is not set. The Stackbone runtime injects it; run this agent through `stackbone dev`.");
16460
+ }
16461
+ return id;
16462
+ }
16463
+ __name(installationId, "installationId");
16464
+
16465
+ // src/surfaces/external/connect/call-connector.ts
16466
+ var EXECUTE_PATH = "/api/connect/execute";
16467
+ function connectorCallError(code, message) {
16468
+ const error = new Error(message);
16469
+ error.code = code;
16470
+ return error;
16471
+ }
16472
+ __name(connectorCallError, "connectorCallError");
16473
+ function errorFromBody(status, body) {
16474
+ if (body && body.ok === false && body.error && typeof body.error.code === "string") {
16475
+ return connectorCallError(body.error.code, body.error.message ?? `Stackbone Connect broker rejected the call (code "${body.error.code}").`);
16476
+ }
16477
+ return connectorCallError("credential_error", `Stackbone Connect broker responded ${status}.`);
16478
+ }
16479
+ __name(errorFromBody, "errorFromBody");
16480
+ async function callConnector(connector, operation, args, opts) {
16481
+ const principal = opts?.principal ?? {
16482
+ type: "app"
16483
+ };
16484
+ const url = `${brokerBaseUrl()}${EXECUTE_PATH}`;
16485
+ const body = JSON.stringify({
16486
+ connector,
16487
+ operation,
16488
+ args: args ?? {},
16489
+ principal,
16490
+ installationId: installationId()
16491
+ });
16492
+ let response;
16493
+ try {
16494
+ response = await fetch(url, {
16495
+ method: "POST",
16496
+ headers: {
16497
+ "content-type": "application/json",
16498
+ ...signBrokerHeaders()
16499
+ },
16500
+ body
16501
+ });
16502
+ } catch (cause) {
16503
+ throw connectorCallError("execute_failed", `Stackbone Connect broker is unreachable: ${cause instanceof Error ? cause.message : String(cause)}`);
16504
+ }
16505
+ const parsed = await response.json().catch(() => null);
16506
+ if (!response.ok || parsed && parsed.ok === false) {
16507
+ throw errorFromBody(response.status, parsed ?? null);
16508
+ }
16509
+ if (!parsed || parsed.ok !== true) {
16510
+ throw connectorCallError("invalid_output", "Stackbone Connect broker returned a malformed execute response.");
16511
+ }
16512
+ return parsed.output;
16513
+ }
16514
+ __name(callConnector, "callConnector");
16515
+ var connectorHandle = /* @__PURE__ */ __name((id) => new Proxy(/* @__PURE__ */ Object.create(null), {
16516
+ get(_target, prop) {
16517
+ if (typeof prop !== "string" || prop === "then") return void 0;
16518
+ if (prop === "call") {
16519
+ return (operation, args, opts) => callConnector(id, operation, args, opts);
16520
+ }
16521
+ return (args, opts) => callConnector(id, prop, args, opts);
16522
+ }
16523
+ }), "connectorHandle");
16524
+ var connection = /* @__PURE__ */ __name((id) => connectorHandle(id), "connection");
16255
16525
  var R2_ENDPOINT_HOST_SUFFIX = ".r2.cloudflarestorage.com";
16256
16526
  function createS3CompatClient(options) {
16257
16527
  return new S3Client({
@@ -16681,6 +16951,8 @@ var QueuesModule = class {
16681
16951
  this._http = _http;
16682
16952
  this._gate = gate ?? createModuleGate("queues", resolved);
16683
16953
  }
16954
+ /** @deprecated Classic v2 only. Prefer `startWorkflow(name, input)` from
16955
+ * `@stackbone/sdk/workflow` (a job → a workflow run on the World). */
16684
16956
  async publish(request) {
16685
16957
  return withGate(this._gate, async () => {
16686
16958
  const body = {
@@ -16699,6 +16971,8 @@ var QueuesModule = class {
16699
16971
  });
16700
16972
  });
16701
16973
  }
16974
+ /** @deprecated Classic v2 only. Prefer `scheduleWorkflow(name, input, cron)`
16975
+ * from `@stackbone/sdk/workflow` (a cron → a workflow run on the World). */
16702
16976
  async schedule(request) {
16703
16977
  return withGate(this._gate, async () => {
16704
16978
  const body = {
@@ -16717,6 +16991,8 @@ var QueuesModule = class {
16717
16991
  });
16718
16992
  });
16719
16993
  }
16994
+ /** @deprecated Classic v2 only. Prefer `unschedule(name)` from
16995
+ * `@stackbone/sdk/workflow`. */
16720
16996
  async unschedule(request) {
16721
16997
  return withGate(this._gate, async () => this._http.request({
16722
16998
  method: "POST",
@@ -16728,6 +17004,8 @@ var QueuesModule = class {
16728
17004
  errorMapping: ERROR_MAPPING2
16729
17005
  }));
16730
17006
  }
17007
+ /** @deprecated Classic v2 only. Prefer `listSchedules()` from
17008
+ * `@stackbone/sdk/workflow`. */
16731
17009
  async listSchedules() {
16732
17010
  return withGate(this._gate, async () => this._http.request({
16733
17011
  method: "GET",
@@ -16752,7 +17030,7 @@ var StackboneClient = class {
16752
17030
  _secrets;
16753
17031
  _config;
16754
17032
  _queues;
16755
- _connections;
17033
+ _legacyConnections;
16756
17034
  _memory;
16757
17035
  _prompts;
16758
17036
  _httpClient;
@@ -16806,16 +17084,59 @@ var StackboneClient = class {
16806
17084
  return this._queues;
16807
17085
  }
16808
17086
  /**
16809
- * Live surface — the agent's handle on the workspace's connector connections.
16810
- * `list` / `invoke` make authenticated calls to the control-plane connectors
16811
- * proxy (`/api/v1/agent/connections/*`); the credentials never enter the agent
17087
+ * Legacy surface — the agent's handle on the workspace's connector connections
17088
+ * under the OLD connector model. `list` / `invoke(connector, action, args)` make
17089
+ * authenticated calls to the control-plane connectors proxy
17090
+ * (`/api/v1/agent/connections/*`); the credentials never enter the agent
16812
17091
  * container. Gated against `connections.actions` so the handshake-blocked /
16813
17092
  * capability-missing paths are exercised the same way as the other gated
16814
17093
  * surfaces.
17094
+ *
17095
+ * Named `legacyConnections` (not `connections`) so it no longer sits one letter
17096
+ * from the new peer-free `connection(id)` entrypoint above — the two connector
17097
+ * entrypoints are now unambiguous. Behaviour is unchanged from the old
17098
+ * `connections` member.
16815
17099
  */
16816
- get connections() {
16817
- this._connections ??= new ConnectionsModule(this.resolved, this.http(), createModuleGate("connections", this.resolved, this._contractStore));
16818
- return this._connections;
17100
+ get legacyConnections() {
17101
+ this._legacyConnections ??= new ConnectionsModule(this.resolved, this.http(), createModuleGate("connections", this.resolved, this._contractStore));
17102
+ return this._legacyConnections;
17103
+ }
17104
+ /**
17105
+ * Peer-free connector entrypoint — `stackbone.connection(id)` selects a Stackbone
17106
+ * Connect connector by its verbatim id and returns a typed handle whose generated
17107
+ * operations (`.sendMail({ ... })`, typed via the `StackboneConnections` registry)
17108
+ * and dynamic `.call(operation, args)` escape hatch both resolve to the same broker
17109
+ * call (`POST /api/connect/execute`, HMAC scheme A). It is a plain HMAC fetch — it
17110
+ * imports NO `eve` peer — so it is wired directly onto the client with no lazy
17111
+ * loading and pulls no new peer into the main barrel.
17112
+ *
17113
+ * This is the namespaced form of the top-level `connection(...)` export (now
17114
+ * `@deprecated`); both delegate to the same implementation. Distinct from the
17115
+ * plural `connections` surface above, which is the control-plane connectors proxy
17116
+ * (`list` / `invoke`).
17117
+ */
17118
+ get connection() {
17119
+ return connection;
17120
+ }
17121
+ /**
17122
+ * Namespaced sibling-agent entrypoint — `stackbone.agent(id)` selects a sibling
17123
+ * eve agent by its verbatim name and returns a lazy eve `Client`, so a workflow
17124
+ * step delegates with `stackbone.agent('support').session().send({ ... })`. The
17125
+ * name is typed against the augmentable `AgentRegistry` (declared names
17126
+ * autocomplete, a typo is a compile error).
17127
+ *
17128
+ * Peer isolation is load-bearing: selecting the agent and opening a session are
17129
+ * synchronous and import NO `eve` peer — only the session's already-async leaves
17130
+ * (`send` / `stream`) resolve `eve/client` via dynamic import on first use. So a
17131
+ * tool-only agent that imports `@stackbone/sdk` and never calls `agent(...)` never
17132
+ * eager-loads the optional `eve` peer and cannot crash-loop on a missing dep.
17133
+ *
17134
+ * This is the namespaced form of the top-level `eveAgent(...)` export (now
17135
+ * `@deprecated`) on the `@stackbone/sdk/workflow` subpath; both produce the same
17136
+ * signed workflow→agent call and the same eve `Client` API.
17137
+ */
17138
+ get agent() {
17139
+ return agent;
16819
17140
  }
16820
17141
  /**
16821
17142
  * Pending surface — runtime not built. Every method returns
@@ -16984,7 +17305,9 @@ var SDK_ERROR_CODE_PREFIXES = {
16984
17305
  "unavailable"
16985
17306
  ],
16986
17307
  /**
16987
- * `client.connections` — the agent → control plane connectors proxy. Both
17308
+ * `client.legacyConnections` — the agent → control plane connectors proxy
17309
+ * (legacy connector model). The `connections_*` code prefix stays stable (it
17310
+ * names the wire domain, not the client accessor). Both
16988
17311
  * methods (`list`, `invoke`) hit the `/api/v1/agent/connections/*` endpoints
16989
17312
  * over `HttpClient`, so the full status→domain remap (`connections_unauthorized`,
16990
17313
  * `connections_not_found`, `connections_unavailable`, …) is in play. The agent
@@ -17165,6 +17488,9 @@ function assertCapabilityShape(name, capability) {
17165
17488
  }
17166
17489
  __name(assertCapabilityShape, "assertCapabilityShape");
17167
17490
 
17491
+ // src/runtime/define-workspace.ts
17492
+ var defineWorkspace = /* @__PURE__ */ __name((workspace) => workspace, "defineWorkspace");
17493
+
17168
17494
  // src/runtime/logger.ts
17169
17495
  var writeLine = /* @__PURE__ */ __name((stream, level, msg, bindings, meta, now) => {
17170
17496
  const record = {
@@ -17202,6 +17528,65 @@ function getInvocationContext() {
17202
17528
  return storage.getStore();
17203
17529
  }
17204
17530
  __name(getInvocationContext, "getInvocationContext");
17531
+ function runWithCallerId(id, fn, options) {
17532
+ const context = {
17533
+ runId: id,
17534
+ invocationId: options?.invocationId ?? id,
17535
+ // Only attach `handler` when supplied: `exactOptionalPropertyTypes` forbids
17536
+ // an explicit `undefined` on an optional property.
17537
+ ...options?.handler !== void 0 ? {
17538
+ handler: options.handler
17539
+ } : {}
17540
+ };
17541
+ return runWithInvocationContext(context, fn);
17542
+ }
17543
+ __name(runWithCallerId, "runWithCallerId");
17544
+
17545
+ // src/runtime/workflow-starter.ts
17546
+ var current;
17547
+ function setWorkflowStarter(starter) {
17548
+ current = starter;
17549
+ }
17550
+ __name(setWorkflowStarter, "setWorkflowStarter");
17551
+ function getWorkflowStarter() {
17552
+ if (!current) {
17553
+ throw new Error("No workflow starter is bound. `startWorkflow` / `startWorkflowAndWait` can only be called from inside a running workflow \u2014 the runtime binds the starter on its first dispatch.");
17554
+ }
17555
+ return current;
17556
+ }
17557
+ __name(getWorkflowStarter, "getWorkflowStarter");
17558
+
17559
+ // src/runtime/workflow-scheduler.ts
17560
+ var current2;
17561
+ function setWorkflowScheduler(scheduler) {
17562
+ current2 = scheduler;
17563
+ }
17564
+ __name(setWorkflowScheduler, "setWorkflowScheduler");
17565
+ function getWorkflowScheduler() {
17566
+ if (!current2) {
17567
+ throw new Error("No workflow scheduler is bound. `scheduleWorkflow` / `unschedule` / `listSchedules` can only be called inside a running workflow runtime \u2014 the runtime binds the scheduler on its first dispatch.");
17568
+ }
17569
+ return current2;
17570
+ }
17571
+ __name(getWorkflowScheduler, "getWorkflowScheduler");
17572
+
17573
+ // src/runtime/ambient-client.ts
17574
+ var cached;
17575
+ function resolveAmbientClient() {
17576
+ cached ??= createClient();
17577
+ return cached;
17578
+ }
17579
+ __name(resolveAmbientClient, "resolveAmbientClient");
17580
+ var stackbone = new Proxy({}, {
17581
+ get(_target, prop) {
17582
+ const client = resolveAmbientClient();
17583
+ const value = Reflect.get(client, prop, client);
17584
+ return typeof value === "function" ? value.bind(client) : value;
17585
+ },
17586
+ has(_target, prop) {
17587
+ return Reflect.has(resolveAmbientClient(), prop);
17588
+ }
17589
+ });
17205
17590
  var patched = /* @__PURE__ */ new WeakSet();
17206
17591
  function installInvocationConsoleCapture(options = {}) {
17207
17592
  const target = options.console ?? console;
@@ -17267,9 +17652,7 @@ var STORED_TO_SDK_ENV = {
17267
17652
  S3_REGION: "STACKBONE_S3_REGION",
17268
17653
  // OpenRouter (`client.ai`) — identity.
17269
17654
  OPENROUTER_API_KEY: "OPENROUTER_API_KEY",
17270
- OPENROUTER_BASE_URL: "OPENROUTER_BASE_URL",
17271
- // Axiom (observability) — identity.
17272
- AXIOM_TOKEN: "AXIOM_TOKEN"
17655
+ OPENROUTER_BASE_URL: "OPENROUTER_BASE_URL"
17273
17656
  };
17274
17657
  function rehydrateSystemSecretsRows(env, rows, cipher, databaseUrl) {
17275
17658
  const applied = [];
@@ -17498,6 +17881,6 @@ var analyzeAgentSchemas = /* @__PURE__ */ __name((pair) => {
17498
17881
  };
17499
17882
  }, "analyzeAgentSchemas");
17500
17883
 
17501
- export { INVOCATION_ID_HEADER, INVOKE_TIMEOUT_HARD_CAP_MS, RESERVED_ERROR_CODES, RESERVED_HANDLER_NAMES, RUN_ID_HEADER, STORED_TO_SDK_ENV, StackboneClient, analyzeAgentSchemas, createClient, createStructuredLogger, defineAgent, getInvocationContext, installInvocationConsoleCapture, invokeRequestSchema, isReservedErrorCode, isSdkErrorCode, loadSystemSecretsIntoEnv, rehydrateSystemSecretsRows, runWithInvocationContext };
17884
+ export { INVOCATION_ID_HEADER, INVOKE_TIMEOUT_HARD_CAP_MS, RESERVED_ERROR_CODES, RESERVED_HANDLER_NAMES, RUN_ID_HEADER, STORED_TO_SDK_ENV, StackboneClient, analyzeAgentSchemas, createClient, createStructuredLogger, defineAgent, defineWorkspace, getInvocationContext, getWorkflowScheduler, getWorkflowStarter, installInvocationConsoleCapture, invokeRequestSchema, isReservedErrorCode, isSdkErrorCode, loadSystemSecretsIntoEnv, rehydrateSystemSecretsRows, runWithCallerId, runWithInvocationContext, setWorkflowScheduler, setWorkflowStarter, stackbone };
17502
17885
  //# sourceMappingURL=index.js.map
17503
17886
  //# sourceMappingURL=index.js.map