@acosmi/sdk-ts 2.6.0 → 2.8.0

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.
@@ -1261,10 +1261,17 @@ async function authorize(meta, clientID, scopes, opts = {}) {
1261
1261
  codeRejecter(new Error(`authorization denied: ${errMsg}`));
1262
1262
  return;
1263
1263
  }
1264
- res.setHeader("Content-Type", "text/html; charset=utf-8");
1265
- res.end(
1266
- `<!DOCTYPE html><html><head><meta charset="utf-8"><title>\u6388\u6743\u6210\u529F</title></head><body style="font-family:system-ui,sans-serif;text-align:center;padding:60px 20px"><h2>\u6388\u6743\u6210\u529F</h2><p>\u5DF2\u5B8C\u6210\u8EAB\u4EFD\u8BA4\u8BC1, \u8BF7\u8FD4\u56DE\u5E94\u7528\u7EE7\u7EED\u4F7F\u7528\u3002</p><p style="color:#888;font-size:14px">\u6B64\u7A97\u53E3\u5C06\u5728 3 \u79D2\u540E\u81EA\u52A8\u5173\u95ED\u2026</p><script>setTimeout(function(){window.close()},3000)</script></body></html>`
1267
- );
1264
+ const successRedirect = resolveSuccessRedirect(opts.successRedirectURL);
1265
+ if (successRedirect) {
1266
+ res.statusCode = 302;
1267
+ res.setHeader("Location", successRedirect);
1268
+ res.end();
1269
+ } else {
1270
+ res.setHeader("Content-Type", "text/html; charset=utf-8");
1271
+ res.end(
1272
+ `<!DOCTYPE html><html><head><meta charset="utf-8"><title>\u6388\u6743\u6210\u529F</title></head><body style="font-family:system-ui,sans-serif;text-align:center;padding:60px 20px"><h2>\u6388\u6743\u6210\u529F</h2><p>\u5DF2\u5B8C\u6210\u8EAB\u4EFD\u8BA4\u8BC1, \u8BF7\u8FD4\u56DE\u5E94\u7528\u7EE7\u7EED\u4F7F\u7528\u3002</p><p style="color:#888;font-size:14px">\u6B64\u7A97\u53E3\u5C06\u5728 3 \u79D2\u540E\u81EA\u52A8\u5173\u95ED\u2026</p><script>setTimeout(function(){window.close()},3000)</script></body></html>`
1273
+ );
1274
+ }
1268
1275
  codeResolver(code);
1269
1276
  });
1270
1277
  const authURL = new URL(meta.authorization_endpoint);
@@ -1326,6 +1333,16 @@ async function authorize(meta, clientID, scopes, opts = {}) {
1326
1333
  function htmlEscape(s) {
1327
1334
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
1328
1335
  }
1336
+ function resolveSuccessRedirect(raw) {
1337
+ if (!raw) return null;
1338
+ try {
1339
+ const u = new URL(raw);
1340
+ if (u.protocol !== "http:" && u.protocol !== "https:") return null;
1341
+ return u.toString();
1342
+ } catch {
1343
+ return null;
1344
+ }
1345
+ }
1329
1346
  async function createWebAuthorizationRequest(meta, opts) {
1330
1347
  const verifier = await generateCodeVerifier();
1331
1348
  const challenge = await codeChallenge(verifier);
@@ -4765,6 +4782,8 @@ async function sleepWithSignal2(ms, signal) {
4765
4782
  }
4766
4783
 
4767
4784
  // src/agent-runs/types.ts
4785
+ var AGENT_RUN_META_TITLE = "title";
4786
+ var AGENT_RUN_META_WORKSPACE = "workspace";
4768
4787
  var AgentRunStreamError = class extends Error {
4769
4788
  event;
4770
4789
  code;
@@ -4940,6 +4959,33 @@ var AgentRunsClient = class {
4940
4959
  );
4941
4960
  return fromWireCreateResponse(resp);
4942
4961
  }
4962
+ /**
4963
+ * List the caller's own agent runs, newest first (GET /agent-runs, Phase 5C
4964
+ * console). Returns view metadata only — never session tokens, policies or
4965
+ * messages (contract §6). Filter remote-control runs with
4966
+ * `{ runtime: 'crabcode_remote' }`.
4967
+ */
4968
+ async list(opts = {}, signal) {
4969
+ const params = new URLSearchParams();
4970
+ if (opts.runtime) params.set("runtime", opts.runtime);
4971
+ if (opts.status) params.set("status", opts.status);
4972
+ if (opts.page != null) params.set("page", String(opts.page));
4973
+ if (opts.pageSize != null) params.set("page_size", String(opts.pageSize));
4974
+ const qs = params.toString();
4975
+ const resp = await this.requestAPI(
4976
+ "GET",
4977
+ `/agent-runs${qs ? `?${qs}` : ""}`,
4978
+ null,
4979
+ signal,
4980
+ { retryOn401: true }
4981
+ );
4982
+ return {
4983
+ records: (resp.records ?? []).map(fromWireRun),
4984
+ total: typeof resp.total === "number" ? resp.total : 0,
4985
+ page: typeof resp.page === "number" ? resp.page : 1,
4986
+ pageSize: typeof resp.pageSize === "number" ? resp.pageSize : 20
4987
+ };
4988
+ }
4943
4989
  get(runId, signal) {
4944
4990
  return this.requestAPI(
4945
4991
  "GET",
@@ -5001,6 +5047,73 @@ var AgentRunsClient = class {
5001
5047
  [Symbol.asyncIterator]: () => this.streamRemoteControlGen(runId, signal)
5002
5048
  };
5003
5049
  }
5050
+ /**
5051
+ * Submit a permission decision for a pending `permission_request` event
5052
+ * (POST /agent-runs/:runId/permission-results, contract §4/§9/§14).
5053
+ *
5054
+ * Only `approved` | `rejected` may be submitted by clients — `timeout` /
5055
+ * `cancelled` are produced server-side. Requires an OAuth token with the
5056
+ * explicit `remote_control` scope (or a web JWT). 409 means the remote
5057
+ * session is gone (e.g. already terminated).
5058
+ */
5059
+ async submitPermissionResult(runId, result, signal) {
5060
+ await this.requestAPI(
5061
+ "POST",
5062
+ `/agent-runs/${encodeURIComponent(runId)}/permission-results`,
5063
+ {
5064
+ request_id: result.requestId,
5065
+ decision: result.decision,
5066
+ reason: result.reason
5067
+ },
5068
+ signal,
5069
+ { retryOn401: false }
5070
+ );
5071
+ }
5072
+ /**
5073
+ * Append a mid-session user message to a remote run
5074
+ * (POST /agent-runs/:runId/messages, Phase 5C). The message role is
5075
+ * hard-coded to 'user' server-side (contract §6 #5 prompt-injection
5076
+ * defence); content is limited to 64KB. Requires the explicit
5077
+ * `remote_control` scope (or a web JWT).
5078
+ */
5079
+ async submitUserMessage(runId, message, signal) {
5080
+ const resp = await this.requestAPI(
5081
+ "POST",
5082
+ `/agent-runs/${encodeURIComponent(runId)}/messages`,
5083
+ { request_id: message.requestId, content: message.content },
5084
+ signal,
5085
+ { retryOn401: false }
5086
+ );
5087
+ return {
5088
+ ok: resp?.ok === true,
5089
+ requestId: resp?.request_id ?? message.requestId ?? ""
5090
+ };
5091
+ }
5092
+ /**
5093
+ * Reveal the one-shot remote session token for a desktop-runner run
5094
+ * (POST /agent-runs/:runId/remote-token, Phase 5B; contract §18.1).
5095
+ *
5096
+ * Desktop launcher only: the token is single-consumption (a second call
5097
+ * returns 409) and must never touch browser storage — receive it in the
5098
+ * native layer and inject it into the CrabCode child-process env only
5099
+ * (contract §6). Cloud / local_embedded runners never expose tokens over
5100
+ * HTTP (403). Requires the explicit `remote_control` scope.
5101
+ */
5102
+ async revealRemoteToken(runId, signal) {
5103
+ const resp = await this.requestAPI(
5104
+ "POST",
5105
+ `/agent-runs/${encodeURIComponent(runId)}/remote-token`,
5106
+ {},
5107
+ signal,
5108
+ { retryOn401: false }
5109
+ );
5110
+ return {
5111
+ accessToken: resp?.access_token ?? "",
5112
+ sessionUrl: resp?.session_url ?? "",
5113
+ tenantId: resp?.tenant_id ?? "",
5114
+ workspace: resp?.workspace || void 0
5115
+ };
5116
+ }
5004
5117
  async *streamRemoteControlGen(runId, signal) {
5005
5118
  const resp = await this.requestRaw(
5006
5119
  "GET",
@@ -5251,6 +5364,7 @@ function toWireCreateRequest(req) {
5251
5364
  adapter: req.adapter,
5252
5365
  permission_policy: req.permissionPolicy ? toWirePermissionPolicy(req.permissionPolicy) : void 0,
5253
5366
  workspace_policy: req.workspacePolicy ? toWireWorkspacePolicy(req.workspacePolicy) : void 0,
5367
+ byok_credential_ref: req.byokCredentialRef,
5254
5368
  artifact_policy: req.artifactPolicy ? {
5255
5369
  enabled: req.artifactPolicy.enabled,
5256
5370
  max_files: req.artifactPolicy.maxFiles
@@ -5283,7 +5397,10 @@ function fromWireRun(resp) {
5283
5397
  startedAt: resp.started_at,
5284
5398
  completedAt: resp.completed_at,
5285
5399
  error: normalizeError(resp.error),
5286
- metadata: resp.metadata
5400
+ metadata: resp.metadata,
5401
+ runtime: resp.runtime,
5402
+ runner: resp.runner,
5403
+ adapter: resp.adapter
5287
5404
  };
5288
5405
  }
5289
5406
  function fromWireArtifact(resp) {
@@ -5541,6 +5658,87 @@ function errorMessage(e) {
5541
5658
  return e instanceof Error ? e.message : String(e);
5542
5659
  }
5543
5660
 
5661
+ // src/agent-runs/byok.ts
5662
+ function fromWireByok(v) {
5663
+ return {
5664
+ credentialRef: v.credential_ref ?? "",
5665
+ provider: v.provider ?? "",
5666
+ name: v.name || void 0,
5667
+ baseUrl: v.base_url || void 0,
5668
+ fingerprint: v.fingerprint || void 0,
5669
+ status: v.status ?? "",
5670
+ createdAt: v.created_at || void 0,
5671
+ lastUsedAt: v.last_used_at || void 0
5672
+ };
5673
+ }
5674
+ var byokByClient = /* @__PURE__ */ new WeakMap();
5675
+ Object.defineProperty(Client.prototype, "crabcodeByok", {
5676
+ configurable: true,
5677
+ enumerable: false,
5678
+ get() {
5679
+ let existing = byokByClient.get(this);
5680
+ if (!existing) {
5681
+ existing = new CrabCodeByokClient(this);
5682
+ byokByClient.set(this, existing);
5683
+ }
5684
+ return existing;
5685
+ }
5686
+ });
5687
+ var CrabCodeByokClient = class {
5688
+ constructor(client) {
5689
+ this.client = client;
5690
+ }
5691
+ client;
5692
+ /** 列出调用者自己的密钥 (masked; 新→旧, 服务端上限 100 条)。 */
5693
+ async list(signal) {
5694
+ const resp = await this.client.doJSON(
5695
+ "GET",
5696
+ "/crabcode/byok-credentials",
5697
+ null,
5698
+ signal
5699
+ );
5700
+ return (resp.data?.items ?? []).map(fromWireByok);
5701
+ }
5702
+ /**
5703
+ * 创建密钥 — 明文一次性提交, 返回 masked 视图。
5704
+ * 单用户上限 20 把; provider='custom' 必须带 https:// baseUrl。
5705
+ */
5706
+ async create(req, signal) {
5707
+ const resp = await this.client.doJSON(
5708
+ "POST",
5709
+ "/crabcode/byok-credentials",
5710
+ {
5711
+ provider: req.provider,
5712
+ name: req.name,
5713
+ base_url: req.baseUrl,
5714
+ plaintext: req.plaintext
5715
+ },
5716
+ signal
5717
+ );
5718
+ return fromWireByok(resp.data ?? {});
5719
+ }
5720
+ /** 轮换密钥明文 — credentialRef 不变, fingerprint 更新。已吊销的密钥不可轮换 (400)。 */
5721
+ async rotate(credentialRef, newPlaintext, signal) {
5722
+ const resp = await this.client.doJSON(
5723
+ "POST",
5724
+ `/crabcode/byok-credentials/${encodeURIComponent(credentialRef)}/rotate`,
5725
+ { new_plaintext: newPlaintext },
5726
+ signal
5727
+ );
5728
+ return fromWireByok(resp.data ?? {});
5729
+ }
5730
+ /** 吊销密钥 (软状态 + 服务端抹密文, 不可恢复; 幂等 — 重复吊销返回当前视图)。 */
5731
+ async revoke(credentialRef, signal) {
5732
+ const resp = await this.client.doJSON(
5733
+ "POST",
5734
+ `/crabcode/byok-credentials/${encodeURIComponent(credentialRef)}/revoke`,
5735
+ {},
5736
+ signal
5737
+ );
5738
+ return fromWireByok(resp.data ?? {});
5739
+ }
5740
+ };
5741
+
5544
5742
  // src/compliance/scopes.ts
5545
5743
  var ScopeComplianceEvidenceRead = "compliance:evidence:read";
5546
5744
  var ScopeComplianceEvidenceWrite = "compliance:evidence:write";
@@ -7194,6 +7392,132 @@ function asCredentialRef(s) {
7194
7392
  return s;
7195
7393
  }
7196
7394
 
7395
+ // src/chatbridge/client.ts
7396
+ var chatBridgeByClient = /* @__PURE__ */ new WeakMap();
7397
+ Object.defineProperty(Client.prototype, "chatBridge", {
7398
+ configurable: true,
7399
+ enumerable: false,
7400
+ get() {
7401
+ let existing = chatBridgeByClient.get(this);
7402
+ if (!existing) {
7403
+ existing = new ChatBridgeClient(this);
7404
+ chatBridgeByClient.set(this, existing);
7405
+ }
7406
+ return existing;
7407
+ }
7408
+ });
7409
+ var ChatBridgeClient = class {
7410
+ constructor(client) {
7411
+ this.client = client;
7412
+ }
7413
+ client;
7414
+ // ---------------------------------------------------------------------------
7415
+ // Integration 管理面
7416
+ // ---------------------------------------------------------------------------
7417
+ /** 创建平台集成 (chat_bridge:write)。云端控制台与下游 (CrabCode) 调的是同一端点/同一份数据。 */
7418
+ async createIntegration(req, signal) {
7419
+ const resp = await this.client.doJSON(
7420
+ "POST",
7421
+ "/chat-bridge/integrations",
7422
+ {
7423
+ app_id: req.appId,
7424
+ platform: req.platform,
7425
+ region: req.region,
7426
+ workspace_id: req.workspaceId,
7427
+ bot_id: req.botId,
7428
+ config_json: req.configJson
7429
+ },
7430
+ signal
7431
+ );
7432
+ return resp.data;
7433
+ }
7434
+ /** 列出本租户集成 (chat_bridge:read; masked 视图)。可按 appId 过滤。 */
7435
+ async listIntegrations(appId, signal) {
7436
+ const qs = appId ? `?app_id=${encodeURIComponent(appId)}` : "";
7437
+ const resp = await this.client.doJSON(
7438
+ "GET",
7439
+ `/chat-bridge/integrations${qs}`,
7440
+ null,
7441
+ signal
7442
+ );
7443
+ return resp.data?.items ?? [];
7444
+ }
7445
+ /** 取单个集成 (chat_bridge:read)。不存在/跨租户一律 404。 */
7446
+ async getIntegration(id, signal) {
7447
+ const resp = await this.client.doJSON(
7448
+ "GET",
7449
+ `/chat-bridge/integrations/${encodeURIComponent(id)}`,
7450
+ null,
7451
+ signal
7452
+ );
7453
+ return resp.data;
7454
+ }
7455
+ /** 更新集成状态 (chat_bridge:write): pending | active | suspended | revoked。 */
7456
+ async updateIntegrationStatus(id, status, signal) {
7457
+ await this.client.doJSON(
7458
+ "PATCH",
7459
+ `/chat-bridge/integrations/${encodeURIComponent(id)}/status`,
7460
+ { status },
7461
+ signal
7462
+ );
7463
+ }
7464
+ // ---------------------------------------------------------------------------
7465
+ // Credential 管理面 (vault)
7466
+ // ---------------------------------------------------------------------------
7467
+ /** 存凭证 (chat_bridge:write) — 明文一次性提交, 返回 masked 记录 (ref+fingerprint)。 */
7468
+ async storeCredential(integrationId, req, signal) {
7469
+ const resp = await this.client.doJSON(
7470
+ "POST",
7471
+ `/chat-bridge/integrations/${encodeURIComponent(integrationId)}/credentials`,
7472
+ {
7473
+ secret_kind: req.secretKind,
7474
+ plaintext: req.plaintext,
7475
+ region: req.region,
7476
+ platform: req.platform
7477
+ },
7478
+ signal
7479
+ );
7480
+ return brandCredential(resp.data);
7481
+ }
7482
+ /** 列出集成的凭证 (chat_bridge:read; masked, 永不含明文/密文)。 */
7483
+ async listCredentials(integrationId, signal) {
7484
+ const resp = await this.client.doJSON(
7485
+ "GET",
7486
+ `/chat-bridge/integrations/${encodeURIComponent(integrationId)}/credentials`,
7487
+ null,
7488
+ signal
7489
+ );
7490
+ return (resp.data?.items ?? []).map(brandCredential);
7491
+ }
7492
+ /** 轮换凭证 (chat_bridge:rotate, 高风险) — ref 不变, fingerprint 更新。 */
7493
+ async rotateCredential(integrationId, secretKind, newPlaintext, signal) {
7494
+ const resp = await this.client.doJSON(
7495
+ "POST",
7496
+ `/chat-bridge/integrations/${encodeURIComponent(integrationId)}/credentials/rotate`,
7497
+ { secret_kind: secretKind, new_plaintext: newPlaintext },
7498
+ signal
7499
+ );
7500
+ return brandCredential(resp.data);
7501
+ }
7502
+ /** 吊销凭证 (chat_bridge:rotate) — 软吊销 + 服务端抹密文。 */
7503
+ async revokeCredential(credentialRef, signal) {
7504
+ await this.client.doJSON(
7505
+ "POST",
7506
+ `/chat-bridge/credentials/${encodeURIComponent(credentialRef)}/revoke`,
7507
+ {},
7508
+ signal
7509
+ );
7510
+ }
7511
+ };
7512
+ function brandCredential(c) {
7513
+ if (c && typeof c.credentialRef === "string") {
7514
+ return { ...c, credentialRef: asCredentialRef(c.credentialRef) };
7515
+ }
7516
+ return c;
7517
+ }
7518
+
7519
+ exports.AGENT_RUN_META_TITLE = AGENT_RUN_META_TITLE;
7520
+ exports.AGENT_RUN_META_WORKSPACE = AGENT_RUN_META_WORKSPACE;
7197
7521
  exports.ALL_INTEGRATION_STATUS = ALL_INTEGRATION_STATUS;
7198
7522
  exports.ALL_PLATFORMS = ALL_PLATFORMS;
7199
7523
  exports.ALL_REGIONS = ALL_REGIONS;
@@ -7201,9 +7525,11 @@ exports.AgentRunStreamError = AgentRunStreamError;
7201
7525
  exports.AgentRunsClient = AgentRunsClient;
7202
7526
  exports.AudienceEnum = AudienceEnum;
7203
7527
  exports.BillingModeEnum = BillingModeEnum;
7528
+ exports.ChatBridgeClient = ChatBridgeClient;
7204
7529
  exports.Client = Client;
7205
7530
  exports.ComplianceClient = ComplianceClient;
7206
7531
  exports.CompliancePollError = CompliancePollError;
7532
+ exports.CrabCodeByokClient = CrabCodeByokClient;
7207
7533
  exports.DEFAULT_API_TIMEOUT_MS = DEFAULT_API_TIMEOUT_MS;
7208
7534
  exports.DEFAULT_GATEWAY_BASE_URL = DEFAULT_GATEWAY_BASE_URL;
7209
7535
  exports.DefaultRetryPolicy = DefaultRetryPolicy;