@openagentpack/sdk 0.2.0-beta.0 → 0.3.0-beta-e537ab3-20260722

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
@@ -35,9 +35,22 @@ var REQUIRED_METHODS_BY_KIND = {
35
35
  skill: ["createSkill", "updateSkill", "deleteSkill"],
36
36
  agent: ["createAgent", "updateAgent", "deleteAgent"],
37
37
  template: ["createTemplate", "updateTemplate", "archiveTemplate"],
38
- memory_store: ["createMemoryStore", "deleteMemoryStore"],
38
+ memory_store: [
39
+ "createMemoryStore",
40
+ "deleteMemoryStore",
41
+ "listMemoryStores",
42
+ "getMemoryStore",
43
+ "updateMemoryStore",
44
+ "createMemory",
45
+ "listMemories",
46
+ "getMemory",
47
+ "updateMemory",
48
+ "deleteMemory"
49
+ ],
39
50
  deployment: ["createDeployment", "updateDeployment", "deleteDeployment", "runDeployment", "getDeployment"],
40
- session: ["createSession", "listSessions", "getSession", "deleteSession", "sendSessionMessage"]
51
+ session: ["createSession", "listSessions", "getSession", "deleteSession", "sendSessionMessage"],
52
+ identity: ["createIdentity", "updateIdentity", "deleteIdentity"],
53
+ channel: ["createChannel", "updateChannel", "deleteChannel"]
41
54
  };
42
55
 
43
56
  // src/internal/providers/registry.ts
@@ -45,13 +58,13 @@ var registry = /* @__PURE__ */ new Map();
45
58
  function registerProvider(def) {
46
59
  registry.set(def.name, def);
47
60
  }
48
- function validateProviderFacets(def, adapter) {
61
+ function validateProviderFacets(def, adapter2) {
49
62
  const missing = [];
50
63
  for (const [kind, methods] of Object.entries(REQUIRED_METHODS_BY_KIND)) {
51
64
  if (!isSupported(def.capabilities, kind)) continue;
52
- for (const method of methods) {
53
- if (typeof adapter[method] !== "function") {
54
- missing.push(`${kind}.${method}`);
65
+ for (const method2 of methods) {
66
+ if (typeof adapter2[method2] !== "function") {
67
+ missing.push(`${kind}.${method2}`);
55
68
  }
56
69
  }
57
70
  }
@@ -75,9 +88,9 @@ function buildProviders(providersConfig, projectName) {
75
88
  throw new UserError(`Unknown provider '${name}'. Registered: ${Array.from(registry.keys()).join(", ")}`);
76
89
  }
77
90
  const parsed = def.configSchema.parse(rawConfig);
78
- const adapter = def.createAdapter(parsed, projectName);
79
- validateProviderFacets(def, adapter);
80
- adapters.set(name, adapter);
91
+ const adapter2 = def.createAdapter(parsed, projectName);
92
+ validateProviderFacets(def, adapter2);
93
+ adapters.set(name, adapter2);
81
94
  }
82
95
  return adapters;
83
96
  }
@@ -144,9 +157,9 @@ function buildProviderFromEnv(providerName, projectName) {
144
157
  }
145
158
  const config = resolveProviderConfigFromEnv(providerName);
146
159
  const parsed = def.configSchema.parse(config);
147
- const adapter = def.createAdapter(parsed, projectName);
148
- validateProviderFacets(def, adapter);
149
- return adapter;
160
+ const adapter2 = def.createAdapter(parsed, projectName);
161
+ validateProviderFacets(def, adapter2);
162
+ return adapter2;
150
163
  }
151
164
 
152
165
  // src/internal/providers/claude/adapter.ts
@@ -285,6 +298,7 @@ var BaseApiClient = class {
285
298
  buffer = buffer.slice(boundary + 2);
286
299
  boundary = buffer.indexOf("\n\n");
287
300
  const dataLines = [];
301
+ let sseId;
288
302
  for (const line of frame.split("\n")) {
289
303
  if (line.startsWith(":")) continue;
290
304
  if (line.startsWith("event:") && line.slice(6).trim() === "heartbeat") {
@@ -294,11 +308,18 @@ var BaseApiClient = class {
294
308
  if (line.startsWith("data:")) {
295
309
  dataLines.push(line.slice(5).trimStart());
296
310
  }
311
+ if (line.startsWith("id:")) {
312
+ sseId = line.slice(3).trimStart();
313
+ }
297
314
  }
298
315
  if (dataLines.length === 0) continue;
299
316
  const json = dataLines.join("\n");
300
317
  try {
301
- yield JSON.parse(json);
318
+ const parsed = JSON.parse(json);
319
+ if (sseId !== void 0 && parsed.id === void 0) {
320
+ parsed.id = sseId;
321
+ }
322
+ yield parsed;
302
323
  } catch {
303
324
  }
304
325
  }
@@ -352,6 +373,216 @@ function toRemoteResource(res) {
352
373
  };
353
374
  }
354
375
 
376
+ // src/internal/providers/memory-api.ts
377
+ function query(path, values) {
378
+ const params = new URLSearchParams();
379
+ for (const [key, value] of Object.entries(values)) {
380
+ if (value !== void 0 && value !== null) params.set(key, String(value));
381
+ }
382
+ const encoded = params.toString();
383
+ return encoded ? `${path}?${encoded}` : path;
384
+ }
385
+ function canonicalPath(path) {
386
+ return path.replace(/^\/+/, "");
387
+ }
388
+ function providerPath(path, style) {
389
+ const relative = canonicalPath(path);
390
+ return style === "absolute" ? `/${relative}` : relative;
391
+ }
392
+ function page(raw, map) {
393
+ const body = raw;
394
+ const data = (body.data ?? body.items ?? body.memories ?? body.memory_stores ?? body.memory_versions ?? []).map(map);
395
+ const next = body.next_cursor ?? body.next_page ?? body.last_id;
396
+ return { data, has_more: Boolean(body.has_more ?? next), ...next ? { next_cursor: next } : {} };
397
+ }
398
+ function mapMemoryStore(raw) {
399
+ return {
400
+ id: String(raw.id),
401
+ type: "memory_store",
402
+ name: String(raw.name ?? ""),
403
+ description: String(raw.description ?? ""),
404
+ metadata: raw.metadata ?? {},
405
+ ...raw.status ? { status: String(raw.status) } : {},
406
+ ...typeof (raw.entry_count ?? raw.memory_count) === "number" ? { entry_count: Number(raw.entry_count ?? raw.memory_count) } : {},
407
+ ...typeof (raw.total_size ?? raw.storage_bytes) === "number" ? { total_size: Number(raw.total_size ?? raw.storage_bytes) } : {},
408
+ ...typeof raw.session_count === "number" ? { session_count: raw.session_count } : {},
409
+ created_by: raw.created_by,
410
+ created_at: String(raw.created_at ?? ""),
411
+ updated_at: String(raw.updated_at ?? raw.created_at ?? ""),
412
+ archived_at: raw.archived_at ?? null
413
+ };
414
+ }
415
+ function mapMemory(raw) {
416
+ return {
417
+ id: String(raw.id),
418
+ type: "memory",
419
+ memory_store_id: String(raw.memory_store_id ?? raw.store_id ?? ""),
420
+ path: canonicalPath(String(raw.path ?? "")),
421
+ content: raw.content,
422
+ content_size_bytes: Number(raw.content_size_bytes ?? raw.size ?? 0),
423
+ content_sha256: String(raw.content_sha256 ?? ""),
424
+ ...typeof raw.version === "number" ? { version: raw.version } : {},
425
+ ...raw.memory_version_id ? { memory_version_id: String(raw.memory_version_id) } : {},
426
+ metadata: raw.metadata ?? {},
427
+ created_by: raw.created_by,
428
+ created_at: String(raw.created_at ?? ""),
429
+ updated_at: String(raw.updated_at ?? raw.created_at ?? "")
430
+ };
431
+ }
432
+ function mapMemoryListItem(raw) {
433
+ if (raw.type === "memory_prefix") return { type: "memory_prefix", path: canonicalPath(String(raw.path ?? "")) };
434
+ return mapMemory(raw);
435
+ }
436
+ function mapMemoryVersion(raw) {
437
+ const operation = String(raw.operation ?? raw.action ?? "updated");
438
+ return {
439
+ id: String(raw.id),
440
+ type: "memory_version",
441
+ memory_store_id: String(raw.memory_store_id ?? raw.store_id ?? ""),
442
+ memory_id: String(raw.memory_id ?? raw.entry_id ?? ""),
443
+ path: (raw.path ?? raw.entry_path) == null ? raw.path ?? raw.entry_path : canonicalPath(String(raw.path ?? raw.entry_path)),
444
+ content: raw.content,
445
+ content_size_bytes: raw.content_size_bytes ?? raw.size,
446
+ content_sha256: raw.content_sha256,
447
+ operation: operation === "modified" ? "updated" : operation,
448
+ ...typeof raw.version === "number" ? { version: raw.version } : {},
449
+ ...typeof raw.redacted === "boolean" ? { redacted: raw.redacted } : {},
450
+ redacted_at: raw.redacted_at,
451
+ created_by: raw.created_by,
452
+ created_at: String(raw.created_at ?? "")
453
+ };
454
+ }
455
+ var ProviderMemoryApi = class {
456
+ constructor(client, dialect) {
457
+ this.client = client;
458
+ this.dialect = dialect;
459
+ }
460
+ client;
461
+ dialect;
462
+ async listStores(options = {}) {
463
+ const raw = await this.client.get(
464
+ query("/memory_stores", {
465
+ limit: options.limit,
466
+ [this.dialect.cursorParam]: options.cursor,
467
+ include_archived: this.dialect.supportsIncludeArchived ? options.include_archived : void 0
468
+ })
469
+ );
470
+ return page(raw, mapMemoryStore);
471
+ }
472
+ async getStore(id) {
473
+ return mapMemoryStore(await this.client.get(`/memory_stores/${id}`));
474
+ }
475
+ async updateStore(id, input) {
476
+ let body = { ...input };
477
+ if (this.dialect.storeMetadataMode === "merge_patch" && input.metadata !== void 0) {
478
+ const current = await this.getStore(id);
479
+ body = {
480
+ ...input,
481
+ metadata: {
482
+ ...Object.fromEntries(Object.keys(current.metadata).map((key) => [key, null])),
483
+ ...input.metadata
484
+ }
485
+ };
486
+ }
487
+ return mapMemoryStore(await this.client.post(`/memory_stores/${id}`, body));
488
+ }
489
+ async archiveStore(id) {
490
+ return mapMemoryStore(await this.client.post(`/memory_stores/${id}/archive`, {}));
491
+ }
492
+ async createMemory(storeId, input) {
493
+ const body = {
494
+ path: providerPath(input.path, this.dialect.pathStyle),
495
+ content: input.content,
496
+ ...this.dialect.supportsMemoryMetadata && input.metadata ? { metadata: input.metadata } : {}
497
+ };
498
+ return mapMemory(await this.client.post(`/memory_stores/${storeId}/memories`, body));
499
+ }
500
+ async listMemories(storeId, options = {}) {
501
+ const raw = await this.client.get(
502
+ query(`/memory_stores/${storeId}/memories`, {
503
+ limit: options.limit,
504
+ [this.dialect.cursorParam]: options.cursor,
505
+ [this.dialect.prefixParam]: options.prefix ? providerPath(options.prefix, this.dialect.pathStyle) : void 0,
506
+ depth: options.depth,
507
+ view: this.dialect.supportsView ? options.view : void 0
508
+ })
509
+ );
510
+ return page(raw, mapMemoryListItem);
511
+ }
512
+ async getMemory(storeId, memoryId) {
513
+ const path = `/memory_stores/${storeId}/memories/${memoryId}${this.dialect.supportsView ? "?view=full" : ""}`;
514
+ return mapMemory(await this.client.get(path));
515
+ }
516
+ async updateMemory(storeId, memoryId, input) {
517
+ const { expected_content_sha256, ...values } = input;
518
+ const body = {
519
+ ...values.content !== void 0 ? { content: values.content } : {},
520
+ ...this.dialect.supportsMemoryMetadata && values.metadata ? { metadata: values.metadata } : {},
521
+ ...this.dialect.supportsPathUpdate !== false && values.path ? { path: providerPath(values.path, this.dialect.pathStyle) } : {}
522
+ };
523
+ if (expected_content_sha256 && this.dialect.updatePrecondition !== "none") {
524
+ if (this.dialect.updatePrecondition === "precondition") {
525
+ body.precondition = { type: "content_sha256", content_sha256: expected_content_sha256 };
526
+ } else {
527
+ body[this.dialect.updatePrecondition] = expected_content_sha256;
528
+ }
529
+ }
530
+ const path = `/memory_stores/${storeId}/memories/${memoryId}${this.dialect.supportsView ? "?view=full" : ""}`;
531
+ const raw = await this.client.post(path, body);
532
+ return mapMemory(raw);
533
+ }
534
+ async deleteMemory(storeId, memoryId, expected) {
535
+ await this.client.delete(
536
+ query(`/memory_stores/${storeId}/memories/${memoryId}`, {
537
+ expected_content_sha256: this.dialect.supportsDeletePrecondition ? expected : void 0
538
+ })
539
+ );
540
+ }
541
+ async listVersions(storeId, options = {}) {
542
+ const segment = this.dialect.versionsSegment ?? "memory_versions";
543
+ const raw = await this.client.get(
544
+ query(`/memory_stores/${storeId}/${segment}`, {
545
+ limit: options.limit,
546
+ [this.dialect.cursorParam]: options.cursor,
547
+ memory_id: options.memory_id,
548
+ view: this.dialect.supportsView ? options.view : void 0
549
+ })
550
+ );
551
+ return page(raw, mapMemoryVersion);
552
+ }
553
+ async getVersion(storeId, versionId) {
554
+ const segment = this.dialect.versionsSegment ?? "memory_versions";
555
+ return mapMemoryVersion(
556
+ await this.client.get(
557
+ `/memory_stores/${storeId}/${segment}/${versionId}${this.dialect.supportsView ? "?view=full" : ""}`
558
+ )
559
+ );
560
+ }
561
+ async redactVersion(storeId, versionId) {
562
+ const segment = this.dialect.versionsSegment ?? "memory_versions";
563
+ return mapMemoryVersion(
564
+ await this.client.post(`/memory_stores/${storeId}/${segment}/${versionId}/redact`, {})
565
+ );
566
+ }
567
+ async batchCreateMemories(storeId, input) {
568
+ const body = {
569
+ items: input.items.map((item) => ({
570
+ path: providerPath(item.path, this.dialect.pathStyle),
571
+ content: item.content
572
+ })),
573
+ on_conflict: input.on_conflict
574
+ };
575
+ const raw = await this.client.post(`/memory_stores/${storeId}/memories/batch_create`, body);
576
+ return {
577
+ results: (raw.results ?? []).map((item) => ({
578
+ path: canonicalPath(item.path),
579
+ ...item.memory ? { memory: mapMemory(item.memory) } : {},
580
+ ...item.error ? { error: item.error } : {}
581
+ }))
582
+ };
583
+ }
584
+ };
585
+
355
586
  // src/internal/providers/session-event-response.ts
356
587
  async function listSessionEventsPaged(client, sessionId, options, toEvent, config) {
357
588
  const params = new URLSearchParams();
@@ -626,8 +857,193 @@ function stripAgentsMetadata(value) {
626
857
  return Object.keys(out).length > 0 ? out : void 0;
627
858
  }
628
859
 
860
+ // src/internal/utils/sandbox-mount.ts
861
+ var PROVIDER_MOUNT_PREFIXES = {
862
+ qoder: "/data",
863
+ claude: "/workspace",
864
+ bailian: "/mnt",
865
+ ark: "/mnt"
866
+ };
867
+ function joinAbsolute(prefix, sub) {
868
+ const left = prefix.replace(/\/+$/, "");
869
+ const right = sub.replace(/^\/+/, "");
870
+ return `${left}/${right}`;
871
+ }
872
+ function quoteShellWord(value) {
873
+ return `'${value.replaceAll("'", `'"'"'`)}'`;
874
+ }
875
+ function stripUrlQueryAndFragment(value) {
876
+ const queryIndex = value.indexOf("?");
877
+ const fragmentIndex = value.indexOf("#");
878
+ if (queryIndex === -1) {
879
+ return fragmentIndex === -1 ? value : value.slice(0, fragmentIndex);
880
+ }
881
+ if (fragmentIndex === -1) return value.slice(0, queryIndex);
882
+ return value.slice(0, Math.min(queryIndex, fragmentIndex));
883
+ }
884
+ function stripGitSuffix(value) {
885
+ return value.toLowerCase().endsWith(".git") ? value.slice(0, -4) : value;
886
+ }
887
+ function lastRemotePathSegment(value) {
888
+ const lastSlash = value.lastIndexOf("/");
889
+ const lastColon = value.lastIndexOf(":");
890
+ return value.slice(Math.max(lastSlash, lastColon) + 1).trim();
891
+ }
892
+ function providerMountPrefix(provider) {
893
+ return PROVIDER_MOUNT_PREFIXES[provider];
894
+ }
895
+ function resolveSandboxMountPath(provider, mountPath) {
896
+ const prefix = providerMountPrefix(provider);
897
+ if (!prefix) return mountPath;
898
+ if (mountPath === prefix || mountPath.startsWith(`${prefix}/`)) return mountPath;
899
+ if (mountPath.startsWith("/")) {
900
+ throw new UserError(`${provider} mount_path must start with '${prefix}/'; received '${mountPath}'.`);
901
+ }
902
+ return joinAbsolute(prefix, mountPath);
903
+ }
904
+ function resolveRepositoryMountPath(provider, resource) {
905
+ const prefix = providerMountPrefix(provider);
906
+ if (!prefix) throw new UserError(`Provider '${provider}' has no declared mount path prefix.`);
907
+ if (resource.mount_path) {
908
+ if (resource.mount_path !== prefix && !resource.mount_path.startsWith(`${prefix}/`)) {
909
+ throw new UserError(`${provider} Git repository Session resource mount_path must start with '${prefix}/'.`);
910
+ }
911
+ return resource.mount_path;
912
+ }
913
+ const repositoryName = stripGitSuffix(lastRemotePathSegment(stripUrlQueryAndFragment(resource.url)));
914
+ if (!repositoryName) {
915
+ throw new UserError(`Cannot derive a ${provider} Git repository mount path from URL '${resource.url}'.`);
916
+ }
917
+ return provider === "qoder" ? `${prefix}/workspace/${repositoryName}` : `${prefix}/${repositoryName}`;
918
+ }
919
+ function composeFileMountHint(files, provider) {
920
+ if (!files || files.length === 0) return "";
921
+ const lines = files.map((f) => `- ${resolveSandboxMountPath(provider, f.mount_path)}`);
922
+ return [
923
+ "The user uploaded files. They are available at the following sandbox paths:",
924
+ ...lines,
925
+ "Read them from these paths when relevant."
926
+ ].join("\n");
927
+ }
928
+ function prependFileHint(prompt, files, provider) {
929
+ const hint = composeFileMountHint(files, provider);
930
+ if (!hint) return prompt;
931
+ return `${hint}
932
+
933
+ ${prompt}`;
934
+ }
935
+ var FILE_MENTION_START = "\u27E6file:";
936
+ var FILE_MENTION_END = "\u27E7";
937
+ function rewriteFileMentions(prompt, provider) {
938
+ let cursor = 0;
939
+ let rewritten = "";
940
+ while (cursor < prompt.length) {
941
+ const start = prompt.indexOf(FILE_MENTION_START, cursor);
942
+ if (start === -1) {
943
+ rewritten += prompt.slice(cursor);
944
+ break;
945
+ }
946
+ const mountPathStart = start + FILE_MENTION_START.length;
947
+ const end = prompt.indexOf(FILE_MENTION_END, mountPathStart);
948
+ if (end === -1) {
949
+ rewritten += prompt.slice(cursor);
950
+ break;
951
+ }
952
+ rewritten += prompt.slice(cursor, start);
953
+ rewritten += resolveSandboxMountPath(provider, prompt.slice(mountPathStart, end));
954
+ cursor = end + FILE_MENTION_END.length;
955
+ }
956
+ return rewritten;
957
+ }
958
+ function preparePromptForProvider(prompt, files, provider) {
959
+ return prependFileHint(rewriteFileMentions(prompt, provider), files, provider);
960
+ }
961
+ function prepareInitialSessionPrompt(prompt, bindings, provider) {
962
+ const prepared = preparePromptForProvider(prompt, bindings.files, provider);
963
+ const repositories = (bindings.resources ?? []).filter(
964
+ (resource) => resource.type === "github_repository"
965
+ );
966
+ if (repositories.length === 0) return prepared;
967
+ const paths = repositories.map((resource) => resolveRepositoryMountPath(provider, resource));
968
+ if (paths.length === 1) {
969
+ const path = paths[0];
970
+ return [
971
+ `The Git working tree for this task is mounted at \`${path}\`.`,
972
+ "Work only inside this directory unless the user explicitly requests otherwise.",
973
+ "Prefix every shell command with:",
974
+ `cd -- ${quoteShellWord(path)} &&`,
975
+ `Use absolute paths under \`${path}\` for non-shell file tools.`,
976
+ "",
977
+ prepared
978
+ ].join("\n");
979
+ }
980
+ const lines = ["Git working trees for this task are mounted at:", ...paths.map((path) => `- ${path}`)];
981
+ lines.push("Choose the appropriate working tree for the task before inspecting or modifying files.");
982
+ return `${lines.join("\n")}
983
+
984
+ ${prepared}`;
985
+ }
986
+
987
+ // src/internal/utils/tool-permissions.ts
988
+ function canonicalToolName(name) {
989
+ return name.trim().replace(/[^a-zA-Z0-9]+/g, "").toLowerCase();
990
+ }
991
+ function resolveBuiltinTools(tools, options = {}) {
992
+ const permissionByName = /* @__PURE__ */ new Map();
993
+ for (const [name, permission] of Object.entries(tools.permissions ?? {})) {
994
+ permissionByName.set(canonicalToolName(name), permission);
995
+ }
996
+ const supportedByName = options.supportedWireNames ? new Map([...options.supportedWireNames].map((name) => [canonicalToolName(name), name])) : void 0;
997
+ return tools.builtin.flatMap((configuredName) => {
998
+ const candidate = options.toWireName?.(configuredName) ?? configuredName;
999
+ const wireName = supportedByName?.get(canonicalToolName(candidate)) ?? (supportedByName ? void 0 : candidate);
1000
+ if (!wireName) return [];
1001
+ return [
1002
+ {
1003
+ configuredName,
1004
+ wireName,
1005
+ permission: permissionByName.get(canonicalToolName(configuredName)) ?? tools.default_permission ?? "allow"
1006
+ }
1007
+ ];
1008
+ });
1009
+ }
1010
+ function toPermissionPolicy(permission) {
1011
+ return { type: permission === "ask" ? "always_ask" : "always_allow" };
1012
+ }
1013
+ function permissionOverridesFromWire(configs, toConfigName = (name) => name) {
1014
+ const permissions = {};
1015
+ for (const config of configs) {
1016
+ if (config.enabled === false) continue;
1017
+ const rawPolicy = config.permission_policy;
1018
+ const type = typeof rawPolicy === "string" ? rawPolicy : rawPolicy && typeof rawPolicy === "object" ? rawPolicy.type : void 0;
1019
+ if (type === "always_ask") permissions[toConfigName(config.name)] = "ask";
1020
+ else if (type === "always_allow") permissions[toConfigName(config.name)] = "allow";
1021
+ }
1022
+ return Object.keys(permissions).length ? permissions : void 0;
1023
+ }
1024
+
1025
+ // src/internal/providers/session-resource-mapper.ts
1026
+ function resolveGithubRepositoryMountPath(provider, resource) {
1027
+ return resolveRepositoryMountPath(provider, resource);
1028
+ }
1029
+ function mapGithubRepositorySessionResource(resource, options = {}) {
1030
+ const entry = {
1031
+ type: "github_repository",
1032
+ url: options.mapUrl?.(resource.url) ?? resource.url,
1033
+ authorization_token: resource.authorization_token
1034
+ };
1035
+ if (resource.checkout?.branch) entry.checkout = { type: "branch", name: resource.checkout.branch };
1036
+ else if (resource.checkout?.commit) entry.checkout = { type: "commit", sha: resource.checkout.commit };
1037
+ const mountPath = options.mapMountPath?.(resource) ?? resource.mount_path;
1038
+ if (mountPath) entry.mount_path = mountPath;
1039
+ return entry;
1040
+ }
1041
+
629
1042
  // src/internal/providers/claude/mapper.ts
630
1043
  var CLAUDE_BUILTINS = /* @__PURE__ */ new Set(["read", "write", "edit", "bash", "glob", "grep", "web_search", "web_fetch"]);
1044
+ function normalizeGithubRepositoryUrlForClaude(url) {
1045
+ return url.replace(/\.git\/?$/, "");
1046
+ }
631
1047
  function credToDecl(raw, vaultName) {
632
1048
  const auth = raw.auth ?? {};
633
1049
  const name = raw.display_name || raw.id || "credential";
@@ -698,6 +1114,7 @@ function agentToDecl(raw) {
698
1114
  const skills = raw.skills;
699
1115
  const multiagent = raw.multiagent;
700
1116
  let builtinTools;
1117
+ let builtinPermissions;
701
1118
  let allToolsEnabled = false;
702
1119
  if (tools?.length) {
703
1120
  const toolset = tools.find((t) => t.type === "agent_toolset_20260401");
@@ -706,6 +1123,7 @@ function agentToDecl(raw) {
706
1123
  const configs = toolset.configs ?? [];
707
1124
  if (configs.length > 0) {
708
1125
  builtinTools = configs.filter((c) => c.enabled !== false).map((c) => c.name);
1126
+ builtinPermissions = permissionOverridesFromWire(configs);
709
1127
  } else if (defaultConfig?.enabled) {
710
1128
  allToolsEnabled = true;
711
1129
  }
@@ -732,7 +1150,7 @@ function agentToDecl(raw) {
732
1150
  }
733
1151
  let toolsDecl;
734
1152
  if (builtinTools?.length) {
735
- toolsDecl = { builtin: builtinTools };
1153
+ toolsDecl = { builtin: builtinTools, permissions: builtinPermissions };
736
1154
  } else if (allToolsEnabled) {
737
1155
  toolsDecl = {
738
1156
  builtin: ["read", "write", "edit", "bash", "glob", "grep", "web_search", "web_fetch"]
@@ -792,16 +1210,11 @@ function mapAgent(name, decl, refs, version, projectName) {
792
1210
  body.metadata = decl.metadata;
793
1211
  }
794
1212
  if (decl.tools) {
795
- const toolConfigs = decl.tools.builtin.filter((toolName) => CLAUDE_BUILTINS.has(toolName)).map((toolName) => {
796
- const permission = decl.tools?.permissions?.[toolName] ?? "allow";
797
- return {
798
- name: toolName,
799
- enabled: true,
800
- permission_policy: {
801
- type: permission === "ask" ? "always_ask" : "always_allow"
802
- }
803
- };
804
- });
1213
+ const toolConfigs = resolveBuiltinTools(decl.tools, { supportedWireNames: CLAUDE_BUILTINS }).map((tool) => ({
1214
+ name: tool.wireName,
1215
+ enabled: true,
1216
+ permission_policy: toPermissionPolicy(tool.permission)
1217
+ }));
805
1218
  body.tools = [
806
1219
  {
807
1220
  type: "agent_toolset_20260401",
@@ -867,6 +1280,23 @@ function mapDeployment(name, decl, refs, projectName, uploadedFiles) {
867
1280
  }
868
1281
  return body;
869
1282
  }
1283
+ function mapDeploymentUpdate(name, decl, refs, projectName, uploadedFiles, existingMetadata) {
1284
+ const body = mapDeployment(name, decl, refs, projectName, uploadedFiles);
1285
+ body.vault_ids = refs.vault_ids;
1286
+ body.resources = mapDeploymentResources(decl, refs, uploadedFiles);
1287
+ if (decl.schedule) {
1288
+ body.schedule = { type: "cron", expression: decl.schedule.expression, timezone: decl.schedule.timezone };
1289
+ }
1290
+ body.description = decl.description ?? "";
1291
+ const desiredMetadata = projectName ? injectMetadata(decl.metadata, projectName, name) : decl.metadata ?? {};
1292
+ body.metadata = {
1293
+ ...Object.fromEntries(
1294
+ Object.keys(existingMetadata ?? {}).filter((key) => !(key in desiredMetadata)).map((key) => [key, null])
1295
+ ),
1296
+ ...desiredMetadata
1297
+ };
1298
+ return body;
1299
+ }
870
1300
  function mapInitialEvents(events) {
871
1301
  return events.map((ev) => {
872
1302
  if (ev.type === "user.message" || ev.type === "system.message") {
@@ -900,7 +1330,7 @@ function mapDeploymentResources(decl, refs, uploadedFiles) {
900
1330
  } else if (r.type === "github_repository") {
901
1331
  const entry = {
902
1332
  type: "github_repository",
903
- url: r.url
1333
+ url: normalizeGithubRepositoryUrlForClaude(r.url)
904
1334
  };
905
1335
  if (r.authorization_token) entry.authorization_token = r.authorization_token;
906
1336
  if (r.checkout?.branch) {
@@ -1029,8 +1459,16 @@ function mapSession(bindings) {
1029
1459
  resources.push({
1030
1460
  type: "file",
1031
1461
  file_id: f.file_id,
1032
- mount_path: f.mount_path
1462
+ mount_path: resolveSandboxMountPath("claude", f.mount_path)
1033
1463
  });
1464
+ for (const resource of bindings.resources ?? []) {
1465
+ resources.push(
1466
+ mapGithubRepositorySessionResource(resource, {
1467
+ mapUrl: normalizeGithubRepositoryUrlForClaude,
1468
+ mapMountPath: (item) => resolveGithubRepositoryMountPath("claude", item)
1469
+ })
1470
+ );
1471
+ }
1034
1472
  if (resources.length) body.resources = resources;
1035
1473
  return body;
1036
1474
  }
@@ -1039,10 +1477,30 @@ function mapSession(bindings) {
1039
1477
  var ClaudeAdapter = class _ClaudeAdapter {
1040
1478
  name = "claude";
1041
1479
  eventResume = false;
1480
+ memoryCapabilities = {
1481
+ archive_store: true,
1482
+ batch_create: false,
1483
+ versions: true,
1484
+ optimistic_concurrency: true,
1485
+ memory_metadata: false
1486
+ };
1042
1487
  client;
1488
+ memoryClient;
1489
+ memoryApi;
1043
1490
  projectName;
1044
1491
  constructor(apiKey, beta, projectName) {
1045
1492
  this.client = new ClaudeClient({ apiKey, beta });
1493
+ this.memoryClient = new ClaudeClient({ apiKey, beta: "agent-memory-2026-07-22" });
1494
+ this.memoryApi = new ProviderMemoryApi(this.memoryClient, {
1495
+ pathStyle: "absolute",
1496
+ cursorParam: "page",
1497
+ updatePrecondition: "precondition",
1498
+ prefixParam: "path_prefix",
1499
+ supportsView: true,
1500
+ supportsMemoryMetadata: false,
1501
+ supportsDeletePrecondition: true,
1502
+ supportsIncludeArchived: true
1503
+ });
1046
1504
  this.projectName = projectName ?? "";
1047
1505
  }
1048
1506
  async validate() {
@@ -1058,7 +1516,13 @@ var ClaudeAdapter = class _ClaudeAdapter {
1058
1516
  file: "/files"
1059
1517
  };
1060
1518
  async findResource(type, name, id) {
1061
- const raw = await locateRemote(this.client, _ClaudeAdapter.ENDPOINT_MAP[type], name, id, notArchived);
1519
+ const raw = await locateRemote(
1520
+ type === "memory_store" ? this.memoryClient : this.client,
1521
+ _ClaudeAdapter.ENDPOINT_MAP[type],
1522
+ name,
1523
+ id,
1524
+ notArchived
1525
+ );
1062
1526
  return raw ? toRemoteResource(raw) : null;
1063
1527
  }
1064
1528
  async listAgents(filter) {
@@ -1191,6 +1655,62 @@ var ClaudeAdapter = class _ClaudeAdapter {
1191
1655
  async deleteAgent(id) {
1192
1656
  await this.client.post(`/agents/${id}/archive`, {});
1193
1657
  }
1658
+ async createMemoryStore(name, decl) {
1659
+ const res = await this.memoryClient.post("/memory_stores", {
1660
+ name,
1661
+ description: decl.description,
1662
+ metadata: decl.metadata
1663
+ });
1664
+ const storeId = String(res.id);
1665
+ try {
1666
+ for (const entry of decl.entries ?? []) {
1667
+ await this.memoryApi.createMemory(storeId, { path: entry.key, content: entry.content });
1668
+ }
1669
+ } catch (error) {
1670
+ await this.memoryClient.delete(`/memory_stores/${storeId}`).catch(() => void 0);
1671
+ throw error;
1672
+ }
1673
+ return toRemoteResource(res);
1674
+ }
1675
+ async deleteMemoryStore(id) {
1676
+ await this.memoryClient.delete(`/memory_stores/${id}`);
1677
+ }
1678
+ listMemoryStores(options) {
1679
+ return this.memoryApi.listStores(options);
1680
+ }
1681
+ getMemoryStore(id) {
1682
+ return this.memoryApi.getStore(id);
1683
+ }
1684
+ updateMemoryStore(id, input) {
1685
+ return this.memoryApi.updateStore(id, input);
1686
+ }
1687
+ archiveMemoryStore(id) {
1688
+ return this.memoryApi.archiveStore(id);
1689
+ }
1690
+ createMemory(storeId, input) {
1691
+ return this.memoryApi.createMemory(storeId, input);
1692
+ }
1693
+ listMemories(storeId, options) {
1694
+ return this.memoryApi.listMemories(storeId, options);
1695
+ }
1696
+ getMemory(storeId, memoryId) {
1697
+ return this.memoryApi.getMemory(storeId, memoryId);
1698
+ }
1699
+ updateMemory(storeId, memoryId, input) {
1700
+ return this.memoryApi.updateMemory(storeId, memoryId, input);
1701
+ }
1702
+ deleteMemory(storeId, memoryId, expected) {
1703
+ return this.memoryApi.deleteMemory(storeId, memoryId, expected);
1704
+ }
1705
+ listMemoryVersions(storeId, options) {
1706
+ return this.memoryApi.listVersions(storeId, options);
1707
+ }
1708
+ getMemoryVersion(storeId, versionId) {
1709
+ return this.memoryApi.getVersion(storeId, versionId);
1710
+ }
1711
+ redactMemoryVersion(storeId, versionId) {
1712
+ return this.memoryApi.redactVersion(storeId, versionId);
1713
+ }
1194
1714
  async createDeployment(name, decl, refs, basePath) {
1195
1715
  const uploaded = await this.uploadDeploymentFiles(decl, basePath);
1196
1716
  const body = mapDeployment(name, decl, refs, this.projectName, uploaded);
@@ -1199,7 +1719,20 @@ var ClaudeAdapter = class _ClaudeAdapter {
1199
1719
  }
1200
1720
  async updateDeployment(id, name, decl, refs, basePath) {
1201
1721
  const uploaded = await this.uploadDeploymentFiles(decl, basePath);
1202
- const body = mapDeployment(name, decl, refs, this.projectName, uploaded);
1722
+ const current = await this.client.get(`/deployments/${id}`);
1723
+ if (current.schedule && !decl.schedule) {
1724
+ throw new UserError(
1725
+ `Deployment '${name}' cannot remove its schedule through the documented Claude update API; archive and recreate it as a manual deployment.`
1726
+ );
1727
+ }
1728
+ const body = mapDeploymentUpdate(
1729
+ name,
1730
+ decl,
1731
+ refs,
1732
+ this.projectName,
1733
+ uploaded,
1734
+ current.metadata
1735
+ );
1203
1736
  const res = await this.client.post(`/deployments/${id}`, body);
1204
1737
  return toRemoteResource(res);
1205
1738
  }
@@ -1251,6 +1784,36 @@ var ClaudeAdapter = class _ClaudeAdapter {
1251
1784
  attributes: res
1252
1785
  };
1253
1786
  }
1787
+ async listDeployments(filter) {
1788
+ const params = new URLSearchParams();
1789
+ if (filter?.agent_id) params.set("agent_id", filter.agent_id);
1790
+ if (filter?.status) params.set("status", filter.status);
1791
+ if (filter?.include_archived) params.set("include_archived", "true");
1792
+ if (filter?.limit) params.set("limit", String(filter.limit));
1793
+ if (filter?.page) params.set("page", filter.page);
1794
+ if (filter?.created_at_gte) params.set("created_at[gte]", filter.created_at_gte);
1795
+ if (filter?.created_at_lte) params.set("created_at[lte]", filter.created_at_lte);
1796
+ const query2 = params.toString();
1797
+ const res = await this.client.get(`/deployments${query2 ? `?${query2}` : ""}`);
1798
+ const nextPage = res.next_page ?? void 0;
1799
+ return {
1800
+ deployments: (res.data ?? []).map(toDeploymentInfo),
1801
+ has_more: nextPage !== void 0,
1802
+ next_page: nextPage
1803
+ };
1804
+ }
1805
+ async pauseDeployment(ctx) {
1806
+ return this.setDeploymentPaused(ctx, true);
1807
+ }
1808
+ async unpauseDeployment(ctx) {
1809
+ return this.setDeploymentPaused(ctx, false);
1810
+ }
1811
+ async setDeploymentPaused(ctx, paused) {
1812
+ if (!ctx.id) throw new UserError(`Deployment '${ctx.name}' has no remote id; run \`agents apply\` first.`);
1813
+ const action = paused ? "pause" : "unpause";
1814
+ const res = await this.client.post(`/deployments/${ctx.id}/${action}`, {});
1815
+ return toDeploymentInfo(res);
1816
+ }
1254
1817
  async createSession(bindings) {
1255
1818
  if (bindings.delivery === "forward") throw new UserError("Claude does not support Forward sessions.");
1256
1819
  const body = mapSession(bindings);
@@ -1322,6 +1885,16 @@ var ClaudeAdapter = class _ClaudeAdapter {
1322
1885
  await this.client.delete(`/files/${id}`);
1323
1886
  }
1324
1887
  };
1888
+ function toDeploymentInfo(res) {
1889
+ const sched = res.schedule;
1890
+ return {
1891
+ id: res.id ?? null,
1892
+ status: res.status ?? "unknown",
1893
+ paused_reason: res.paused_reason ?? void 0,
1894
+ schedule: sched ? { expression: sched.expression, timezone: sched.timezone } : void 0,
1895
+ attributes: res
1896
+ };
1897
+ }
1325
1898
  function toSessionInfo(res) {
1326
1899
  return buildSessionInfo(
1327
1900
  res,
@@ -1353,15 +1926,13 @@ var CLAUDE_CAPABILITIES = {
1353
1926
  skill: { tier: "native", reason: "skills API with files[] upload" },
1354
1927
  agent: { tier: "native", reason: "managed agents API" },
1355
1928
  template: { tier: "unsupported", reason: "no Forward Template equivalent on Claude" },
1356
- memory_store: {
1357
- tier: "unsupported",
1358
- reason: "Claude exposes Memory Stores, but the OpenAgentPack adapter has not implemented them yet",
1359
- remediation: "use skill knowledge or MCP until Claude Memory Store support is added to the adapter"
1360
- },
1929
+ memory_store: { tier: "native", reason: "beta memory_stores API" },
1361
1930
  mcp_server: { tier: "native", reason: "mcp_servers field on agent" },
1362
1931
  multiagent: { tier: "native", reason: "coordinator + roster topology" },
1363
1932
  deployment: { tier: "native", reason: "deployments API" },
1364
- session: { tier: "native", reason: "sessions API" }
1933
+ session: { tier: "native", reason: "sessions API" },
1934
+ identity: { tier: "unsupported", reason: "no mapped Identity primitive on Claude" },
1935
+ channel: { tier: "unsupported", reason: "no mapped messaging Channel primitive on Claude" }
1365
1936
  };
1366
1937
 
1367
1938
  // src/internal/providers/claude/config.ts
@@ -1376,6 +1947,7 @@ registerProvider({
1376
1947
  name: "claude",
1377
1948
  configSchema: claudeConfigSchema,
1378
1949
  capabilities: CLAUDE_CAPABILITIES,
1950
+ features: { tool_permissions: true, session_resources: ["github_repository"] },
1379
1951
  createAdapter: (config, projectName) => {
1380
1952
  const c = config;
1381
1953
  return new ClaudeAdapter(c.api_key, c.beta, projectName);
@@ -1384,7 +1956,7 @@ registerProvider({
1384
1956
 
1385
1957
  // src/internal/providers/qoder/adapter.ts
1386
1958
  import { readFileSync as readFileSync2 } from "fs";
1387
- import { basename as basename3, dirname as dirname2, resolve as resolve2 } from "path";
1959
+ import { basename as basename2, dirname as dirname2, resolve as resolve2 } from "path";
1388
1960
  import JSZip2 from "jszip";
1389
1961
 
1390
1962
  // src/internal/providers/qoder/client.ts
@@ -1409,57 +1981,6 @@ var QoderClient = class extends BaseApiClient {
1409
1981
  }
1410
1982
  };
1411
1983
 
1412
- // src/internal/utils/sandbox-mount.ts
1413
- var AGENTS_SESSION_PREFIX = "/mnt/session";
1414
- function joinAbsolute(prefix, sub) {
1415
- const left = prefix.replace(/\/+$/, "");
1416
- const right = sub.replace(/^\/+/, "");
1417
- return `${left}/${right}`;
1418
- }
1419
- function basename2(p) {
1420
- const trimmed = p.replace(/\/+$/, "");
1421
- const idx = trimmed.lastIndexOf("/");
1422
- return idx === -1 ? trimmed : trimmed.slice(idx + 1);
1423
- }
1424
- function resolveSandboxMountPath(provider, mountPath) {
1425
- switch (provider) {
1426
- case "ark":
1427
- case "bailian":
1428
- case "claude":
1429
- return joinAbsolute(AGENTS_SESSION_PREFIX, mountPath);
1430
- case "qoder":
1431
- return joinAbsolute("/data", basename2(mountPath));
1432
- default:
1433
- return mountPath;
1434
- }
1435
- }
1436
- function composeFileMountHint(files, provider) {
1437
- if (!files || files.length === 0) return "";
1438
- const lines = files.map((f) => `- ${resolveSandboxMountPath(provider, f.mount_path)}`);
1439
- return [
1440
- "The user uploaded files. They are available at the following sandbox paths:",
1441
- ...lines,
1442
- "Read them from these paths when relevant."
1443
- ].join("\n");
1444
- }
1445
- function prependFileHint(prompt, files, provider) {
1446
- const hint = composeFileMountHint(files, provider);
1447
- if (!hint) return prompt;
1448
- return `${hint}
1449
-
1450
- ${prompt}`;
1451
- }
1452
- var FILE_MENTION_SENTINEL_RE = /\u27E6file:(.+?)\u27E7/g;
1453
- function rewriteFileMentions(prompt, provider) {
1454
- return prompt.replace(
1455
- FILE_MENTION_SENTINEL_RE,
1456
- (_match, mountPath) => resolveSandboxMountPath(provider, mountPath)
1457
- );
1458
- }
1459
- function preparePromptForProvider(prompt, files, provider) {
1460
- return prependFileHint(rewriteFileMentions(prompt, provider), files, provider);
1461
- }
1462
-
1463
1984
  // src/internal/providers/qoder/mapper.ts
1464
1985
  function toPascalCase(name) {
1465
1986
  return name.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[^a-zA-Z0-9]+/g, " ").trim().split(/\s+/).map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join("");
@@ -1572,6 +2093,7 @@ function agentToDecl2(raw) {
1572
2093
  const mcpServers = raw.mcp_servers;
1573
2094
  const skills = raw.skills;
1574
2095
  let builtinTools;
2096
+ let builtinPermissions;
1575
2097
  if (tools?.length) {
1576
2098
  const toolset = tools.find((t) => t.type === "agent_toolset_20260401");
1577
2099
  if (toolset && Array.isArray(toolset.enabled_tools)) {
@@ -1579,6 +2101,7 @@ function agentToDecl2(raw) {
1579
2101
  } else if (toolset) {
1580
2102
  const configs = toolset.configs ?? [];
1581
2103
  builtinTools = configs.filter((c) => c.enabled !== false).map((c) => normalizeToolNameFromQoder(c.name));
2104
+ builtinPermissions = permissionOverridesFromWire(configs, normalizeToolNameFromQoder);
1582
2105
  }
1583
2106
  }
1584
2107
  let mcpServerDecls;
@@ -1600,16 +2123,17 @@ function agentToDecl2(raw) {
1600
2123
  description: raw.description,
1601
2124
  model: raw.model,
1602
2125
  instructions: raw.system,
1603
- tools: builtinTools?.length ? { builtin: builtinTools } : void 0,
2126
+ tools: builtinTools?.length ? { builtin: builtinTools, permissions: builtinPermissions } : void 0,
1604
2127
  mcp_servers: mcpServerDecls,
1605
2128
  skills: skillDecls,
1606
2129
  metadata: stripAgentsMetadata(raw.metadata)
1607
2130
  });
1608
2131
  }
1609
- function mapMemoryStore(name, decl) {
2132
+ function mapMemoryStore2(name, decl) {
1610
2133
  return {
1611
2134
  name,
1612
- description: decl.description
2135
+ description: decl.description,
2136
+ metadata: decl.metadata
1613
2137
  };
1614
2138
  }
1615
2139
  function mapDeployment2(name, decl, refs, projectName, uploadedFiles) {
@@ -1630,6 +2154,7 @@ function mapDeployment2(name, decl, refs, projectName, uploadedFiles) {
1630
2154
  };
1631
2155
  }
1632
2156
  if (decl.description) body.description = decl.description;
2157
+ if (decl.environment_variables !== void 0) body.environment_variables = decl.environment_variables;
1633
2158
  if (projectName) {
1634
2159
  body.metadata = injectMetadata(decl.metadata, projectName, name);
1635
2160
  } else if (decl.metadata) {
@@ -1637,6 +2162,24 @@ function mapDeployment2(name, decl, refs, projectName, uploadedFiles) {
1637
2162
  }
1638
2163
  return body;
1639
2164
  }
2165
+ function mapDeploymentUpdate2(name, decl, refs, projectName, uploadedFiles, existingMetadata) {
2166
+ const body = mapDeployment2(name, decl, refs, projectName, uploadedFiles);
2167
+ body.vault_ids = refs.vault_ids;
2168
+ body.resources = mapDeploymentResources2(decl, refs, uploadedFiles);
2169
+ if (decl.schedule) {
2170
+ body.schedule = { type: "cron", expression: decl.schedule.expression, timezone: decl.schedule.timezone };
2171
+ }
2172
+ body.description = decl.description ?? "";
2173
+ body.environment_variables = decl.environment_variables ?? null;
2174
+ const desiredMetadata = projectName ? injectMetadata(decl.metadata, projectName, name) : decl.metadata ?? {};
2175
+ body.metadata = {
2176
+ ...Object.fromEntries(
2177
+ Object.keys(existingMetadata ?? {}).filter((key) => !(key in desiredMetadata)).map((key) => [key, null])
2178
+ ),
2179
+ ...desiredMetadata
2180
+ };
2181
+ return body;
2182
+ }
1640
2183
  function mapDeploymentInitialEvents(events) {
1641
2184
  return events.map((ev) => {
1642
2185
  if (ev.type === "user.message" || ev.type === "system.message") {
@@ -1713,11 +2256,14 @@ function mapAgent2(name, decl, refs, version, projectName) {
1713
2256
  body.metadata = decl.metadata;
1714
2257
  }
1715
2258
  if (decl.tools) {
1716
- const enabledTools = decl.tools.builtin.map((t) => normalizeToolNameForQoder(t));
1717
2259
  body.tools = [
1718
2260
  {
1719
2261
  type: "agent_toolset_20260401",
1720
- enabled_tools: enabledTools
2262
+ configs: resolveBuiltinTools(decl.tools, { toWireName: normalizeToolNameForQoder }).map((tool) => ({
2263
+ name: tool.wireName,
2264
+ enabled: true,
2265
+ permission_policy: toPermissionPolicy(tool.permission)
2266
+ }))
1721
2267
  }
1722
2268
  ];
1723
2269
  } else {
@@ -1775,19 +2321,14 @@ function mapForwardTemplate(name, decl, refs, projectName) {
1775
2321
  if (projectName) body.metadata = injectMetadata(decl.metadata, projectName, name);
1776
2322
  else body.metadata = decl.metadata ?? {};
1777
2323
  if (decl.tools) {
1778
- const permissions = decl.tools.permissions ?? {};
1779
2324
  body.tools = [
1780
2325
  {
1781
2326
  type: "agent_toolset_20260401",
1782
- configs: decl.tools.builtin.map((tool) => {
1783
- const normalized = normalizeToolNameForQoder(tool);
1784
- const policy = permissions[tool] ?? permissions[tool.toLowerCase()] ?? permissions[normalized];
1785
- return {
1786
- name: normalized,
1787
- enabled: true,
1788
- ...policy ? { permission_policy: { type: policy === "ask" ? "always_ask" : "always_allow" } } : {}
1789
- };
1790
- })
2327
+ configs: resolveBuiltinTools(decl.tools, { toWireName: normalizeToolNameForQoder }).map((tool) => ({
2328
+ name: tool.wireName,
2329
+ enabled: true,
2330
+ permission_policy: toPermissionPolicy(tool.permission)
2331
+ }))
1791
2332
  }
1792
2333
  ];
1793
2334
  } else {
@@ -1843,6 +2384,7 @@ function toSessionEvent3(raw) {
1843
2384
  const rawType = raw.type ?? "";
1844
2385
  const type = QODER_EVENT_MAP[rawType] ?? "unknown";
1845
2386
  const event = { type, raw_type: rawType, raw };
2387
+ if (typeof raw.id === "string") event.id = raw.id;
1846
2388
  if (typeof raw.role === "string") event.role = raw.role;
1847
2389
  if (type === "message") {
1848
2390
  event.role = roleFromType2(rawType, raw.role);
@@ -1853,12 +2395,15 @@ function toSessionEvent3(raw) {
1853
2395
  } else if (type === "tool_result") {
1854
2396
  event.content = extractContentText2(raw);
1855
2397
  } else if (type === "status") {
2398
+ const stopReason = extractStopReason2(raw.stop_reason);
1856
2399
  if (rawType === "session.thread_status_idle") {
1857
2400
  event.status = "running";
2401
+ } else if (rawType === "session.status_idle" && stopReason === "requires_action") {
2402
+ event.status = "running";
1858
2403
  } else {
1859
2404
  event.status = rawType.includes("idle") ? "idle" : rawType.includes("terminated") ? "terminated" : "running";
1860
2405
  }
1861
- event.stop_reason = extractStopReason2(raw.stop_reason);
2406
+ event.stop_reason = stopReason;
1862
2407
  } else if (type === "error") {
1863
2408
  event.content = extractErrorMessage2(raw);
1864
2409
  }
@@ -1920,6 +2465,13 @@ function mapSession2(bindings) {
1920
2465
  for (const id of bindings.memory_store_ids) resources.push({ type: "memory_store", memory_store_id: id });
1921
2466
  for (const f of bindings.files ?? [])
1922
2467
  resources.push({ type: "file", file_id: f.file_id, mount_path: resolveSandboxMountPath("qoder", f.mount_path) });
2468
+ for (const resource of bindings.resources ?? []) {
2469
+ resources.push(
2470
+ mapGithubRepositorySessionResource(resource, {
2471
+ mapMountPath: (item) => resolveGithubRepositoryMountPath("qoder", item)
2472
+ })
2473
+ );
2474
+ }
1923
2475
  if (resources.length) body.resources = resources;
1924
2476
  return body;
1925
2477
  }
@@ -1930,17 +2482,46 @@ function deriveForwardGateway(cloudGateway) {
1930
2482
  const trimmed = cloudGateway.replace(/\/$/, "");
1931
2483
  return trimmed.endsWith("/cloud") ? `${trimmed.slice(0, -"/cloud".length)}/forward` : `${trimmed}/forward`;
1932
2484
  }
1933
- var QODER_DEFAULT_IDENTITY_EXTERNAL_ID = "__qca_admin_identity__";
2485
+ function toDeploymentInfo2(res) {
2486
+ const sched = res.schedule;
2487
+ return {
2488
+ id: res.id ?? null,
2489
+ status: res.status ?? "unknown",
2490
+ paused_reason: res.paused_reason ?? void 0,
2491
+ schedule: sched ? { expression: sched.expression, timezone: sched.timezone } : void 0,
2492
+ attributes: res
2493
+ };
2494
+ }
1934
2495
  var QoderAdapter = class _QoderAdapter {
1935
2496
  name = "qoder";
1936
2497
  eventResume = true;
2498
+ memoryCapabilities = {
2499
+ archive_store: true,
2500
+ batch_create: false,
2501
+ versions: true,
2502
+ optimistic_concurrency: true,
2503
+ memory_metadata: true
2504
+ };
1937
2505
  client;
2506
+ memoryApi;
1938
2507
  forwardClient;
1939
2508
  projectName;
1940
2509
  forwardSessionIds = /* @__PURE__ */ new Set();
1941
- defaultForwardIdentityId;
1942
2510
  constructor(apiKey, gateway, projectName, forwardGateway) {
1943
2511
  this.client = new QoderClient({ apiKey, gateway });
2512
+ this.memoryApi = new ProviderMemoryApi(this.client, {
2513
+ pathStyle: "relative",
2514
+ cursorParam: "after_id",
2515
+ updatePrecondition: "content_sha256",
2516
+ prefixParam: "prefix",
2517
+ versionsSegment: "versions",
2518
+ storeMetadataMode: "merge_patch",
2519
+ supportsView: false,
2520
+ supportsMemoryMetadata: true,
2521
+ supportsPathUpdate: false,
2522
+ supportsDeletePrecondition: false,
2523
+ supportsIncludeArchived: true
2524
+ });
1944
2525
  this.forwardClient = new QoderClient({
1945
2526
  apiKey,
1946
2527
  gateway: forwardGateway ?? deriveForwardGateway(gateway)
@@ -1956,14 +2537,29 @@ var QoderAdapter = class _QoderAdapter {
1956
2537
  vault: "/vaults",
1957
2538
  skill: "/skills",
1958
2539
  memory_store: "/memory_stores",
1959
- file: "/files"
1960
- // deployment omitted: emulated on Qoder, no remote listing endpoint
2540
+ file: "/files",
2541
+ deployment: "/deployments"
1961
2542
  };
1962
2543
  async findResource(type, name, id) {
1963
2544
  if (type === "template") {
1964
2545
  const raw2 = await locateRemote(this.forwardClient, "/templates", name, id, (item) => item.status !== "archived");
1965
2546
  return raw2 ? toRemoteResource(raw2) : null;
1966
2547
  }
2548
+ if (type === "identity") {
2549
+ try {
2550
+ if (id) return toRemoteResource(await this.forwardClient.get(`/identities/${id}`));
2551
+ const res = await this.forwardClient.get(`/identities?external_id=${encodeURIComponent(name)}&limit=100`);
2552
+ const raw2 = (res.data ?? []).find((item) => item.external_id === name);
2553
+ return raw2 ? toRemoteResource(raw2) : null;
2554
+ } catch (err) {
2555
+ if (ApiError.isNotFound(err)) return null;
2556
+ throw err;
2557
+ }
2558
+ }
2559
+ if (type === "channel") {
2560
+ const raw2 = await locateRemote(this.forwardClient, "/channels", name, id, () => true);
2561
+ return raw2 ? toRemoteResource(raw2) : null;
2562
+ }
1967
2563
  const raw = await locateRemote(this.client, _QoderAdapter.ENDPOINT_MAP[type], name, id, notArchived);
1968
2564
  return raw ? toRemoteResource(raw) : null;
1969
2565
  }
@@ -2009,12 +2605,23 @@ var QoderAdapter = class _QoderAdapter {
2009
2605
  return toRestSkillInfo(res);
2010
2606
  }
2011
2607
  getDriftSupport(type) {
2012
- if (type === "agent" || type === "environment" || type === "template") return "full";
2608
+ if (type === "agent" || type === "environment" || type === "template" || type === "identity" || type === "channel")
2609
+ return "full";
2013
2610
  if (type === "deployment") return "unsupported";
2014
2611
  return _QoderAdapter.ENDPOINT_MAP[type] ? "existence" : "unsupported";
2015
2612
  }
2016
2613
  async readComparableResource(type, id, name) {
2017
- if (type !== "agent" && type !== "environment" && type !== "template") return null;
2614
+ if (type !== "agent" && type !== "environment" && type !== "template" && type !== "identity" && type !== "channel")
2615
+ return null;
2616
+ if (type === "identity" || type === "channel") {
2617
+ const remote = await this.findResource(type, name, id);
2618
+ if (!remote?.id) return null;
2619
+ const raw2 = await this.forwardClient.get(
2620
+ `/${type === "identity" ? "identities" : "channels"}/${remote.id}`
2621
+ );
2622
+ const comparable2 = this.normalizeRemote(type, raw2);
2623
+ return { id: remote.id, type, comparable: comparable2, snapshot: comparable2 };
2624
+ }
2018
2625
  const isTemplate = type === "template";
2019
2626
  const endpoint = type === "agent" ? "/agents" : type === "environment" ? "/environments" : "/templates";
2020
2627
  const raw = await locateRemote(
@@ -2048,6 +2655,16 @@ var QoderAdapter = class _QoderAdapter {
2048
2655
  );
2049
2656
  }
2050
2657
  if (type === "template") return null;
2658
+ if (type === "identity") {
2659
+ const identity = decl;
2660
+ if (identity.identity_id) return null;
2661
+ return this.normalizeRemote(type, {
2662
+ external_id: identity.external_id,
2663
+ name: identity.name ?? name,
2664
+ enabled: identity.enabled ?? true,
2665
+ metadata: identity.metadata ?? {}
2666
+ });
2667
+ }
2051
2668
  return null;
2052
2669
  }
2053
2670
  normalizeRemote(type, raw) {
@@ -2081,6 +2698,27 @@ var QoderAdapter = class _QoderAdapter {
2081
2698
  metadata: stripAgentsMetadata(raw.metadata)
2082
2699
  });
2083
2700
  }
2701
+ if (type === "identity") {
2702
+ return compactDeep({
2703
+ external_id: raw.external_id,
2704
+ name: raw.name,
2705
+ enabled: raw.enabled,
2706
+ metadata: raw.metadata ?? {}
2707
+ });
2708
+ }
2709
+ if (type === "channel") {
2710
+ const channelConfig = raw.channel_config ?? {};
2711
+ return compactDeep({
2712
+ identity_id: raw.identity_id,
2713
+ template_id: raw.template_id,
2714
+ channel_type: raw.channel_type,
2715
+ name: raw.name,
2716
+ enabled: raw.enabled,
2717
+ channel_config: {
2718
+ response_options: channelConfig.response_options ?? {}
2719
+ }
2720
+ });
2721
+ }
2084
2722
  return compactDeep({
2085
2723
  description: raw.description,
2086
2724
  model: normalizeModel(raw.model),
@@ -2190,6 +2828,71 @@ var QoderAdapter = class _QoderAdapter {
2190
2828
  async archiveTemplate(id) {
2191
2829
  await this.forwardClient.post(`/templates/${id}/archive`, {});
2192
2830
  }
2831
+ async createIdentity(name, decl) {
2832
+ if (decl.identity_id) return { id: decl.identity_id, type: "identity" };
2833
+ const res = await this.forwardClient.post("/identities", {
2834
+ external_id: decl.external_id,
2835
+ name: decl.name ?? name,
2836
+ enabled: decl.enabled ?? true,
2837
+ metadata: decl.metadata ?? {}
2838
+ });
2839
+ return toRemoteResource(res);
2840
+ }
2841
+ async updateIdentity(id, name, decl) {
2842
+ if (decl.identity_id) return { id: decl.identity_id, type: "identity" };
2843
+ const current = await this.forwardClient.get(`/identities/${id}`);
2844
+ const currentMetadata = current.metadata ?? {};
2845
+ const desiredMetadata = decl.metadata ?? {};
2846
+ const metadata = { ...desiredMetadata };
2847
+ for (const key of Object.keys(currentMetadata)) {
2848
+ if (!(key in desiredMetadata)) metadata[key] = "";
2849
+ }
2850
+ const res = await this.forwardClient.post(`/identities/${id}`, {
2851
+ external_id: decl.external_id,
2852
+ name: decl.name ?? name,
2853
+ enabled: decl.enabled ?? true,
2854
+ metadata
2855
+ });
2856
+ return toRemoteResource(res);
2857
+ }
2858
+ async deleteIdentity(id) {
2859
+ await this.forwardClient.delete(`/identities/${id}`);
2860
+ }
2861
+ async createChannel(name, decl, refs) {
2862
+ const res = await this.forwardClient.post("/channels", this.mapChannel(name, decl, refs));
2863
+ return toRemoteResource(res);
2864
+ }
2865
+ async updateChannel(id, name, decl, refs) {
2866
+ const current = await this.forwardClient.get(`/channels/${id}`);
2867
+ if (current.channel_type !== decl.type) {
2868
+ await this.deleteChannel(id);
2869
+ return this.createChannel(name, decl, refs);
2870
+ }
2871
+ const body = this.mapChannel(name, decl, refs);
2872
+ delete body.channel_type;
2873
+ const res = await this.forwardClient.post(`/channels/${id}`, body);
2874
+ return toRemoteResource(res);
2875
+ }
2876
+ async deleteChannel(id) {
2877
+ await this.forwardClient.delete(`/channels/${id}`);
2878
+ }
2879
+ mapChannel(name, decl, refs) {
2880
+ return {
2881
+ identity_id: refs.identity_id,
2882
+ template_id: refs.agent_id,
2883
+ channel_type: decl.type,
2884
+ name: decl.name ?? name,
2885
+ enabled: decl.enabled ?? true,
2886
+ channel_config: {
2887
+ credentials: decl.credentials,
2888
+ response_options: {
2889
+ include_tool_calls: false,
2890
+ include_thinking: false,
2891
+ ...decl.options ?? {}
2892
+ }
2893
+ }
2894
+ };
2895
+ }
2193
2896
  async registerForwardVaults(vaultIds) {
2194
2897
  for (const id of vaultIds) {
2195
2898
  await this.forwardClient.post("/resources/registry", {
@@ -2199,22 +2902,58 @@ var QoderAdapter = class _QoderAdapter {
2199
2902
  }
2200
2903
  }
2201
2904
  async createMemoryStore(name, decl) {
2202
- const body = mapMemoryStore(name, decl);
2905
+ const body = mapMemoryStore2(name, decl);
2203
2906
  const res = await this.client.post("/memory_stores", body);
2204
2907
  const storeId = res.id;
2205
- if (decl.entries?.length) {
2206
- for (const entry of decl.entries) {
2207
- await this.client.post(`/memory_stores/${storeId}/memories`, {
2208
- content: entry.content,
2209
- path: entry.key
2210
- });
2908
+ try {
2909
+ for (const entry of decl.entries ?? []) {
2910
+ await this.memoryApi.createMemory(storeId, { content: entry.content, path: entry.key });
2211
2911
  }
2912
+ } catch (error) {
2913
+ await this.client.delete(`/memory_stores/${storeId}`).catch(() => void 0);
2914
+ throw error;
2212
2915
  }
2213
2916
  return toRemoteResource(res);
2214
2917
  }
2215
2918
  async deleteMemoryStore(id) {
2216
2919
  await this.client.delete(`/memory_stores/${id}`);
2217
2920
  }
2921
+ listMemoryStores(options) {
2922
+ return this.memoryApi.listStores(options);
2923
+ }
2924
+ getMemoryStore(id) {
2925
+ return this.memoryApi.getStore(id);
2926
+ }
2927
+ updateMemoryStore(id, input) {
2928
+ return this.memoryApi.updateStore(id, input);
2929
+ }
2930
+ archiveMemoryStore(id) {
2931
+ return this.memoryApi.archiveStore(id);
2932
+ }
2933
+ createMemory(storeId, input) {
2934
+ return this.memoryApi.createMemory(storeId, input);
2935
+ }
2936
+ listMemories(storeId, options) {
2937
+ return this.memoryApi.listMemories(storeId, options);
2938
+ }
2939
+ getMemory(storeId, memoryId) {
2940
+ return this.memoryApi.getMemory(storeId, memoryId);
2941
+ }
2942
+ updateMemory(storeId, memoryId, input) {
2943
+ return this.memoryApi.updateMemory(storeId, memoryId, input);
2944
+ }
2945
+ deleteMemory(storeId, memoryId, expected) {
2946
+ return this.memoryApi.deleteMemory(storeId, memoryId, expected);
2947
+ }
2948
+ listMemoryVersions(storeId, options) {
2949
+ return this.memoryApi.listVersions(storeId, options);
2950
+ }
2951
+ getMemoryVersion(storeId, versionId) {
2952
+ return this.memoryApi.getVersion(storeId, versionId);
2953
+ }
2954
+ redactMemoryVersion(storeId, versionId) {
2955
+ return this.memoryApi.redactVersion(storeId, versionId);
2956
+ }
2218
2957
  async createDeployment(name, decl, refs, basePath) {
2219
2958
  const uploaded = await this.uploadDeploymentFiles(decl, basePath);
2220
2959
  const body = mapDeployment2(name, decl, refs, this.projectName, uploaded);
@@ -2223,7 +2962,20 @@ var QoderAdapter = class _QoderAdapter {
2223
2962
  }
2224
2963
  async updateDeployment(id, name, decl, refs, basePath) {
2225
2964
  const uploaded = await this.uploadDeploymentFiles(decl, basePath);
2226
- const body = mapDeployment2(name, decl, refs, this.projectName, uploaded);
2965
+ const current = await this.client.get(`/deployments/${id}`);
2966
+ if (current.schedule && !decl.schedule) {
2967
+ throw new UserError(
2968
+ `Deployment '${name}' cannot remove its schedule through the documented Qoder update API; archive and recreate it as a manual deployment.`
2969
+ );
2970
+ }
2971
+ const body = mapDeploymentUpdate2(
2972
+ name,
2973
+ decl,
2974
+ refs,
2975
+ this.projectName,
2976
+ uploaded,
2977
+ current.metadata
2978
+ );
2227
2979
  const res = await this.client.post(`/deployments/${id}`, body);
2228
2980
  return toRemoteResource(res);
2229
2981
  }
@@ -2258,6 +3010,35 @@ var QoderAdapter = class _QoderAdapter {
2258
3010
  attributes: res
2259
3011
  };
2260
3012
  }
3013
+ async listDeployments(filter) {
3014
+ const params = new URLSearchParams();
3015
+ if (filter?.agent_id) params.set("agent_id", filter.agent_id);
3016
+ if (filter?.status) params.set("status", filter.status);
3017
+ if (filter?.include_archived) params.set("include_archived", "true");
3018
+ if (filter?.limit) params.set("limit", String(filter.limit));
3019
+ if (filter?.page) params.set("page", filter.page);
3020
+ if (filter?.created_at_gte) params.set("created_at[gte]", filter.created_at_gte);
3021
+ if (filter?.created_at_lte) params.set("created_at[lte]", filter.created_at_lte);
3022
+ const query2 = params.toString();
3023
+ const res = await this.client.get(`/deployments${query2 ? `?${query2}` : ""}`);
3024
+ return {
3025
+ deployments: (res.data ?? []).map(toDeploymentInfo2),
3026
+ has_more: Boolean(res.has_more),
3027
+ next_page: res.next_page ?? void 0
3028
+ };
3029
+ }
3030
+ async pauseDeployment(ctx) {
3031
+ return this.setDeploymentPaused(ctx, true);
3032
+ }
3033
+ async unpauseDeployment(ctx) {
3034
+ return this.setDeploymentPaused(ctx, false);
3035
+ }
3036
+ async setDeploymentPaused(ctx, paused) {
3037
+ if (!ctx.id) throw new UserError(`Deployment '${ctx.name}' has no remote id; run \`agents apply\` first.`);
3038
+ const action = paused ? "pause" : "unpause";
3039
+ const res = await this.client.post(`/deployments/${ctx.id}/${action}`, {});
3040
+ return toDeploymentInfo2(res);
3041
+ }
2261
3042
  async uploadDeploymentFiles(decl, basePath) {
2262
3043
  const map = /* @__PURE__ */ new Map();
2263
3044
  for (const r of decl.resources ?? []) {
@@ -2271,16 +3052,18 @@ var QoderAdapter = class _QoderAdapter {
2271
3052
  const fullPath = resolve2(dirname2(basePath), source);
2272
3053
  const content = readFileSync2(fullPath);
2273
3054
  const formData = new FormData();
2274
- formData.append("file", new File([new Uint8Array(content)], basename3(fullPath)));
3055
+ formData.append("file", new File([new Uint8Array(content)], basename2(fullPath)));
2275
3056
  formData.append("purpose", "session_resource");
2276
3057
  const res = await this.client.postFormData("/files", formData);
2277
3058
  return res.file_id ?? res.id;
2278
3059
  }
2279
3060
  async createSession(bindings) {
2280
3061
  if (bindings.delivery === "forward") {
2281
- const identityId = bindings.identity_id ?? await this.resolveDefaultForwardIdentityId();
3062
+ if (!bindings.identity_id) {
3063
+ throw new UserError("Qoder Forward sessions require an explicit resolved identity_id.");
3064
+ }
2282
3065
  const body2 = {
2283
- identity_id: identityId,
3066
+ identity_id: bindings.identity_id,
2284
3067
  template_id: bindings.template_id,
2285
3068
  incremental_streaming_enabled: false
2286
3069
  };
@@ -2302,30 +3085,6 @@ var QoderAdapter = class _QoderAdapter {
2302
3085
  const res = await this.client.post("/sessions", body);
2303
3086
  return toSessionInfo2(res);
2304
3087
  }
2305
- async resolveDefaultForwardIdentityId() {
2306
- if (this.defaultForwardIdentityId) return this.defaultForwardIdentityId;
2307
- let afterId;
2308
- do {
2309
- const params = new URLSearchParams({ limit: "100" });
2310
- if (afterId) params.set("after_id", afterId);
2311
- const res = await this.forwardClient.get(`/identities?${params}`);
2312
- const identities = res.data ?? [];
2313
- const match = identities.find(
2314
- (identity) => identity.external_id === QODER_DEFAULT_IDENTITY_EXTERNAL_ID && identity.enabled !== false && identity.archived !== true
2315
- );
2316
- if (typeof match?.id === "string") {
2317
- this.defaultForwardIdentityId = match.id;
2318
- return match.id;
2319
- }
2320
- const hasMore = res.has_more ?? false;
2321
- const nextId = hasMore ? res.last_id ?? void 0 : void 0;
2322
- if (!nextId || nextId === afterId) break;
2323
- afterId = nextId;
2324
- } while (afterId);
2325
- throw new UserError(
2326
- `Qoder default Forward Identity '${QODER_DEFAULT_IDENTITY_EXTERNAL_ID}' was not found. Ask Qoder to provision it, set defaults.session.qoder.identity_id, or pass --identity-id.`
2327
- );
2328
- }
2329
3088
  async listSessions(filter) {
2330
3089
  if (filter?.agent_id?.startsWith("tmpl_")) {
2331
3090
  const params2 = new URLSearchParams({ template_id: filter.agent_id });
@@ -2448,8 +3207,8 @@ var QoderAdapter = class _QoderAdapter {
2448
3207
  if (options?.order) params.set("order", options.order);
2449
3208
  const afterId = options?.after_id ?? options?.page_token ?? options?.page;
2450
3209
  if (afterId) params.set("after_id", afterId);
2451
- const query = params.toString();
2452
- const res = await this.forwardClient.get(`/sessions/${sessionId}/events${query ? `?${query}` : ""}`);
3210
+ const query2 = params.toString();
3211
+ const res = await this.forwardClient.get(`/sessions/${sessionId}/events${query2 ? `?${query2}` : ""}`);
2453
3212
  const data = res.data ?? [];
2454
3213
  const hasMore = res.has_more ?? false;
2455
3214
  return {
@@ -2466,7 +3225,7 @@ var QoderAdapter = class _QoderAdapter {
2466
3225
  async uploadFile(filePath, options) {
2467
3226
  const resolved = resolve2(filePath);
2468
3227
  const content = readFileSync2(resolved);
2469
- const fileName = options?.name ?? basename3(resolved);
3228
+ const fileName = options?.name ?? basename2(resolved);
2470
3229
  return this.uploadFileContent(new Uint8Array(content), fileName, {
2471
3230
  purpose: options?.purpose
2472
3231
  });
@@ -2573,7 +3332,9 @@ var QODER_CAPABILITIES = {
2573
3332
  tier: "native",
2574
3333
  reason: "deployments API with scheduled and manual runs"
2575
3334
  },
2576
- session: { tier: "native", reason: "sessions API" }
3335
+ session: { tier: "native", reason: "sessions API" },
3336
+ identity: { tier: "native", reason: "Forward Identities API" },
3337
+ channel: { tier: "native", reason: "Forward Channels API" }
2577
3338
  };
2578
3339
 
2579
3340
  // src/internal/providers/qoder/config.ts
@@ -2589,6 +3350,7 @@ registerProvider({
2589
3350
  name: "qoder",
2590
3351
  configSchema: qoderConfigSchema,
2591
3352
  capabilities: QODER_CAPABILITIES,
3353
+ features: { tool_permissions: true, session_resources: ["github_repository"] },
2592
3354
  createAdapter: (config, projectName) => {
2593
3355
  const c = config;
2594
3356
  return new QoderAdapter(c.api_key, c.gateway, projectName, c.forward_gateway);
@@ -2597,7 +3359,7 @@ registerProvider({
2597
3359
 
2598
3360
  // src/internal/providers/bailian/adapter.ts
2599
3361
  import { readFileSync as readFileSync3 } from "fs";
2600
- import { basename as basename4, dirname as dirname3, extname, resolve as resolve3 } from "path";
3362
+ import { basename as basename3, dirname as dirname3, extname, resolve as resolve3 } from "path";
2601
3363
  import JSZip3 from "jszip";
2602
3364
 
2603
3365
  // src/internal/providers/bailian/client.ts
@@ -2791,8 +3553,8 @@ function mapAgent3(name, decl, refs, version, projectName, skillVersions) {
2791
3553
  }
2792
3554
  const BAILIAN_BUILTINS = /* @__PURE__ */ new Set(["bash", "read", "write", "edit", "glob", "grep", "download_file"]);
2793
3555
  if (decl.tools) {
2794
- const toolConfigs = decl.tools.builtin.filter((t) => BAILIAN_BUILTINS.has(t)).map((toolName) => ({
2795
- name: toolName,
3556
+ const toolConfigs = resolveBuiltinTools(decl.tools, { supportedWireNames: BAILIAN_BUILTINS }).map((tool) => ({
3557
+ name: tool.wireName,
2796
3558
  enabled: true
2797
3559
  }));
2798
3560
  body.tools = [
@@ -2854,7 +3616,13 @@ function mapSession3(bindings) {
2854
3616
  if (bindings.metadata) body.metadata = bindings.metadata;
2855
3617
  if (bindings.vault_ids.length) body.vault_ids = bindings.vault_ids;
2856
3618
  const resources = [];
2857
- for (const f of bindings.files ?? []) resources.push({ type: "file", file_id: f.file_id, mount_path: f.mount_path });
3619
+ for (const f of bindings.files ?? []) {
3620
+ resources.push({
3621
+ type: "file",
3622
+ file_id: f.file_id,
3623
+ mount_path: resolveSandboxMountPath("bailian", f.mount_path)
3624
+ });
3625
+ }
2858
3626
  if (resources.length) body.resources = resources;
2859
3627
  if (bindings.memory_store_ids.length) body.memory_store_ids = bindings.memory_store_ids;
2860
3628
  return body;
@@ -3302,7 +4070,7 @@ var BailianAdapter = class _BailianAdapter {
3302
4070
  const fullPath = resolve3(dirname3(basePath), source);
3303
4071
  const content = readFileSync3(fullPath);
3304
4072
  const formData = new FormData();
3305
- formData.append("file", new File([new Uint8Array(content)], basename4(fullPath)));
4073
+ formData.append("file", new File([new Uint8Array(content)], basename3(fullPath)));
3306
4074
  const res = await this.client.postFormData("/files", formData);
3307
4075
  const fileId = res.id;
3308
4076
  await this.waitForFileAvailable(fileId);
@@ -3367,7 +4135,7 @@ var BailianAdapter = class _BailianAdapter {
3367
4135
  async uploadFile(filePath, options) {
3368
4136
  const resolved = resolve3(filePath);
3369
4137
  const content = readFileSync3(resolved);
3370
- const fileName = options?.name ?? basename4(resolved);
4138
+ const fileName = options?.name ?? basename3(resolved);
3371
4139
  return this.uploadFileContent(new Uint8Array(content), fileName, {
3372
4140
  purpose: options?.purpose
3373
4141
  });
@@ -3494,7 +4262,9 @@ var BAILIAN_CAPABILITIES = {
3494
4262
  reason: "no deployment primitive on Bailian; expanded into a session at run time",
3495
4263
  remediation: "scheduling and outcome rubrics are not enforced server-side \u2014 use external cron/CI for always-on or scheduled runs"
3496
4264
  },
3497
- session: { tier: "native", reason: "sessions API" }
4265
+ session: { tier: "native", reason: "sessions API" },
4266
+ identity: { tier: "unsupported", reason: "no mapped Identity primitive on Bailian" },
4267
+ channel: { tier: "unsupported", reason: "no mapped messaging Channel primitive on Bailian" }
3498
4268
  };
3499
4269
 
3500
4270
  // src/internal/providers/bailian/config.ts
@@ -3510,6 +4280,7 @@ registerProvider({
3510
4280
  name: "bailian",
3511
4281
  configSchema: bailianConfigSchema,
3512
4282
  capabilities: BAILIAN_CAPABILITIES,
4283
+ features: { tool_permissions: false, session_resources: [] },
3513
4284
  createAdapter: (config, projectName) => {
3514
4285
  const c = config;
3515
4286
  return new BailianAdapter(c.api_key, c.workspace_id, c.base_url, projectName);
@@ -3518,7 +4289,7 @@ registerProvider({
3518
4289
 
3519
4290
  // src/internal/providers/ark/adapter.ts
3520
4291
  import { readFileSync as readFileSync4 } from "fs";
3521
- import { basename as basename5, dirname as dirname4, resolve as resolve4 } from "path";
4292
+ import { basename as basename4, dirname as dirname4, resolve as resolve4 } from "path";
3522
4293
  import JSZip4 from "jszip";
3523
4294
 
3524
4295
  // src/internal/providers/resource-naming.ts
@@ -3643,6 +4414,7 @@ function agentToDecl4(raw) {
3643
4414
  const skills = raw.skills;
3644
4415
  const multiagent = raw.multiagent;
3645
4416
  let builtinTools;
4417
+ let builtinPermissions;
3646
4418
  let allToolsEnabled = false;
3647
4419
  if (tools?.length) {
3648
4420
  const toolset = tools.find((t) => t.type === "agent_toolset_20260701");
@@ -3651,6 +4423,7 @@ function agentToDecl4(raw) {
3651
4423
  const configs = toolset.configs ?? [];
3652
4424
  if (configs.length > 0) {
3653
4425
  builtinTools = configs.filter((c) => c.enabled !== false).map((c) => c.name);
4426
+ builtinPermissions = permissionOverridesFromWire(configs);
3654
4427
  } else if (defaultConfig?.enabled) {
3655
4428
  allToolsEnabled = true;
3656
4429
  }
@@ -3681,7 +4454,7 @@ function agentToDecl4(raw) {
3681
4454
  }
3682
4455
  let toolsDecl;
3683
4456
  if (builtinTools?.length) {
3684
- toolsDecl = { builtin: builtinTools };
4457
+ toolsDecl = { builtin: builtinTools, permissions: builtinPermissions };
3685
4458
  } else if (allToolsEnabled) {
3686
4459
  toolsDecl = {
3687
4460
  builtin: ["read", "write", "edit", "bash", "glob", "grep", "web_search", "web_fetch"]
@@ -3713,10 +4486,11 @@ function mapEnvironment4(name, decl, projectName, wireName) {
3713
4486
  if (decl.description) body.description = decl.description;
3714
4487
  return body;
3715
4488
  }
3716
- function mapMemoryStore2(name, decl) {
4489
+ function mapMemoryStore3(name, decl) {
3717
4490
  return {
3718
4491
  name,
3719
- description: decl.description
4492
+ description: decl.description,
4493
+ metadata: decl.metadata
3720
4494
  };
3721
4495
  }
3722
4496
  function mapAgent4(name, decl, refs, version, projectName) {
@@ -3741,16 +4515,11 @@ function mapAgent4(name, decl, refs, version, projectName) {
3741
4515
  body.metadata = decl.metadata;
3742
4516
  }
3743
4517
  if (decl.tools) {
3744
- const toolConfigs = decl.tools.builtin.filter((toolName) => ARK_BUILTINS.has(toolName)).map((toolName) => {
3745
- const permission = decl.tools?.permissions?.[toolName] ?? "allow";
3746
- return {
3747
- name: toolName,
3748
- enabled: true,
3749
- permission_policy: {
3750
- type: permission === "ask" ? "always_ask" : "always_allow"
3751
- }
3752
- };
3753
- });
4518
+ const toolConfigs = resolveBuiltinTools(decl.tools, { supportedWireNames: ARK_BUILTINS }).map((tool) => ({
4519
+ name: tool.wireName,
4520
+ enabled: true,
4521
+ permission_policy: toPermissionPolicy(tool.permission)
4522
+ }));
3754
4523
  body.tools = [
3755
4524
  {
3756
4525
  type: "agent_toolset_20260701",
@@ -3905,7 +4674,7 @@ function mapSession4(bindings) {
3905
4674
  resources.push({
3906
4675
  type: "file",
3907
4676
  file_id: f.file_id,
3908
- mount_path: f.mount_path
4677
+ mount_path: resolveSandboxMountPath("ark", f.mount_path)
3909
4678
  });
3910
4679
  if (resources.length) body.resources = resources;
3911
4680
  return body;
@@ -3915,10 +4684,28 @@ function mapSession4(bindings) {
3915
4684
  var ArkAdapter = class _ArkAdapter {
3916
4685
  name = "ark";
3917
4686
  eventResume = false;
4687
+ memoryCapabilities = {
4688
+ archive_store: false,
4689
+ batch_create: true,
4690
+ versions: false,
4691
+ optimistic_concurrency: false,
4692
+ memory_metadata: false
4693
+ };
3918
4694
  client;
4695
+ memoryApi;
3919
4696
  projectName;
3920
4697
  constructor(apiKey, projectName) {
3921
4698
  this.client = new ArkClient({ apiKey });
4699
+ this.memoryApi = new ProviderMemoryApi(this.client, {
4700
+ pathStyle: "absolute",
4701
+ cursorParam: "page",
4702
+ updatePrecondition: "none",
4703
+ prefixParam: "path_prefix",
4704
+ supportsView: false,
4705
+ supportsMemoryMetadata: false,
4706
+ supportsDeletePrecondition: false,
4707
+ supportsIncludeArchived: false
4708
+ });
3922
4709
  this.projectName = projectName ?? "";
3923
4710
  }
3924
4711
  async validate() {
@@ -4071,22 +4858,49 @@ var ArkAdapter = class _ArkAdapter {
4071
4858
  await this.client.delete(`/agents/${id}`);
4072
4859
  }
4073
4860
  async createMemoryStore(name, decl) {
4074
- const body = mapMemoryStore2(name, decl);
4861
+ const body = mapMemoryStore3(name, decl);
4075
4862
  const res = await this.client.post("/memory_stores", body);
4076
4863
  const storeId = res.id;
4077
- if (decl.entries?.length) {
4078
- for (const entry of decl.entries) {
4079
- await this.client.post(`/memory_stores/${storeId}/memories`, {
4080
- content: entry.content,
4081
- path: entry.key
4082
- });
4864
+ try {
4865
+ for (const entry of decl.entries ?? []) {
4866
+ await this.memoryApi.createMemory(storeId, { content: entry.content, path: entry.key });
4083
4867
  }
4868
+ } catch (error) {
4869
+ await this.client.delete(`/memory_stores/${storeId}`).catch(() => void 0);
4870
+ throw error;
4084
4871
  }
4085
4872
  return toRemoteResource(res);
4086
4873
  }
4087
4874
  async deleteMemoryStore(id) {
4088
4875
  await this.client.delete(`/memory_stores/${id}`);
4089
4876
  }
4877
+ listMemoryStores(options) {
4878
+ return this.memoryApi.listStores(options);
4879
+ }
4880
+ getMemoryStore(id) {
4881
+ return this.memoryApi.getStore(id);
4882
+ }
4883
+ updateMemoryStore(id, input) {
4884
+ return this.memoryApi.updateStore(id, input);
4885
+ }
4886
+ createMemory(storeId, input) {
4887
+ return this.memoryApi.createMemory(storeId, input);
4888
+ }
4889
+ batchCreateMemories(storeId, input) {
4890
+ return this.memoryApi.batchCreateMemories(storeId, input);
4891
+ }
4892
+ listMemories(storeId, options) {
4893
+ return this.memoryApi.listMemories(storeId, options);
4894
+ }
4895
+ getMemory(storeId, memoryId) {
4896
+ return this.memoryApi.getMemory(storeId, memoryId);
4897
+ }
4898
+ updateMemory(storeId, memoryId, input) {
4899
+ return this.memoryApi.updateMemory(storeId, memoryId, input);
4900
+ }
4901
+ deleteMemory(storeId, memoryId, expected) {
4902
+ return this.memoryApi.deleteMemory(storeId, memoryId, expected);
4903
+ }
4090
4904
  // --- Deployment (emulated) ---
4091
4905
  // Ark has no /deployments endpoint. A deployment is recorded in state with
4092
4906
  // remote_id = null and materialized into a session at run time (mirrors qoder).
@@ -4134,7 +4948,7 @@ var ArkAdapter = class _ArkAdapter {
4134
4948
  const fullPath = resolve4(dirname4(basePath), source);
4135
4949
  const content = readFileSync4(fullPath);
4136
4950
  const formData = new FormData();
4137
- formData.append("file", new File([new Uint8Array(content)], basename5(fullPath)));
4951
+ formData.append("file", new File([new Uint8Array(content)], basename4(fullPath)));
4138
4952
  formData.append("purpose", "agent");
4139
4953
  const res = await this.client.postFormData("/files", formData);
4140
4954
  return res.file_id ?? res.id;
@@ -4183,7 +4997,7 @@ var ArkAdapter = class _ArkAdapter {
4183
4997
  async uploadFile(filePath, options) {
4184
4998
  const resolved = resolve4(filePath);
4185
4999
  const content = readFileSync4(resolved);
4186
- const fileName = options?.name ?? basename5(resolved);
5000
+ const fileName = options?.name ?? basename4(resolved);
4187
5001
  return this.uploadFileContent(new Uint8Array(content), fileName, {
4188
5002
  purpose: options?.purpose
4189
5003
  });
@@ -4248,7 +5062,9 @@ var ARK_CAPABILITIES = {
4248
5062
  tier: "emulated",
4249
5063
  reason: "no deployment primitive on Ark; expanded into a session at run time"
4250
5064
  },
4251
- session: { tier: "native", reason: "sessions API" }
5065
+ session: { tier: "native", reason: "sessions API" },
5066
+ identity: { tier: "unsupported", reason: "no mapped Identity primitive on Ark" },
5067
+ channel: { tier: "unsupported", reason: "no mapped messaging Channel primitive on Ark" }
4252
5068
  };
4253
5069
 
4254
5070
  // src/internal/providers/ark/config.ts
@@ -4262,6 +5078,7 @@ registerProvider({
4262
5078
  name: "ark",
4263
5079
  configSchema: arkConfigSchema,
4264
5080
  capabilities: ARK_CAPABILITIES,
5081
+ features: { tool_permissions: true, session_resources: [] },
4265
5082
  createAdapter: (config, projectName) => {
4266
5083
  const c = config;
4267
5084
  return new ArkAdapter(c.api_key, projectName);
@@ -4308,11 +5125,11 @@ async function writeProjectRuntime(input, fn) {
4308
5125
  );
4309
5126
  }
4310
5127
  function getRuntimeProvider(ctx, providerName) {
4311
- const adapter = ctx.providers.get(providerName);
4312
- if (!adapter) {
5128
+ const adapter2 = ctx.providers.get(providerName);
5129
+ if (!adapter2) {
4313
5130
  throw new UserError(`Provider '${providerName}' not configured.`);
4314
5131
  }
4315
- return adapter;
5132
+ return adapter2;
4316
5133
  }
4317
5134
 
4318
5135
  // src/internal/parser/file-resolver.ts
@@ -4374,7 +5191,7 @@ async function resolveFileReferences(config, configPath) {
4374
5191
  }
4375
5192
 
4376
5193
  // src/internal/parser/resolve-project-config.ts
4377
- import { basename as basename6, dirname as dirname7, resolve as resolve7 } from "path";
5194
+ import { basename as basename5, dirname as dirname7, resolve as resolve7 } from "path";
4378
5195
 
4379
5196
  // src/internal/parser/schema.ts
4380
5197
  import { z as z5 } from "zod";
@@ -4444,6 +5261,7 @@ var memoryEntrySchema = z5.object({
4444
5261
  var memoryStoreSchema = z5.object({
4445
5262
  description: z5.string(),
4446
5263
  provider: z5.string().optional(),
5264
+ metadata: z5.record(z5.string(), z5.string()).optional(),
4447
5265
  entries: z5.array(memoryEntrySchema).optional()
4448
5266
  });
4449
5267
  var skillSchema = z5.object({
@@ -4460,6 +5278,23 @@ var fileSchema = z5.object({
4460
5278
  purpose: z5.string().optional(),
4461
5279
  provider: z5.string().optional()
4462
5280
  });
5281
+ var managedIdentitySchema = z5.object({
5282
+ provider: z5.string().optional(),
5283
+ external_id: z5.string().trim().min(1),
5284
+ name: z5.string().trim().min(1).optional(),
5285
+ enabled: z5.boolean().optional(),
5286
+ metadata: z5.record(z5.string(), z5.string()).optional(),
5287
+ identity_id: z5.never().optional()
5288
+ });
5289
+ var externalIdentitySchema = z5.object({
5290
+ provider: z5.string().optional(),
5291
+ identity_id: z5.string().trim().min(1),
5292
+ external_id: z5.never().optional(),
5293
+ name: z5.never().optional(),
5294
+ enabled: z5.never().optional(),
5295
+ metadata: z5.never().optional()
5296
+ });
5297
+ var identitySchema = z5.union([managedIdentitySchema, externalIdentitySchema]);
4463
5298
  var urlMcpServerSchema = z5.object({
4464
5299
  name: z5.string(),
4465
5300
  type: z5.enum(["url", "http"]).optional(),
@@ -4501,8 +5336,32 @@ var mcpToolkitSchema = z5.object({
4501
5336
  }));
4502
5337
  var toolsSchema = z5.object({
4503
5338
  builtin: z5.array(z5.string()),
5339
+ default_permission: z5.enum(["allow", "ask"]).optional(),
4504
5340
  mcp: z5.array(mcpToolkitSchema).optional(),
4505
5341
  permissions: z5.record(z5.string(), z5.enum(["allow", "ask"])).optional()
5342
+ }).superRefine((tools, ctx) => {
5343
+ const enabled = new Set(tools.builtin.map(canonicalToolName));
5344
+ const seen = /* @__PURE__ */ new Map();
5345
+ for (const key of Object.keys(tools.permissions ?? {})) {
5346
+ const canonical = canonicalToolName(key);
5347
+ const previous = seen.get(canonical);
5348
+ if (previous) {
5349
+ ctx.addIssue({
5350
+ code: "custom",
5351
+ path: ["permissions", key],
5352
+ message: `duplicates permission key '${previous}' after tool-name normalization`
5353
+ });
5354
+ } else {
5355
+ seen.set(canonical, key);
5356
+ }
5357
+ if (!enabled.has(canonical)) {
5358
+ ctx.addIssue({
5359
+ code: "custom",
5360
+ path: ["permissions", key],
5361
+ message: `references tool '${key}' which is not enabled in tools.builtin`
5362
+ });
5363
+ }
5364
+ }
4506
5365
  });
4507
5366
  var multiagentSchema = z5.object({
4508
5367
  type: z5.literal("coordinator"),
@@ -4523,6 +5382,15 @@ var agentSkillRefSchema = z5.object({
4523
5382
  var agentDeliverySchema = z5.object({
4524
5383
  type: z5.enum(["managed", "forward"])
4525
5384
  });
5385
+ var sessionGithubRepoResourceSchema = z5.object({
5386
+ type: z5.literal("github_repository"),
5387
+ url: z5.string().url(),
5388
+ checkout: z5.object({ branch: z5.string().min(1).optional(), commit: z5.string().min(1).optional() }).refine((value) => !(value.branch && value.commit), {
5389
+ message: "checkout accepts either branch or commit, not both"
5390
+ }).optional(),
5391
+ mount_path: z5.string().optional(),
5392
+ authorization_token: z5.string().min(1)
5393
+ });
4526
5394
  var agentSchema = z5.object({
4527
5395
  name: z5.string().optional(),
4528
5396
  description: z5.string().optional(),
@@ -4536,10 +5404,21 @@ var agentSchema = z5.object({
4536
5404
  skills: z5.array(z5.union([z5.string(), agentSkillRefSchema])).optional(),
4537
5405
  vault: z5.string().optional(),
4538
5406
  memory_stores: z5.array(z5.string()).optional(),
5407
+ resources: z5.array(sessionGithubRepoResourceSchema).optional(),
4539
5408
  multiagent: multiagentSchema.optional(),
4540
5409
  metadata: z5.record(z5.string(), z5.string()).optional(),
4541
5410
  delivery: z5.record(z5.string(), agentDeliverySchema).optional()
4542
5411
  });
5412
+ var channelSchema = z5.object({
5413
+ provider: z5.string().optional(),
5414
+ agent: z5.string().min(1),
5415
+ identity: z5.string().min(1).optional(),
5416
+ type: z5.string().min(1),
5417
+ name: z5.string().trim().min(1).optional(),
5418
+ enabled: z5.boolean().optional(),
5419
+ credentials: z5.record(z5.string(), coerceString).optional(),
5420
+ options: z5.record(z5.string(), z5.unknown()).optional()
5421
+ });
4543
5422
  var deploymentFileResourceSchema = z5.object({
4544
5423
  type: z5.literal("file"),
4545
5424
  file_id: z5.string().optional(),
@@ -4593,18 +5472,15 @@ var deploymentSchema = z5.object({
4593
5472
  schedule: scheduleSchema.optional(),
4594
5473
  description: z5.string().optional(),
4595
5474
  provider: z5.string().optional(),
4596
- metadata: z5.record(z5.string(), z5.string()).optional()
5475
+ metadata: z5.record(z5.string(), z5.string()).optional(),
5476
+ environment_variables: z5.string().optional()
4597
5477
  });
4598
5478
  var projectConfigSchema = z5.object({
4599
5479
  version: z5.string(),
4600
5480
  providers: z5.record(z5.string(), z5.unknown()),
4601
5481
  defaults: z5.object({
4602
5482
  provider: z5.string().optional(),
4603
- session: z5.object({
4604
- qoder: z5.object({
4605
- identity_id: z5.string().min(1).optional()
4606
- }).optional()
4607
- }).optional()
5483
+ identity: z5.string().min(1).optional()
4608
5484
  }).optional(),
4609
5485
  environments: z5.record(z5.string(), environmentSchema).optional(),
4610
5486
  tunnels: z5.record(z5.string(), tunnelSchema).optional(),
@@ -4612,7 +5488,9 @@ var projectConfigSchema = z5.object({
4612
5488
  memory_stores: z5.record(z5.string(), memoryStoreSchema).optional(),
4613
5489
  skills: z5.record(z5.string(), skillSchema).optional(),
4614
5490
  files: z5.record(z5.string(), fileSchema).optional(),
5491
+ identities: z5.record(z5.string(), identitySchema).optional(),
4615
5492
  agents: z5.record(z5.string(), agentSchema).optional(),
5493
+ channels: z5.record(z5.string(), channelSchema).optional(),
4616
5494
  deployments: z5.record(z5.string(), deploymentSchema).optional()
4617
5495
  });
4618
5496
 
@@ -4666,7 +5544,7 @@ async function loadConfig(filePath, resolveEnv = false) {
4666
5544
  // src/internal/parser/resolve-project-config.ts
4667
5545
  async function resolveProjectConfig(filePath, options = {}) {
4668
5546
  const configPath = resolve7(filePath);
4669
- const projectName = options.projectName ?? basename6(dirname7(configPath));
5547
+ const projectName = options.projectName ?? basename5(dirname7(configPath));
4670
5548
  const { config: parsed, errors } = await loadConfig(configPath, options.resolveEnv ?? true);
4671
5549
  if (errors.length > 0) {
4672
5550
  throw new UserError(errors.join("\n"));
@@ -4728,6 +5606,10 @@ function getResourceDeclaration(address, config) {
4728
5606
  return config.agents?.[name] ?? null;
4729
5607
  case "file":
4730
5608
  return config.files?.[name] ?? null;
5609
+ case "identity":
5610
+ return config.identities?.[name] ?? null;
5611
+ case "channel":
5612
+ return config.channels?.[name] ?? null;
4731
5613
  case "deployment":
4732
5614
  return config.deployments?.[name] ?? null;
4733
5615
  default:
@@ -4784,8 +5666,26 @@ async function computeResourceHash(address, config, basePath, state) {
4784
5666
  const refs = resolveTemplateReferenceIds(decl, config, address.provider, state);
4785
5667
  return contentHash({ decl, refs });
4786
5668
  }
5669
+ if (address.type === "channel") {
5670
+ const refs = resolveChannelReferenceIds(
5671
+ decl,
5672
+ config,
5673
+ address.provider,
5674
+ state
5675
+ );
5676
+ return contentHash({ decl, refs });
5677
+ }
4787
5678
  return contentHash(decl);
4788
5679
  }
5680
+ function resolveChannelReferenceIds(decl, config, provider, state) {
5681
+ const agent = config.agents?.[decl.agent];
5682
+ const agentType = agent?.delivery?.[provider]?.type === "forward" ? "template" : "agent";
5683
+ const identity = decl.identity ?? config.defaults?.identity;
5684
+ return {
5685
+ agent_id: state?.getResource({ type: agentType, name: decl.agent, provider })?.remote_id,
5686
+ identity_id: identity ? state?.getResource({ type: "identity", name: identity, provider })?.remote_id : void 0
5687
+ };
5688
+ }
4789
5689
  function resolveTemplateReferenceIds(decl, config, provider, state) {
4790
5690
  const environment = decl.environment ? config.environments?.[decl.environment] : void 0;
4791
5691
  const tunnel = decl.tunnel ? config.tunnels?.[decl.tunnel] : void 0;
@@ -4884,14 +5784,14 @@ function structurallyEqual(left, right) {
4884
5784
  }
4885
5785
 
4886
5786
  // src/internal/providers/drift-support.ts
4887
- function supportsFullDrift(adapter, type) {
4888
- return adapter.getDriftSupport?.(type) === "full" && typeof adapter.readComparableResource === "function";
5787
+ function supportsFullDrift(adapter2, type) {
5788
+ return adapter2.getDriftSupport?.(type) === "full" && typeof adapter2.readComparableResource === "function";
4889
5789
  }
4890
- async function readComparableIfSupported(adapter, type, id, name) {
4891
- if (!supportsFullDrift(adapter, type)) return null;
4892
- if (typeof adapter.readComparableResource !== "function") return null;
5790
+ async function readComparableIfSupported(adapter2, type, id, name) {
5791
+ if (!supportsFullDrift(adapter2, type)) return null;
5792
+ if (typeof adapter2.readComparableResource !== "function") return null;
4893
5793
  try {
4894
- return await adapter.readComparableResource(type, id, name);
5794
+ return await adapter2.readComparableResource(type, id, name);
4895
5795
  } catch {
4896
5796
  return null;
4897
5797
  }
@@ -5026,6 +5926,20 @@ function resolveDeploymentRefs(deploymentName, config, provider, state) {
5026
5926
  memory_store_ids
5027
5927
  };
5028
5928
  }
5929
+ function resolveChannelRefs(channelName, config, provider, state) {
5930
+ const channel = config.channels?.[channelName];
5931
+ if (!channel) throw new UserError(`Channel '${channelName}' not found in config`);
5932
+ const agent = config.agents?.[channel.agent];
5933
+ if (!agent) throw new UserError(`Channel '${channelName}' references unknown agent '${channel.agent}'`);
5934
+ const agentType = agent.delivery?.[provider]?.type === "forward" ? "template" : "agent";
5935
+ const agent_id = requireRef(state, { type: agentType, name: channel.agent, provider });
5936
+ const identityName = channel.identity ?? config.defaults?.identity;
5937
+ if (!identityName) {
5938
+ throw new UserError(`Channel '${channelName}' must declare identity or use defaults.identity.`);
5939
+ }
5940
+ const identity_id = requireRef(state, { type: "identity", name: identityName, provider });
5941
+ return { identity_id, agent_id };
5942
+ }
5029
5943
  function resolveTunnelIdFromConfig(config, tunnelName, provider) {
5030
5944
  if (provider !== "qoder") {
5031
5945
  throw new UserError("Tunnels are supported only by Qoder BYOC sessions.");
@@ -5078,10 +5992,10 @@ async function executePlan(plan, ctx, options = {}) {
5078
5992
  const failed = /* @__PURE__ */ new Set();
5079
5993
  let stateUpdated = false;
5080
5994
  for (const action of plan.actions) {
5081
- if (action.address.type !== "environment") continue;
5082
- const decl = ctx.config.environments?.[action.address.name];
5995
+ if (action.address.type !== "environment" && action.address.type !== "identity") continue;
5083
5996
  const existing = ctx.state.getResource(action.address);
5084
- if (decl?.environment_id && existing && !existing.externally_managed) {
5997
+ const externalId = action.address.type === "environment" ? ctx.config.environments?.[action.address.name]?.environment_id : ctx.config.identities?.[action.address.name]?.identity_id;
5998
+ if (externalId && existing && !existing.externally_managed) {
5085
5999
  ctx.state.setResource({ ...existing, externally_managed: true });
5086
6000
  stateUpdated = true;
5087
6001
  }
@@ -5225,9 +6139,9 @@ async function executeActionInner(action, provider, ctx) {
5225
6139
  const existing = ctx.state.getResource(address);
5226
6140
  if (!existing) return false;
5227
6141
  const id = existing.remote_id;
5228
- if (type === "environment") {
5229
- const decl = ctx.config.environments?.[name];
5230
- if (existing.externally_managed || decl?.environment_id) {
6142
+ if (type === "environment" || type === "identity") {
6143
+ const externalReference = type === "environment" ? ctx.config.environments?.[name]?.environment_id : ctx.config.identities?.[name]?.identity_id;
6144
+ if (existing.externally_managed || externalReference) {
5231
6145
  ctx.state.removeResource(address);
5232
6146
  return false;
5233
6147
  }
@@ -5262,6 +6176,16 @@ async function executeActionInner(action, provider, ctx) {
5262
6176
  case "file":
5263
6177
  await provider.deleteFile(id);
5264
6178
  break;
6179
+ case "identity":
6180
+ if (!provider.deleteIdentity)
6181
+ throw new UserError(`Provider '${address.provider}' does not support identities`);
6182
+ await provider.deleteIdentity(id);
6183
+ break;
6184
+ case "channel":
6185
+ if (!provider.deleteChannel)
6186
+ throw new UserError(`Provider '${address.provider}' does not support channels`);
6187
+ await provider.deleteChannel(id);
6188
+ break;
5265
6189
  }
5266
6190
  } catch (err) {
5267
6191
  if (!ApiError.isNotFound(err)) throw err;
@@ -5383,27 +6307,51 @@ async function executeActionInner(action, provider, ctx) {
5383
6307
  break;
5384
6308
  }
5385
6309
  case "memory_store": {
5386
- const createMemoryStore = provider.createMemoryStore?.bind(provider);
5387
- const deleteMemoryStore = provider.deleteMemoryStore?.bind(provider);
5388
- if (!createMemoryStore || !deleteMemoryStore) throw memoryStoreUnsupported(address.provider);
6310
+ const createMemoryStore2 = provider.createMemoryStore?.bind(provider);
6311
+ const deleteMemoryStore2 = provider.deleteMemoryStore?.bind(provider);
6312
+ if (!createMemoryStore2 || !deleteMemoryStore2) throw memoryStoreUnsupported(address.provider);
5389
6313
  const decl = ctx.config.memory_stores[name];
5390
- if (isUpdate) {
5391
- try {
5392
- result = await createMemoryStore(name, decl);
5393
- await deleteMemoryStore(existingId);
5394
- } catch {
5395
- await deleteMemoryStore(existingId);
5396
- result = await createMemoryStore(name, decl);
6314
+ if (!provider.updateMemoryStore || !provider.listMemories || !provider.createMemory || !provider.updateMemory) {
6315
+ throw memoryStoreUnsupported(address.provider);
6316
+ }
6317
+ const reconcile = async (storeId) => {
6318
+ const store = await provider.updateMemoryStore(storeId, {
6319
+ name,
6320
+ description: decl.description,
6321
+ metadata: decl.metadata ?? {}
6322
+ });
6323
+ const current = /* @__PURE__ */ new Map();
6324
+ let cursor;
6325
+ do {
6326
+ const page2 = await provider.listMemories(storeId, { limit: 100, cursor, view: "basic" });
6327
+ for (const memory of page2.data) {
6328
+ if (memory.type === "memory") current.set(memory.path, memory);
6329
+ }
6330
+ cursor = page2.has_more ? page2.next_cursor : void 0;
6331
+ } while (cursor);
6332
+ for (const entry of decl.entries ?? []) {
6333
+ const existing = current.get(entry.key.replace(/^\/+/, ""));
6334
+ if (existing) {
6335
+ if (existing.content_sha256 !== sha256(entry.content)) {
6336
+ await provider.updateMemory(storeId, existing.id, {
6337
+ content: entry.content,
6338
+ expected_content_sha256: existing.content_sha256
6339
+ });
6340
+ }
6341
+ } else {
6342
+ await provider.createMemory(storeId, { path: entry.key, content: entry.content });
6343
+ }
5397
6344
  }
6345
+ return store;
6346
+ };
6347
+ if (isUpdate) {
6348
+ result = await reconcile(existingId);
5398
6349
  } else {
5399
6350
  try {
5400
- result = await createMemoryStore(name, decl);
6351
+ result = await createMemoryStore2(name, decl);
5401
6352
  } catch (err) {
5402
6353
  result = await adoptOnConflict(err, address, provider, ctx.onFeedback, {
5403
- onExisting: async (existing) => {
5404
- await deleteMemoryStore(existing.id);
5405
- return createMemoryStore(name, decl);
5406
- }
6354
+ onExisting: async (existing) => reconcile(existing.id)
5407
6355
  });
5408
6356
  adopted = true;
5409
6357
  }
@@ -5451,6 +6399,63 @@ async function executeActionInner(action, provider, ctx) {
5451
6399
  }
5452
6400
  break;
5453
6401
  }
6402
+ case "identity": {
6403
+ const createIdentity = provider.createIdentity?.bind(provider);
6404
+ const updateIdentity = provider.updateIdentity?.bind(provider);
6405
+ if (!createIdentity || !updateIdentity) {
6406
+ throw new UserError(`Provider '${address.provider}' does not support identities`);
6407
+ }
6408
+ const decl = ctx.config.identities[name];
6409
+ if (decl.identity_id) {
6410
+ const remote2 = await provider.findResource("identity", name, decl.identity_id);
6411
+ if (!remote2?.id) {
6412
+ throw new UserError(
6413
+ `External identity.${name} '${decl.identity_id}' was not found on provider '${address.provider}'.`
6414
+ );
6415
+ }
6416
+ result = remote2;
6417
+ break;
6418
+ }
6419
+ if (isUpdate) {
6420
+ if (ctx.state.getResource(address)?.externally_managed) {
6421
+ throw new UserError(`identity.${name} is recorded as an external reference; refusing to modify it remotely.`);
6422
+ }
6423
+ result = await updateIdentity(existingId, name, decl);
6424
+ } else {
6425
+ try {
6426
+ result = await createIdentity(name, decl);
6427
+ } catch (err) {
6428
+ if (!(err instanceof ConflictError)) throw err;
6429
+ const existing = await provider.findResource("identity", decl.external_id);
6430
+ if (!existing?.id) throw err;
6431
+ result = await updateIdentity(existing.id, name, decl);
6432
+ adopted = true;
6433
+ }
6434
+ }
6435
+ break;
6436
+ }
6437
+ case "channel": {
6438
+ const createChannel = provider.createChannel?.bind(provider);
6439
+ const updateChannel = provider.updateChannel?.bind(provider);
6440
+ if (!createChannel || !updateChannel) {
6441
+ throw new UserError(`Provider '${address.provider}' does not support channels`);
6442
+ }
6443
+ const decl = ctx.config.channels[name];
6444
+ const refs = resolveChannelRefs(name, ctx.config, address.provider, ctx.state);
6445
+ if (isUpdate) {
6446
+ result = await updateChannel(existingId, name, decl, refs);
6447
+ } else {
6448
+ try {
6449
+ result = await createChannel(name, decl, refs);
6450
+ } catch (err) {
6451
+ result = await adoptOnConflict(err, address, provider, ctx.onFeedback, {
6452
+ onExisting: (existing) => updateChannel(existing.id, name, decl, refs)
6453
+ });
6454
+ adopted = true;
6455
+ }
6456
+ }
6457
+ break;
6458
+ }
5454
6459
  case "deployment": {
5455
6460
  const decl = ctx.config.deployments[name];
5456
6461
  const refs = resolveDeploymentRefs(name, ctx.config, address.provider, ctx.state);
@@ -5503,7 +6508,7 @@ async function executeActionInner(action, provider, ctx) {
5503
6508
  ctx.state.setResource({
5504
6509
  address,
5505
6510
  remote_id: result.id,
5506
- externally_managed: priorResource?.externally_managed || type === "environment" && ctx.config.environments?.[name]?.environment_id ? true : void 0,
6511
+ externally_managed: priorResource?.externally_managed || type === "environment" && ctx.config.environments?.[name]?.environment_id || type === "identity" && ctx.config.identities?.[name]?.identity_id ? true : void 0,
5507
6512
  version: result.version,
5508
6513
  content_hash: hash,
5509
6514
  desired_hash: hash,
@@ -5637,6 +6642,13 @@ function collectReferenceDiagnostics(config, diagnostics) {
5637
6642
  const vaultNames = new Set(Object.keys(config.vaults ?? {}));
5638
6643
  const memoryNames = new Set(Object.keys(config.memory_stores ?? {}));
5639
6644
  const agentNames = new Set(Object.keys(config.agents ?? {}));
6645
+ const identityNames = new Set(Object.keys(config.identities ?? {}));
6646
+ if (config.defaults?.identity && !identityNames.has(config.defaults.identity)) {
6647
+ diagnostics.error(
6648
+ "config.defaults.identity.unknown",
6649
+ `defaults.identity references unknown identity '${config.defaults.identity}'`
6650
+ );
6651
+ }
5640
6652
  for (const [name, agent] of Object.entries(config.agents ?? {})) {
5641
6653
  if (agent.environment && !envNames.has(agent.environment)) {
5642
6654
  diagnostics.error(
@@ -5686,6 +6698,23 @@ function collectReferenceDiagnostics(config, diagnostics) {
5686
6698
  );
5687
6699
  }
5688
6700
  }
6701
+ for (const [name, channel] of Object.entries(config.channels ?? {})) {
6702
+ if (!agentNames.has(channel.agent)) {
6703
+ diagnostics.error("config.channel.agent.unknown", `channel.${name}: references unknown agent '${channel.agent}'`);
6704
+ }
6705
+ const identity = channel.identity ?? config.defaults?.identity;
6706
+ if (!identity) {
6707
+ diagnostics.error(
6708
+ "config.channel.identity.required",
6709
+ `channel.${name}: declare identity or configure defaults.identity`
6710
+ );
6711
+ } else if (!identityNames.has(identity)) {
6712
+ diagnostics.error(
6713
+ "config.channel.identity.unknown",
6714
+ `channel.${name}: references unknown identity '${identity}'`
6715
+ );
6716
+ }
6717
+ }
5689
6718
  }
5690
6719
  function collectProviderCapabilities(config, providers, diagnostics) {
5691
6720
  for (const providerName of providers) {
@@ -5698,9 +6727,120 @@ function collectProviderCapabilities(config, providers, diagnostics) {
5698
6727
  continue;
5699
6728
  }
5700
6729
  const caps = def.capabilities;
6730
+ for (const [name, identity] of Object.entries(config.identities ?? {})) {
6731
+ if (identity.provider && identity.provider !== providerName) continue;
6732
+ if (!isSupported(caps, "identity")) {
6733
+ diagnostics.error(
6734
+ `${providerName}.identity.unsupported`,
6735
+ `${caps.identity.reason}. ${caps.identity.remediation ?? ""}`.trim(),
6736
+ { type: "identity", name, provider: providerName }
6737
+ );
6738
+ }
6739
+ }
6740
+ for (const [name, channel] of Object.entries(config.channels ?? {})) {
6741
+ if (channel.provider && channel.provider !== providerName) continue;
6742
+ if (!isSupported(caps, "channel")) {
6743
+ diagnostics.error(
6744
+ `${providerName}.channel.unsupported`,
6745
+ `${caps.channel.reason}. ${caps.channel.remediation ?? ""}`.trim(),
6746
+ { type: "channel", name, provider: providerName }
6747
+ );
6748
+ continue;
6749
+ }
6750
+ if (providerName === "qoder") {
6751
+ const agent = config.agents?.[channel.agent];
6752
+ if (agent?.provider && agent.provider !== providerName) {
6753
+ diagnostics.error(
6754
+ "config.channel.agent.provider_mismatch",
6755
+ `channel.${name}: agent '${channel.agent}' is pinned to provider '${agent.provider}'.`,
6756
+ { type: "channel", name, provider: providerName }
6757
+ );
6758
+ }
6759
+ const identityName = channel.identity ?? config.defaults?.identity;
6760
+ const identity = identityName ? config.identities?.[identityName] : void 0;
6761
+ if (identity?.provider && identity.provider !== providerName) {
6762
+ diagnostics.error(
6763
+ "config.channel.identity.provider_mismatch",
6764
+ `channel.${name}: identity '${identityName}' is pinned to provider '${identity.provider}'.`,
6765
+ { type: "channel", name, provider: providerName }
6766
+ );
6767
+ }
6768
+ if (agent && agent.delivery?.qoder?.type !== "forward") {
6769
+ diagnostics.error(
6770
+ "qoder.channel.forward_template.required",
6771
+ `channel.${name}: Qoder Channels require agent '${channel.agent}' to use delivery.qoder.type: forward.`,
6772
+ { type: "channel", name, provider: providerName }
6773
+ );
6774
+ }
6775
+ const requiredCredentials = {
6776
+ dingtalk: ["client_id", "client_secret"],
6777
+ feishu: ["app_id", "app_secret"],
6778
+ wecom: ["bot_id", "secret"]
6779
+ };
6780
+ if (channel.type === "wechat") {
6781
+ diagnostics.error(
6782
+ "qoder.channel.wechat.credentials.unsupported",
6783
+ `channel.${name}: personal WeChat supports QR binding only; credential-based apply is unavailable.`,
6784
+ { type: "channel", name, provider: providerName }
6785
+ );
6786
+ } else if (!requiredCredentials[channel.type]) {
6787
+ diagnostics.error(
6788
+ "qoder.channel.type.unsupported",
6789
+ `channel.${name}: unsupported Qoder channel type '${channel.type}'.`,
6790
+ { type: "channel", name, provider: providerName }
6791
+ );
6792
+ } else {
6793
+ const missing = requiredCredentials[channel.type].filter((key) => !channel.credentials?.[key]);
6794
+ if (missing.length) {
6795
+ diagnostics.error(
6796
+ "qoder.channel.credentials.required",
6797
+ `channel.${name}: '${channel.type}' requires credentials: ${missing.join(", ")}.`,
6798
+ { type: "channel", name, provider: providerName }
6799
+ );
6800
+ }
6801
+ }
6802
+ }
6803
+ }
5701
6804
  for (const [name, agent] of Object.entries(config.agents ?? {})) {
5702
6805
  if (agent.provider && agent.provider !== providerName) continue;
5703
6806
  const delivery = agent.delivery?.[providerName]?.type ?? "managed";
6807
+ const address = {
6808
+ type: delivery === "forward" ? "template" : "agent",
6809
+ name,
6810
+ provider: providerName
6811
+ };
6812
+ const asksForApproval = agent.tools?.default_permission === "ask" || Object.values(agent.tools?.permissions ?? {}).some((permission) => permission === "ask");
6813
+ if (asksForApproval && !def.features.tool_permissions) {
6814
+ diagnostics.error(
6815
+ `${providerName}.agent.tool_permissions.unsupported`,
6816
+ `agent.${name}: provider '${providerName}' cannot enforce interactive tool permission 'ask'.`,
6817
+ address
6818
+ );
6819
+ }
6820
+ for (const resource of agent.resources ?? []) {
6821
+ if (!def.features.session_resources.includes(resource.type)) {
6822
+ diagnostics.error(
6823
+ `${providerName}.agent.session_resource.${resource.type}.unsupported`,
6824
+ `agent.${name}: provider '${providerName}' does not support Session resource type '${resource.type}'.`,
6825
+ address
6826
+ );
6827
+ }
6828
+ const mountPrefix = providerMountPrefix(providerName);
6829
+ if (mountPrefix && resource.mount_path && resource.mount_path !== mountPrefix && !resource.mount_path.startsWith(`${mountPrefix}/`)) {
6830
+ diagnostics.error(
6831
+ `${providerName}.agent.session_resource.mount_path.invalid`,
6832
+ `agent.${name}: ${providerName} Session resource mount_path must start with '${mountPrefix}/'.`,
6833
+ address
6834
+ );
6835
+ }
6836
+ }
6837
+ if (delivery === "forward" && agent.resources?.length) {
6838
+ diagnostics.error(
6839
+ `${providerName}.template.session_resources.unsupported`,
6840
+ `agent.${name}: Forward delivery cannot attach Agent Session resources; use managed delivery.`,
6841
+ address
6842
+ );
6843
+ }
5704
6844
  if (delivery === "forward" && !isSupported(caps, "template")) {
5705
6845
  diagnostics.error(
5706
6846
  `${providerName}.agent.delivery.forward.unsupported`,
@@ -5774,6 +6914,14 @@ function collectProviderCapabilities(config, providers, diagnostics) {
5774
6914
  }
5775
6915
  }
5776
6916
  for (const [name, deployment] of Object.entries(config.deployments ?? {})) {
6917
+ if (deployment.provider && deployment.provider !== providerName) continue;
6918
+ if (deployment.environment_variables !== void 0) {
6919
+ diagnostics.error(
6920
+ `${providerName}.deployment.environment_variables.unsupported`,
6921
+ `deployment.${name}: environment_variables is supported only by Qoder deployments; remove it or pin this deployment to the qoder provider.`,
6922
+ { type: "deployment", name, provider: providerName }
6923
+ );
6924
+ }
5777
6925
  if (deployment.tunnel && (!deployment.provider || deployment.provider === providerName)) {
5778
6926
  diagnostics.error(
5779
6927
  `${providerName}.deployment.tunnel.unsupported`,
@@ -5911,6 +7059,13 @@ function buildDependencyGraph(config, targetProviders) {
5911
7059
  addNode({ type: "file", name, provider });
5912
7060
  }
5913
7061
  }
7062
+ if (config.identities && isSupported(caps, "identity")) {
7063
+ for (const name of Object.keys(config.identities)) {
7064
+ const decl = config.identities[name];
7065
+ if (decl.provider && decl.provider !== provider) continue;
7066
+ addNode({ type: "identity", name, provider });
7067
+ }
7068
+ }
5914
7069
  if (config.agents) {
5915
7070
  for (const name of Object.keys(config.agents)) {
5916
7071
  const decl = config.agents[name];
@@ -6002,6 +7157,23 @@ function buildDependencyGraph(config, targetProviders) {
6002
7157
  }
6003
7158
  }
6004
7159
  }
7160
+ if (config.channels && isSupported(caps, "channel")) {
7161
+ for (const name of Object.keys(config.channels)) {
7162
+ const decl = config.channels[name];
7163
+ if (decl.provider && decl.provider !== provider) continue;
7164
+ const channelAddr = { type: "channel", name, provider };
7165
+ addNode(channelAddr);
7166
+ const agentDecl = config.agents?.[decl.agent];
7167
+ const agentType = agentDecl ? resolveAgentMaterialization(provider, agentDecl).resourceType : "agent";
7168
+ const agentAddr = { type: agentType, name: decl.agent, provider };
7169
+ if (nodes.has(addressKey(agentAddr))) addEdge(channelAddr, agentAddr);
7170
+ const identityName = decl.identity ?? config.defaults?.identity;
7171
+ if (identityName) {
7172
+ const identityAddr = { type: "identity", name: identityName, provider };
7173
+ if (nodes.has(addressKey(identityAddr))) addEdge(channelAddr, identityAddr);
7174
+ }
7175
+ }
7176
+ }
6005
7177
  }
6006
7178
  return { nodes, edges };
6007
7179
  }
@@ -6071,9 +7243,28 @@ async function buildPlan(config, state, options = {}) {
6071
7243
  );
6072
7244
  }
6073
7245
  }
6074
- const isExternalEnv = address.type === "environment" && Boolean(config.environments?.[address.name]?.environment_id);
6075
- const createReason = isExternalEnv ? "Record external environment reference (no remote mutation)" : "Resource does not exist in state";
6076
- const updateSuffix = isExternalEnv ? " \u2014 external reference, no remote mutation" : "";
7246
+ if (address.type === "identity" && existing) {
7247
+ const identityDecl = config.identities?.[address.name];
7248
+ if (existing.externally_managed && identityDecl && !identityDecl.identity_id) {
7249
+ diagnostics.error(
7250
+ "plan.identity.ownership_transition",
7251
+ `identity.${address.name} is recorded as an external reference (${existing.remote_id ?? "unknown id"}); replacing identity_id with a managed declaration would modify and eventually delete an Identity this project does not own. Restore identity_id or release the state reference first.`,
7252
+ address
7253
+ );
7254
+ stateIndex.delete(key);
7255
+ continue;
7256
+ }
7257
+ if (!existing.externally_managed && existing.remote_id && identityDecl?.identity_id && identityDecl.identity_id !== existing.remote_id) {
7258
+ diagnostics.warning(
7259
+ "plan.identity.ownership_orphan",
7260
+ `identity.${address.name}: switching to external reference '${identityDecl.identity_id}' orphans the previously managed Identity '${existing.remote_id}'.`,
7261
+ address
7262
+ );
7263
+ }
7264
+ }
7265
+ const isExternalReference2 = address.type === "environment" && Boolean(config.environments?.[address.name]?.environment_id) || address.type === "identity" && Boolean(config.identities?.[address.name]?.identity_id);
7266
+ const createReason = isExternalReference2 ? `Record external ${address.type} reference (no remote mutation)` : "Resource does not exist in state";
7267
+ const updateSuffix = isExternalReference2 ? " \u2014 external reference, no remote mutation" : "";
6077
7268
  if (!existing) {
6078
7269
  actions.push({
6079
7270
  action: "create",
@@ -6319,7 +7510,9 @@ var IMPORTABLE_RESOURCE_TYPES = /* @__PURE__ */ new Set([
6319
7510
  "memory_store",
6320
7511
  "skill",
6321
7512
  "agent",
6322
- "template"
7513
+ "template",
7514
+ "identity",
7515
+ "channel"
6323
7516
  ]);
6324
7517
  async function importResource(ctx, address, remoteId, options = {}) {
6325
7518
  if (!IMPORTABLE_RESOURCE_TYPES.has(address.type)) {
@@ -6482,25 +7675,25 @@ function resolveSyncProvider(config, explicitProvider) {
6482
7675
  );
6483
7676
  }
6484
7677
  async function syncProviderResourcesFromEnv(opts) {
6485
- const adapter = buildProviderFromEnv(opts.provider);
7678
+ const adapter2 = buildProviderFromEnv(opts.provider);
6486
7679
  const providers = await providersBlockFromFile(opts.configPath, opts.provider);
6487
- return assembleSyncedConfig(adapter, opts.provider, {
7680
+ return assembleSyncedConfig(adapter2, opts.provider, {
6488
7681
  types: opts.types,
6489
7682
  version: "1",
6490
7683
  providers
6491
7684
  });
6492
7685
  }
6493
7686
  async function syncProviderResourcesFromContext(ctx, opts) {
6494
- const adapter = getRuntimeProvider(ctx, opts.provider);
7687
+ const adapter2 = getRuntimeProvider(ctx, opts.provider);
6495
7688
  const providers = await providersBlockFromFile(ctx.configPath ?? opts.configPath, opts.provider);
6496
- return assembleSyncedConfig(adapter, opts.provider, {
7689
+ return assembleSyncedConfig(adapter2, opts.provider, {
6497
7690
  types: opts.types,
6498
7691
  version: ctx.config.version ?? "1",
6499
7692
  providers
6500
7693
  });
6501
7694
  }
6502
- async function assembleSyncedConfig(adapter, provider, opts) {
6503
- if (!adapter.exportResources) {
7695
+ async function assembleSyncedConfig(adapter2, provider, opts) {
7696
+ if (!adapter2.exportResources) {
6504
7697
  throw new UserError(`Provider '${provider}' does not support sync (no exportResources).`);
6505
7698
  }
6506
7699
  const types = opts.types ?? ["environment", "vault", "file", "skill", "agent"];
@@ -6511,7 +7704,7 @@ async function assembleSyncedConfig(adapter, provider, opts) {
6511
7704
  if (!groupKey) {
6512
7705
  throw new UserError(`Resource type '${type}' is not syncable yet.`);
6513
7706
  }
6514
- const exported = await adapter.exportResources(type);
7707
+ const exported = await adapter2.exportResources(type);
6515
7708
  let group = groups[groupKey];
6516
7709
  if (!group) {
6517
7710
  group = {};
@@ -6523,8 +7716,8 @@ async function assembleSyncedConfig(adapter, provider, opts) {
6523
7716
  }
6524
7717
  }
6525
7718
  let skillFiles;
6526
- if (types.includes("skill") && adapter.downloadAllSkillFiles) {
6527
- skillFiles = await adapter.downloadAllSkillFiles();
7719
+ if (types.includes("skill") && adapter2.downloadAllSkillFiles) {
7720
+ skillFiles = await adapter2.downloadAllSkillFiles();
6528
7721
  }
6529
7722
  const config = {
6530
7723
  version: opts.version ?? "1",
@@ -6691,6 +7884,12 @@ async function readYaml(path) {
6691
7884
  }
6692
7885
 
6693
7886
  // src/internal/core/deployment-runtime.ts
7887
+ async function listRemoteDeploymentsForContext(ctx, provider, filter) {
7888
+ const adapter2 = getRuntimeProvider(ctx, provider);
7889
+ if (!adapter2.listDeployments)
7890
+ throw new UserError(`Provider '${provider}' does not support remote deployment listing.`);
7891
+ return adapter2.listDeployments(filter);
7892
+ }
6694
7893
  function listDeploymentsForContext(ctx, providerFilter) {
6695
7894
  let rows = ctx.state.listResources().filter((resource) => resource.address.type === "deployment");
6696
7895
  if (providerFilter) {
@@ -6709,9 +7908,9 @@ function listDeploymentsForContext(ctx, providerFilter) {
6709
7908
  };
6710
7909
  });
6711
7910
  }
6712
- async function getDeploymentDetailsForContext(ctx, name, adapter, resolvedProvider) {
7911
+ async function getDeploymentDetailsForContext(ctx, name, adapter2, resolvedProvider) {
6713
7912
  const provider = resolvedProvider ?? resolveDeploymentProvider(name, ctx.config);
6714
- const effectiveAdapter = adapter ?? getRuntimeProvider(ctx, provider);
7913
+ const effectiveAdapter = adapter2 ?? getRuntimeProvider(ctx, provider);
6715
7914
  const depCtx = buildDeploymentContext(ctx, name, provider);
6716
7915
  return {
6717
7916
  name,
@@ -6725,9 +7924,9 @@ async function getDeploymentDetailsForContext(ctx, name, adapter, resolvedProvid
6725
7924
  info: await effectiveAdapter.getDeployment(depCtx)
6726
7925
  };
6727
7926
  }
6728
- async function runDeploymentForContext(ctx, name, adapter, resolvedProvider) {
7927
+ async function runDeploymentForContext(ctx, name, adapter2, resolvedProvider) {
6729
7928
  const provider = resolvedProvider ?? resolveDeploymentProvider(name, ctx.config);
6730
- const effectiveAdapter = adapter ?? getRuntimeProvider(ctx, provider);
7929
+ const effectiveAdapter = adapter2 ?? getRuntimeProvider(ctx, provider);
6731
7930
  const depCtx = buildDeploymentContext(ctx, name, provider);
6732
7931
  return {
6733
7932
  name,
@@ -6735,6 +7934,14 @@ async function runDeploymentForContext(ctx, name, adapter, resolvedProvider) {
6735
7934
  result: await effectiveAdapter.runDeployment(depCtx)
6736
7935
  };
6737
7936
  }
7937
+ async function pauseDeploymentForContext(ctx, name, paused, resolvedProvider) {
7938
+ const provider = resolvedProvider ?? resolveDeploymentProvider(name, ctx.config);
7939
+ const adapter2 = getRuntimeProvider(ctx, provider);
7940
+ const operation = paused ? adapter2.pauseDeployment : adapter2.unpauseDeployment;
7941
+ if (!operation)
7942
+ throw new UserError(`Provider '${provider}' does not support ${paused ? "pausing" : "unpausing"} deployments.`);
7943
+ return operation.call(adapter2, buildDeploymentContext(ctx, name, provider));
7944
+ }
6738
7945
  function getDeploymentRuntimeProviderForContext(ctx, name, overrideProvider) {
6739
7946
  return resolveDeploymentProvider(name, ctx.config, overrideProvider);
6740
7947
  }
@@ -6774,13 +7981,15 @@ function buildDeploymentContext(ctx, name, provider) {
6774
7981
  // src/internal/core/destroy-runtime.ts
6775
7982
  var destroyOrder = {
6776
7983
  deployment: 0,
7984
+ channel: 0,
6777
7985
  agent: 1,
6778
7986
  template: 1,
6779
- skill: 2,
6780
- memory_store: 3,
6781
- vault: 4,
6782
- file: 5,
6783
- environment: 6
7987
+ identity: 2,
7988
+ skill: 3,
7989
+ memory_store: 4,
7990
+ vault: 5,
7991
+ file: 6,
7992
+ environment: 7
6784
7993
  };
6785
7994
  function planDestroyProjectContext(ctx) {
6786
7995
  const resources = [...ctx.state.listResources()].sort(
@@ -6811,7 +8020,7 @@ async function destroyPlannedProjectResources(planned, options = {}) {
6811
8020
  };
6812
8021
  }
6813
8022
  async function destroyOneResource(ctx, resource, options) {
6814
- if (isExternalEnvironment(ctx, resource)) {
8023
+ if (isExternalReference(ctx, resource)) {
6815
8024
  ctx.state.removeResource(resource.address);
6816
8025
  return successResult(resource, "reference_removed");
6817
8026
  }
@@ -6875,8 +8084,15 @@ async function destroyOneResource(ctx, resource, options) {
6875
8084
  return failureResult(resource, error);
6876
8085
  }
6877
8086
  }
6878
- function isExternalEnvironment(ctx, resource) {
6879
- return resource.address.type === "environment" && (resource.externally_managed || Boolean(ctx.config.environments?.[resource.address.name]?.environment_id));
8087
+ function isExternalReference(ctx, resource) {
8088
+ if (resource.externally_managed) return true;
8089
+ if (resource.address.type === "environment") {
8090
+ return Boolean(ctx.config.environments?.[resource.address.name]?.environment_id);
8091
+ }
8092
+ if (resource.address.type === "identity") {
8093
+ return Boolean(ctx.config.identities?.[resource.address.name]?.identity_id);
8094
+ }
8095
+ return false;
6880
8096
  }
6881
8097
  function successResult(resource, reason) {
6882
8098
  return { resource, status: "success", reason };
@@ -6916,6 +8132,17 @@ async function deleteRemoteResource(provider, type, id, cascade) {
6916
8132
  case "deployment":
6917
8133
  await provider.deleteDeployment(id);
6918
8134
  return;
8135
+ case "identity":
8136
+ if (!provider.deleteIdentity) throw new UserError(`Provider does not support identities`);
8137
+ await provider.deleteIdentity(id);
8138
+ return;
8139
+ case "channel":
8140
+ if (!provider.deleteChannel) throw new UserError(`Provider does not support channels`);
8141
+ await provider.deleteChannel(id);
8142
+ return;
8143
+ case "file":
8144
+ await provider.deleteFile(id);
8145
+ return;
6919
8146
  }
6920
8147
  }
6921
8148
  function isReferencedError(error) {
@@ -6930,11 +8157,11 @@ async function listProviderModelsForContext(providers, providerFilter) {
6930
8157
  const targetProviders = providerFilter ? [providerFilter] : Array.from(providers.keys());
6931
8158
  const result = [];
6932
8159
  for (const name of targetProviders) {
6933
- const adapter = providers.get(name);
6934
- if (!adapter) {
8160
+ const adapter2 = providers.get(name);
8161
+ if (!adapter2) {
6935
8162
  throw new UserError(`Provider '${name}' is not configured.`);
6936
8163
  }
6937
- if (!adapter.listModels) {
8164
+ if (!adapter2.listModels) {
6938
8165
  result.push({
6939
8166
  provider: name,
6940
8167
  supportsDynamicListing: false,
@@ -6945,7 +8172,7 @@ async function listProviderModelsForContext(providers, providerFilter) {
6945
8172
  result.push({
6946
8173
  provider: name,
6947
8174
  supportsDynamicListing: true,
6948
- models: await adapter.listModels()
8175
+ models: await adapter2.listModels()
6949
8176
  });
6950
8177
  }
6951
8178
  return result;
@@ -6960,6 +8187,89 @@ function listProviderDiscovery() {
6960
8187
  })).sort((a, b) => a.name.localeCompare(b.name));
6961
8188
  }
6962
8189
 
8190
+ // src/internal/core/memory-runtime.ts
8191
+ function adapter(providers, provider) {
8192
+ const value = providers.get(provider);
8193
+ if (!value) throw new UserError(`Provider '${provider}' is not configured.`);
8194
+ return value;
8195
+ }
8196
+ function method(value, name) {
8197
+ const fn = value[name];
8198
+ if (typeof fn !== "function")
8199
+ throw new UserError(`Provider '${value.name}' does not support memory operation '${String(name)}'.`);
8200
+ return fn.bind(value);
8201
+ }
8202
+ function listMemoryStores(providers, provider, options) {
8203
+ const value = adapter(providers, provider);
8204
+ return method(value, "listMemoryStores")(options);
8205
+ }
8206
+ function getMemoryProviderCapabilities(providers, provider) {
8207
+ const value = adapter(providers, provider);
8208
+ if (!value.memoryCapabilities) throw new UserError(`Provider '${provider}' does not support memory stores.`);
8209
+ return value.memoryCapabilities;
8210
+ }
8211
+ async function createMemoryStore(providers, provider, input) {
8212
+ const value = adapter(providers, provider);
8213
+ const created = await method(value, "createMemoryStore")(input.name, {
8214
+ description: input.description ?? "",
8215
+ metadata: input.metadata
8216
+ });
8217
+ if (!created.id) throw new UserError(`Provider '${provider}' returned no memory store id.`);
8218
+ return method(value, "getMemoryStore")(created.id);
8219
+ }
8220
+ function deleteMemoryStore(providers, provider, id) {
8221
+ const value = adapter(providers, provider);
8222
+ return method(value, "deleteMemoryStore")(id);
8223
+ }
8224
+ function getMemoryStore(providers, provider, id) {
8225
+ const value = adapter(providers, provider);
8226
+ return method(value, "getMemoryStore")(id);
8227
+ }
8228
+ function updateMemoryStore(providers, provider, id, input) {
8229
+ const value = adapter(providers, provider);
8230
+ return method(value, "updateMemoryStore")(id, input);
8231
+ }
8232
+ function archiveMemoryStore(providers, provider, id) {
8233
+ const value = adapter(providers, provider);
8234
+ return method(value, "archiveMemoryStore")(id);
8235
+ }
8236
+ function createMemory(providers, provider, storeId, input) {
8237
+ const value = adapter(providers, provider);
8238
+ return method(value, "createMemory")(storeId, input);
8239
+ }
8240
+ function batchCreateMemories(providers, provider, storeId, input) {
8241
+ const value = adapter(providers, provider);
8242
+ return method(value, "batchCreateMemories")(storeId, input);
8243
+ }
8244
+ function listMemories(providers, provider, storeId, options) {
8245
+ const value = adapter(providers, provider);
8246
+ return method(value, "listMemories")(storeId, options);
8247
+ }
8248
+ function getMemory(providers, provider, storeId, memoryId) {
8249
+ const value = adapter(providers, provider);
8250
+ return method(value, "getMemory")(storeId, memoryId);
8251
+ }
8252
+ function updateMemory(providers, provider, storeId, memoryId, input) {
8253
+ const value = adapter(providers, provider);
8254
+ return method(value, "updateMemory")(storeId, memoryId, input);
8255
+ }
8256
+ function deleteMemory(providers, provider, storeId, memoryId, expected) {
8257
+ const value = adapter(providers, provider);
8258
+ return method(value, "deleteMemory")(storeId, memoryId, expected);
8259
+ }
8260
+ function listMemoryVersions(providers, provider, storeId, options) {
8261
+ const value = adapter(providers, provider);
8262
+ return method(value, "listMemoryVersions")(storeId, options);
8263
+ }
8264
+ function getMemoryVersion(providers, provider, storeId, versionId) {
8265
+ const value = adapter(providers, provider);
8266
+ return method(value, "getMemoryVersion")(storeId, versionId);
8267
+ }
8268
+ function redactMemoryVersion(providers, provider, storeId, versionId) {
8269
+ const value = adapter(providers, provider);
8270
+ return method(value, "redactMemoryVersion")(storeId, versionId);
8271
+ }
8272
+
6963
8273
  // src/internal/core/agent-builder.ts
6964
8274
  function buildAgentDecl(base, input) {
6965
8275
  const model = input.model ?? base?.model;
@@ -7033,13 +8343,33 @@ function buildSessionBindings(agentName, config, provider, state, options = {})
7033
8343
  const available = Object.keys(config.agents ?? {}).join(", ");
7034
8344
  throw new UserError(`Agent '${agentName}' not found in config. Available agents: ${available || "(none)"}`);
7035
8345
  }
8346
+ const sessionResources = options.resources ?? agent.resources;
8347
+ const providerFeatures = getProvider(provider)?.features;
8348
+ for (const resource of sessionResources ?? []) {
8349
+ if (!providerFeatures?.session_resources.includes(resource.type)) {
8350
+ throw new UserError(
8351
+ `Provider '${provider}' does not support Session resource type '${resource.type}' for agent '${agentName}'.`
8352
+ );
8353
+ }
8354
+ }
7036
8355
  if (resolveAgentMaterialization(provider, agent).resourceType === "template") {
8356
+ if (sessionResources?.length) {
8357
+ throw new UserError(
8358
+ `Forward session for '${agentName}' cannot attach Agent resources. Use managed delivery for GitHub repositories.`
8359
+ );
8360
+ }
7037
8361
  const templateId = requireRef(state, { type: "template", name: agentName, provider });
7038
- const identityId = options.identityId ?? config.defaults?.session?.qoder?.identity_id;
8362
+ const defaultIdentity = config.defaults?.identity;
8363
+ const identityId = options.identityId ?? (defaultIdentity ? requireRef(state, { type: "identity", name: defaultIdentity, provider }) : void 0);
8364
+ if (!identityId) {
8365
+ throw new UserError(
8366
+ `Forward session for '${agentName}' requires an Identity. Configure defaults.identity or pass --identity-id.`
8367
+ );
8368
+ }
7039
8369
  return {
7040
8370
  delivery: "forward",
7041
8371
  template_id: templateId,
7042
- ...identityId ? { identity_id: identityId } : {},
8372
+ identity_id: identityId,
7043
8373
  files: (options.files ?? []).map((file) => ({ file_id: file.fileId, mount_path: file.mountPath })),
7044
8374
  title: options.title,
7045
8375
  metadata: options.metadata
@@ -7085,6 +8415,7 @@ function buildSessionBindings(agentName, config, provider, state, options = {})
7085
8415
  vault_ids: vaultIds,
7086
8416
  memory_store_ids: memoryStoreIds,
7087
8417
  files: (options.files ?? []).map((f) => ({ file_id: f.fileId, mount_path: f.mountPath })),
8418
+ resources: sessionResources,
7088
8419
  title: options.title,
7089
8420
  metadata: options.metadata
7090
8421
  };
@@ -7123,9 +8454,9 @@ async function listCloudAgents(ctx, options = {}) {
7123
8454
  throw new UserError("Multiple providers configured. Pass `provider` to list cloud agents.");
7124
8455
  }
7125
8456
  }
7126
- const adapter = getRuntimeProvider(ctx, provider);
7127
- if (!adapter.listAgents) return [];
7128
- return adapter.listAgents({ prefix: options.prefix, limit: options.limit });
8457
+ const adapter2 = getRuntimeProvider(ctx, provider);
8458
+ if (!adapter2.listAgents) return [];
8459
+ return adapter2.listAgents({ prefix: options.prefix, limit: options.limit });
7129
8460
  }
7130
8461
  function resolveSingleProvider(ctx, provider) {
7131
8462
  if (provider) return provider;
@@ -7134,55 +8465,55 @@ function resolveSingleProvider(ctx, provider) {
7134
8465
  throw new UserError("Multiple providers configured. Pass `provider` to target one.");
7135
8466
  }
7136
8467
  async function listCloudEnvironments(ctx, options = {}) {
7137
- const adapter = getRuntimeProvider(
8468
+ const adapter2 = getRuntimeProvider(
7138
8469
  ctx,
7139
8470
  resolveSingleProvider(ctx, options.provider)
7140
8471
  );
7141
- if (!adapter.listEnvironments) return [];
7142
- return adapter.listEnvironments({ limit: options.limit });
8472
+ if (!adapter2.listEnvironments) return [];
8473
+ return adapter2.listEnvironments({ limit: options.limit });
7143
8474
  }
7144
8475
  async function createCloudEnvironment(ctx, name, decl, options = {}) {
7145
- const adapter = getRuntimeProvider(
8476
+ const adapter2 = getRuntimeProvider(
7146
8477
  ctx,
7147
8478
  resolveSingleProvider(ctx, options.provider)
7148
8479
  );
7149
- return adapter.createEnvironment(name, decl);
8480
+ return adapter2.createEnvironment(name, decl);
7150
8481
  }
7151
8482
  async function deleteCloudEnvironment(ctx, id, options = {}) {
7152
- const adapter = getRuntimeProvider(
8483
+ const adapter2 = getRuntimeProvider(
7153
8484
  ctx,
7154
8485
  resolveSingleProvider(ctx, options.provider)
7155
8486
  );
7156
- await adapter.deleteEnvironment(id);
8487
+ await adapter2.deleteEnvironment(id);
7157
8488
  }
7158
8489
  async function listCloudVaults(ctx, options = {}) {
7159
- const adapter = getRuntimeProvider(
8490
+ const adapter2 = getRuntimeProvider(
7160
8491
  ctx,
7161
8492
  resolveSingleProvider(ctx, options.provider)
7162
8493
  );
7163
- if (!adapter.listVaults) return [];
7164
- return adapter.listVaults({ limit: options.limit });
8494
+ if (!adapter2.listVaults) return [];
8495
+ return adapter2.listVaults({ limit: options.limit });
7165
8496
  }
7166
8497
  async function createCloudVault(ctx, name, decl, options = {}) {
7167
- const adapter = getRuntimeProvider(
8498
+ const adapter2 = getRuntimeProvider(
7168
8499
  ctx,
7169
8500
  resolveSingleProvider(ctx, options.provider)
7170
8501
  );
7171
- return adapter.createVault(name, decl);
8502
+ return adapter2.createVault(name, decl);
7172
8503
  }
7173
8504
  async function deleteCloudVault(ctx, id, options = {}) {
7174
- const adapter = getRuntimeProvider(
8505
+ const adapter2 = getRuntimeProvider(
7175
8506
  ctx,
7176
8507
  resolveSingleProvider(ctx, options.provider)
7177
8508
  );
7178
- await adapter.deleteVault(id);
8509
+ await adapter2.deleteVault(id);
7179
8510
  }
7180
8511
  async function archiveCloudAgent(ctx, id, options = {}) {
7181
- const adapter = getRuntimeProvider(
8512
+ const adapter2 = getRuntimeProvider(
7182
8513
  ctx,
7183
8514
  resolveSingleProvider(ctx, options.provider)
7184
8515
  );
7185
- await adapter.deleteAgent(id);
8516
+ await adapter2.deleteAgent(id);
7186
8517
  }
7187
8518
  function getAgent(ctx, agentId) {
7188
8519
  const agent = ctx.config.agents?.[agentId];
@@ -7454,6 +8785,7 @@ function toAgentSkillRef(skill) {
7454
8785
  var TERMINAL_SESSION_STATUSES = /* @__PURE__ */ new Set(["idle", "completed", "failed", "terminated", "deleted"]);
7455
8786
  var DEFAULT_POLL_INTERVAL_MS = 2e3;
7456
8787
  var DEFAULT_POLL_TIMEOUT_MS = 10 * 60 * 1e3;
8788
+ var POLL_INITIAL_INTERVAL_MS = 300;
7457
8789
  function resolveAgentName(agents, agentName) {
7458
8790
  if (agentName) return agentName;
7459
8791
  const names = Object.keys(agents ?? {});
@@ -7469,11 +8801,11 @@ function isTerminalSessionStatus(status) {
7469
8801
  function resolveSessionRuntime(ctx, target = {}) {
7470
8802
  const agentName = resolveAgentName(ctx.config.agents, target.agent);
7471
8803
  const provider = resolveSessionProvider(agentName, ctx.config, target.provider);
7472
- const adapter = getRuntimeProvider(ctx, provider);
7473
- return { agentName, provider, adapter };
8804
+ const adapter2 = getRuntimeProvider(ctx, provider);
8805
+ return { agentName, provider, adapter: adapter2 };
7474
8806
  }
7475
8807
  async function createSessionForAgent(ctx, options = {}) {
7476
- const { agentName, provider, adapter } = resolveSessionRuntime(ctx, options);
8808
+ const { agentName, provider, adapter: adapter2 } = resolveSessionRuntime(ctx, options);
7477
8809
  const bindings = buildSessionBindings(agentName, ctx.config, provider, ctx.state, {
7478
8810
  identityId: options.identityId,
7479
8811
  environment: options.environment,
@@ -7484,14 +8816,15 @@ async function createSessionForAgent(ctx, options = {}) {
7484
8816
  vaultIds: options.vaultIds,
7485
8817
  memoryStores: options.memoryStores,
7486
8818
  files: options.files,
8819
+ resources: options.resources,
7487
8820
  title: options.title,
7488
8821
  metadata: options.metadata
7489
8822
  });
7490
- const session = await adapter.createSession(bindings);
8823
+ const session = await adapter2.createSession(bindings);
7491
8824
  return { agentName, provider, session };
7492
8825
  }
7493
8826
  async function startSessionRun(ctx, prompt, options = {}) {
7494
- const { agentName, provider, adapter } = resolveSessionRuntime(ctx, options);
8827
+ const { agentName, provider, adapter: adapter2 } = resolveSessionRuntime(ctx, options);
7495
8828
  const bindings = buildSessionBindings(agentName, ctx.config, provider, ctx.state, {
7496
8829
  identityId: options.identityId,
7497
8830
  environment: options.environment,
@@ -7502,60 +8835,59 @@ async function startSessionRun(ctx, prompt, options = {}) {
7502
8835
  vaultIds: options.vaultIds,
7503
8836
  memoryStores: options.memoryStores,
7504
8837
  files: options.files,
8838
+ resources: options.resources,
7505
8839
  title: options.title,
7506
8840
  metadata: options.metadata
7507
8841
  });
7508
- const session = await adapter.createSession(bindings);
8842
+ const session = await adapter2.createSession(bindings);
7509
8843
  return {
7510
8844
  agentName,
7511
8845
  provider,
7512
8846
  session,
7513
- events: streamMessageEvents(adapter, session.id, preparePromptForProvider(prompt, bindings.files, provider))
8847
+ events: streamMessageEvents(adapter2, session.id, prepareInitialSessionPrompt(prompt, bindings, provider))
7514
8848
  };
7515
8849
  }
7516
- function streamMessageEvents(adapter, sessionId, message) {
7517
- if (adapter.eventResume) {
7518
- return streamWithResume(adapter, sessionId, message);
8850
+ function streamMessageEvents(adapter2, sessionId, message) {
8851
+ if (adapter2.eventResume) {
8852
+ return streamWithResume(adapter2, sessionId, message);
7519
8853
  }
7520
- return streamConnectBeforeSend(adapter, sessionId, message);
8854
+ return streamConnectBeforeSend(adapter2, sessionId, message);
7521
8855
  }
7522
8856
  async function sendSessionMessageStreaming(ctx, sessionId, message, options = {}) {
7523
- const adapter = resolveDirectAdapter(ctx, options.provider);
7524
- return streamMessageEvents(adapter, sessionId, message);
8857
+ const adapter2 = resolveDirectAdapter(ctx, options.provider);
8858
+ return streamMessageEvents(adapter2, sessionId, message);
7525
8859
  }
7526
8860
  async function startSessionRunPolling(ctx, prompt, options = {}) {
7527
- const run = await createSessionForAgent(ctx, options);
7528
- const adapter = getRuntimeProvider(ctx, run.provider);
7529
- const hintedPrompt = preparePromptForProvider(
7530
- prompt,
7531
- options.files?.map((f) => ({ mount_path: f.mountPath })),
7532
- run.provider
7533
- );
7534
- const collected = await sendSessionMessageAndCollectEvents(adapter, run.session.id, hintedPrompt, options);
7535
- return { ...run, ...collected };
7536
- }
7537
- async function sendSessionMessageAndCollectEvents(adapter, sessionId, message, options = {}) {
7538
- const eventId = await adapter.sendSessionMessage(sessionId, message);
7539
- return collectEventsUntilTerminal(adapter, sessionId, {
7540
- afterId: adapter.eventResume ? eventId : void 0,
8861
+ const { agentName, provider, adapter: adapter2 } = resolveSessionRuntime(ctx, options);
8862
+ const bindings = buildSessionBindings(agentName, ctx.config, provider, ctx.state, options);
8863
+ const session = await adapter2.createSession(bindings);
8864
+ const initialPrompt = prepareInitialSessionPrompt(prompt, bindings, provider);
8865
+ const collected = await sendSessionMessageAndCollectEvents(adapter2, session.id, initialPrompt, options);
8866
+ return { agentName, provider, session, ...collected };
8867
+ }
8868
+ async function sendSessionMessageAndCollectEvents(adapter2, sessionId, message, options = {}) {
8869
+ const eventId = await adapter2.sendSessionMessage(sessionId, message);
8870
+ return collectEventsUntilTerminal(adapter2, sessionId, {
8871
+ afterId: adapter2.eventResume ? eventId : void 0,
7541
8872
  pollIntervalMs: options.pollIntervalMs,
7542
8873
  pollTimeoutMs: options.pollTimeoutMs
7543
8874
  }).then((result) => ({ eventId, ...result }));
7544
8875
  }
7545
8876
  async function sendSessionMessagePolling(ctx, sessionId, message, options = {}) {
7546
- const adapter = resolveDirectAdapter(ctx, options.provider);
7547
- return sendSessionMessageAndCollectEvents(adapter, sessionId, message, options);
8877
+ const adapter2 = resolveDirectAdapter(ctx, options.provider);
8878
+ return sendSessionMessageAndCollectEvents(adapter2, sessionId, message, options);
7548
8879
  }
7549
- async function collectEventsUntilTerminal(adapter, sessionId, options = {}) {
8880
+ async function collectEventsUntilTerminal(adapter2, sessionId, options = {}) {
7550
8881
  const start = Date.now();
7551
- const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
8882
+ const maxPollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
7552
8883
  const pollTimeoutMs = options.pollTimeoutMs ?? DEFAULT_POLL_TIMEOUT_MS;
8884
+ let currentIntervalMs = Math.min(POLL_INITIAL_INTERVAL_MS, maxPollIntervalMs);
7553
8885
  let terminalStatus = "idle";
7554
8886
  let result;
7555
8887
  if (options.afterId) {
7556
8888
  while (true) {
7557
8889
  assertNotTimedOut(start, pollTimeoutMs);
7558
- result = await adapter.listSessionEvents(sessionId, {
8890
+ result = await adapter2.listSessionEvents(sessionId, {
7559
8891
  limit: 100,
7560
8892
  after_id: options.afterId
7561
8893
  });
@@ -7566,19 +8898,21 @@ async function collectEventsUntilTerminal(adapter, sessionId, options = {}) {
7566
8898
  terminalStatus = terminalEvent.status;
7567
8899
  break;
7568
8900
  }
7569
- await delay(pollIntervalMs);
8901
+ await delay(currentIntervalMs);
8902
+ currentIntervalMs = Math.min(currentIntervalMs * 2, maxPollIntervalMs);
7570
8903
  }
7571
8904
  } else {
7572
8905
  while (true) {
7573
8906
  assertNotTimedOut(start, pollTimeoutMs);
7574
- const session = await adapter.getSession(sessionId);
8907
+ const session = await adapter2.getSession(sessionId);
7575
8908
  if (isTerminalSessionStatus(session.status)) {
7576
8909
  terminalStatus = session.status;
7577
8910
  break;
7578
8911
  }
7579
- await delay(pollIntervalMs);
8912
+ await delay(currentIntervalMs);
8913
+ currentIntervalMs = Math.min(currentIntervalMs * 2, maxPollIntervalMs);
7580
8914
  }
7581
- result = await adapter.listSessionEvents(sessionId, { limit: 100 });
8915
+ result = await adapter2.listSessionEvents(sessionId, { limit: 100 });
7582
8916
  }
7583
8917
  return { terminalStatus, result };
7584
8918
  }
@@ -7613,9 +8947,9 @@ async function listSessionsForProject(ctx, options = {}) {
7613
8947
  throw new UserError("Multiple providers configured. Use --provider to specify one.");
7614
8948
  }
7615
8949
  }
7616
- const adapter = getRuntimeProvider(ctx, provider);
7617
- const result = await adapter.listSessions(agentId ? { ...options.filter, agent_id: agentId } : options.filter);
7618
- return { provider, adapter, agentId, agentName, result };
8950
+ const adapter2 = getRuntimeProvider(ctx, provider);
8951
+ const result = await adapter2.listSessions(agentId ? { ...options.filter, agent_id: agentId } : options.filter);
8952
+ return { provider, adapter: adapter2, agentId, agentName, result };
7619
8953
  }
7620
8954
  async function listSessionSummaries(ctx, options = {}) {
7621
8955
  const listed = await listSessionsForProject(ctx, options);
@@ -7653,48 +8987,48 @@ async function listSessionEvents(ctx, sessionId, options = {}) {
7653
8987
  );
7654
8988
  }
7655
8989
  async function uploadFile(ctx, content, filename, options = {}) {
7656
- const adapter = resolveDirectAdapter(ctx, options.provider);
7657
- const purpose = options.purpose ?? defaultFileUploadPurpose(adapter.name);
7658
- const info = await adapter.uploadFileContent(content, filename, {
8990
+ const adapter2 = resolveDirectAdapter(ctx, options.provider);
8991
+ const purpose = options.purpose ?? defaultFileUploadPurpose(adapter2.name);
8992
+ const info = await adapter2.uploadFileContent(content, filename, {
7659
8993
  mimeType: options.mimeType,
7660
8994
  purpose
7661
8995
  });
7662
- return enrichProviderFileInfo(adapter.name, info);
8996
+ return enrichProviderFileInfo(adapter2.name, info);
7663
8997
  }
7664
8998
  async function deleteFile(ctx, id, options = {}) {
7665
8999
  await resolveDirectAdapter(ctx, options.provider).deleteFile(id);
7666
9000
  }
7667
9001
  async function getFileInfo(ctx, id, options = {}) {
7668
- const adapter = resolveDirectAdapter(ctx, options.provider);
7669
- if (!adapter.getFileInfo) throw new UserError("Provider does not support file metadata lookup");
7670
- const info = await adapter.getFileInfo(id);
7671
- return enrichProviderFileInfo(adapter.name, info);
9002
+ const adapter2 = resolveDirectAdapter(ctx, options.provider);
9003
+ if (!adapter2.getFileInfo) throw new UserError("Provider does not support file metadata lookup");
9004
+ const info = await adapter2.getFileInfo(id);
9005
+ return enrichProviderFileInfo(adapter2.name, info);
7672
9006
  }
7673
9007
  async function getFileDownloadUrl(ctx, id, options = {}) {
7674
- const adapter = resolveDirectAdapter(ctx, options.provider);
7675
- if (!adapter.getFileDownloadUrl) throw new UserError("Provider does not support file downloads");
7676
- return adapter.getFileDownloadUrl(id);
9008
+ const adapter2 = resolveDirectAdapter(ctx, options.provider);
9009
+ if (!adapter2.getFileDownloadUrl) throw new UserError("Provider does not support file downloads");
9010
+ return adapter2.getFileDownloadUrl(id);
7677
9011
  }
7678
9012
  async function listFiles(ctx, options = {}) {
7679
- const adapter = resolveDirectAdapter(ctx, options.provider);
7680
- if (!adapter.listFiles) return [];
7681
- const all = await adapter.listFiles();
7682
- return all.map((info) => enrichProviderFileInfo(adapter.name, info));
9013
+ const adapter2 = resolveDirectAdapter(ctx, options.provider);
9014
+ if (!adapter2.listFiles) return [];
9015
+ const all = await adapter2.listFiles();
9016
+ return all.map((info) => enrichProviderFileInfo(adapter2.name, info));
7683
9017
  }
7684
9018
  async function listSkills(ctx, options = {}) {
7685
- const adapter = resolveDirectAdapter(ctx, options.provider);
7686
- if (!adapter.listSkills) return [];
7687
- return adapter.listSkills(options.source);
9019
+ const adapter2 = resolveDirectAdapter(ctx, options.provider);
9020
+ if (!adapter2.listSkills) return [];
9021
+ return adapter2.listSkills(options.source);
7688
9022
  }
7689
9023
  async function getSkillInfo(ctx, id, options = {}) {
7690
- const adapter = resolveDirectAdapter(ctx, options.provider);
7691
- if (!adapter.getSkillInfo) throw new UserError("Provider does not support skill metadata lookup");
7692
- return adapter.getSkillInfo(id);
9024
+ const adapter2 = resolveDirectAdapter(ctx, options.provider);
9025
+ if (!adapter2.getSkillInfo) throw new UserError("Provider does not support skill metadata lookup");
9026
+ return adapter2.getSkillInfo(id);
7693
9027
  }
7694
9028
  async function createSkillFromFileId(ctx, fileId, options = {}) {
7695
- const adapter = resolveDirectAdapter(ctx, options.provider);
7696
- if (!adapter.createSkillFromFileId) throw new UserError("Provider does not support skill creation");
7697
- return adapter.createSkillFromFileId(fileId);
9029
+ const adapter2 = resolveDirectAdapter(ctx, options.provider);
9030
+ if (!adapter2.createSkillFromFileId) throw new UserError("Provider does not support skill creation");
9031
+ return adapter2.createSkillFromFileId(fileId);
7698
9032
  }
7699
9033
  async function deleteSkill(ctx, id, options = {}) {
7700
9034
  await resolveDirectAdapter(ctx, options.provider).deleteSkill(id);
@@ -7722,19 +9056,40 @@ function buildAgentNameByRemoteId(ctx, provider) {
7722
9056
  }
7723
9057
  return names;
7724
9058
  }
7725
- async function* streamWithResume(adapter, sessionId, message) {
7726
- const eventId = await adapter.sendSessionMessage(sessionId, message);
7727
- yield* adapter.streamSessionEvents(sessionId, eventId ? { after_id: eventId } : void 0);
9059
+ async function* streamWithResume(adapter2, sessionId, message) {
9060
+ const eventId = await adapter2.sendSessionMessage(sessionId, message);
9061
+ let lastEventId = eventId;
9062
+ let reachedTerminal = false;
9063
+ let reconnectIntervalMs = POLL_INITIAL_INTERVAL_MS;
9064
+ const start = Date.now();
9065
+ while (!reachedTerminal) {
9066
+ assertNotTimedOut(start, DEFAULT_POLL_TIMEOUT_MS);
9067
+ for await (const event of adapter2.streamSessionEvents(
9068
+ sessionId,
9069
+ lastEventId ? { after_id: lastEventId } : void 0
9070
+ )) {
9071
+ if (event.id) lastEventId = event.id;
9072
+ yield event;
9073
+ if (event.type === "status" && isTerminalSessionStatus(event.status)) {
9074
+ reachedTerminal = true;
9075
+ break;
9076
+ }
9077
+ }
9078
+ if (!reachedTerminal) {
9079
+ await delay(reconnectIntervalMs);
9080
+ reconnectIntervalMs = Math.min(reconnectIntervalMs * 2, DEFAULT_POLL_INTERVAL_MS);
9081
+ }
9082
+ }
7728
9083
  }
7729
- async function* streamConnectBeforeSend(adapter, sessionId, message) {
7730
- const iterator = adapter.streamSessionEvents(sessionId)[Symbol.asyncIterator]();
9084
+ async function* streamConnectBeforeSend(adapter2, sessionId, message) {
9085
+ const iterator = adapter2.streamSessionEvents(sessionId)[Symbol.asyncIterator]();
7731
9086
  let sent = false;
7732
9087
  try {
7733
9088
  while (true) {
7734
9089
  const next = iterator.next();
7735
9090
  if (!sent) {
7736
9091
  sent = true;
7737
- await adapter.sendSessionMessage(sessionId, message);
9092
+ await adapter2.sendSessionMessage(sessionId, message);
7738
9093
  }
7739
9094
  const item = await next;
7740
9095
  if (item.done) return;
@@ -7979,11 +9334,11 @@ var StateManager = class _StateManager {
7979
9334
  listResources() {
7980
9335
  return [...this.state.resources];
7981
9336
  }
7982
- findResource(query) {
9337
+ findResource(query2) {
7983
9338
  return this.state.resources.find((resource) => {
7984
- const matchType = resource.address.type === query.type;
7985
- const matchName = resource.address.name === query.name;
7986
- const matchProvider = !query.provider || resource.address.provider === query.provider;
9339
+ const matchType = resource.address.type === query2.type;
9340
+ const matchName = resource.address.name === query2.name;
9341
+ const matchProvider = !query2.provider || resource.address.provider === query2.provider;
7987
9342
  return matchType && matchName && matchProvider;
7988
9343
  });
7989
9344
  }
@@ -8066,11 +9421,11 @@ var InMemoryStateManager = class _InMemoryStateManager {
8066
9421
  listResources() {
8067
9422
  return [...this.state.resources];
8068
9423
  }
8069
- findResource(query) {
9424
+ findResource(query2) {
8070
9425
  return this.state.resources.find((resource) => {
8071
- const matchType = resource.address.type === query.type;
8072
- const matchName = resource.address.name === query.name;
8073
- const matchProvider = !query.provider || resource.address.provider === query.provider;
9426
+ const matchType = resource.address.type === query2.type;
9427
+ const matchName = resource.address.name === query2.name;
9428
+ const matchProvider = !query2.provider || resource.address.provider === query2.provider;
8074
9429
  return matchType && matchName && matchProvider;
8075
9430
  });
8076
9431
  }
@@ -8117,7 +9472,9 @@ var ResourceTypeSchema = z6.enum([
8117
9472
  "agent",
8118
9473
  "template",
8119
9474
  "deployment",
8120
- "file"
9475
+ "file",
9476
+ "identity",
9477
+ "channel"
8121
9478
  ]);
8122
9479
  var ResourceAddressSchema = z6.object({
8123
9480
  type: ResourceTypeSchema,
@@ -8408,13 +9765,17 @@ export {
8408
9765
  UserError,
8409
9766
  applyProviderConfigToEnv,
8410
9767
  archiveCloudAgent,
9768
+ archiveMemoryStore,
8411
9769
  areRuntimeCredentialsReady,
9770
+ batchCreateMemories,
8412
9771
  bootstrapRuntimeCredentials,
8413
9772
  bootstrapRuntimeCredentialsSync,
8414
9773
  buildAgentDecl,
8415
9774
  collectConfigReferences,
8416
9775
  createCloudEnvironment,
8417
9776
  createCloudVault,
9777
+ createMemory,
9778
+ createMemoryStore,
8418
9779
  createProjectRuntime,
8419
9780
  createSessionForAgent,
8420
9781
  createSkillFromFileId,
@@ -8422,6 +9783,8 @@ export {
8422
9783
  deleteCloudEnvironment,
8423
9784
  deleteCloudVault,
8424
9785
  deleteFile,
9786
+ deleteMemory,
9787
+ deleteMemoryStore,
8425
9788
  deleteSession,
8426
9789
  deleteSkill,
8427
9790
  destroyPlannedProjectResources,
@@ -8432,6 +9795,10 @@ export {
8432
9795
  getDeploymentRuntimeProviderForContext,
8433
9796
  getFileDownloadUrl,
8434
9797
  getFileInfo,
9798
+ getMemory,
9799
+ getMemoryProviderCapabilities,
9800
+ getMemoryStore,
9801
+ getMemoryVersion,
8435
9802
  getSession,
8436
9803
  getSkillInfo,
8437
9804
  importResource,
@@ -8442,8 +9809,12 @@ export {
8442
9809
  listCloudVaults,
8443
9810
  listDeploymentsForContext,
8444
9811
  listFiles,
9812
+ listMemories,
9813
+ listMemoryStores,
9814
+ listMemoryVersions,
8445
9815
  listProviderModelsForContext,
8446
9816
  listProviderNames,
9817
+ listRemoteDeploymentsForContext,
8447
9818
  listSessionEvents,
8448
9819
  listSessionSummaries,
8449
9820
  listSkills,
@@ -8452,16 +9823,20 @@ export {
8452
9823
  loadProviderConfigIntoEnvSync,
8453
9824
  migrateConfig,
8454
9825
  parseStateAddress,
9826
+ pauseDeploymentForContext,
8455
9827
  planDestroyProjectContext,
8456
9828
  planProjectContext,
9829
+ prepareInitialSessionPrompt,
8457
9830
  preparePromptForProvider,
8458
9831
  prependFileHint,
8459
9832
  providerConfigPath,
8460
9833
  readProjectRuntime,
9834
+ redactMemoryVersion,
8461
9835
  resolveActiveProvider,
8462
9836
  resolveProjectConfig,
8463
9837
  resolveProjectConfigFromObject,
8464
9838
  resolveProviderConfigFromEnv,
9839
+ resolveRepositoryMountPath,
8465
9840
  resolveSessionProvider,
8466
9841
  resolveSyncProvider,
8467
9842
  rewriteFileMentions,
@@ -8475,6 +9850,8 @@ export {
8475
9850
  syncProjectResourcesWithStateBackend,
8476
9851
  syncProviderResourcesFromContext,
8477
9852
  syncProviderResourcesFromEnv,
9853
+ updateMemory,
9854
+ updateMemoryStore,
8478
9855
  uploadFile,
8479
9856
  validateProjectConfig,
8480
9857
  writeProjectRuntime