@standardagents/builder 0.40.2 → 0.40.4

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
@@ -30657,17 +30657,23 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
30657
30657
  return cursor.rowsWritten > 0;
30658
30658
  }
30659
30659
  /** Approve a pending device login: mint a personal API key for the user and
30660
- * park its plaintext for the single claim. Returns false when the code is
30661
- * unknown, expired, or not pending. */
30660
+ * park its plaintext for the single claim. A retry by the same user remains
30661
+ * successful after the row is approved or claimed, without minting another
30662
+ * key. Returns false for unknown, expired, denied, or differently-owned
30663
+ * logins. */
30662
30664
  async approveDeviceLogin(params) {
30663
30665
  await this.ensureMigrated();
30664
30666
  await this.sweepDeviceLogins();
30665
30667
  const cursor = await this.ctx.storage.sql.exec(
30666
- `SELECT status FROM device_logins WHERE code_hash = ?`,
30668
+ `SELECT status, user_id FROM device_logins WHERE code_hash = ?`,
30667
30669
  params.code_hash
30668
30670
  );
30669
30671
  const row = cursor.toArray()[0];
30670
- if (!row || row.status !== "pending") return false;
30672
+ if (!row) return false;
30673
+ if (row.status === "approved" || row.status === "claimed") {
30674
+ return row.user_id === params.user_id;
30675
+ }
30676
+ if (row.status !== "pending") return false;
30671
30677
  await this.createApiKey({
30672
30678
  name: params.key_name,
30673
30679
  key_hash: params.token_hash,
@@ -34826,7 +34832,7 @@ ${resultContent}${attachmentSummary}`;
34826
34832
  void 0,
34827
34833
  INTERNAL_TOOL_DELIVERY
34828
34834
  );
34829
- if (delivered) sides.add(delivered.side);
34835
+ if (delivered?.resume) sides.add(delivered.side);
34830
34836
  }
34831
34837
  if (threadId) {
34832
34838
  for (const side of sides) {
@@ -35128,14 +35134,17 @@ ${resultContent}${attachmentSummary}`;
35128
35134
  deliveredResultWaiters = /* @__PURE__ */ new Map();
35129
35135
  notifyDeliveredResultWaiters(toolCallId) {
35130
35136
  const waiters = this.deliveredResultWaiters?.get(toolCallId);
35131
- if (!waiters) return;
35137
+ if (!waiters || waiters.size === 0) return false;
35132
35138
  this.deliveredResultWaiters.delete(toolCallId);
35139
+ let notified = false;
35133
35140
  for (const wake of waiters) {
35134
35141
  try {
35135
35142
  wake();
35143
+ notified = true;
35136
35144
  } catch {
35137
35145
  }
35138
35146
  }
35147
+ return notified;
35139
35148
  }
35140
35149
  /**
35141
35150
  * Await a parked forwarded call's delivered result: one immediate read,
@@ -35280,37 +35289,46 @@ ${resultContent}${attachmentSummary}`;
35280
35289
  const side = pending.side === "b" ? "b" : "a";
35281
35290
  const content = ok ? result ?? "" : `Error: ${error ?? "tool failed"}`;
35282
35291
  const toolStatus = ok ? "success" : "error";
35283
- await this.ctx.storage.sql.exec(
35284
- `UPDATE messages SET content = ?, tool_status = ? WHERE tool_call_id = ? AND role = 'tool'`,
35285
- content,
35286
- toolStatus,
35287
- toolCallId
35288
- );
35289
- const updated = await this.ctx.storage.sql.exec(
35290
- `SELECT COUNT(*) AS total FROM messages WHERE tool_call_id = ? AND role = 'tool'`,
35291
- toolCallId
35292
- );
35293
- if (Number(updated.toArray()[0]?.total ?? 0) === 0) {
35294
- const toolRow = await this.ctx.storage.sql.exec(
35295
- `SELECT tool FROM pending_client_calls WHERE tool_call_id = ? LIMIT 1`,
35292
+ const resultMessageId = crypto.randomUUID();
35293
+ const resultCreatedAt = Date.now() * TIMESTAMP_MULTIPLIER;
35294
+ const accepted = this.ctx.storage.transactionSync(() => {
35295
+ const claimed = this.ctx.storage.sql.exec(
35296
+ `UPDATE pending_client_calls
35297
+ SET status = 'resolved'
35298
+ WHERE tool_call_id = ? AND status = 'pending'`,
35296
35299
  toolCallId
35297
35300
  );
35298
- await this.ctx.storage.sql.exec(
35299
- `INSERT INTO messages (id, role, content, name, tool_call_id, tool_status, created_at, status, prompt)
35300
- VALUES (?, 'tool', ?, ?, ?, ?, ?, 'completed', NULL)`,
35301
- crypto.randomUUID(),
35301
+ if (claimed.rowsWritten !== 1) return false;
35302
+ this.ctx.storage.sql.exec(
35303
+ `UPDATE messages SET content = ?, tool_status = ? WHERE tool_call_id = ? AND role = 'tool'`,
35302
35304
  content,
35303
- toolRow.toArray()[0]?.tool ?? null,
35304
- toolCallId,
35305
35305
  toolStatus,
35306
- Date.now() * TIMESTAMP_MULTIPLIER
35306
+ toolCallId
35307
35307
  );
35308
- }
35309
- await this.ctx.storage.sql.exec(
35310
- `UPDATE pending_client_calls SET status = 'resolved' WHERE tool_call_id = ?`,
35311
- toolCallId
35312
- );
35313
- this.notifyDeliveredResultWaiters(toolCallId);
35308
+ const updated = this.ctx.storage.sql.exec(
35309
+ `SELECT COUNT(*) AS total FROM messages WHERE tool_call_id = ? AND role = 'tool'`,
35310
+ toolCallId
35311
+ );
35312
+ if (Number(updated.toArray()[0]?.total ?? 0) === 0) {
35313
+ const toolRow = this.ctx.storage.sql.exec(
35314
+ `SELECT tool FROM pending_client_calls WHERE tool_call_id = ? LIMIT 1`,
35315
+ toolCallId
35316
+ );
35317
+ this.ctx.storage.sql.exec(
35318
+ `INSERT INTO messages (id, role, content, name, tool_call_id, tool_status, created_at, status, prompt)
35319
+ VALUES (?, 'tool', ?, ?, ?, ?, ?, 'completed', NULL)`,
35320
+ resultMessageId,
35321
+ content,
35322
+ toolRow.toArray()[0]?.tool ?? null,
35323
+ toolCallId,
35324
+ toolStatus,
35325
+ resultCreatedAt
35326
+ );
35327
+ }
35328
+ return true;
35329
+ });
35330
+ if (!accepted) return null;
35331
+ const resumedInline = this.notifyDeliveredResultWaiters(toolCallId);
35314
35332
  try {
35315
35333
  const msgCursor = await this.ctx.storage.sql.exec(
35316
35334
  `SELECT id, role, content, name, tool_call_id, tool_status, created_at, depth
@@ -35321,7 +35339,7 @@ ${resultContent}${attachmentSummary}`;
35321
35339
  if (msg) this.broadcastMessage(msg);
35322
35340
  } catch {
35323
35341
  }
35324
- return { side };
35342
+ return { side, resume: !resumedInline };
35325
35343
  }
35326
35344
  // ─── Runtime byte streams ──────────────────────────────────────────────────
35327
35345
  // The existing bridge frames carry opaque capability metadata and bytes