@openagentpack/sdk 0.3.2 → 0.4.0-beta-2472720-20260827

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  toSessionEvent
3
- } from "./chunk-GAAU67HX.js";
3
+ } from "./chunk-6PDVAFLK.js";
4
4
  import {
5
5
  defaultFileUploadPurpose,
6
6
  enrichProviderFileInfo
@@ -58,10 +58,10 @@ var BaseApiClient = class {
58
58
  if (this.isConflict(res.status, body)) throw new ConflictError(res.status, body, this.errorPrefix);
59
59
  throw new ApiError(res.status, body, this.errorPrefix);
60
60
  }
61
- async post(path, body) {
61
+ async post(path, body, options) {
62
62
  const res = await resolveFetch()(`${this.baseUrl}${path}`, {
63
63
  method: "POST",
64
- headers: this.headers(),
64
+ headers: { ...this.headers(), ...options?.headers },
65
65
  body: JSON.stringify(body)
66
66
  });
67
67
  await this.throwIfError(res);
@@ -628,6 +628,13 @@ async function listSessionEventsPaged(client, sessionId, options, toEvent, confi
628
628
  const params = new URLSearchParams();
629
629
  if (options?.limit) params.set("limit", String(options.limit));
630
630
  if (options?.order) params.set("order", options.order);
631
+ if (config?.forwardTypes !== false) {
632
+ for (const type of options?.types ?? []) params.append("types", type);
633
+ }
634
+ if (options?.created_at_gt) params.set("created_at[gt]", options.created_at_gt);
635
+ if (options?.created_at_gte) params.set("created_at[gte]", options.created_at_gte);
636
+ if (options?.created_at_lt) params.set("created_at[lt]", options.created_at_lt);
637
+ if (options?.created_at_lte) params.set("created_at[lte]", options.created_at_lte);
631
638
  const pageCursor = options?.page_token ?? options?.page;
632
639
  if (pageCursor) params.set("page", pageCursor);
633
640
  if (config?.forwardAfterId && options?.after_id) params.set("after_id", options.after_id);
@@ -794,7 +801,8 @@ function toCloudAgent(raw) {
794
801
  workspace_id: raw.workspace_id,
795
802
  created_at: raw.created_at,
796
803
  updated_at: raw.updated_at,
797
- archived_at: raw.archived_at ?? null
804
+ archived_at: raw.archived_at ?? null,
805
+ attributes: raw
798
806
  };
799
807
  }
800
808
  function toCloudEnvironment(raw) {
@@ -810,7 +818,8 @@ function toCloudEnvironment(raw) {
810
818
  workspace_id: raw.workspace_id,
811
819
  created_at: raw.created_at,
812
820
  updated_at: raw.updated_at,
813
- archived_at: raw.archived_at ?? null
821
+ archived_at: raw.archived_at ?? null,
822
+ attributes: raw
814
823
  };
815
824
  }
816
825
  function toCloudVault(raw) {
@@ -821,7 +830,8 @@ function toCloudVault(raw) {
821
830
  type: raw.type,
822
831
  created_at: raw.created_at ?? null,
823
832
  updated_at: raw.updated_at ?? null,
824
- archived_at: raw.archived_at ?? null
833
+ archived_at: raw.archived_at ?? null,
834
+ attributes: raw
825
835
  };
826
836
  }
827
837
  function toRestFileInfo(res) {
@@ -833,7 +843,9 @@ function toRestFileInfo(res) {
833
843
  created_at: res.created_at,
834
844
  downloadable: res.downloadable,
835
845
  status: res.status,
836
- purpose: res.purpose
846
+ purpose: res.purpose,
847
+ scope: res.scope,
848
+ attributes: res
837
849
  };
838
850
  }
839
851
  function toRestSkillInfo(res) {
@@ -846,7 +858,8 @@ function toRestSkillInfo(res) {
846
858
  status: "active",
847
859
  latest_version: res.latest_version,
848
860
  created_at: res.created_at,
849
- updated_at: res.updated_at
861
+ updated_at: res.updated_at,
862
+ attributes: res
850
863
  };
851
864
  }
852
865
 
@@ -1238,7 +1251,7 @@ function mapAgent(name, decl, refs, version, projectName) {
1238
1251
  }
1239
1252
  }
1240
1253
  const body = {
1241
- name,
1254
+ name: decl.name ?? name,
1242
1255
  model: modelValue,
1243
1256
  system: decl.instructions
1244
1257
  };
@@ -2059,6 +2072,13 @@ function mapEnvironment2(name, decl, projectName) {
2059
2072
  metadata: injectMetadata(decl.metadata, projectName, name)
2060
2073
  };
2061
2074
  }
2075
+ function mapForwardEnvironment(name, decl, projectName) {
2076
+ const body = mapEnvironment2(name, decl, projectName);
2077
+ const config = { ...body.config };
2078
+ delete config.networking;
2079
+ body.config = config;
2080
+ return body;
2081
+ }
2062
2082
  function mapVault(name, decl, projectName) {
2063
2083
  const body = { display_name: decl.display_name };
2064
2084
  if (projectName) body.metadata = injectMetadata(decl.metadata, projectName, name);
@@ -2176,6 +2196,7 @@ function agentToDecl2(raw) {
2176
2196
  }));
2177
2197
  }
2178
2198
  return compactDeep({
2199
+ name: raw.name,
2179
2200
  description: raw.description,
2180
2201
  model: raw.model,
2181
2202
  instructions: raw.system,
@@ -2300,7 +2321,7 @@ function mapAgent2(name, decl, refs, version, projectName) {
2300
2321
  model = typeof qoderModel === "string" ? qoderModel : qoderModel.id;
2301
2322
  }
2302
2323
  const body = {
2303
- name,
2324
+ name: decl.name ?? name,
2304
2325
  model,
2305
2326
  system: decl.instructions
2306
2327
  };
@@ -2373,10 +2394,12 @@ function mapForwardTemplate(name, decl, refs, projectName) {
2373
2394
  environment_id: refs.environment_id,
2374
2395
  vault_ids: refs.vault_ids
2375
2396
  };
2397
+ body.files = Object.fromEntries((refs.file_ids ?? []).map((id) => [id, { enabled: true }]));
2376
2398
  if (refs.tunnel_id) body.tunnel_id = refs.tunnel_id;
2377
2399
  if (projectName) body.metadata = injectMetadata(decl.metadata, projectName, name);
2378
2400
  else body.metadata = decl.metadata ?? {};
2379
2401
  if (decl.environment_variables) body.environment_variables = decl.environment_variables;
2402
+ if (decl.managed_tool_config) body.managed_tool_config = decl.managed_tool_config;
2380
2403
  if (decl.tools) {
2381
2404
  body.tools = [
2382
2405
  {
@@ -2565,6 +2588,7 @@ var QoderAdapter = class _QoderAdapter {
2565
2588
  client;
2566
2589
  memoryApi;
2567
2590
  forwardClient;
2591
+ forwardMemoryApi;
2568
2592
  projectName;
2569
2593
  forwardSessionIds = /* @__PURE__ */ new Set();
2570
2594
  constructor(apiKey, gateway, projectName, forwardGateway) {
@@ -2586,6 +2610,19 @@ var QoderAdapter = class _QoderAdapter {
2586
2610
  apiKey,
2587
2611
  gateway: forwardGateway ?? deriveForwardGateway(gateway)
2588
2612
  });
2613
+ this.forwardMemoryApi = new ProviderMemoryApi(this.forwardClient, {
2614
+ pathStyle: "relative",
2615
+ cursorParam: "after_id",
2616
+ updatePrecondition: "content_sha256",
2617
+ prefixParam: "prefix",
2618
+ versionsSegment: "versions",
2619
+ storeMetadataMode: "merge_patch",
2620
+ supportsView: false,
2621
+ supportsMemoryMetadata: true,
2622
+ supportsPathUpdate: false,
2623
+ supportsDeletePrecondition: false,
2624
+ supportsIncludeArchived: true
2625
+ });
2589
2626
  this.projectName = projectName ?? "";
2590
2627
  }
2591
2628
  async validate() {
@@ -2600,7 +2637,7 @@ var QoderAdapter = class _QoderAdapter {
2600
2637
  file: "/files",
2601
2638
  deployment: "/deployments"
2602
2639
  };
2603
- async findResource(type, name, id) {
2640
+ async findResource(type, name, id, mode) {
2604
2641
  if (type === "template") {
2605
2642
  const raw2 = await locateRemote(this.forwardClient, "/templates", name, id, (item) => item.status !== "archived");
2606
2643
  return raw2 ? toRemoteResource(raw2) : null;
@@ -2620,7 +2657,14 @@ var QoderAdapter = class _QoderAdapter {
2620
2657
  const raw2 = await locateRemote(this.forwardClient, "/channels", name, id, () => true);
2621
2658
  return raw2 ? toRemoteResource(raw2) : null;
2622
2659
  }
2623
- const raw = await locateRemote(this.client, _QoderAdapter.ENDPOINT_MAP[type], name, id, notArchived);
2660
+ if (type === "environment" && id && mode === "auto") {
2661
+ const managed = await locateRemote(this.client, "/environments", name, id, notArchived);
2662
+ if (managed) return toRemoteResource(managed);
2663
+ const forward = await locateRemote(this.forwardClient, "/environments", name, id, notArchived);
2664
+ return forward ? toRemoteResource(forward) : null;
2665
+ }
2666
+ const client = mode === "forward" && (type === "environment" || type === "skill" || type === "vault" || type === "memory_store" || type === "file") ? this.forwardClient : this.client;
2667
+ const raw = await locateRemote(client, _QoderAdapter.ENDPOINT_MAP[type], name, id, notArchived);
2624
2668
  return raw ? toRemoteResource(raw) : null;
2625
2669
  }
2626
2670
  async listAgents(filter) {
@@ -2764,18 +2808,24 @@ var QoderAdapter = class _QoderAdapter {
2764
2808
  }
2765
2809
  if (type === "channel") {
2766
2810
  const channelConfig = raw.channel_config ?? {};
2767
- return compactDeep({
2768
- identity_id: raw.identity_id,
2769
- template_id: raw.template_id,
2811
+ const mode = raw.identity_resolution?.mode ?? "fixed";
2812
+ const normalized = {
2813
+ identity_resolution: { mode },
2770
2814
  channel_type: raw.channel_type,
2771
2815
  name: raw.name,
2772
2816
  enabled: raw.enabled,
2773
2817
  channel_config: {
2774
2818
  response_options: channelConfig.response_options ?? {}
2775
2819
  }
2776
- });
2820
+ };
2821
+ if (mode === "fixed") {
2822
+ normalized.identity_id = raw.identity_id;
2823
+ normalized.template_id = raw.template_id;
2824
+ }
2825
+ return compactDeep(normalized);
2777
2826
  }
2778
2827
  return compactDeep({
2828
+ name: raw.name,
2779
2829
  description: raw.description,
2780
2830
  model: normalizeModel(raw.model),
2781
2831
  instructions: raw.system,
@@ -2784,24 +2834,41 @@ var QoderAdapter = class _QoderAdapter {
2784
2834
  metadata: stripAgentsMetadata(raw.metadata)
2785
2835
  });
2786
2836
  }
2787
- async createEnvironment(name, decl) {
2788
- const body = mapEnvironment2(name, decl, this.projectName);
2789
- const res = await this.client.post("/environments", body);
2837
+ async createEnvironment(name, decl, mode = "managed") {
2838
+ const body = mode === "forward" ? mapForwardEnvironment(name, decl, this.projectName) : mapEnvironment2(name, decl, this.projectName);
2839
+ const res = await (mode === "forward" ? this.forwardClient : this.client).post("/environments", body);
2790
2840
  return toRemoteResource(res);
2791
2841
  }
2792
- async updateEnvironment(id, name, decl) {
2793
- const body = mapEnvironment2(name, decl, this.projectName);
2794
- const current = await this.client.get(`/environments/${id}`);
2842
+ async updateEnvironment(id, name, decl, mode = "managed") {
2843
+ const body = mode === "forward" ? mapForwardEnvironment(name, decl, this.projectName) : mapEnvironment2(name, decl, this.projectName);
2844
+ const client = mode === "forward" ? this.forwardClient : this.client;
2845
+ const current = await client.get(`/environments/${id}`);
2795
2846
  const currentMetadata = current.metadata ?? {};
2796
2847
  const metadata = { ...body.metadata ?? {} };
2797
2848
  for (const key of Object.keys(currentMetadata)) {
2798
2849
  if (!key.startsWith("agents.") && !(key in metadata)) metadata[key] = null;
2799
2850
  }
2800
2851
  body.metadata = metadata;
2801
- const res = await this.client.post(`/environments/${id}`, body);
2852
+ const res = await client.post(`/environments/${id}`, body);
2802
2853
  return toRemoteResource(res);
2803
2854
  }
2804
- async deleteEnvironment(id, cascade = false) {
2855
+ async deleteEnvironment(id, cascade = false, mode = "managed") {
2856
+ if (mode === "forward") {
2857
+ try {
2858
+ await this.forwardClient.delete(`/environments/${id}`);
2859
+ return;
2860
+ } catch (err) {
2861
+ const isConflict = err instanceof ApiError && (err.statusCode === 409 || err.responseBody.includes("in use"));
2862
+ if (!isConflict) throw err;
2863
+ if (!cascade) {
2864
+ throw new UserError(
2865
+ `Environment ${id} is referenced by one or more Forward sessions. Use --cascade to archive the environment.`
2866
+ );
2867
+ }
2868
+ await this.forwardClient.post(`/environments/${id}/archive`, {});
2869
+ return;
2870
+ }
2871
+ }
2805
2872
  try {
2806
2873
  await this.client.delete(`/environments/${id}`);
2807
2874
  return;
@@ -2828,17 +2895,18 @@ var QoderAdapter = class _QoderAdapter {
2828
2895
  await this.client.post(`/environments/${id}/archive`, {});
2829
2896
  }
2830
2897
  }
2831
- async createVault(name, decl) {
2898
+ async createVault(name, decl, mode = "managed") {
2899
+ const client = mode === "forward" ? this.forwardClient : this.client;
2832
2900
  const body = mapVault(name, decl, this.projectName);
2833
- const res = await this.client.post("/vaults", body);
2901
+ const res = await client.post("/vaults", body);
2834
2902
  const vaultId = res.id;
2835
2903
  for (const cred of decl.credentials ?? []) {
2836
- await this.client.post(`/vaults/${vaultId}/credentials`, mapCredential(cred));
2904
+ await client.post(`/vaults/${vaultId}/credentials`, mapCredential(cred));
2837
2905
  }
2838
2906
  return toRemoteResource(res);
2839
2907
  }
2840
- async deleteVault(id) {
2841
- await this.client.delete(`/vaults/${id}`);
2908
+ async deleteVault(id, mode = "managed") {
2909
+ await (mode === "forward" ? this.forwardClient : this.client).delete(`/vaults/${id}`);
2842
2910
  }
2843
2911
  async exportResources(type) {
2844
2912
  return exportRemoteResources(this.client, type, {
@@ -2849,17 +2917,24 @@ var QoderAdapter = class _QoderAdapter {
2849
2917
  agentToDecl: agentToDecl2
2850
2918
  });
2851
2919
  }
2852
- async createSkill(name, decl, files) {
2920
+ async createSkill(name, decl, files, mode = "managed") {
2853
2921
  const formData = await buildSkillFormData(name, decl, files);
2854
- const res = await this.client.postFormData("/skills", formData);
2922
+ const res = await (mode === "forward" ? this.forwardClient : this.client).postFormData(
2923
+ "/skills",
2924
+ formData
2925
+ );
2855
2926
  return toRemoteResource(res);
2856
2927
  }
2857
- async updateSkill(id, name, decl, files) {
2858
- await this.client.delete(`/skills/${id}`);
2859
- return this.createSkill(name, decl, files);
2928
+ async updateSkill(id, name, decl, files, mode = "managed") {
2929
+ const client = mode === "forward" ? this.forwardClient : this.client;
2930
+ const packageName = skillNameFromFiles(files) ?? name;
2931
+ const formData = await buildSkillFormData(packageName, decl, files, "files", false, true);
2932
+ await client.postFormData(`/skills/${id}/versions`, formData);
2933
+ const current = await client.get(`/skills/${id}`);
2934
+ return toRemoteResource(current);
2860
2935
  }
2861
- async deleteSkill(id) {
2862
- await this.client.delete(`/skills/${id}`);
2936
+ async deleteSkill(id, mode = "managed") {
2937
+ await (mode === "forward" ? this.forwardClient : this.client).delete(`/skills/${id}`);
2863
2938
  }
2864
2939
  async createAgent(name, decl, refs) {
2865
2940
  const body = mapAgent2(name, decl, refs, void 0, this.projectName);
@@ -2876,21 +2951,89 @@ var QoderAdapter = class _QoderAdapter {
2876
2951
  await this.client.delete(`/agents/${id}`);
2877
2952
  }
2878
2953
  async createTemplate(name, decl, refs) {
2879
- await this.registerForwardVaults(refs.vault_ids);
2880
2954
  const body = mapForwardTemplate(name, decl, refs, this.projectName);
2881
2955
  const res = await this.forwardClient.post("/templates", body);
2956
+ await this.reconcileForwardMemoryMounts(res.id, refs);
2882
2957
  return toRemoteResource(res);
2883
2958
  }
2884
2959
  async updateTemplate(id, name, decl, refs) {
2885
- await this.registerForwardVaults(refs.vault_ids);
2886
2960
  const body = mapForwardTemplate(name, decl, refs, this.projectName);
2887
2961
  if (!refs.tunnel_id) body.tunnel_id = null;
2888
2962
  const res = await this.forwardClient.post(`/templates/${id}`, body);
2963
+ await this.reconcileForwardMemoryMounts(id, refs);
2889
2964
  return toRemoteResource(res);
2890
2965
  }
2891
- async archiveTemplate(id) {
2966
+ async archiveTemplate(id, ownedMemoryStoreIds = []) {
2967
+ const owned = new Set(ownedMemoryStoreIds);
2968
+ if (owned.size > 0) {
2969
+ for (const identity of await this.forwardClient.getAllPaged("/identities")) {
2970
+ if (typeof identity.id !== "string") continue;
2971
+ const path = `/identities/${identity.id}/templates/${id}/memory_stores`;
2972
+ try {
2973
+ const mounts = await this.forwardClient.get(path);
2974
+ for (const mount of mounts.data ?? []) {
2975
+ const storeId = mount.memory_store_id;
2976
+ if (mount.system_managed !== true && typeof storeId === "string" && owned.has(storeId)) {
2977
+ await this.forwardClient.delete(`${path}/${storeId}`);
2978
+ }
2979
+ }
2980
+ } catch (error) {
2981
+ if (!ApiError.isNotFound(error)) throw error;
2982
+ }
2983
+ }
2984
+ }
2892
2985
  await this.forwardClient.post(`/templates/${id}/archive`, {});
2893
2986
  }
2987
+ async reconcileForwardMemoryMounts(templateId, refs) {
2988
+ if (refs.memory_store_ids === void 0) return;
2989
+ const desired = new Set(refs.memory_store_ids ?? []);
2990
+ if (!refs.identity_id) {
2991
+ if (desired.size > 0) throw new UserError("Qoder Forward Memory Store mounts require an Identity.");
2992
+ return;
2993
+ }
2994
+ const path = `/identities/${refs.identity_id}/templates/${templateId}/memory_stores`;
2995
+ const current = await this.forwardClient.get(path);
2996
+ const explicit = (current.data ?? []).filter((mount) => mount.system_managed !== true);
2997
+ const owned = new Set(refs.owned_memory_store_ids ?? refs.memory_store_ids ?? []);
2998
+ for (const mount of explicit) {
2999
+ const storeId = mount.memory_store_id;
3000
+ if (typeof storeId === "string" && owned.has(storeId) && !desired.has(storeId)) {
3001
+ await this.forwardClient.delete(`${path}/${storeId}`);
3002
+ }
3003
+ }
3004
+ const mounted = new Set(
3005
+ explicit.map((mount) => mount.memory_store_id).filter((id) => typeof id === "string")
3006
+ );
3007
+ for (const memoryStoreId of desired) {
3008
+ if (!mounted.has(memoryStoreId)) await this.forwardClient.post(path, { memory_store_id: memoryStoreId });
3009
+ }
3010
+ }
3011
+ async reconcileDefaultMemoryStore(identityId, templateId, desired) {
3012
+ const storeId = await this.findDefaultMemoryStoreId(identityId, templateId);
3013
+ if (!storeId) return { status: "pending" };
3014
+ const current = await this.forwardClient.get(`/memory_stores/${storeId}`);
3015
+ const descriptionChanged = desired.description !== void 0 && current.description !== desired.description;
3016
+ if (current.name === desired.name && !descriptionChanged) {
3017
+ return { status: "unchanged", memory_store_id: storeId };
3018
+ }
3019
+ await this.forwardClient.post(`/memory_stores/${storeId}`, {
3020
+ name: desired.name,
3021
+ ...desired.description !== void 0 ? { description: desired.description } : {}
3022
+ });
3023
+ return { status: "updated", memory_store_id: storeId };
3024
+ }
3025
+ async findDefaultMemoryStoreId(identityId, templateId) {
3026
+ const mounts = await this.forwardClient.get(
3027
+ `/identities/${identityId}/templates/${templateId}/memory_stores`
3028
+ );
3029
+ const writableDefault = (mounts.data ?? []).find(
3030
+ (mount) => mount.system_managed === true && mount.access === "read_write"
3031
+ );
3032
+ return typeof writableDefault?.memory_store_id === "string" ? writableDefault.memory_store_id : null;
3033
+ }
3034
+ async deleteDefaultMemoryStore(id) {
3035
+ await this.client.delete(`/memory_stores/${id}`);
3036
+ }
2894
3037
  async createIdentity(name, decl) {
2895
3038
  if (decl.identity_id) return { id: decl.identity_id, type: "identity" };
2896
3039
  const res = await this.forwardClient.post("/identities", {
@@ -2927,12 +3070,14 @@ var QoderAdapter = class _QoderAdapter {
2927
3070
  }
2928
3071
  async updateChannel(id, name, decl, refs) {
2929
3072
  const current = await this.forwardClient.get(`/channels/${id}`);
2930
- if (current.channel_type !== decl.type) {
3073
+ const currentMode = current.identity_resolution?.mode ?? "fixed";
3074
+ if (current.channel_type !== decl.type || currentMode !== (decl.mode ?? "fixed")) {
2931
3075
  await this.deleteChannel(id);
2932
3076
  return this.createChannel(name, decl, refs);
2933
3077
  }
2934
3078
  const body = this.mapChannel(name, decl, refs);
2935
3079
  delete body.channel_type;
3080
+ delete body.identity_resolution;
2936
3081
  const res = await this.forwardClient.post(`/channels/${id}`, body);
2937
3082
  return toRemoteResource(res);
2938
3083
  }
@@ -2940,9 +3085,8 @@ var QoderAdapter = class _QoderAdapter {
2940
3085
  await this.forwardClient.delete(`/channels/${id}`);
2941
3086
  }
2942
3087
  mapChannel(name, decl, refs) {
2943
- return {
2944
- identity_id: refs.identity_id,
2945
- template_id: refs.agent_id,
3088
+ const mode = decl.mode ?? "fixed";
3089
+ const body = {
2946
3090
  channel_type: decl.type,
2947
3091
  name: decl.name ?? name,
2948
3092
  enabled: decl.enabled ?? true,
@@ -2955,22 +3099,27 @@ var QoderAdapter = class _QoderAdapter {
2955
3099
  }
2956
3100
  }
2957
3101
  };
2958
- }
2959
- async registerForwardVaults(vaultIds) {
2960
- for (const id of vaultIds) {
2961
- await this.forwardClient.post("/resources/registry", {
2962
- type: "vault",
2963
- resource: { id }
2964
- });
3102
+ if (mode === "pairing") {
3103
+ body.identity_resolution = { mode: "pairing" };
3104
+ } else {
3105
+ body.identity_id = refs.identity_id;
3106
+ body.template_id = refs.agent_id;
2965
3107
  }
3108
+ return body;
2966
3109
  }
2967
- async createMemoryStore(name, decl) {
3110
+ async createMemoryStore(name, decl, mode = "managed") {
2968
3111
  const body = mapMemoryStore2(name, decl);
2969
- const res = await this.client.post("/memory_stores", body);
3112
+ const client = mode === "forward" ? this.forwardClient : this.client;
3113
+ const memoryApi = mode === "forward" ? this.forwardMemoryApi : this.memoryApi;
3114
+ const res = await client.post(
3115
+ "/memory_stores",
3116
+ body,
3117
+ mode === "forward" ? { headers: { "Idempotency-Key": crypto.randomUUID() } } : void 0
3118
+ );
2970
3119
  const storeId = res.id;
2971
3120
  try {
2972
3121
  for (const entry of decl.entries ?? []) {
2973
- await this.memoryApi.createMemory(storeId, { content: entry.content, path: entry.key });
3122
+ await memoryApi.createMemory(storeId, { content: entry.content, path: entry.key });
2974
3123
  }
2975
3124
  } catch (error) {
2976
3125
  await this.client.delete(`/memory_stores/${storeId}`).catch(() => void 0);
@@ -2978,7 +3127,7 @@ var QoderAdapter = class _QoderAdapter {
2978
3127
  }
2979
3128
  return toRemoteResource(res);
2980
3129
  }
2981
- async deleteMemoryStore(id) {
3130
+ async deleteMemoryStore(id, _mode = "managed") {
2982
3131
  await this.client.delete(`/memory_stores/${id}`);
2983
3132
  }
2984
3133
  listMemoryStores(options) {
@@ -2987,23 +3136,23 @@ var QoderAdapter = class _QoderAdapter {
2987
3136
  getMemoryStore(id) {
2988
3137
  return this.memoryApi.getStore(id);
2989
3138
  }
2990
- updateMemoryStore(id, input) {
2991
- return this.memoryApi.updateStore(id, input);
3139
+ updateMemoryStore(id, input, mode = "managed") {
3140
+ return (mode === "forward" ? this.forwardMemoryApi : this.memoryApi).updateStore(id, input);
2992
3141
  }
2993
3142
  archiveMemoryStore(id) {
2994
3143
  return this.memoryApi.archiveStore(id);
2995
3144
  }
2996
- createMemory(storeId, input) {
2997
- return this.memoryApi.createMemory(storeId, input);
3145
+ createMemory(storeId, input, mode = "managed") {
3146
+ return (mode === "forward" ? this.forwardMemoryApi : this.memoryApi).createMemory(storeId, input);
2998
3147
  }
2999
- listMemories(storeId, options) {
3000
- return this.memoryApi.listMemories(storeId, options);
3148
+ listMemories(storeId, options, mode = "managed") {
3149
+ return (mode === "forward" ? this.forwardMemoryApi : this.memoryApi).listMemories(storeId, options);
3001
3150
  }
3002
3151
  getMemory(storeId, memoryId) {
3003
3152
  return this.memoryApi.getMemory(storeId, memoryId);
3004
3153
  }
3005
- updateMemory(storeId, memoryId, input) {
3006
- return this.memoryApi.updateMemory(storeId, memoryId, input);
3154
+ updateMemory(storeId, memoryId, input, mode = "managed") {
3155
+ return (mode === "forward" ? this.forwardMemoryApi : this.memoryApi).updateMemory(storeId, memoryId, input);
3007
3156
  }
3008
3157
  deleteMemory(storeId, memoryId, expected) {
3009
3158
  return this.memoryApi.deleteMemory(storeId, memoryId, expected);
@@ -3292,30 +3441,42 @@ var QoderAdapter = class _QoderAdapter {
3292
3441
  return res.data;
3293
3442
  }
3294
3443
  // --- Files ---
3295
- async uploadFile(filePath, options) {
3444
+ async uploadFile(filePath, options, mode = "managed") {
3445
+ if (mode === "forward" && options?.purpose && !["user_upload", "session_resource"].includes(options.purpose)) {
3446
+ throw new UserError(
3447
+ `Qoder Forward File purpose must be 'user_upload' or 'session_resource', got '${options.purpose}'.`
3448
+ );
3449
+ }
3296
3450
  const resolved = resolve2(filePath);
3297
3451
  const content = readFileSync2(resolved);
3298
3452
  const fileName = options?.name ?? basename2(resolved);
3299
- return this.uploadFileContent(new Uint8Array(content), fileName, {
3300
- purpose: options?.purpose
3301
- });
3453
+ const formData = buildFileFormData(new Uint8Array(content), fileName, { purpose: options?.purpose });
3454
+ const res = await (mode === "forward" ? this.forwardClient : this.client).postFormData(
3455
+ "/files",
3456
+ formData
3457
+ );
3458
+ return toRestFileInfo(res);
3302
3459
  }
3303
3460
  async uploadFileContent(content, filename, options) {
3304
- const formData = new FormData();
3305
- const bytes = new Uint8Array(content);
3306
- formData.append(
3307
- "file",
3308
- options?.mimeType ? new File([bytes], filename, { type: options.mimeType }) : new File([bytes], filename)
3309
- );
3310
- if (filename) formData.append("name", filename);
3311
- if (options?.purpose) formData.append("purpose", options.purpose);
3461
+ const formData = buildFileFormData(content, filename, options);
3312
3462
  const res = await this.client.postFormData("/files", formData);
3313
3463
  return toRestFileInfo(res);
3314
3464
  }
3315
- async deleteFile(id) {
3316
- await this.client.delete(`/files/${id}`);
3465
+ async deleteFile(id, mode = "managed") {
3466
+ await (mode === "forward" ? this.forwardClient : this.client).delete(`/files/${id}`);
3317
3467
  }
3318
3468
  };
3469
+ function buildFileFormData(content, filename, options) {
3470
+ const formData = new FormData();
3471
+ const bytes = new Uint8Array(content);
3472
+ formData.append(
3473
+ "file",
3474
+ options?.mimeType ? new File([bytes], filename, { type: options.mimeType }) : new File([bytes], filename)
3475
+ );
3476
+ if (filename) formData.append("name", filename);
3477
+ if (options?.purpose) formData.append("purpose", options.purpose);
3478
+ return formData;
3479
+ }
3319
3480
  function toSessionInfo2(res) {
3320
3481
  return buildSessionInfo(res, (r) => r.memory_store_ids ?? []);
3321
3482
  }
@@ -3365,22 +3526,24 @@ function normalizeQoderMcpServers(value) {
3365
3526
  });
3366
3527
  });
3367
3528
  }
3368
- async function buildSkillFormData(name, decl, files) {
3529
+ async function buildSkillFormData(name, decl, files, fileField = "file", includeCreateFields = true, prefixTopLevelDirectory = false) {
3369
3530
  const zip = new JSZip2();
3370
3531
  for (const f of files) {
3371
- zip.file(f.relativePath, f.content);
3532
+ zip.file(prefixTopLevelDirectory ? `${name}/${f.relativePath}` : f.relativePath, f.content);
3372
3533
  }
3373
3534
  const zipContent = await zip.generateAsync({ type: "uint8array" });
3374
3535
  const formData = new FormData();
3375
3536
  formData.append(
3376
- "file",
3537
+ fileField,
3377
3538
  new File([new Uint8Array(zipContent)], `${name}.zip`, {
3378
3539
  type: "application/zip"
3379
3540
  })
3380
3541
  );
3381
- formData.append("name", name);
3382
- formData.append("type", "custom");
3383
- if (decl.description) formData.append("description", decl.description);
3542
+ if (includeCreateFields) {
3543
+ formData.append("name", name);
3544
+ formData.append("type", "custom");
3545
+ if (decl.description) formData.append("description", decl.description);
3546
+ }
3384
3547
  return formData;
3385
3548
  }
3386
3549
 
@@ -3495,7 +3658,7 @@ function mapVault2(name, decl, projectName) {
3495
3658
  }
3496
3659
  function mapCredential2(cred) {
3497
3660
  if (cred.type === "environment_variable") {
3498
- return {
3661
+ const body2 = {
3499
3662
  auth: {
3500
3663
  type: "environment_variable",
3501
3664
  secret_name: cred.secret_name,
@@ -3504,8 +3667,10 @@ function mapCredential2(cred) {
3504
3667
  },
3505
3668
  display_name: cred.name
3506
3669
  };
3670
+ if (cred.metadata) body2.metadata = cred.metadata;
3671
+ return body2;
3507
3672
  }
3508
- return {
3673
+ const body = {
3509
3674
  auth: {
3510
3675
  type: cred.type,
3511
3676
  token: cred.access_token,
@@ -3513,6 +3678,8 @@ function mapCredential2(cred) {
3513
3678
  },
3514
3679
  display_name: cred.name
3515
3680
  };
3681
+ if (cred.metadata) body.metadata = cred.metadata;
3682
+ return body;
3516
3683
  }
3517
3684
  function credToDecl3(raw, vaultName) {
3518
3685
  const auth = raw.auth ?? {};
@@ -3522,6 +3689,7 @@ function credToDecl3(raw, vaultName) {
3522
3689
  return {
3523
3690
  name,
3524
3691
  type: "static_bearer",
3692
+ metadata: stripAgentsMetadata(raw.metadata),
3525
3693
  mcp_server_url: auth.mcp_server_url ?? "",
3526
3694
  access_token: placeholder
3527
3695
  };
@@ -3530,6 +3698,7 @@ function credToDecl3(raw, vaultName) {
3530
3698
  return {
3531
3699
  name,
3532
3700
  type: "environment_variable",
3701
+ metadata: stripAgentsMetadata(raw.metadata),
3533
3702
  secret_name: auth.secret_name ?? name,
3534
3703
  secret_value: placeholder,
3535
3704
  networking: networking ?? { type: "unrestricted" }
@@ -3597,6 +3766,7 @@ function agentToDecl3(raw) {
3597
3766
  const model = raw.model;
3598
3767
  const modelValue = typeof model === "object" && model ? model.id : model;
3599
3768
  return compactDeep({
3769
+ name: raw.name,
3600
3770
  description: raw.description,
3601
3771
  model: modelValue,
3602
3772
  instructions: raw.system,
@@ -3616,7 +3786,7 @@ function mapAgent3(name, decl, refs, version, projectName, skillVersions) {
3616
3786
  modelId = typeof bailianModel === "string" ? bailianModel : bailianModel.id;
3617
3787
  }
3618
3788
  const body = {
3619
- name,
3789
+ name: decl.name ?? name,
3620
3790
  model: { id: modelId },
3621
3791
  system: decl.instructions
3622
3792
  };
@@ -3709,7 +3879,7 @@ function mapDeployment3(name, decl, refs, projectName, uploadedFiles) {
3709
3879
  const agent = { id: refs.agent_id };
3710
3880
  if (refs.agent_version !== void 0) agent.version = refs.agent_version;
3711
3881
  const body = {
3712
- name,
3882
+ name: decl.name ?? name,
3713
3883
  agent,
3714
3884
  environment_id: refs.environment_id,
3715
3885
  initial_events: mapMessageEvents(decl.initial_events)
@@ -3847,6 +4017,7 @@ var BailianAdapter = class _BailianAdapter {
3847
4017
  });
3848
4018
  }
3849
4019
  return compactDeep({
4020
+ name: raw.name,
3850
4021
  description: raw.description,
3851
4022
  model: normalizeBailianModel(raw.model),
3852
4023
  instructions: raw.system,
@@ -3878,6 +4049,18 @@ var BailianAdapter = class _BailianAdapter {
3878
4049
  async deleteEnvironment(id) {
3879
4050
  await this.client.delete(`/environments/${id}`);
3880
4051
  }
4052
+ async listEnvironmentResources(options) {
4053
+ const params = cursorParams(options);
4054
+ if (options?.include_archived !== void 0) {
4055
+ params.set("include_archived", String(options.include_archived));
4056
+ }
4057
+ const res = await this.client.get(withQuery("/environments", params));
4058
+ return cursorPage(res, toCloudEnvironment);
4059
+ }
4060
+ async getRemoteEnvironment(id) {
4061
+ const res = await this.client.get(`/environments/${id}`);
4062
+ return toCloudEnvironment(res);
4063
+ }
3881
4064
  // --- Agent ---
3882
4065
  async createAgent(name, decl, refs) {
3883
4066
  const skillVersions = await this.fetchSkillVersions(refs);
@@ -3926,6 +4109,25 @@ var BailianAdapter = class _BailianAdapter {
3926
4109
  async deleteAgent(id) {
3927
4110
  await this.client.post(`/agents/${id}/archive`, {});
3928
4111
  }
4112
+ async listAgentResources(options) {
4113
+ const params = cursorParams(options);
4114
+ if (options?.include_archived !== void 0) {
4115
+ params.set("include_archived", String(options.include_archived));
4116
+ }
4117
+ const res = await this.client.get(withQuery("/agents", params));
4118
+ return cursorPage(res, toCloudAgent);
4119
+ }
4120
+ async getRemoteAgent(id, version) {
4121
+ const params = new URLSearchParams();
4122
+ if (version !== void 0) params.set("version", String(version));
4123
+ const res = await this.client.get(withQuery(`/agents/${id}`, params));
4124
+ return toCloudAgent(res);
4125
+ }
4126
+ async listAgentVersions(id, options) {
4127
+ const params = cursorParams(options);
4128
+ const res = await this.client.get(withQuery(`/agents/${id}/versions`, params));
4129
+ return cursorPage(res, toCloudAgent);
4130
+ }
3929
4131
  // --- Skill (2-step: Files API → Skills API) ---
3930
4132
  async createSkill(name, decl, files) {
3931
4133
  const fileId = await this.uploadSkillZip(name, decl, files);
@@ -4024,10 +4226,31 @@ var BailianAdapter = class _BailianAdapter {
4024
4226
  const all = await this.client.getAllPaged(path);
4025
4227
  return all.map(toBailianSkillInfo);
4026
4228
  }
4229
+ async listSkillResources(options) {
4230
+ const params = cursorParams(options);
4231
+ if (options?.source === "official") params.set("source", "official");
4232
+ if (options?.source === "custom") params.set("source", "customer");
4233
+ const res = await this.client.get(withQuery("/skills", params));
4234
+ return cursorPage(res, toBailianSkillInfo);
4235
+ }
4027
4236
  async getSkillInfo(id) {
4028
4237
  const res = await this.client.get(`/skills/${id}`);
4029
4238
  return toBailianSkillInfo(res);
4030
4239
  }
4240
+ async listSkillVersions(id, options) {
4241
+ const params = cursorParams(options);
4242
+ const res = await this.client.get(withQuery(`/skills/${id}/versions`, params));
4243
+ return cursorPage(res, toSkillVersionInfo);
4244
+ }
4245
+ async getSkillVersion(id, version) {
4246
+ const res = await this.client.get(`/skills/${id}/versions/${encodeURIComponent(version)}`);
4247
+ return toSkillVersionInfo(res);
4248
+ }
4249
+ async getSkillDownloadInfo(id, version) {
4250
+ return await this.client.get(
4251
+ `/skills/${id}/versions/${encodeURIComponent(version)}/content`
4252
+ );
4253
+ }
4031
4254
  // Non-blocking create: file already uploaded → POST /skills with retry for residual OSS
4032
4255
  // replication lag (postSkillWithRetry covers SKILL_FILE_NOT_FOUND for a few seconds), and return
4033
4256
  // the initial status WITHOUT waiting for the security scan. Callers MUST ensure the file has
@@ -4057,7 +4280,7 @@ var BailianAdapter = class _BailianAdapter {
4057
4280
  }
4058
4281
  async waitForFileReady(fileId) {
4059
4282
  const start = Date.now();
4060
- let delay2 = FILE_SCAN_BACKOFF.initial;
4283
+ let delay3 = FILE_SCAN_BACKOFF.initial;
4061
4284
  let logged = false;
4062
4285
  while (true) {
4063
4286
  const detail = await this.client.get(`/files/${fileId}`);
@@ -4076,8 +4299,8 @@ var BailianAdapter = class _BailianAdapter {
4076
4299
  );
4077
4300
  return;
4078
4301
  }
4079
- await new Promise((r) => setTimeout(r, delay2));
4080
- delay2 = Math.min(delay2 * FILE_SCAN_BACKOFF.factor, FILE_SCAN_BACKOFF.max);
4302
+ await new Promise((r) => setTimeout(r, delay3));
4303
+ delay3 = Math.min(delay3 * FILE_SCAN_BACKOFF.factor, FILE_SCAN_BACKOFF.max);
4081
4304
  }
4082
4305
  }
4083
4306
  // --- Vault (Vaults API) ---
@@ -4099,6 +4322,18 @@ var BailianAdapter = class _BailianAdapter {
4099
4322
  const all = await this.client.getAllPaged("/vaults");
4100
4323
  return all.map(toCloudVault);
4101
4324
  }
4325
+ async listVaultResources(options) {
4326
+ const params = cursorParams(options);
4327
+ if (options?.include_archived !== void 0) {
4328
+ params.set("include_archived", String(options.include_archived));
4329
+ }
4330
+ const res = await this.client.get(withQuery("/vaults", params));
4331
+ return cursorPage(res, toCloudVault);
4332
+ }
4333
+ async getRemoteVault(id) {
4334
+ const res = await this.client.get(`/vaults/${id}`);
4335
+ return toCloudVault(res);
4336
+ }
4102
4337
  async getVault(id) {
4103
4338
  return await this.client.get(`/vaults/${id}`);
4104
4339
  }
@@ -4120,7 +4355,21 @@ var BailianAdapter = class _BailianAdapter {
4120
4355
  }
4121
4356
  async listCredentials(vaultId) {
4122
4357
  const all = await this.client.getAllPaged(`/vaults/${vaultId}/credentials`);
4123
- return all.map(toRemoteResource);
4358
+ return all.map((raw) => {
4359
+ const auth = raw.auth ?? {};
4360
+ const networking = auth.networking;
4361
+ const metadata = raw.metadata;
4362
+ return {
4363
+ id: raw.id,
4364
+ display_name: raw.display_name ?? raw.id,
4365
+ auth_type: auth.type ?? "",
4366
+ secret_name: auth.secret_name,
4367
+ networking_type: networking?.type,
4368
+ metadata: metadata ? Object.fromEntries(
4369
+ Object.entries(metadata).filter((entry) => typeof entry[1] === "string")
4370
+ ) : void 0
4371
+ };
4372
+ });
4124
4373
  }
4125
4374
  async getCredential(vaultId, credentialId) {
4126
4375
  return await this.client.get(`/vaults/${vaultId}/credentials/${credentialId}`);
@@ -4170,11 +4419,7 @@ var BailianAdapter = class _BailianAdapter {
4170
4419
  throw new UserError(`Deployment '${ctx.name}' has no remote id; run \`agents apply\` first.`);
4171
4420
  }
4172
4421
  const res = await this.client.post(`/deployments/${ctx.id}/run`, {});
4173
- return {
4174
- run_id: res.id,
4175
- session_id: res.session_id ?? null,
4176
- error: res.error ?? void 0
4177
- };
4422
+ return toDeploymentRunResult(res);
4178
4423
  }
4179
4424
  async getDeployment(ctx) {
4180
4425
  if (!ctx.id) {
@@ -4186,6 +4431,7 @@ var BailianAdapter = class _BailianAdapter {
4186
4431
  async listDeployments(filter) {
4187
4432
  const params = new URLSearchParams();
4188
4433
  if (filter?.agent_id) params.set("agent_id", filter.agent_id);
4434
+ if (filter?.keyword) params.set("keyword", filter.keyword);
4189
4435
  if (filter?.status) params.set("status", filter.status);
4190
4436
  if (filter?.include_archived) params.set("include_archived", "true");
4191
4437
  if (filter?.limit) params.set("limit", String(filter.limit));
@@ -4201,6 +4447,32 @@ var BailianAdapter = class _BailianAdapter {
4201
4447
  next_page: nextPage
4202
4448
  };
4203
4449
  }
4450
+ async getDeploymentById(id) {
4451
+ const res = await this.client.get(`/deployments/${id}`);
4452
+ return toDeploymentInfo3(res);
4453
+ }
4454
+ async runDeploymentById(id) {
4455
+ const res = await this.client.post(`/deployments/${id}/run`, {});
4456
+ return toDeploymentRunResult(res);
4457
+ }
4458
+ async pauseDeploymentById(id) {
4459
+ const res = await this.client.post(`/deployments/${id}/pause`, {});
4460
+ return toDeploymentInfo3(res);
4461
+ }
4462
+ async unpauseDeploymentById(id) {
4463
+ const res = await this.client.post(`/deployments/${id}/unpause`, {});
4464
+ return toDeploymentInfo3(res);
4465
+ }
4466
+ async listDeploymentRuns(deploymentId, options) {
4467
+ const res = await this.client.get(
4468
+ withQuery(`/deployments/${deploymentId}/runs`, cursorParams(options))
4469
+ );
4470
+ return cursorPage(res, toDeploymentRunInfo);
4471
+ }
4472
+ async getDeploymentRun(runId) {
4473
+ const res = await this.client.get(`/deployment_runs/${runId}`);
4474
+ return toDeploymentRunInfo(res);
4475
+ }
4204
4476
  async pauseDeployment(ctx) {
4205
4477
  return this.setDeploymentPaused(ctx, true);
4206
4478
  }
@@ -4255,6 +4527,9 @@ var BailianAdapter = class _BailianAdapter {
4255
4527
  async listSessions(filter) {
4256
4528
  const params = new URLSearchParams();
4257
4529
  if (filter?.agent_id) params.set("agent_id", filter.agent_id);
4530
+ for (const status of filter?.statuses ?? []) params.append("statuses[]", status);
4531
+ if (filter?.created_at_gte) params.set("created_at[gte]", filter.created_at_gte);
4532
+ if (filter?.created_at_lte) params.set("created_at[lte]", filter.created_at_lte);
4258
4533
  if (filter?.limit) params.set("limit", String(filter.limit));
4259
4534
  if (filter?.page) params.set("page", filter.page);
4260
4535
  const qs = params.toString();
@@ -4271,6 +4546,15 @@ var BailianAdapter = class _BailianAdapter {
4271
4546
  const res = await this.client.get(`/sessions/${id}`);
4272
4547
  return toSessionInfo3(res);
4273
4548
  }
4549
+ async updateSession(id, input) {
4550
+ const res = await this.client.post(`/sessions/${id}`, input);
4551
+ if (!res.agent || !res.environment_id) return this.getSession(id);
4552
+ return toSessionInfo3(res);
4553
+ }
4554
+ async archiveSession(id) {
4555
+ const res = await this.client.post(`/sessions/${id}/archive`, {});
4556
+ return toSessionInfo3(res);
4557
+ }
4274
4558
  async deleteSession(id) {
4275
4559
  await this.client.delete(`/sessions/${id}`);
4276
4560
  }
@@ -4279,13 +4563,20 @@ var BailianAdapter = class _BailianAdapter {
4279
4563
  const res = await this.client.post(`/sessions/${sessionId}/events`, body);
4280
4564
  return extractCreatedEventId(res);
4281
4565
  }
4566
+ async sendSessionEvents(sessionId, events) {
4567
+ const res = await this.client.post(`/sessions/${sessionId}/events`, { input: events });
4568
+ return {
4569
+ event_ids: extractCreatedEventIds(res),
4570
+ attributes: res
4571
+ };
4572
+ }
4282
4573
  async *streamSessionEvents(sessionId, _options) {
4283
4574
  for await (const raw of this.client.sse(`/sessions/${sessionId}/events/stream`)) {
4284
4575
  yield toSessionEvent(raw);
4285
4576
  }
4286
4577
  }
4287
4578
  async listSessionEvents(sessionId, options) {
4288
- return listSessionEventsPaged(this.client, sessionId, options, toSessionEvent);
4579
+ return listSessionEventsPaged(this.client, sessionId, options, toSessionEvent, { forwardTypes: false });
4289
4580
  }
4290
4581
  // --- Files ---
4291
4582
  async uploadFile(filePath, options) {
@@ -4311,6 +4602,15 @@ var BailianAdapter = class _BailianAdapter {
4311
4602
  const all = await this.client.getAllPaged("/files");
4312
4603
  return all.map(toRestFileInfo);
4313
4604
  }
4605
+ async listFileResources(options) {
4606
+ const params = cursorParams(options);
4607
+ if (options?.scope_id) params.set("scope_id", options.scope_id);
4608
+ const res = await this.client.get(withQuery("/files", params));
4609
+ return cursorPage(res, toRestFileInfo);
4610
+ }
4611
+ async downloadFileContent(id) {
4612
+ return new Uint8Array(await this.client.getBuffer(`/files/${id}/content`));
4613
+ }
4314
4614
  async deleteFile(id) {
4315
4615
  await this.client.delete(`/files/${id}`);
4316
4616
  }
@@ -4345,9 +4645,77 @@ function toBailianSkillInfo(res) {
4345
4645
  status: skillStatusFromString(res.status),
4346
4646
  latest_version: res.latest_version,
4347
4647
  created_at: res.created_at,
4348
- updated_at: res.updated_at
4648
+ updated_at: res.updated_at,
4649
+ attributes: res
4650
+ };
4651
+ }
4652
+ function cursorParams(options) {
4653
+ const params = new URLSearchParams();
4654
+ if (options?.limit !== void 0) params.set("limit", String(options.limit));
4655
+ if (options?.page) params.set("page", options.page);
4656
+ return params;
4657
+ }
4658
+ function withQuery(path, params) {
4659
+ const query2 = params.toString();
4660
+ return query2 ? `${path}?${query2}` : path;
4661
+ }
4662
+ function cursorPage(res, mapper) {
4663
+ const nextPage = res.next_page ?? void 0;
4664
+ return {
4665
+ data: (res.data ?? []).map(mapper),
4666
+ has_more: res.has_more ?? nextPage !== void 0,
4667
+ next_page: nextPage
4668
+ };
4669
+ }
4670
+ function toSkillVersionInfo(res) {
4671
+ return {
4672
+ id: res.id,
4673
+ skill_id: res.skill_id ?? "",
4674
+ type: res.type ?? "skill_version",
4675
+ name: res.name,
4676
+ description: res.description,
4677
+ version: res.version ?? "",
4678
+ status: res.status,
4679
+ created_at: res.created_at,
4680
+ updated_at: res.updated_at,
4681
+ additional_properties: res.additional_properties,
4682
+ attributes: res
4683
+ };
4684
+ }
4685
+ function toDeploymentRunResult(res) {
4686
+ return {
4687
+ run_id: res.id,
4688
+ session_id: res.session_id ?? null,
4689
+ error: res.error ?? void 0
4690
+ };
4691
+ }
4692
+ function toDeploymentRunInfo(res) {
4693
+ return {
4694
+ id: res.id ?? "",
4695
+ deployment_id: res.deployment_id,
4696
+ session_id: res.session_id ?? void 0,
4697
+ status: res.status,
4698
+ error: res.error ?? void 0,
4699
+ created_at: res.created_at,
4700
+ updated_at: res.updated_at,
4701
+ attributes: res
4349
4702
  };
4350
4703
  }
4704
+ function extractCreatedEventIds(res) {
4705
+ const ids = /* @__PURE__ */ new Set();
4706
+ const topLevel = extractCreatedEventId(res);
4707
+ if (topLevel) ids.add(topLevel);
4708
+ for (const key of ["data", "events"]) {
4709
+ const items = res[key];
4710
+ if (!Array.isArray(items)) continue;
4711
+ for (const item of items) {
4712
+ if (!item || typeof item !== "object") continue;
4713
+ const id = item.id;
4714
+ if (typeof id === "string") ids.add(id);
4715
+ }
4716
+ }
4717
+ return Array.from(ids);
4718
+ }
4351
4719
  function normalizeBailianModel(value) {
4352
4720
  if (value && typeof value === "object" && "id" in value) {
4353
4721
  return value.id;
@@ -4673,7 +5041,7 @@ function mapAgent4(name, decl, refs, version, projectName) {
4673
5041
  if (!arkModel) throw new UserError(`No Ark model specified for agent '${name}'`);
4674
5042
  const modelValue = typeof arkModel === "string" ? { id: arkModel } : { id: arkModel.id };
4675
5043
  const body = {
4676
- name,
5044
+ name: decl.name ?? name,
4677
5045
  model: modelValue,
4678
5046
  system: decl.instructions
4679
5047
  };
@@ -5407,6 +5775,7 @@ var coerceString = z5.union([z5.string(), z5.number()]).transform(String);
5407
5775
  var staticBearerCredentialSchema = z5.object({
5408
5776
  name: z5.string(),
5409
5777
  type: z5.literal("static_bearer"),
5778
+ metadata: z5.record(z5.string(), z5.string()).optional(),
5410
5779
  mcp_server_url: z5.string(),
5411
5780
  access_token: coerceString,
5412
5781
  protocol: z5.enum(["sse", "streamable_http"]).optional()
@@ -5414,6 +5783,7 @@ var staticBearerCredentialSchema = z5.object({
5414
5783
  var environmentVariableCredentialSchema = z5.object({
5415
5784
  name: z5.string(),
5416
5785
  type: z5.literal("environment_variable"),
5786
+ metadata: z5.record(z5.string(), z5.string()).optional(),
5417
5787
  secret_name: z5.string(),
5418
5788
  secret_value: coerceString,
5419
5789
  networking: z5.object({ type: z5.enum(["unrestricted", "limited"]) }).optional()
@@ -5556,6 +5926,9 @@ var agentSkillRefSchema = z5.object({
5556
5926
  var agentDeliverySchema = z5.object({
5557
5927
  type: z5.enum(["managed", "forward"])
5558
5928
  });
5929
+ var managedToolConfigSchema = z5.object({
5930
+ enabled_tools: z5.array(z5.string().min(1))
5931
+ });
5559
5932
  var sessionGithubRepoResourceSchema = z5.object({
5560
5933
  type: z5.literal("github_repository"),
5561
5934
  url: z5.string().url(),
@@ -5577,19 +5950,27 @@ var agentSchema = z5.object({
5577
5950
  mcp_servers: z5.array(mcpServerSchema).optional(),
5578
5951
  skills: z5.array(z5.union([z5.string(), agentSkillRefSchema])).optional(),
5579
5952
  vault: z5.string().optional(),
5953
+ files: z5.array(z5.string()).optional(),
5580
5954
  memory_stores: z5.array(z5.string()).optional(),
5955
+ default_memory_store: z5.object({
5956
+ name: z5.string().trim().min(1).max(255),
5957
+ description: z5.string().max(1024).optional(),
5958
+ delete_on_destroy: z5.boolean().optional().default(false)
5959
+ }).optional(),
5581
5960
  resources: z5.array(sessionGithubRepoResourceSchema).optional(),
5582
5961
  multiagent: multiagentSchema.optional(),
5583
5962
  metadata: z5.record(z5.string(), z5.string()).optional(),
5584
5963
  environment_variables: z5.record(z5.string().min(1), z5.string()).optional(),
5964
+ managed_tool_config: managedToolConfigSchema.optional(),
5585
5965
  delivery: z5.record(z5.string(), agentDeliverySchema).optional()
5586
5966
  });
5587
5967
  var channelSchema = z5.object({
5588
5968
  provider: z5.string().optional(),
5589
- agent: z5.string().min(1),
5969
+ agent: z5.string().min(1).optional(),
5590
5970
  identity: z5.string().min(1).optional(),
5591
5971
  type: z5.string().min(1),
5592
5972
  name: z5.string().trim().min(1).optional(),
5973
+ mode: z5.enum(["fixed", "pairing"]).optional().default("fixed"),
5593
5974
  enabled: z5.boolean().optional(),
5594
5975
  credentials: z5.record(z5.string(), coerceString).optional(),
5595
5976
  options: z5.record(z5.string(), z5.unknown()).optional()
@@ -5636,6 +6017,7 @@ var scheduleSchema = z5.object({
5636
6017
  timezone: z5.string()
5637
6018
  });
5638
6019
  var deploymentSchema = z5.object({
6020
+ name: z5.string().optional(),
5639
6021
  agent: z5.string(),
5640
6022
  agent_version: z5.number().int().optional(),
5641
6023
  environment: z5.string().optional(),
@@ -5828,15 +6210,24 @@ async function computeResourceHash(address, config, basePath, state) {
5828
6210
  if (!decl) return "";
5829
6211
  if (address.type === "skill") {
5830
6212
  const skillDecl = decl;
6213
+ const apiMode = resolveQoderApiMode(address.type, address.name, address.provider, config);
5831
6214
  if (basePath) {
5832
6215
  const fileHash = computeSkillContentHash(skillDecl.source, basePath);
5833
- return contentHash({ decl, fileHash });
6216
+ return contentHash({ decl, fileHash, apiMode });
5834
6217
  }
6218
+ return contentHash({ decl, apiMode });
6219
+ }
6220
+ if (address.type === "environment" || address.type === "vault" || address.type === "memory_store") {
6221
+ return contentHash({ decl, apiMode: resolveQoderApiMode(address.type, address.name, address.provider, config) });
5835
6222
  }
5836
6223
  if (address.type === "file" && basePath) {
5837
6224
  const fileDecl = decl;
5838
6225
  const fileHash = computeLocalFileContentHash(fileDecl.source, basePath);
5839
- return contentHash({ decl, fileHash });
6226
+ return contentHash({
6227
+ decl,
6228
+ fileHash,
6229
+ apiMode: resolveQoderApiMode("file", address.name, address.provider, config)
6230
+ });
5840
6231
  }
5841
6232
  if (address.type === "deployment") {
5842
6233
  const refs = resolveDeploymentReferenceIds(decl, config, address.provider, state);
@@ -5858,13 +6249,28 @@ async function computeResourceHash(address, config, basePath, state) {
5858
6249
  }
5859
6250
  return contentHash(decl);
5860
6251
  }
6252
+ function resolveQoderApiMode(type, name, provider, config) {
6253
+ if (provider !== "qoder") return void 0;
6254
+ if (type === "environment" && config.environments?.[name]?.environment_id) return "auto";
6255
+ for (const agent of Object.values(config.agents ?? {})) {
6256
+ if (agent.provider && agent.provider !== provider) continue;
6257
+ const referenced = type === "environment" ? agent.environment === name : type === "skill" ? agent.skills?.some(
6258
+ (skill) => typeof skill === "string" ? skill === name : skill.type === "custom" && skill.skill_id === name
6259
+ ) : type === "vault" ? agent.vault === name : type === "memory_store" ? agent.memory_stores?.includes(name) : agent.files?.includes(name);
6260
+ if (referenced && agent.delivery?.qoder?.type === "forward") return "forward";
6261
+ }
6262
+ return "managed";
6263
+ }
5861
6264
  function computeReplacementFingerprint(address, config) {
5862
6265
  if (address.type !== "channel") return void 0;
5863
6266
  const decl = config.channels?.[address.name];
5864
6267
  if (!decl) return void 0;
5865
- return contentHash({ channel_type: decl.type, credentials: decl.credentials ?? {} });
6268
+ return contentHash({ channel_type: decl.type, mode: decl.mode ?? "fixed", credentials: decl.credentials ?? {} });
5866
6269
  }
5867
6270
  function resolveChannelReferenceIds(decl, config, provider, state) {
6271
+ if (decl.mode === "pairing" || !decl.agent) {
6272
+ return { mode: "pairing" };
6273
+ }
5868
6274
  const agent = config.agents?.[decl.agent];
5869
6275
  const agentType = agent?.delivery?.[provider]?.type === "forward" ? "template" : "agent";
5870
6276
  const identity = decl.identity ?? config.defaults?.identity;
@@ -5887,7 +6293,14 @@ function resolveTemplateReferenceIds(decl, config, provider, state) {
5887
6293
  environment_id: environment?.environment_id ?? (decl.environment ? state?.getResource({ type: "environment", name: decl.environment, provider })?.remote_id ?? void 0 : void 0),
5888
6294
  tunnel_id: tunnel?.tunnel_id,
5889
6295
  vault_ids: decl.vault ? [state?.getResource({ type: "vault", name: decl.vault, provider })?.remote_id ?? decl.vault] : [],
5890
- skill_ids: skillIds
6296
+ skill_ids: skillIds,
6297
+ memory_store_ids: (decl.memory_stores ?? []).map(
6298
+ (memoryStore) => state?.getResource({ type: "memory_store", name: memoryStore, provider })?.remote_id ?? memoryStore
6299
+ ),
6300
+ file_ids: (decl.files ?? []).map(
6301
+ (file) => state?.getResource({ type: "file", name: file, provider })?.remote_id ?? file
6302
+ ),
6303
+ identity_id: decl.memory_stores?.length && config.defaults?.identity ? state?.getResource({ type: "identity", name: config.defaults.identity, provider })?.remote_id : void 0
5891
6304
  };
5892
6305
  }
5893
6306
  function resolveDeploymentReferenceIds(decl, config, provider, state) {
@@ -6067,11 +6480,21 @@ function resolveTemplateRefs(agentName, config, provider, state) {
6067
6480
  const environment = config.environments?.[agent.environment];
6068
6481
  if (!environment) throw new UserError(`Environment '${agent.environment}' is not defined in config.`);
6069
6482
  const agentRefs = resolveAgentRefs(agentName, config, provider, state);
6483
+ const memoryStoreIds = (agent.memory_stores ?? []).map(
6484
+ (memoryStore) => requireRef(state, { type: "memory_store", name: memoryStore, provider })
6485
+ );
6486
+ const identityName = config.defaults?.identity;
6070
6487
  return {
6071
6488
  ...agentRefs,
6072
6489
  environment_id: environment.environment_id ?? requireRef(state, { type: "environment", name: agent.environment, provider }),
6073
6490
  ...agent.tunnel ? { tunnel_id: resolveTunnelIdFromConfig(config, agent.tunnel, provider) } : {},
6074
- vault_ids: agent.vault ? [requireRef(state, { type: "vault", name: agent.vault, provider })] : []
6491
+ vault_ids: agent.vault ? [requireRef(state, { type: "vault", name: agent.vault, provider })] : [],
6492
+ file_ids: (agent.files ?? []).map((file) => requireRef(state, { type: "file", name: file, provider })),
6493
+ memory_store_ids: memoryStoreIds,
6494
+ owned_memory_store_ids: state.listResources().filter(
6495
+ (resource) => resource.address.provider === provider && resource.address.type === "memory_store" && resource.api_mode === "forward" && typeof resource.remote_id === "string"
6496
+ ).map((resource) => resource.remote_id),
6497
+ ...identityName ? { identity_id: requireRef(state, { type: "identity", name: identityName, provider }) } : {}
6075
6498
  };
6076
6499
  }
6077
6500
  function resolveDeploymentRefs(deploymentName, config, provider, state) {
@@ -6133,6 +6556,12 @@ function resolveDeploymentRefs(deploymentName, config, provider, state) {
6133
6556
  function resolveChannelRefs(channelName, config, provider, state) {
6134
6557
  const channel = config.channels?.[channelName];
6135
6558
  if (!channel) throw new UserError(`Channel '${channelName}' not found in config`);
6559
+ if (channel.mode === "pairing") {
6560
+ return {};
6561
+ }
6562
+ if (!channel.agent) {
6563
+ throw new UserError(`Channel '${channelName}' is fixed mode and must declare agent`);
6564
+ }
6136
6565
  const agent = config.agents?.[channel.agent];
6137
6566
  if (!agent) throw new UserError(`Channel '${channelName}' references unknown agent '${channel.agent}'`);
6138
6567
  const agentType = agent.delivery?.[provider]?.type === "forward" ? "template" : "agent";
@@ -6156,8 +6585,61 @@ function resolveTunnelIdFromConfig(config, tunnelName, provider) {
6156
6585
  }
6157
6586
 
6158
6587
  // src/internal/executor/skill-resolver.ts
6588
+ import { dirname as dirname9 } from "path";
6589
+
6590
+ // src/internal/core/skill-source.ts
6159
6591
  import { readFileSync as readFileSync7, statSync as statSync3 } from "fs";
6160
- import { dirname as dirname9, resolve as resolve10 } from "path";
6592
+ import { basename as basename6, resolve as resolve10 } from "path";
6593
+ import { parse } from "yaml";
6594
+ async function inspectSkillSource(source, options = {}) {
6595
+ if (/^https?:\/\//i.test(source)) {
6596
+ throw new UserError("Skill source inspection only accepts a local directory, zip, or SKILL.md file.");
6597
+ }
6598
+ const sourcePath = resolve10(options.basePath ?? process.cwd(), source);
6599
+ const sourceStat = statSync3(sourcePath, { throwIfNoEntry: false });
6600
+ if (!sourceStat) throw new UserError(`Skill source not found: ${source}`);
6601
+ let files;
6602
+ if (sourceStat.isDirectory()) {
6603
+ files = collectFiles(sourcePath, "");
6604
+ } else if (sourceStat.isFile() && sourcePath.toLowerCase().endsWith(".zip")) {
6605
+ files = await extractSkillZipFiles(readFileSync7(sourcePath));
6606
+ } else if (sourceStat.isFile() && basename6(sourcePath).toLowerCase() === "skill.md") {
6607
+ files = [{ relativePath: "SKILL.md", content: readFileSync7(sourcePath) }];
6608
+ } else {
6609
+ throw new UserError("Skill source must be a directory, .zip archive, or SKILL.md file.");
6610
+ }
6611
+ const normalizedFiles = normalizeSkillRoot(files);
6612
+ const manifest = normalizedFiles.find((file) => file.relativePath === "SKILL.md");
6613
+ const name = parseSkillManifestName(manifest.content);
6614
+ return { name, sourcePath, files: normalizedFiles };
6615
+ }
6616
+ function normalizeSkillRoot(files) {
6617
+ if (files.some((file) => file.relativePath === "SKILL.md")) return files;
6618
+ const manifests = files.filter((file) => file.relativePath.endsWith("/SKILL.md"));
6619
+ if (manifests.length === 0) throw new UserError("Skill source does not contain SKILL.md.");
6620
+ if (manifests.length > 1) {
6621
+ throw new UserError("Skill source contains multiple SKILL.md files and has no unambiguous root.");
6622
+ }
6623
+ const prefix = manifests[0].relativePath.slice(0, -"SKILL.md".length);
6624
+ return files.filter((file) => file.relativePath.startsWith(prefix)).map((file) => ({ ...file, relativePath: file.relativePath.slice(prefix.length) }));
6625
+ }
6626
+ function parseSkillManifestName(content) {
6627
+ const text = content.toString("utf8");
6628
+ const frontmatter = text.match(/^---\s*\r?\n([\s\S]*?)\r?\n---(?:\s*\r?\n|$)/);
6629
+ if (!frontmatter) throw new UserError("SKILL.md must start with YAML frontmatter containing a name.");
6630
+ let manifest;
6631
+ try {
6632
+ manifest = parse(frontmatter[1]);
6633
+ } catch (error) {
6634
+ throw new UserError(`Invalid SKILL.md frontmatter: ${error instanceof Error ? error.message : String(error)}`);
6635
+ }
6636
+ const rawName = manifest && typeof manifest === "object" ? manifest.name : void 0;
6637
+ const name = typeof rawName === "string" ? rawName.trim() : "";
6638
+ if (!name) throw new UserError("SKILL.md frontmatter must contain a non-empty name.");
6639
+ return name;
6640
+ }
6641
+
6642
+ // src/internal/executor/skill-resolver.ts
6161
6643
  async function resolveSkillFiles(decl, ctx) {
6162
6644
  if (/^https?:\/\//i.test(decl.source)) {
6163
6645
  const res = await resolveFetch()(decl.source);
@@ -6165,19 +6647,7 @@ async function resolveSkillFiles(decl, ctx) {
6165
6647
  return extractSkillZipFiles(Buffer.from(await res.arrayBuffer()));
6166
6648
  }
6167
6649
  if (!ctx.configPath) return [];
6168
- const sourcePath = resolve10(dirname9(ctx.configPath), decl.source);
6169
- const stat = statSync3(sourcePath, { throwIfNoEntry: false });
6170
- if (stat?.isDirectory()) {
6171
- return collectFiles(sourcePath, "");
6172
- }
6173
- if (stat?.isFile()) {
6174
- if (sourcePath.endsWith(".zip")) {
6175
- return extractSkillZipFiles(readFileSync7(sourcePath));
6176
- }
6177
- const content = readFileSync7(sourcePath);
6178
- return [{ relativePath: "SKILL.md", content }];
6179
- }
6180
- return [];
6650
+ return (await inspectSkillSource(decl.source, { basePath: dirname9(ctx.configPath) })).files;
6181
6651
  }
6182
6652
 
6183
6653
  // src/internal/executor/executor.ts
@@ -6255,6 +6725,7 @@ async function executePlan(plan, ctx, options = {}) {
6255
6725
  await runWithConcurrency(level, concurrency, runAction);
6256
6726
  await ctx.state.save();
6257
6727
  }
6728
+ await reconcileDefaultMemoryStores(ctx, new Set(plan.actions.map((action) => action.address.provider)));
6258
6729
  for (const action of deletions) {
6259
6730
  await runAction(action);
6260
6731
  await ctx.state.save();
@@ -6265,6 +6736,41 @@ async function executePlan(plan, ctx, options = {}) {
6265
6736
  partial: results.some((r) => r.status === "failed")
6266
6737
  };
6267
6738
  }
6739
+ async function reconcileDefaultMemoryStores(ctx, plannedProviders) {
6740
+ const identityName = ctx.config.defaults?.identity;
6741
+ for (const [agentName, agent] of Object.entries(ctx.config.agents ?? {})) {
6742
+ const desired = agent.default_memory_store;
6743
+ if (!desired || agent.delivery?.qoder?.type !== "forward") continue;
6744
+ const providerName = "qoder";
6745
+ if (agent.provider && agent.provider !== providerName || !plannedProviders.has(providerName)) continue;
6746
+ const provider = ctx.providers.get(providerName);
6747
+ if (!provider?.reconcileDefaultMemoryStore || !identityName) continue;
6748
+ const identityId = ctx.state.getResource({
6749
+ type: "identity",
6750
+ name: identityName,
6751
+ provider: providerName
6752
+ })?.remote_id;
6753
+ const templateId = ctx.state.getResource({ type: "template", name: agentName, provider: providerName })?.remote_id;
6754
+ if (!identityId || !templateId) continue;
6755
+ const result = await provider.reconcileDefaultMemoryStore(identityId, templateId, desired);
6756
+ const resource = { type: "template", name: agentName, provider: providerName };
6757
+ if (result.status === "pending") {
6758
+ emitRuntimeFeedback(ctx.onFeedback, {
6759
+ type: "provider_wait",
6760
+ level: "warning",
6761
+ resource,
6762
+ message: `default memory store for template.${agentName} is pending \u2014 create the first Forward Session, then run apply again`
6763
+ });
6764
+ } else if (result.status === "updated") {
6765
+ emitRuntimeFeedback(ctx.onFeedback, {
6766
+ type: "resource_action_success",
6767
+ level: "success",
6768
+ resource,
6769
+ message: `updated default memory store for template.${agentName} to "${desired.name}"`
6770
+ });
6771
+ }
6772
+ }
6773
+ }
6268
6774
  async function runWithConcurrency(items, limit, worker) {
6269
6775
  if (items.length === 0) return;
6270
6776
  let cursor = 0;
@@ -6343,6 +6849,7 @@ async function executeActionInner(action, provider, ctx) {
6343
6849
  const existing = ctx.state.getResource(address);
6344
6850
  if (!existing) return false;
6345
6851
  const id = existing.remote_id;
6852
+ const apiMode2 = existing.api_mode;
6346
6853
  if (type === "environment" || type === "identity") {
6347
6854
  const externalReference = type === "environment" ? ctx.config.environments?.[name]?.environment_id : ctx.config.identities?.[name]?.identity_id;
6348
6855
  if (existing.externally_managed || externalReference) {
@@ -6354,13 +6861,13 @@ async function executeActionInner(action, provider, ctx) {
6354
6861
  try {
6355
6862
  switch (type) {
6356
6863
  case "environment":
6357
- await provider.deleteEnvironment(id);
6864
+ await provider.deleteEnvironment(id, false, apiMode2);
6358
6865
  break;
6359
6866
  case "vault":
6360
- await provider.deleteVault(id);
6867
+ await provider.deleteVault(id, apiMode2);
6361
6868
  break;
6362
6869
  case "skill":
6363
- await provider.deleteSkill(id);
6870
+ await provider.deleteSkill(id, apiMode2);
6364
6871
  break;
6365
6872
  case "agent":
6366
6873
  await provider.deleteAgent(id);
@@ -6368,17 +6875,17 @@ async function executeActionInner(action, provider, ctx) {
6368
6875
  case "template":
6369
6876
  if (!provider.archiveTemplate)
6370
6877
  throw new UserError(`Provider '${address.provider}' does not support templates`);
6371
- await provider.archiveTemplate(id);
6878
+ await provider.archiveTemplate(id, ownedForwardMemoryStoreIds(ctx, address.provider));
6372
6879
  break;
6373
6880
  case "memory_store":
6374
6881
  if (!provider.deleteMemoryStore) throw memoryStoreUnsupported(address.provider);
6375
- await provider.deleteMemoryStore(id);
6882
+ await provider.deleteMemoryStore(id, apiMode2);
6376
6883
  break;
6377
6884
  case "deployment":
6378
6885
  await provider.deleteDeployment(id);
6379
6886
  break;
6380
6887
  case "file":
6381
- await provider.deleteFile(id);
6888
+ await provider.deleteFile(id, apiMode2);
6382
6889
  break;
6383
6890
  case "identity":
6384
6891
  if (!provider.deleteIdentity)
@@ -6407,6 +6914,9 @@ async function executeActionInner(action, provider, ctx) {
6407
6914
  const isUpdate = action.action === "update";
6408
6915
  const priorAddress = action.previousAddress ?? address;
6409
6916
  const existingId = isUpdate ? ctx.state.getResource(priorAddress)?.remote_id : void 0;
6917
+ const apiMode = resolveResourceApiMode(type, name, address.provider, ctx.config);
6918
+ const priorApiMode = ctx.state.getResource(priorAddress)?.api_mode ?? (address.provider === "qoder" ? "managed" : void 0);
6919
+ const apiModeChanged = isUpdate && apiMode !== void 0 && priorApiMode !== apiMode;
6410
6920
  let result;
6411
6921
  switch (type) {
6412
6922
  case "environment": {
@@ -6421,6 +6931,17 @@ async function executeActionInner(action, provider, ctx) {
6421
6931
  resource: action.address,
6422
6932
  message: `${action.action} ${action.address.type}.${action.address.name} (${action.address.provider}) \u2014 external reference, no remote mutation`
6423
6933
  });
6934
+ } else if (apiModeChanged) {
6935
+ try {
6936
+ result = await provider.createEnvironment(remoteName, decl, apiMode);
6937
+ } catch (err) {
6938
+ result = await adoptOnConflict(err, address, provider, ctx.onFeedback, {
6939
+ mode: apiMode,
6940
+ onExisting: (existing) => provider.updateEnvironment(existing.id, remoteName, decl, apiMode)
6941
+ });
6942
+ adopted = true;
6943
+ }
6944
+ if (existingId) await provider.deleteEnvironment(existingId, false, priorApiMode);
6424
6945
  } else if (isUpdate) {
6425
6946
  const prior = ctx.state.getResource(address);
6426
6947
  if (prior?.externally_managed) {
@@ -6428,13 +6949,14 @@ async function executeActionInner(action, provider, ctx) {
6428
6949
  `environment.${name} is recorded as an external reference (${prior.remote_id ?? "unknown id"}); refusing to modify it remotely. Restore 'environment_id' to keep it as a reference, or release it first with 'agents state rm environment.${name}' (then 'agents state import' to adopt it as a managed resource).`
6429
6950
  );
6430
6951
  }
6431
- result = await provider.updateEnvironment(existingId, remoteName, decl);
6952
+ result = await provider.updateEnvironment(existingId, remoteName, decl, apiMode);
6432
6953
  } else {
6433
6954
  try {
6434
- result = await provider.createEnvironment(remoteName, decl);
6955
+ result = await provider.createEnvironment(remoteName, decl, apiMode);
6435
6956
  } catch (err) {
6436
6957
  result = await adoptOnConflict(err, address, provider, ctx.onFeedback, {
6437
- onExisting: (existing) => provider.updateEnvironment(existing.id, remoteName, decl)
6958
+ mode: apiMode,
6959
+ onExisting: (existing) => provider.updateEnvironment(existing.id, remoteName, decl, apiMode)
6438
6960
  });
6439
6961
  adopted = true;
6440
6962
  }
@@ -6443,22 +6965,26 @@ async function executeActionInner(action, provider, ctx) {
6443
6965
  }
6444
6966
  case "vault": {
6445
6967
  const decl = ctx.config.vaults[name];
6446
- if (isUpdate) {
6968
+ if (apiModeChanged) {
6969
+ result = await provider.createVault(name, decl, apiMode);
6970
+ if (existingId) await provider.deleteVault(existingId, priorApiMode).catch(() => void 0);
6971
+ } else if (isUpdate) {
6447
6972
  try {
6448
- result = await provider.createVault(name, decl);
6449
- await provider.deleteVault(existingId);
6973
+ result = await provider.createVault(name, decl, apiMode);
6974
+ await provider.deleteVault(existingId, apiMode);
6450
6975
  } catch {
6451
- await provider.deleteVault(existingId);
6452
- result = await provider.createVault(name, decl);
6976
+ await provider.deleteVault(existingId, apiMode);
6977
+ result = await provider.createVault(name, decl, apiMode);
6453
6978
  }
6454
6979
  } else {
6455
6980
  try {
6456
- result = await provider.createVault(name, decl);
6981
+ result = await provider.createVault(name, decl, apiMode);
6457
6982
  } catch (err) {
6458
6983
  result = await adoptOnConflict(err, address, provider, ctx.onFeedback, {
6984
+ mode: apiMode,
6459
6985
  onExisting: async (existing) => {
6460
- await provider.deleteVault(existing.id);
6461
- return provider.createVault(name, decl);
6986
+ await provider.deleteVault(existing.id, apiMode);
6987
+ return provider.createVault(name, decl, apiMode);
6462
6988
  }
6463
6989
  });
6464
6990
  adopted = true;
@@ -6482,12 +7008,15 @@ async function executeActionInner(action, provider, ctx) {
6482
7008
  }
6483
7009
  const remoteName = decl.name ?? name;
6484
7010
  const files = await resolveSkillFiles(decl, ctx);
6485
- if (isUpdate) {
6486
- result = await provider.updateSkill(existingId, remoteName, decl, files);
7011
+ if (apiModeChanged) {
7012
+ result = await provider.createSkill(remoteName, decl, files, apiMode);
7013
+ if (existingId) await provider.deleteSkill(existingId, priorApiMode).catch(() => void 0);
7014
+ } else if (isUpdate) {
7015
+ result = await provider.updateSkill(existingId, remoteName, decl, files, apiMode);
6487
7016
  } else {
6488
7017
  const manifestName = skillNameFromFiles(files);
6489
7018
  const searchNames = manifestName && manifestName !== remoteName ? [remoteName, manifestName] : [remoteName];
6490
- const existing = await findExistingByNames(provider, "skill", searchNames);
7019
+ const existing = await findExistingByNames(provider, "skill", searchNames, apiMode);
6491
7020
  if (existing) {
6492
7021
  result = existing.resource;
6493
7022
  emitRuntimeFeedback(ctx.onFeedback, {
@@ -6499,9 +7028,10 @@ async function executeActionInner(action, provider, ctx) {
6499
7028
  adopted = true;
6500
7029
  } else {
6501
7030
  try {
6502
- result = await provider.createSkill(remoteName, decl, files);
7031
+ result = await provider.createSkill(remoteName, decl, files, apiMode);
6503
7032
  } catch (err) {
6504
7033
  result = await adoptOnConflict(err, address, provider, ctx.onFeedback, {
7034
+ mode: apiMode,
6505
7035
  searchNames,
6506
7036
  onExisting: async (existing2) => existing2
6507
7037
  });
@@ -6520,15 +7050,19 @@ async function executeActionInner(action, provider, ctx) {
6520
7050
  throw memoryStoreUnsupported(address.provider);
6521
7051
  }
6522
7052
  const reconcile = async (storeId) => {
6523
- const store = await provider.updateMemoryStore(storeId, {
6524
- name,
6525
- description: decl.description,
6526
- metadata: decl.metadata ?? {}
6527
- });
7053
+ const store = await provider.updateMemoryStore(
7054
+ storeId,
7055
+ {
7056
+ name,
7057
+ description: decl.description,
7058
+ metadata: decl.metadata ?? {}
7059
+ },
7060
+ apiMode
7061
+ );
6528
7062
  const current = /* @__PURE__ */ new Map();
6529
7063
  let cursor;
6530
7064
  do {
6531
- const page2 = await provider.listMemories(storeId, { limit: 100, cursor, view: "basic" });
7065
+ const page2 = await provider.listMemories(storeId, { limit: 100, cursor, view: "basic" }, apiMode);
6532
7066
  for (const memory of page2.data) {
6533
7067
  if (memory.type === "memory") current.set(memory.path, memory);
6534
7068
  }
@@ -6538,24 +7072,33 @@ async function executeActionInner(action, provider, ctx) {
6538
7072
  const existing = current.get(entry.key.replace(/^\/+/, ""));
6539
7073
  if (existing) {
6540
7074
  if (existing.content_sha256 !== sha256(entry.content)) {
6541
- await provider.updateMemory(storeId, existing.id, {
6542
- content: entry.content,
6543
- expected_content_sha256: existing.content_sha256
6544
- });
7075
+ await provider.updateMemory(
7076
+ storeId,
7077
+ existing.id,
7078
+ {
7079
+ content: entry.content,
7080
+ expected_content_sha256: existing.content_sha256
7081
+ },
7082
+ apiMode
7083
+ );
6545
7084
  }
6546
7085
  } else {
6547
- await provider.createMemory(storeId, { path: entry.key, content: entry.content });
7086
+ await provider.createMemory(storeId, { path: entry.key, content: entry.content }, apiMode);
6548
7087
  }
6549
7088
  }
6550
7089
  return store;
6551
7090
  };
6552
- if (isUpdate) {
7091
+ if (apiModeChanged) {
7092
+ result = await createMemoryStore2(name, decl, apiMode);
7093
+ if (existingId) await deleteMemoryStore2(existingId, priorApiMode).catch(() => void 0);
7094
+ } else if (isUpdate) {
6553
7095
  result = await reconcile(existingId);
6554
7096
  } else {
6555
7097
  try {
6556
- result = await createMemoryStore2(name, decl);
7098
+ result = await createMemoryStore2(name, decl, apiMode);
6557
7099
  } catch (err) {
6558
7100
  result = await adoptOnConflict(err, address, provider, ctx.onFeedback, {
7101
+ mode: apiMode,
6559
7102
  onExisting: async (existing) => reconcile(existing.id)
6560
7103
  });
6561
7104
  adopted = true;
@@ -6705,15 +7248,12 @@ async function executeActionInner(action, provider, ctx) {
6705
7248
  const oldId = ctx.state.getResource(address)?.remote_id;
6706
7249
  if (oldId) {
6707
7250
  try {
6708
- await provider.deleteFile(oldId);
7251
+ await provider.deleteFile(oldId, priorApiMode);
6709
7252
  } catch {
6710
7253
  }
6711
7254
  }
6712
7255
  }
6713
- const info = await provider.uploadFile(filePath, {
6714
- name: decl.name,
6715
- purpose: decl.purpose
6716
- });
7256
+ const info = await provider.uploadFile(filePath, { name: decl.name, purpose: decl.purpose }, apiMode);
6717
7257
  result = { id: info.id, type: "file" };
6718
7258
  break;
6719
7259
  }
@@ -6734,6 +7274,7 @@ async function executeActionInner(action, provider, ctx) {
6734
7274
  address,
6735
7275
  remote_id: result.id,
6736
7276
  externally_managed: priorResource?.externally_managed || type === "environment" && ctx.config.environments?.[name]?.environment_id || type === "identity" && ctx.config.identities?.[name]?.identity_id ? true : void 0,
7277
+ api_mode: apiMode,
6737
7278
  version: result.version,
6738
7279
  content_hash: hash,
6739
7280
  desired_hash: hash,
@@ -6748,9 +7289,37 @@ async function executeActionInner(action, provider, ctx) {
6748
7289
  if (action.previousAddress) ctx.state.removeResource(action.previousAddress);
6749
7290
  return adopted;
6750
7291
  }
6751
- async function findExistingByNames(provider, type, names) {
7292
+ function ownedForwardMemoryStoreIds(ctx, provider) {
7293
+ return ctx.state.listResources().filter(
7294
+ (resource) => resource.address.provider === provider && resource.address.type === "memory_store" && resource.api_mode === "forward" && typeof resource.remote_id === "string"
7295
+ ).map((resource) => resource.remote_id);
7296
+ }
7297
+ function resolveResourceApiMode(type, name, provider, config) {
7298
+ if (provider !== "qoder" || type !== "environment" && type !== "skill" && type !== "vault" && type !== "memory_store" && type !== "file") {
7299
+ return void 0;
7300
+ }
7301
+ if (type === "environment" && config.environments?.[name]?.environment_id) return "auto";
7302
+ let managed = false;
7303
+ let forward = false;
7304
+ for (const agent of Object.values(config.agents ?? {})) {
7305
+ if (agent.provider && agent.provider !== provider) continue;
7306
+ const referenced = type === "environment" ? agent.environment === name : type === "skill" ? agent.skills?.some(
7307
+ (skill) => typeof skill === "string" ? skill === name : skill.type === "custom" && skill.skill_id === name
7308
+ ) : type === "vault" ? agent.vault === name : type === "memory_store" ? agent.memory_stores?.includes(name) : agent.files?.includes(name);
7309
+ if (!referenced) continue;
7310
+ if (agent.delivery?.qoder?.type === "forward") forward = true;
7311
+ else managed = true;
7312
+ }
7313
+ if (managed && forward) {
7314
+ throw new UserError(
7315
+ `Qoder ${type}.${name} is referenced by both Managed and Forward agents; declare separate resources for each API domain.`
7316
+ );
7317
+ }
7318
+ return forward ? "forward" : "managed";
7319
+ }
7320
+ async function findExistingByNames(provider, type, names, mode) {
6752
7321
  for (const candidate of names) {
6753
- const found = await provider.findResource(type, candidate);
7322
+ const found = await provider.findResource(type, candidate, void 0, mode);
6754
7323
  if (found && found.id !== null) return { resource: found, name: candidate };
6755
7324
  }
6756
7325
  return null;
@@ -6758,7 +7327,7 @@ async function findExistingByNames(provider, type, names) {
6758
7327
  async function adoptOnConflict(err, address, provider, onFeedback, opts) {
6759
7328
  if (!(err instanceof ConflictError)) throw err;
6760
7329
  const candidates = opts.searchNames?.length ? opts.searchNames : [address.name];
6761
- const existing = await findExistingByNames(provider, address.type, candidates);
7330
+ const existing = await findExistingByNames(provider, address.type, candidates, opts.mode);
6762
7331
  if (!existing) throw nameReservedError(err, address, candidates.join('" / "'));
6763
7332
  emitRuntimeFeedback(onFeedback, {
6764
7333
  type: "resource_adopted",
@@ -6780,6 +7349,236 @@ function nameReservedError(err, address, searchName) {
6780
7349
  );
6781
7350
  }
6782
7351
 
7352
+ // src/internal/core/agent-materialization.ts
7353
+ function resolveAgentMaterialization(provider, agent) {
7354
+ const mode = agent.delivery?.[provider]?.type ?? "managed";
7355
+ if (mode === "managed") return { resourceType: "agent", mode };
7356
+ return { resourceType: "template", mode };
7357
+ }
7358
+
7359
+ // src/internal/graph/dependency.ts
7360
+ function collectDependencyClosure(graph, roots) {
7361
+ const selected = /* @__PURE__ */ new Map();
7362
+ function visit(address) {
7363
+ const key = addressKey(address);
7364
+ if (selected.has(key)) return;
7365
+ selected.set(key, graph.nodes.get(key) ?? address);
7366
+ for (const dependencyKey of graph.edges.get(key) ?? []) {
7367
+ const dependency = graph.nodes.get(dependencyKey);
7368
+ if (dependency) visit(dependency);
7369
+ }
7370
+ }
7371
+ for (const root of roots) visit(root);
7372
+ return [...selected.values()];
7373
+ }
7374
+ function buildDependencyGraph(config, targetProviders) {
7375
+ const nodes = /* @__PURE__ */ new Map();
7376
+ const edges = /* @__PURE__ */ new Map();
7377
+ function addNode(addr) {
7378
+ const key = addressKey(addr);
7379
+ nodes.set(key, addr);
7380
+ if (!edges.has(key)) edges.set(key, /* @__PURE__ */ new Set());
7381
+ }
7382
+ function addEdge(from, to) {
7383
+ const fromKey = addressKey(from);
7384
+ const toKey = addressKey(to);
7385
+ edges.get(fromKey)?.add(toKey);
7386
+ }
7387
+ for (const provider of targetProviders) {
7388
+ const def = getProvider(provider);
7389
+ const caps = def?.capabilities;
7390
+ if (config.environments) {
7391
+ for (const name of Object.keys(config.environments)) {
7392
+ const decl = config.environments[name];
7393
+ if (decl.provider && decl.provider !== provider) continue;
7394
+ addNode({ type: "environment", name, provider });
7395
+ }
7396
+ }
7397
+ if (config.memory_stores) {
7398
+ for (const name of Object.keys(config.memory_stores)) {
7399
+ const decl = config.memory_stores[name];
7400
+ if (decl.provider && decl.provider !== provider) continue;
7401
+ if (!isSupported(caps, "memory_store")) continue;
7402
+ addNode({ type: "memory_store", name, provider });
7403
+ }
7404
+ }
7405
+ if (config.vaults) {
7406
+ for (const name of Object.keys(config.vaults)) {
7407
+ const decl = config.vaults[name];
7408
+ if (decl.provider && decl.provider !== provider) continue;
7409
+ addNode({ type: "vault", name, provider });
7410
+ }
7411
+ }
7412
+ if (config.skills) {
7413
+ for (const name of Object.keys(config.skills)) {
7414
+ const decl = config.skills[name];
7415
+ if (decl.provider && decl.provider !== provider) continue;
7416
+ addNode({ type: "skill", name, provider });
7417
+ }
7418
+ }
7419
+ if (config.files) {
7420
+ for (const name of Object.keys(config.files)) {
7421
+ const decl = config.files[name];
7422
+ if (decl.provider && decl.provider !== provider) continue;
7423
+ addNode({ type: "file", name, provider });
7424
+ }
7425
+ }
7426
+ if (config.identities && isSupported(caps, "identity")) {
7427
+ for (const name of Object.keys(config.identities)) {
7428
+ const decl = config.identities[name];
7429
+ if (decl.provider && decl.provider !== provider) continue;
7430
+ addNode({ type: "identity", name, provider });
7431
+ }
7432
+ }
7433
+ if (config.agents) {
7434
+ for (const name of Object.keys(config.agents)) {
7435
+ const decl = config.agents[name];
7436
+ if (decl.provider && decl.provider !== provider) continue;
7437
+ const materialization = resolveAgentMaterialization(provider, decl);
7438
+ const agentAddr = { type: materialization.resourceType, name, provider };
7439
+ addNode(agentAddr);
7440
+ if ((decl.default_memory_store || decl.memory_stores?.length) && materialization.resourceType === "template") {
7441
+ const identityName = config.defaults?.identity;
7442
+ if (identityName) {
7443
+ const identityAddr = { type: "identity", name: identityName, provider };
7444
+ if (nodes.has(addressKey(identityAddr))) addEdge(agentAddr, identityAddr);
7445
+ }
7446
+ }
7447
+ if (decl.environment && config.environments?.[decl.environment]) {
7448
+ const envAddr = {
7449
+ type: "environment",
7450
+ name: decl.environment,
7451
+ provider
7452
+ };
7453
+ if (nodes.has(addressKey(envAddr))) {
7454
+ addEdge(agentAddr, envAddr);
7455
+ }
7456
+ }
7457
+ if (decl.skills) {
7458
+ for (const skillRef of decl.skills) {
7459
+ if (typeof skillRef !== "string") continue;
7460
+ const skillName = skillRef;
7461
+ const skillAddr = { type: "skill", name: skillName, provider };
7462
+ if (nodes.has(addressKey(skillAddr))) {
7463
+ addEdge(agentAddr, skillAddr);
7464
+ }
7465
+ }
7466
+ }
7467
+ if (decl.vault) {
7468
+ const vaultAddr = { type: "vault", name: decl.vault, provider };
7469
+ if (nodes.has(addressKey(vaultAddr))) {
7470
+ addEdge(agentAddr, vaultAddr);
7471
+ }
7472
+ }
7473
+ if (decl.files) {
7474
+ for (const fileName of decl.files) {
7475
+ const fileAddr = { type: "file", name: fileName, provider };
7476
+ if (nodes.has(addressKey(fileAddr))) addEdge(agentAddr, fileAddr);
7477
+ }
7478
+ }
7479
+ if (decl.memory_stores) {
7480
+ for (const msName of decl.memory_stores) {
7481
+ const msAddr = {
7482
+ type: "memory_store",
7483
+ name: msName,
7484
+ provider
7485
+ };
7486
+ if (nodes.has(addressKey(msAddr))) {
7487
+ addEdge(agentAddr, msAddr);
7488
+ }
7489
+ }
7490
+ }
7491
+ if (decl.multiagent && isSupported(caps, "multiagent")) {
7492
+ for (const subName of decl.multiagent.agents) {
7493
+ const subDecl = config.agents[subName];
7494
+ const subType = subDecl ? resolveAgentMaterialization(provider, subDecl).resourceType : "agent";
7495
+ const subAddr = { type: subType, name: subName, provider };
7496
+ addEdge(agentAddr, subAddr);
7497
+ }
7498
+ }
7499
+ }
7500
+ }
7501
+ if (config.deployments) {
7502
+ for (const name of Object.keys(config.deployments)) {
7503
+ const decl = config.deployments[name];
7504
+ if (decl.provider && decl.provider !== provider) continue;
7505
+ const depAddr = { type: "deployment", name, provider };
7506
+ addNode(depAddr);
7507
+ const agentDecl = config.agents?.[decl.agent];
7508
+ const agentType = agentDecl ? resolveAgentMaterialization(provider, agentDecl).resourceType : "agent";
7509
+ const agentAddr = { type: agentType, name: decl.agent, provider };
7510
+ if (nodes.has(addressKey(agentAddr))) addEdge(depAddr, agentAddr);
7511
+ if (decl.environment) {
7512
+ const envAddr = { type: "environment", name: decl.environment, provider };
7513
+ if (nodes.has(addressKey(envAddr))) addEdge(depAddr, envAddr);
7514
+ }
7515
+ if (decl.vaults) {
7516
+ for (const vName of decl.vaults) {
7517
+ const vAddr = { type: "vault", name: vName, provider };
7518
+ if (nodes.has(addressKey(vAddr))) addEdge(depAddr, vAddr);
7519
+ }
7520
+ }
7521
+ if (decl.memory_stores) {
7522
+ for (const msName of decl.memory_stores) {
7523
+ const msAddr = { type: "memory_store", name: msName, provider };
7524
+ if (nodes.has(addressKey(msAddr))) addEdge(depAddr, msAddr);
7525
+ }
7526
+ }
7527
+ if (decl.resources) {
7528
+ for (const r of decl.resources) {
7529
+ if (r.type === "memory_store") {
7530
+ const msAddr = { type: "memory_store", name: r.memory_store, provider };
7531
+ if (nodes.has(addressKey(msAddr))) addEdge(depAddr, msAddr);
7532
+ }
7533
+ }
7534
+ }
7535
+ }
7536
+ }
7537
+ if (config.channels && isSupported(caps, "channel")) {
7538
+ for (const name of Object.keys(config.channels)) {
7539
+ const decl = config.channels[name];
7540
+ if (decl.provider && decl.provider !== provider) continue;
7541
+ const channelAddr = { type: "channel", name, provider };
7542
+ addNode(channelAddr);
7543
+ if (decl.mode === "pairing" || !decl.agent) continue;
7544
+ const agentDecl = config.agents?.[decl.agent];
7545
+ const agentType = agentDecl ? resolveAgentMaterialization(provider, agentDecl).resourceType : "agent";
7546
+ const agentAddr = { type: agentType, name: decl.agent, provider };
7547
+ if (nodes.has(addressKey(agentAddr))) addEdge(channelAddr, agentAddr);
7548
+ const identityName = decl.identity ?? config.defaults?.identity;
7549
+ if (identityName) {
7550
+ const identityAddr = { type: "identity", name: identityName, provider };
7551
+ if (nodes.has(addressKey(identityAddr))) addEdge(channelAddr, identityAddr);
7552
+ }
7553
+ }
7554
+ }
7555
+ }
7556
+ return { nodes, edges };
7557
+ }
7558
+ function topologicalSort(graph) {
7559
+ const visited = /* @__PURE__ */ new Set();
7560
+ const sorted = [];
7561
+ const visiting = /* @__PURE__ */ new Set();
7562
+ function visit(key) {
7563
+ if (visited.has(key)) return;
7564
+ if (visiting.has(key)) {
7565
+ throw new UserError(`Circular dependency detected involving: ${key}`);
7566
+ }
7567
+ visiting.add(key);
7568
+ const deps = graph.edges.get(key) ?? /* @__PURE__ */ new Set();
7569
+ for (const dep of deps) {
7570
+ visit(dep);
7571
+ }
7572
+ visiting.delete(key);
7573
+ visited.add(key);
7574
+ sorted.push(graph.nodes.get(key));
7575
+ }
7576
+ for (const key of graph.nodes.keys()) {
7577
+ visit(key);
7578
+ }
7579
+ return sorted;
7580
+ }
7581
+
6783
7582
  // src/internal/diagnostics/diagnostics.ts
6784
7583
  var DiagnosticCollector = class {
6785
7584
  items = [];
@@ -6873,6 +7672,7 @@ function collectReferenceDiagnostics(config, diagnostics) {
6873
7672
  const skillNames = new Set(Object.keys(config.skills ?? {}));
6874
7673
  const vaultNames = new Set(Object.keys(config.vaults ?? {}));
6875
7674
  const memoryNames = new Set(Object.keys(config.memory_stores ?? {}));
7675
+ const fileNames = new Set(Object.keys(config.files ?? {}));
6876
7676
  const agentNames = new Set(Object.keys(config.agents ?? {}));
6877
7677
  const identityNames = new Set(Object.keys(config.identities ?? {}));
6878
7678
  if (config.defaults?.identity && !identityNames.has(config.defaults.identity)) {
@@ -6900,6 +7700,11 @@ function collectReferenceDiagnostics(config, diagnostics) {
6900
7700
  if (agent.vault && !vaultNames.has(agent.vault)) {
6901
7701
  diagnostics.error("config.agent.vault.unknown", `agent.${name}: references unknown vault '${agent.vault}'`);
6902
7702
  }
7703
+ for (const file of agent.files ?? []) {
7704
+ if (!fileNames.has(file)) {
7705
+ diagnostics.error("config.agent.file.unknown", `agent.${name}: references unknown file '${file}'`);
7706
+ }
7707
+ }
6903
7708
  for (const memory of agent.memory_stores ?? []) {
6904
7709
  if (!memoryNames.has(memory)) {
6905
7710
  diagnostics.error(
@@ -6931,7 +7736,10 @@ function collectReferenceDiagnostics(config, diagnostics) {
6931
7736
  }
6932
7737
  }
6933
7738
  for (const [name, channel] of Object.entries(config.channels ?? {})) {
6934
- if (!agentNames.has(channel.agent)) {
7739
+ if (channel.mode === "pairing") continue;
7740
+ if (!channel.agent) {
7741
+ diagnostics.error("config.channel.agent.required", `channel.${name}: fixed-mode channels require agent`);
7742
+ } else if (!agentNames.has(channel.agent)) {
6935
7743
  diagnostics.error("config.channel.agent.unknown", `channel.${name}: references unknown agent '${channel.agent}'`);
6936
7744
  }
6937
7745
  const identity = channel.identity ?? config.defaults?.identity;
@@ -7011,29 +7819,31 @@ function collectProviderCapabilities(config, providers, diagnostics) {
7011
7819
  continue;
7012
7820
  }
7013
7821
  if (providerName === "qoder") {
7014
- const agent = config.agents?.[channel.agent];
7015
- if (agent?.provider && agent.provider !== providerName) {
7016
- diagnostics.error(
7017
- "config.channel.agent.provider_mismatch",
7018
- `channel.${name}: agent '${channel.agent}' is pinned to provider '${agent.provider}'.`,
7019
- { type: "channel", name, provider: providerName }
7020
- );
7021
- }
7022
- const identityName = channel.identity ?? config.defaults?.identity;
7023
- const identity = identityName ? config.identities?.[identityName] : void 0;
7024
- if (identity?.provider && identity.provider !== providerName) {
7025
- diagnostics.error(
7026
- "config.channel.identity.provider_mismatch",
7027
- `channel.${name}: identity '${identityName}' is pinned to provider '${identity.provider}'.`,
7028
- { type: "channel", name, provider: providerName }
7029
- );
7030
- }
7031
- if (agent && agent.delivery?.qoder?.type !== "forward") {
7032
- diagnostics.error(
7033
- "qoder.channel.forward_template.required",
7034
- `channel.${name}: Qoder Channels require agent '${channel.agent}' to use delivery.qoder.type: forward.`,
7035
- { type: "channel", name, provider: providerName }
7036
- );
7822
+ if (channel.mode !== "pairing" && channel.agent) {
7823
+ const agent = config.agents?.[channel.agent];
7824
+ if (agent?.provider && agent.provider !== providerName) {
7825
+ diagnostics.error(
7826
+ "config.channel.agent.provider_mismatch",
7827
+ `channel.${name}: agent '${channel.agent}' is pinned to provider '${agent.provider}'.`,
7828
+ { type: "channel", name, provider: providerName }
7829
+ );
7830
+ }
7831
+ const identityName = channel.identity ?? config.defaults?.identity;
7832
+ const identity = identityName ? config.identities?.[identityName] : void 0;
7833
+ if (identity?.provider && identity.provider !== providerName) {
7834
+ diagnostics.error(
7835
+ "config.channel.identity.provider_mismatch",
7836
+ `channel.${name}: identity '${identityName}' is pinned to provider '${identity.provider}'.`,
7837
+ { type: "channel", name, provider: providerName }
7838
+ );
7839
+ }
7840
+ if (agent && agent.delivery?.qoder?.type !== "forward") {
7841
+ diagnostics.error(
7842
+ "qoder.channel.forward_template.required",
7843
+ `channel.${name}: Qoder Channels require agent '${channel.agent}' to use delivery.qoder.type: forward.`,
7844
+ { type: "channel", name, provider: providerName }
7845
+ );
7846
+ }
7037
7847
  }
7038
7848
  const requiredCredentials = {
7039
7849
  dingtalk: ["client_id", "client_secret"],
@@ -7064,6 +7874,46 @@ function collectProviderCapabilities(config, providers, diagnostics) {
7064
7874
  }
7065
7875
  }
7066
7876
  }
7877
+ if (providerName === "qoder") {
7878
+ const domains = /* @__PURE__ */ new Map();
7879
+ for (const agent of Object.values(config.agents ?? {})) {
7880
+ if (agent.provider && agent.provider !== providerName) continue;
7881
+ const mode = agent.delivery?.qoder?.type === "forward" ? "forward" : "managed";
7882
+ const refs = [
7883
+ ...agent.environment && !config.environments?.[agent.environment]?.environment_id ? [`environment:${agent.environment}`] : [],
7884
+ ...(agent.skills ?? []).flatMap(
7885
+ (skill) => typeof skill === "string" ? [`skill:${skill}`] : skill.type === "custom" ? [`skill:${skill.skill_id}`] : []
7886
+ ),
7887
+ ...agent.vault ? [`vault:${agent.vault}`] : [],
7888
+ ...(agent.memory_stores ?? []).map((store) => `memory_store:${store}`),
7889
+ ...(agent.files ?? []).map((file) => `file:${file}`)
7890
+ ];
7891
+ for (const ref of refs) {
7892
+ const modes = domains.get(ref) ?? /* @__PURE__ */ new Set();
7893
+ modes.add(mode);
7894
+ domains.set(ref, modes);
7895
+ }
7896
+ }
7897
+ for (const [ref, modes] of domains) {
7898
+ if (modes.size < 2) continue;
7899
+ const [type, name] = ref.split(":");
7900
+ diagnostics.error(
7901
+ `qoder.${type}.delivery_domain.conflict`,
7902
+ `${type}.${name}: referenced by both Managed and Forward agents; declare separate resources because Qoder uses different API domains.`,
7903
+ { type, name, provider: providerName }
7904
+ );
7905
+ }
7906
+ }
7907
+ for (const [name, agent] of Object.entries(config.agents ?? {})) {
7908
+ if (agent.provider && agent.provider !== providerName) continue;
7909
+ if (agent.files?.length && (providerName !== "qoder" || agent.delivery?.qoder?.type !== "forward")) {
7910
+ diagnostics.error(
7911
+ "config.agent.files.unsupported",
7912
+ `agent.${name}: files are supported only by Qoder Forward Templates.`,
7913
+ { type: resolveAgentMaterialization(providerName, agent).resourceType, name, provider: providerName }
7914
+ );
7915
+ }
7916
+ }
7067
7917
  for (const [name, agent] of Object.entries(config.agents ?? {})) {
7068
7918
  if (agent.provider && agent.provider !== providerName) continue;
7069
7919
  const delivery = agent.delivery?.[providerName]?.type ?? "managed";
@@ -7104,6 +7954,44 @@ function collectProviderCapabilities(config, providers, diagnostics) {
7104
7954
  address
7105
7955
  );
7106
7956
  }
7957
+ if (delivery !== "forward" && agent.managed_tool_config) {
7958
+ diagnostics.error(
7959
+ `${providerName}.agent.managed_tool_config.forward_required`,
7960
+ `agent.${name}: managed_tool_config applies to Forward Templates; set delivery.${providerName}.type: forward or remove it.`,
7961
+ address
7962
+ );
7963
+ }
7964
+ if (agent.default_memory_store) {
7965
+ if (providerName !== "qoder" || delivery !== "forward") {
7966
+ diagnostics.error(
7967
+ `${providerName}.agent.default_memory_store.forward_required`,
7968
+ `agent.${name}: default_memory_store is supported only by Qoder Forward delivery.`,
7969
+ address
7970
+ );
7971
+ } else if (!config.defaults?.identity) {
7972
+ diagnostics.error(
7973
+ "qoder.template.default_memory_store.identity.required",
7974
+ `agent.${name}: default_memory_store requires defaults.identity to select the owning Forward Identity.`,
7975
+ { type: "template", name, provider: providerName }
7976
+ );
7977
+ } else {
7978
+ const identity = config.identities?.[config.defaults.identity];
7979
+ if (identity?.provider && identity.provider !== providerName) {
7980
+ diagnostics.error(
7981
+ "qoder.template.default_memory_store.identity.provider_mismatch",
7982
+ `agent.${name}: defaults.identity '${config.defaults.identity}' is pinned to provider '${identity.provider}'.`,
7983
+ { type: "template", name, provider: providerName }
7984
+ );
7985
+ }
7986
+ if (agent.default_memory_store.delete_on_destroy && identity?.identity_id) {
7987
+ diagnostics.error(
7988
+ "qoder.template.default_memory_store.delete.external_identity",
7989
+ `agent.${name}: delete_on_destroy requires an OpenCMA-managed Identity because an external Identity keeps the default Memory Store mounted.`,
7990
+ { type: "template", name, provider: providerName }
7991
+ );
7992
+ }
7993
+ }
7994
+ }
7107
7995
  if (delivery === "forward" && !isSupported(caps, "template")) {
7108
7996
  diagnostics.error(
7109
7997
  `${providerName}.agent.delivery.forward.unsupported`,
@@ -7119,10 +8007,10 @@ function collectProviderCapabilities(config, providers, diagnostics) {
7119
8007
  { type: "template", name, provider: providerName }
7120
8008
  );
7121
8009
  }
7122
- if (agent.memory_stores?.length) {
8010
+ if (agent.memory_stores?.length && !config.defaults?.identity) {
7123
8011
  diagnostics.error(
7124
- "qoder.template.memory_store.unsupported",
7125
- `agent.${name}: memory_stores are not yet supported by Qoder Forward Template delivery.`,
8012
+ "qoder.template.memory_store.identity.required",
8013
+ `agent.${name}: Forward memory_stores require defaults.identity for the Identity/Template mount.`,
7126
8014
  { type: "template", name, provider: providerName }
7127
8015
  );
7128
8016
  }
@@ -7237,6 +8125,13 @@ function collectProviderCapabilities(config, providers, diagnostics) {
7237
8125
  { type: "agent", name, provider: providerName }
7238
8126
  );
7239
8127
  }
8128
+ if (agent.managed_tool_config && (!agent.provider || agent.provider === providerName)) {
8129
+ diagnostics.error(
8130
+ `${providerName}.agent.managed_tool_config.unsupported`,
8131
+ `agent.${name}: managed_tool_config is supported only by Qoder; remove it or pin this agent to qoder.`,
8132
+ { type: "agent", name, provider: providerName }
8133
+ );
8134
+ }
7240
8135
  if (agent.tunnel && (!agent.provider || agent.provider === providerName)) {
7241
8136
  diagnostics.error(
7242
8137
  `${providerName}.agent.tunnel.unsupported`,
@@ -7307,251 +8202,52 @@ function collectProviderCapabilities(config, providers, diagnostics) {
7307
8202
  `${providerName}.deployment.schedule_unsupported`,
7308
8203
  "Schedules are not enforced server-side on this provider; trigger runs via external cron/CI.",
7309
8204
  addr
7310
- );
7311
- }
7312
- if (dep.initial_events?.some((e) => e.type === "user.define_outcome")) {
7313
- diagnostics.warning(
7314
- `${providerName}.deployment.define_outcome_unsupported`,
7315
- "Outcome rubrics (user.define_outcome) are not enforced server-side on this provider; the run executes without rubric grading.",
7316
- addr
7317
- );
7318
- }
7319
- if (dep.resources?.some((r) => r.type === "github_repository")) {
7320
- diagnostics.warning(
7321
- `${providerName}.deployment.github_repository_unsupported`,
7322
- "github_repository resources are not provisioned on this provider; clone the repository inside the session instead.",
7323
- addr
7324
- );
7325
- }
7326
- if (dep.resources?.some((r) => r.type === "memory_store" && (r.access === "read_only" || r.instructions))) {
7327
- diagnostics.warning(
7328
- `${providerName}.deployment.memory_store_options_unsupported`,
7329
- "Per-resource memory_store access/instructions are not honored on this provider; the store is attached with default access.",
7330
- addr
7331
- );
7332
- }
7333
- }
7334
- }
7335
- }
7336
- }
7337
-
7338
- // src/internal/core/agent-materialization.ts
7339
- function resolveAgentMaterialization(provider, agent) {
7340
- const mode = agent.delivery?.[provider]?.type ?? "managed";
7341
- if (mode === "managed") return { resourceType: "agent", mode };
7342
- return { resourceType: "template", mode };
7343
- }
7344
-
7345
- // src/internal/graph/dependency.ts
7346
- function buildDependencyGraph(config, targetProviders) {
7347
- const nodes = /* @__PURE__ */ new Map();
7348
- const edges = /* @__PURE__ */ new Map();
7349
- function addNode(addr) {
7350
- const key = addressKey(addr);
7351
- nodes.set(key, addr);
7352
- if (!edges.has(key)) edges.set(key, /* @__PURE__ */ new Set());
7353
- }
7354
- function addEdge(from, to) {
7355
- const fromKey = addressKey(from);
7356
- const toKey = addressKey(to);
7357
- edges.get(fromKey)?.add(toKey);
7358
- }
7359
- for (const provider of targetProviders) {
7360
- const def = getProvider(provider);
7361
- const caps = def?.capabilities;
7362
- if (config.environments) {
7363
- for (const name of Object.keys(config.environments)) {
7364
- const decl = config.environments[name];
7365
- if (decl.provider && decl.provider !== provider) continue;
7366
- addNode({ type: "environment", name, provider });
7367
- }
7368
- }
7369
- if (config.memory_stores) {
7370
- for (const name of Object.keys(config.memory_stores)) {
7371
- const decl = config.memory_stores[name];
7372
- if (decl.provider && decl.provider !== provider) continue;
7373
- if (!isSupported(caps, "memory_store")) continue;
7374
- addNode({ type: "memory_store", name, provider });
7375
- }
7376
- }
7377
- if (config.vaults) {
7378
- for (const name of Object.keys(config.vaults)) {
7379
- const decl = config.vaults[name];
7380
- if (decl.provider && decl.provider !== provider) continue;
7381
- addNode({ type: "vault", name, provider });
7382
- }
7383
- }
7384
- if (config.skills) {
7385
- for (const name of Object.keys(config.skills)) {
7386
- const decl = config.skills[name];
7387
- if (decl.provider && decl.provider !== provider) continue;
7388
- addNode({ type: "skill", name, provider });
7389
- }
7390
- }
7391
- if (config.files) {
7392
- for (const name of Object.keys(config.files)) {
7393
- const decl = config.files[name];
7394
- if (decl.provider && decl.provider !== provider) continue;
7395
- addNode({ type: "file", name, provider });
7396
- }
7397
- }
7398
- if (config.identities && isSupported(caps, "identity")) {
7399
- for (const name of Object.keys(config.identities)) {
7400
- const decl = config.identities[name];
7401
- if (decl.provider && decl.provider !== provider) continue;
7402
- addNode({ type: "identity", name, provider });
7403
- }
7404
- }
7405
- if (config.agents) {
7406
- for (const name of Object.keys(config.agents)) {
7407
- const decl = config.agents[name];
7408
- if (decl.provider && decl.provider !== provider) continue;
7409
- const materialization = resolveAgentMaterialization(provider, decl);
7410
- const agentAddr = { type: materialization.resourceType, name, provider };
7411
- addNode(agentAddr);
7412
- if (decl.environment && config.environments?.[decl.environment]) {
7413
- const envAddr = {
7414
- type: "environment",
7415
- name: decl.environment,
7416
- provider
7417
- };
7418
- if (nodes.has(addressKey(envAddr))) {
7419
- addEdge(agentAddr, envAddr);
7420
- }
7421
- }
7422
- if (decl.skills) {
7423
- for (const skillRef of decl.skills) {
7424
- if (typeof skillRef !== "string") continue;
7425
- const skillName = skillRef;
7426
- const skillAddr = { type: "skill", name: skillName, provider };
7427
- if (nodes.has(addressKey(skillAddr))) {
7428
- addEdge(agentAddr, skillAddr);
7429
- }
7430
- }
7431
- }
7432
- if (decl.vault) {
7433
- const vaultAddr = { type: "vault", name: decl.vault, provider };
7434
- if (nodes.has(addressKey(vaultAddr))) {
7435
- addEdge(agentAddr, vaultAddr);
7436
- }
7437
- }
7438
- if (decl.memory_stores) {
7439
- for (const msName of decl.memory_stores) {
7440
- const msAddr = {
7441
- type: "memory_store",
7442
- name: msName,
7443
- provider
7444
- };
7445
- if (nodes.has(addressKey(msAddr))) {
7446
- addEdge(agentAddr, msAddr);
7447
- }
7448
- }
7449
- }
7450
- if (decl.multiagent && isSupported(caps, "multiagent")) {
7451
- for (const subName of decl.multiagent.agents) {
7452
- const subDecl = config.agents[subName];
7453
- const subType = subDecl ? resolveAgentMaterialization(provider, subDecl).resourceType : "agent";
7454
- const subAddr = { type: subType, name: subName, provider };
7455
- addEdge(agentAddr, subAddr);
7456
- }
7457
- }
7458
- }
7459
- }
7460
- if (config.deployments) {
7461
- for (const name of Object.keys(config.deployments)) {
7462
- const decl = config.deployments[name];
7463
- if (decl.provider && decl.provider !== provider) continue;
7464
- const depAddr = { type: "deployment", name, provider };
7465
- addNode(depAddr);
7466
- const agentDecl = config.agents?.[decl.agent];
7467
- const agentType = agentDecl ? resolveAgentMaterialization(provider, agentDecl).resourceType : "agent";
7468
- const agentAddr = { type: agentType, name: decl.agent, provider };
7469
- if (nodes.has(addressKey(agentAddr))) addEdge(depAddr, agentAddr);
7470
- if (decl.environment) {
7471
- const envAddr = { type: "environment", name: decl.environment, provider };
7472
- if (nodes.has(addressKey(envAddr))) addEdge(depAddr, envAddr);
7473
- }
7474
- if (decl.vaults) {
7475
- for (const vName of decl.vaults) {
7476
- const vAddr = { type: "vault", name: vName, provider };
7477
- if (nodes.has(addressKey(vAddr))) addEdge(depAddr, vAddr);
7478
- }
7479
- }
7480
- if (decl.memory_stores) {
7481
- for (const msName of decl.memory_stores) {
7482
- const msAddr = { type: "memory_store", name: msName, provider };
7483
- if (nodes.has(addressKey(msAddr))) addEdge(depAddr, msAddr);
7484
- }
8205
+ );
7485
8206
  }
7486
- if (decl.resources) {
7487
- for (const r of decl.resources) {
7488
- if (r.type === "memory_store") {
7489
- const msAddr = { type: "memory_store", name: r.memory_store, provider };
7490
- if (nodes.has(addressKey(msAddr))) addEdge(depAddr, msAddr);
7491
- }
7492
- }
8207
+ if (dep.initial_events?.some((e) => e.type === "user.define_outcome")) {
8208
+ diagnostics.warning(
8209
+ `${providerName}.deployment.define_outcome_unsupported`,
8210
+ "Outcome rubrics (user.define_outcome) are not enforced server-side on this provider; the run executes without rubric grading.",
8211
+ addr
8212
+ );
7493
8213
  }
7494
- }
7495
- }
7496
- if (config.channels && isSupported(caps, "channel")) {
7497
- for (const name of Object.keys(config.channels)) {
7498
- const decl = config.channels[name];
7499
- if (decl.provider && decl.provider !== provider) continue;
7500
- const channelAddr = { type: "channel", name, provider };
7501
- addNode(channelAddr);
7502
- const agentDecl = config.agents?.[decl.agent];
7503
- const agentType = agentDecl ? resolveAgentMaterialization(provider, agentDecl).resourceType : "agent";
7504
- const agentAddr = { type: agentType, name: decl.agent, provider };
7505
- if (nodes.has(addressKey(agentAddr))) addEdge(channelAddr, agentAddr);
7506
- const identityName = decl.identity ?? config.defaults?.identity;
7507
- if (identityName) {
7508
- const identityAddr = { type: "identity", name: identityName, provider };
7509
- if (nodes.has(addressKey(identityAddr))) addEdge(channelAddr, identityAddr);
8214
+ if (dep.resources?.some((r) => r.type === "github_repository")) {
8215
+ diagnostics.warning(
8216
+ `${providerName}.deployment.github_repository_unsupported`,
8217
+ "github_repository resources are not provisioned on this provider; clone the repository inside the session instead.",
8218
+ addr
8219
+ );
8220
+ }
8221
+ if (dep.resources?.some((r) => r.type === "memory_store" && (r.access === "read_only" || r.instructions))) {
8222
+ diagnostics.warning(
8223
+ `${providerName}.deployment.memory_store_options_unsupported`,
8224
+ "Per-resource memory_store access/instructions are not honored on this provider; the store is attached with default access.",
8225
+ addr
8226
+ );
7510
8227
  }
7511
8228
  }
7512
8229
  }
7513
8230
  }
7514
- return { nodes, edges };
7515
- }
7516
- function topologicalSort(graph) {
7517
- const visited = /* @__PURE__ */ new Set();
7518
- const sorted = [];
7519
- const visiting = /* @__PURE__ */ new Set();
7520
- function visit(key) {
7521
- if (visited.has(key)) return;
7522
- if (visiting.has(key)) {
7523
- throw new UserError(`Circular dependency detected involving: ${key}`);
7524
- }
7525
- visiting.add(key);
7526
- const deps = graph.edges.get(key) ?? /* @__PURE__ */ new Set();
7527
- for (const dep of deps) {
7528
- visit(dep);
7529
- }
7530
- visiting.delete(key);
7531
- visited.add(key);
7532
- sorted.push(graph.nodes.get(key));
7533
- }
7534
- for (const key of graph.nodes.keys()) {
7535
- visit(key);
7536
- }
7537
- return sorted;
7538
8231
  }
7539
8232
 
7540
8233
  // src/internal/planner/planner.ts
7541
8234
  async function buildPlan(config, state, options = {}) {
8235
+ const scopedConfig = options.resourceAddresses ? selectProjectConfig(config, options.resourceAddresses) : config;
8236
+ const resourceKeys = options.resourceAddresses ? new Set(options.resourceAddresses.map(addressKey)) : void 0;
8237
+ const scopedState = resourceKeys ? { ...state, resources: state.resources.filter((resource) => resourceKeys.has(addressKey(resource.address))) } : state;
7542
8238
  const diagnostics = new DiagnosticCollector();
7543
8239
  const actions = [];
7544
- const targetProviders = options.providers ?? resolveTargetProviders(config);
7545
- collectReferenceDiagnostics(config, diagnostics);
7546
- collectProviderCapabilities(config, targetProviders, diagnostics);
7547
- const graph = buildDependencyGraph(config, targetProviders);
8240
+ const targetProviders = options.providers ?? resolveTargetProviders(scopedConfig);
8241
+ collectReferenceDiagnostics(scopedConfig, diagnostics);
8242
+ collectProviderCapabilities(scopedConfig, targetProviders, diagnostics);
8243
+ const graph = buildDependencyGraph(scopedConfig, targetProviders);
7548
8244
  const sorted = topologicalSort(graph);
7549
8245
  const stateIndex = /* @__PURE__ */ new Map();
7550
- for (const res of state.resources) {
8246
+ for (const res of scopedState.resources) {
7551
8247
  stateIndex.set(addressKey(res.address), res);
7552
8248
  }
7553
8249
  const remoteIdLookup = /* @__PURE__ */ new Map();
7554
- for (const res of state.resources) {
8250
+ for (const res of scopedState.resources) {
7555
8251
  remoteIdLookup.set(addressKey(res.address), res);
7556
8252
  }
7557
8253
  const hashStateLookup = { getResource: (addr) => remoteIdLookup.get(addressKey(addr)) };
@@ -7695,9 +8391,53 @@ async function buildPlan(config, state, options = {}) {
7695
8391
  dependencies: replacement ? [replacement] : []
7696
8392
  });
7697
8393
  }
7698
- coalesceChannelRenames(actions, config, state);
8394
+ coalesceChannelRenames(actions, scopedConfig, scopedState);
7699
8395
  return { actions, diagnostics: diagnostics.getAll() };
7700
8396
  }
8397
+ function selectProjectConfig(config, addresses) {
8398
+ const providers = new Set(addresses.map((address) => address.provider));
8399
+ const namesByType = /* @__PURE__ */ new Map();
8400
+ for (const address of addresses) {
8401
+ const names = namesByType.get(address.type) ?? /* @__PURE__ */ new Set();
8402
+ names.add(address.name);
8403
+ namesByType.set(address.type, names);
8404
+ }
8405
+ const pick = (record, names) => {
8406
+ if (!record || !names?.size) return void 0;
8407
+ const selected = Object.fromEntries(Object.entries(record).filter(([name]) => names.has(name)));
8408
+ return Object.keys(selected).length > 0 ? selected : void 0;
8409
+ };
8410
+ const agentNames = /* @__PURE__ */ new Set([...namesByType.get("agent") ?? [], ...namesByType.get("template") ?? []]);
8411
+ const selectedAgents = pick(config.agents, agentNames);
8412
+ const tunnelNames = /* @__PURE__ */ new Set();
8413
+ for (const agent of Object.values(selectedAgents ?? {})) {
8414
+ if (agent.tunnel) tunnelNames.add(agent.tunnel);
8415
+ }
8416
+ for (const deployment of Object.values(pick(config.deployments, namesByType.get("deployment")) ?? {})) {
8417
+ if (deployment.tunnel) tunnelNames.add(deployment.tunnel);
8418
+ }
8419
+ const identityNames = namesByType.get("identity");
8420
+ const selectedProviders = Object.fromEntries(
8421
+ Object.entries(config.providers).filter(([providerName]) => providers.has(providerName))
8422
+ );
8423
+ const defaultProvider = providers.size === 1 ? [...providers][0] : config.defaults?.provider;
8424
+ const defaultIdentity = config.defaults?.identity && identityNames?.has(config.defaults.identity) ? config.defaults.identity : void 0;
8425
+ return {
8426
+ ...config,
8427
+ providers: selectedProviders,
8428
+ defaults: defaultProvider || defaultIdentity ? { provider: defaultProvider, identity: defaultIdentity } : void 0,
8429
+ environments: pick(config.environments, namesByType.get("environment")),
8430
+ tunnels: pick(config.tunnels, tunnelNames),
8431
+ vaults: pick(config.vaults, namesByType.get("vault")),
8432
+ memory_stores: pick(config.memory_stores, namesByType.get("memory_store")),
8433
+ skills: pick(config.skills, namesByType.get("skill")),
8434
+ files: pick(config.files, namesByType.get("file")),
8435
+ identities: pick(config.identities, identityNames),
8436
+ agents: selectedAgents,
8437
+ channels: pick(config.channels, namesByType.get("channel")),
8438
+ deployments: pick(config.deployments, namesByType.get("deployment"))
8439
+ };
8440
+ }
7701
8441
  function coalesceChannelRenames(actions, config, state) {
7702
8442
  const creates = actions.filter((action) => action.action === "create" && action.address.type === "channel");
7703
8443
  const deletes = actions.filter((action) => action.action === "delete" && action.address.type === "channel");
@@ -7777,6 +8517,9 @@ async function refreshState(state, providers, options = {}) {
7777
8517
  const errors = [];
7778
8518
  let dirty = false;
7779
8519
  for (const res of resources) {
8520
+ if (options.resourceKeys && !options.resourceKeys.has(addressKey(res.address))) {
8521
+ continue;
8522
+ }
7780
8523
  if (options.targetProviders && !options.targetProviders.includes(res.address.provider)) {
7781
8524
  continue;
7782
8525
  }
@@ -7839,7 +8582,7 @@ async function refreshState(state, providers, options = {}) {
7839
8582
  dirty = true;
7840
8583
  continue;
7841
8584
  }
7842
- const remote = await provider.findResource(res.address.type, res.address.name, res.remote_id);
8585
+ const remote = await provider.findResource(res.address.type, res.address.name, res.remote_id, res.api_mode);
7843
8586
  if (!remote) {
7844
8587
  if (!options.quiet) {
7845
8588
  emitRuntimeFeedback(options.onFeedback, {
@@ -7890,12 +8633,19 @@ async function refreshState(state, providers, options = {}) {
7890
8633
  }
7891
8634
 
7892
8635
  // src/internal/core/resource-runtime.ts
8636
+ async function planProjectWithStateBackend(input, options = {}) {
8637
+ return readProjectRuntime(input, (ctx) => planProjectContext(ctx, options));
8638
+ }
7893
8639
  async function syncProjectResourcesWithStateBackend(input, options = {}) {
7894
8640
  return writeProjectRuntime(input, async (ctx) => {
7895
8641
  const planned = await planProjectContext(ctx, options);
7896
8642
  if (options.refreshOnly) {
7897
8643
  return { planned };
7898
8644
  }
8645
+ if (options.mode === "create-only") {
8646
+ const errorDiagnostic = planned.plan.diagnostics.find((diagnostic) => diagnostic.severity === "error");
8647
+ if (errorDiagnostic) throw new UserError(errorDiagnostic.message);
8648
+ }
7899
8649
  return {
7900
8650
  planned,
7901
8651
  execution: await executePlannedProject(planned, {
@@ -7963,25 +8713,98 @@ async function importResource(ctx, address, remoteId, options = {}) {
7963
8713
  return resource;
7964
8714
  }
7965
8715
  async function planProjectContext(ctx, options = {}) {
7966
- const targetProviders = resolveTargetProviders2(options.provider);
8716
+ if (options.mode === "create-only" && !options.scope) {
8717
+ throw new UserError("Resource create-only mode requires an explicit resource scope.");
8718
+ }
8719
+ let targetProviders = resolveTargetProviders2(options.provider);
8720
+ if (!targetProviders && options.scope) {
8721
+ targetProviders = [...new Set(options.scope.roots.map((root) => root.provider))];
8722
+ }
8723
+ const selectedAddresses = options.scope ? resolvePlanScope(ctx, targetProviders ?? [], options.scope) : void 0;
8724
+ const resourceKeys = selectedAddresses ? new Set(selectedAddresses.map(addressKey)) : void 0;
7967
8725
  const refreshResult = options.refresh !== false && ctx.state.listResources().length > 0 ? await refreshState(ctx.state, ctx.providers, {
7968
8726
  targetProviders,
8727
+ resourceKeys,
7969
8728
  config: ctx.config,
7970
8729
  quiet: options.quiet ?? true,
7971
8730
  onFeedback: options.onFeedback
7972
8731
  }) : void 0;
7973
- const plan = await buildPlan(ctx.config, ctx.state.getStateFile(), {
8732
+ let plan = await buildPlan(ctx.config, ctx.state.getStateFile(), {
7974
8733
  providers: targetProviders,
7975
- configPath: ctx.configPath
8734
+ configPath: ctx.configPath,
8735
+ resourceAddresses: selectedAddresses
7976
8736
  });
8737
+ if (options.mode === "create-only" && options.scope) {
8738
+ plan = enforceCreateOnlyPlan(plan, options.scope, toResourceRefreshResult(refreshResult));
8739
+ }
7977
8740
  return {
7978
8741
  executionContext: ctx,
7979
8742
  plan,
7980
8743
  refreshResult: toResourceRefreshResult(refreshResult),
7981
8744
  targetProviders,
7982
- destructiveActions: selectDestructive(plan.actions)
8745
+ destructiveActions: selectDestructive(plan.actions),
8746
+ selectedAddresses,
8747
+ mode: options.mode
8748
+ };
8749
+ }
8750
+ function enforceCreateOnlyPlan(plan, scope, refreshResult) {
8751
+ const reasons = [];
8752
+ const rootKeys = new Set(scope.roots.map(addressKey));
8753
+ const refreshError = refreshResult?.errors[0];
8754
+ if (refreshError) {
8755
+ reasons.push(
8756
+ `Cannot verify scoped dependencies because refresh failed for ${addressKey(refreshError.resource.address)}: ${refreshError.error}`
8757
+ );
8758
+ }
8759
+ for (const root of scope.roots) {
8760
+ const rootKey = addressKey(root);
8761
+ const rootAction = plan.actions.find((action) => addressKey(action.address) === rootKey);
8762
+ if (!rootAction) {
8763
+ reasons.push(`Scoped plan did not contain target resource ${rootKey}.`);
8764
+ } else if (rootAction.action !== "create") {
8765
+ reasons.push(`Target resource ${rootKey} must be new, but the scoped plan requires '${rootAction.action}'.`);
8766
+ }
8767
+ }
8768
+ const dependencyChanges = plan.actions.filter(
8769
+ (action) => !rootKeys.has(addressKey(action.address)) && action.action !== "no-op"
8770
+ );
8771
+ if (dependencyChanges.length > 0) {
8772
+ const labels = dependencyChanges.map((action) => `${addressKey(action.address)} (${action.action})`).join(", ");
8773
+ reasons.push(`Create-only requires every scoped dependency to be up-to-date. Reconcile first: ${labels}.`);
8774
+ }
8775
+ if (reasons.length === 0) return plan;
8776
+ return {
8777
+ ...plan,
8778
+ diagnostics: [
8779
+ ...plan.diagnostics,
8780
+ {
8781
+ severity: "error",
8782
+ code: "resource.create_only.blocked",
8783
+ message: reasons.join(" "),
8784
+ resource: scope.roots[0]
8785
+ }
8786
+ ]
7983
8787
  };
7984
8788
  }
8789
+ function resolvePlanScope(ctx, targetProviders, scope) {
8790
+ if (scope.roots.length === 0) {
8791
+ throw new UserError("Resource plan scope requires at least one root address.");
8792
+ }
8793
+ for (const root of scope.roots) {
8794
+ if (!targetProviders.includes(root.provider)) {
8795
+ throw new UserError(
8796
+ `Scoped resource ${addressKey(root)} is outside the selected provider set: ${targetProviders.join(", ")}.`
8797
+ );
8798
+ }
8799
+ }
8800
+ const graph = buildDependencyGraph(ctx.config, targetProviders);
8801
+ for (const root of scope.roots) {
8802
+ if (!graph.nodes.has(addressKey(root))) {
8803
+ throw new UserError(`Scoped resource ${addressKey(root)} is not declared in the project config.`);
8804
+ }
8805
+ }
8806
+ return scope.includeDependencies === false ? [...scope.roots] : collectDependencyClosure(graph, scope.roots);
8807
+ }
7985
8808
  async function executePlannedProject(planned, options = {}) {
7986
8809
  const decision = await decideDestructive(planned.destructiveActions, {
7987
8810
  policy: options.policy,
@@ -8025,13 +8848,6 @@ async function decideDestructive(destructiveActions, options = {}) {
8025
8848
  return "blocked";
8026
8849
  }
8027
8850
  }
8028
- function replaceResourcePlan(planned, plan) {
8029
- return {
8030
- ...planned,
8031
- plan,
8032
- destructiveActions: selectDestructive(plan.actions)
8033
- };
8034
- }
8035
8851
  function toResourceRefreshResult(result) {
8036
8852
  if (!result) return void 0;
8037
8853
  return {
@@ -8380,6 +9196,354 @@ function buildDeploymentContext(ctx, name, provider) {
8380
9196
  };
8381
9197
  }
8382
9198
 
9199
+ // src/internal/core/managed-api-runtime.ts
9200
+ function resolveAdapter(ctx, provider) {
9201
+ if (provider) return getRuntimeProvider(ctx, provider);
9202
+ const configured = Array.from(ctx.providers.keys());
9203
+ if (configured.length === 1) return getRuntimeProvider(ctx, configured[0]);
9204
+ throw new UserError("Multiple providers configured. Use --provider to specify one.");
9205
+ }
9206
+ function requiredMethod(value, provider, operation) {
9207
+ if (value) return value;
9208
+ throw new UserError(`Provider '${provider}' does not support ${operation}.`);
9209
+ }
9210
+ async function listRemoteAgents(ctx, options = {}) {
9211
+ const adapter2 = resolveAdapter(ctx, options.provider);
9212
+ const method2 = requiredMethod(adapter2.listAgentResources, adapter2.name, "agent listing");
9213
+ return method2.call(adapter2, options);
9214
+ }
9215
+ async function getRemoteAgent(ctx, id, options = {}) {
9216
+ const adapter2 = resolveAdapter(ctx, options.provider);
9217
+ const method2 = requiredMethod(adapter2.getRemoteAgent, adapter2.name, "agent lookup");
9218
+ return method2.call(adapter2, id, options.version);
9219
+ }
9220
+ async function listRemoteAgentVersions(ctx, id, options = {}) {
9221
+ const adapter2 = resolveAdapter(ctx, options.provider);
9222
+ const method2 = requiredMethod(adapter2.listAgentVersions, adapter2.name, "agent version listing");
9223
+ return method2.call(adapter2, id, options);
9224
+ }
9225
+ async function listRemoteEnvironments(ctx, options = {}) {
9226
+ const adapter2 = resolveAdapter(ctx, options.provider);
9227
+ const method2 = requiredMethod(adapter2.listEnvironmentResources, adapter2.name, "environment listing");
9228
+ return method2.call(adapter2, options);
9229
+ }
9230
+ async function getRemoteEnvironment(ctx, id, options = {}) {
9231
+ const adapter2 = resolveAdapter(ctx, options.provider);
9232
+ const method2 = requiredMethod(adapter2.getRemoteEnvironment, adapter2.name, "environment lookup");
9233
+ return method2.call(adapter2, id);
9234
+ }
9235
+ async function listRemoteVaults(ctx, options = {}) {
9236
+ const adapter2 = resolveAdapter(ctx, options.provider);
9237
+ const method2 = requiredMethod(adapter2.listVaultResources, adapter2.name, "vault listing");
9238
+ return method2.call(adapter2, options);
9239
+ }
9240
+ async function getRemoteVault(ctx, id, options = {}) {
9241
+ const adapter2 = resolveAdapter(ctx, options.provider);
9242
+ const method2 = requiredMethod(adapter2.getRemoteVault, adapter2.name, "vault lookup");
9243
+ return method2.call(adapter2, id);
9244
+ }
9245
+ async function listRemoteSkills(ctx, options = {}) {
9246
+ const adapter2 = resolveAdapter(ctx, options.provider);
9247
+ const method2 = requiredMethod(adapter2.listSkillResources, adapter2.name, "skill listing");
9248
+ return method2.call(adapter2, options);
9249
+ }
9250
+ async function getRemoteSkill(ctx, id, options = {}) {
9251
+ const adapter2 = resolveAdapter(ctx, options.provider);
9252
+ const method2 = requiredMethod(adapter2.getSkillInfo, adapter2.name, "skill lookup");
9253
+ return method2.call(adapter2, id);
9254
+ }
9255
+ async function listRemoteSkillVersions(ctx, id, options = {}) {
9256
+ const adapter2 = resolveAdapter(ctx, options.provider);
9257
+ const method2 = requiredMethod(adapter2.listSkillVersions, adapter2.name, "skill version listing");
9258
+ return method2.call(adapter2, id, options);
9259
+ }
9260
+ async function getRemoteSkillVersion(ctx, id, version, options = {}) {
9261
+ const adapter2 = resolveAdapter(ctx, options.provider);
9262
+ const method2 = requiredMethod(adapter2.getSkillVersion, adapter2.name, "skill version lookup");
9263
+ return method2.call(adapter2, id, version);
9264
+ }
9265
+ async function getRemoteSkillDownloadInfo(ctx, id, version, options = {}) {
9266
+ const adapter2 = resolveAdapter(ctx, options.provider);
9267
+ const method2 = requiredMethod(adapter2.getSkillDownloadInfo, adapter2.name, "skill version download");
9268
+ return method2.call(adapter2, id, version);
9269
+ }
9270
+ async function downloadRemoteSkill(ctx, id, version, options = {}) {
9271
+ const info = await getRemoteSkillDownloadInfo(ctx, id, version, options);
9272
+ const response = await resolveFetch()(info.file_url, { method: "GET" });
9273
+ if (!response.ok) {
9274
+ throw new ApiError(response.status, await response.text(), "Skill download failed");
9275
+ }
9276
+ return new Uint8Array(await response.arrayBuffer());
9277
+ }
9278
+ async function listRemoteFiles(ctx, options = {}) {
9279
+ const adapter2 = resolveAdapter(ctx, options.provider);
9280
+ const method2 = requiredMethod(adapter2.listFileResources, adapter2.name, "file listing");
9281
+ return method2.call(adapter2, options);
9282
+ }
9283
+ async function downloadRemoteFile(ctx, id, options = {}) {
9284
+ const adapter2 = resolveAdapter(ctx, options.provider);
9285
+ const method2 = requiredMethod(adapter2.downloadFileContent, adapter2.name, "file content download");
9286
+ return method2.call(adapter2, id);
9287
+ }
9288
+ async function updateRemoteSession(ctx, id, input, options = {}) {
9289
+ const adapter2 = resolveAdapter(ctx, options.provider);
9290
+ const method2 = requiredMethod(adapter2.updateSession, adapter2.name, "session update");
9291
+ return method2.call(adapter2, id, input);
9292
+ }
9293
+ async function archiveRemoteSession(ctx, id, options = {}) {
9294
+ const adapter2 = resolveAdapter(ctx, options.provider);
9295
+ const method2 = requiredMethod(adapter2.archiveSession, adapter2.name, "session archive");
9296
+ return method2.call(adapter2, id);
9297
+ }
9298
+ async function sendRemoteSessionEvents(ctx, id, events, options = {}) {
9299
+ const adapter2 = resolveAdapter(ctx, options.provider);
9300
+ const method2 = requiredMethod(adapter2.sendSessionEvents, adapter2.name, "generic session event sending");
9301
+ return method2.call(adapter2, id, events);
9302
+ }
9303
+ async function listRemoteDeployments(ctx, options = {}) {
9304
+ const adapter2 = resolveAdapter(ctx, options.provider);
9305
+ const method2 = requiredMethod(adapter2.listDeployments, adapter2.name, "deployment listing");
9306
+ return method2.call(adapter2, options);
9307
+ }
9308
+ async function getRemoteDeployment(ctx, id, options = {}) {
9309
+ const adapter2 = resolveAdapter(ctx, options.provider);
9310
+ const method2 = requiredMethod(adapter2.getDeploymentById, adapter2.name, "deployment lookup");
9311
+ return method2.call(adapter2, id);
9312
+ }
9313
+ async function runRemoteDeployment(ctx, id, options = {}) {
9314
+ const adapter2 = resolveAdapter(ctx, options.provider);
9315
+ const method2 = requiredMethod(adapter2.runDeploymentById, adapter2.name, "deployment run");
9316
+ return method2.call(adapter2, id);
9317
+ }
9318
+ async function setRemoteDeploymentPaused(ctx, id, paused, options = {}) {
9319
+ const adapter2 = resolveAdapter(ctx, options.provider);
9320
+ const method2 = paused ? adapter2.pauseDeploymentById : adapter2.unpauseDeploymentById;
9321
+ return requiredMethod(method2, adapter2.name, `${paused ? "pausing" : "unpausing"} deployments`).call(adapter2, id);
9322
+ }
9323
+ async function listRemoteDeploymentRuns(ctx, deploymentId, options = {}) {
9324
+ const adapter2 = resolveAdapter(ctx, options.provider);
9325
+ const method2 = requiredMethod(adapter2.listDeploymentRuns, adapter2.name, "deployment run listing");
9326
+ return method2.call(adapter2, deploymentId, options);
9327
+ }
9328
+ async function getRemoteDeploymentRun(ctx, runId, options = {}) {
9329
+ const adapter2 = resolveAdapter(ctx, options.provider);
9330
+ const method2 = requiredMethod(adapter2.getDeploymentRun, adapter2.name, "deployment run lookup");
9331
+ return method2.call(adapter2, runId);
9332
+ }
9333
+ var API_KEY = { supported: true, auth: "api_key" };
9334
+ var CLIENT_SEARCH = {
9335
+ supported: true,
9336
+ auth: "api_key",
9337
+ reason: "Client-side filtering over the corresponding list API."
9338
+ };
9339
+ var UNSUPPORTED_MODEL = {
9340
+ supported: false,
9341
+ auth: null,
9342
+ reason: "The public Managed Agents API does not expose a model catalog endpoint."
9343
+ };
9344
+ var UNSUPPORTED_THREAD = {
9345
+ supported: false,
9346
+ auth: null,
9347
+ reason: "Managed Agents exposes child-thread ids and lifecycle events through Session Events, but no independent Thread resource API."
9348
+ };
9349
+ var UNSUPPORTED_OAUTH = {
9350
+ supported: false,
9351
+ auth: null,
9352
+ reason: "The public Managed Agents data plane does not expose MCP OAuth login."
9353
+ };
9354
+ var BAILIAN_OPERATIONS = {
9355
+ "agent.create": { ...API_KEY, reason: "YAML declaration plus scoped create-only apply." },
9356
+ "agent.list": API_KEY,
9357
+ "agent.get": API_KEY,
9358
+ "agent.search": CLIENT_SEARCH,
9359
+ "agent.versions": API_KEY,
9360
+ "environment.create": { ...API_KEY, reason: "YAML declaration plus scoped create-only apply." },
9361
+ "environment.list": API_KEY,
9362
+ "environment.get": API_KEY,
9363
+ "environment.search": CLIENT_SEARCH,
9364
+ "skill.create": { ...API_KEY, reason: "YAML declaration plus scoped create-only apply." },
9365
+ "skill.list": API_KEY,
9366
+ "skill.get": API_KEY,
9367
+ "skill.search": CLIENT_SEARCH,
9368
+ "skill.versions": API_KEY,
9369
+ "skill.download": API_KEY,
9370
+ "vault.create": { ...API_KEY, reason: "YAML declaration plus scoped create-only apply." },
9371
+ "vault.credential.create": { ...API_KEY, reason: "YAML declaration plus scoped Vault transaction." },
9372
+ "vault.list": API_KEY,
9373
+ "vault.get": API_KEY,
9374
+ "vault.search": CLIENT_SEARCH,
9375
+ "deployment.create": { ...API_KEY, reason: "YAML declaration plus scoped create-only apply." },
9376
+ "deployment.list": API_KEY,
9377
+ "deployment.get": API_KEY,
9378
+ "deployment.search": { ...API_KEY, reason: "Maps to the server-side keyword parameter." },
9379
+ "deployment.runs.list": API_KEY,
9380
+ "deployment.runs.get": API_KEY,
9381
+ "deployment.run": API_KEY,
9382
+ "deployment.pause": API_KEY,
9383
+ "deployment.unpause": API_KEY,
9384
+ "session.create": API_KEY,
9385
+ "session.list": API_KEY,
9386
+ "session.get": API_KEY,
9387
+ "session.search": CLIENT_SEARCH,
9388
+ "session.update": API_KEY,
9389
+ "session.archive": API_KEY,
9390
+ "session.delete": API_KEY,
9391
+ "session.run": { ...API_KEY, reason: "Client composition of session create and event send/stream." },
9392
+ "session.event.send": API_KEY,
9393
+ "session.event.list": API_KEY,
9394
+ "session.event.stream": API_KEY,
9395
+ "session.debug": { ...API_KEY, reason: "Client-side aggregation of supported read APIs." },
9396
+ "session.export": { ...API_KEY, reason: "Client-side export of supported read APIs." },
9397
+ "file.upload": API_KEY,
9398
+ "file.list": API_KEY,
9399
+ "file.get": API_KEY,
9400
+ "file.search": CLIENT_SEARCH,
9401
+ "file.download": API_KEY,
9402
+ "file.delete": API_KEY,
9403
+ "model.list": UNSUPPORTED_MODEL,
9404
+ "model.search": UNSUPPORTED_MODEL,
9405
+ "session_thread.list": UNSUPPORTED_THREAD,
9406
+ "session_thread.get": UNSUPPORTED_THREAD,
9407
+ "session_thread.archive": UNSUPPORTED_THREAD,
9408
+ "session_thread.events": UNSUPPORTED_THREAD,
9409
+ "mcp.oauth_login": UNSUPPORTED_OAUTH
9410
+ };
9411
+ function getManagedAgentProviderCapabilities(provider) {
9412
+ if (provider === "bailian") {
9413
+ return { provider, operations: { ...BAILIAN_OPERATIONS } };
9414
+ }
9415
+ return {
9416
+ provider,
9417
+ operations: {
9418
+ "managed_agent.api": {
9419
+ supported: false,
9420
+ auth: null,
9421
+ reason: "The operation-level API command surface is currently implemented for Bailian only."
9422
+ }
9423
+ }
9424
+ };
9425
+ }
9426
+
9427
+ // src/internal/core/vault-credential-runtime.ts
9428
+ async function planVaultCredentialCreate(ctx, vaultName, credentialName, options = {}) {
9429
+ const prepared = await prepareVaultCredentialCreate(ctx, vaultName, credentialName, options);
9430
+ return {
9431
+ provider: prepared.provider,
9432
+ vault: vaultName,
9433
+ vaultRemoteId: prepared.vaultState.remote_id,
9434
+ credential: credentialName,
9435
+ remoteChecked: prepared.remoteChecked,
9436
+ reuseRemote: Boolean(prepared.remoteCredential),
9437
+ remoteCredentialId: prepared.remoteCredential?.id
9438
+ };
9439
+ }
9440
+ async function planVaultCredentialCreateWithStateBackend(input, vaultName, credentialName, options = {}) {
9441
+ return readProjectRuntime(input, (ctx) => planVaultCredentialCreate(ctx, vaultName, credentialName, options));
9442
+ }
9443
+ async function createVaultCredential(ctx, vaultName, credentialName, options = {}) {
9444
+ if (options.checkRemote === false) {
9445
+ throw new UserError("Vault Credential create requires the remote duplicate check.");
9446
+ }
9447
+ const prepared = await prepareVaultCredentialCreate(ctx, vaultName, credentialName, options);
9448
+ const remote = prepared.remoteCredential ?? await prepared.adapter.createCredential(prepared.vaultState.remote_id, prepared.credential);
9449
+ if (!remote.id) throw new UserError("Credential create returned no remote id.");
9450
+ const address = { type: "vault", name: vaultName, provider: prepared.provider };
9451
+ const desiredHash = await computeResourceHash(address, ctx.config, ctx.configPath, ctx.state);
9452
+ ctx.state.setResource({
9453
+ ...prepared.vaultState,
9454
+ content_hash: desiredHash,
9455
+ desired_hash: desiredHash,
9456
+ drift_paths: [],
9457
+ drift_status: "unchecked"
9458
+ });
9459
+ await ctx.state.save();
9460
+ return {
9461
+ provider: prepared.provider,
9462
+ vault: vaultName,
9463
+ vaultRemoteId: prepared.vaultState.remote_id,
9464
+ credential: credentialName,
9465
+ remoteChecked: prepared.remoteChecked,
9466
+ credentialId: remote.id,
9467
+ reuseRemote: Boolean(prepared.remoteCredential),
9468
+ remoteCredentialId: prepared.remoteCredential?.id,
9469
+ adopted: Boolean(prepared.remoteCredential)
9470
+ };
9471
+ }
9472
+ async function createVaultCredentialWithStateBackend(input, vaultName, credentialName, options = {}) {
9473
+ return writeProjectRuntime(input, (ctx) => createVaultCredential(ctx, vaultName, credentialName, options));
9474
+ }
9475
+ async function prepareVaultCredentialCreate(ctx, vaultName, credentialName, options) {
9476
+ const vault = ctx.config.vaults?.[vaultName];
9477
+ if (!vault) throw new UserError(`Vault '${vaultName}' is not declared in the project config.`);
9478
+ const provider = resolveVaultProvider(ctx, vault.provider, options.provider);
9479
+ const credential = vault.credentials.at(-1);
9480
+ if (!credential || credential.name !== credentialName) {
9481
+ throw new UserError(`Credential '${credentialName}' must be the final newly appended entry in vault.${vaultName}.`);
9482
+ }
9483
+ if (vault.credentials.slice(0, -1).some((entry) => entry.name === credentialName)) {
9484
+ throw new UserError(`Vault '${vaultName}' already declares a credential named '${credentialName}'.`);
9485
+ }
9486
+ const address = { type: "vault", name: vaultName, provider };
9487
+ const priorConfig = structuredClone(ctx.config);
9488
+ priorConfig.vaults[vaultName] = {
9489
+ ...priorConfig.vaults[vaultName],
9490
+ credentials: priorConfig.vaults[vaultName].credentials.slice(0, -1)
9491
+ };
9492
+ const priorPlan = await planProjectContext(
9493
+ { ...ctx, config: priorConfig },
9494
+ {
9495
+ provider,
9496
+ scope: { roots: [address] },
9497
+ refresh: options.refresh,
9498
+ quiet: options.quiet ?? true
9499
+ }
9500
+ );
9501
+ const refreshError = priorPlan.refreshResult?.errors[0];
9502
+ if (refreshError) {
9503
+ throw new UserError(`Cannot verify vault.${vaultName} because refresh failed: ${refreshError.error}`);
9504
+ }
9505
+ const errorDiagnostic = priorPlan.plan.diagnostics.find((diagnostic) => diagnostic.severity === "error");
9506
+ if (errorDiagnostic) throw new UserError(errorDiagnostic.message);
9507
+ const vaultAction = priorPlan.plan.actions.find(
9508
+ (action) => action.address.type === "vault" && action.address.name === vaultName
9509
+ );
9510
+ if (vaultAction?.action !== "no-op") {
9511
+ throw new UserError(
9512
+ `vault.${vaultName} must be tracked and up-to-date before adding a credential; current action is '${vaultAction?.action ?? "missing"}'.`
9513
+ );
9514
+ }
9515
+ const vaultState = ctx.state.getResource(address);
9516
+ if (!vaultState?.remote_id) throw new UserError(`vault.${vaultName} has no tracked remote id.`);
9517
+ const adapter2 = getRuntimeProvider(ctx, provider);
9518
+ if (!adapter2.createCredential || !adapter2.listCredentials) {
9519
+ throw new UserError(`Provider '${provider}' does not support scoped Vault Credential create.`);
9520
+ }
9521
+ const remoteChecked = options.checkRemote !== false;
9522
+ const sameName = remoteChecked ? (await adapter2.listCredentials(vaultState.remote_id)).filter(
9523
+ (remoteCredential) => remoteCredential.display_name === credentialName
9524
+ ) : [];
9525
+ const exact = sameName.find((remoteCredential) => credentialMatches(remoteCredential, credential));
9526
+ if (sameName.length > 0 && !exact) {
9527
+ throw new UserError(`Vault '${vaultName}' already has a different remote credential named '${credentialName}'.`);
9528
+ }
9529
+ return { provider, credential, vaultState, adapter: adapter2, remoteChecked, remoteCredential: exact };
9530
+ }
9531
+ function resolveVaultProvider(ctx, declaredProvider, requestedProvider) {
9532
+ if (requestedProvider && declaredProvider && requestedProvider !== declaredProvider) {
9533
+ throw new UserError(
9534
+ `Vault provider '${declaredProvider}' does not match requested provider '${requestedProvider}'.`
9535
+ );
9536
+ }
9537
+ const provider = requestedProvider ?? declaredProvider ?? ctx.config.defaults?.provider;
9538
+ if (provider && provider !== "all") return provider;
9539
+ const configured = [...ctx.providers.keys()];
9540
+ if (configured.length === 1) return configured[0];
9541
+ throw new UserError("Cannot infer one provider for Vault Credential create.");
9542
+ }
9543
+ function credentialMatches(remote, desired) {
9544
+ return remote.auth_type === desired.type && remote.secret_name === desired.secret_name && (remote.networking_type ?? "unrestricted") === (desired.networking?.type ?? "unrestricted");
9545
+ }
9546
+
8383
9547
  // src/internal/core/destroy-runtime.ts
8384
9548
  var destroyOrder = {
8385
9549
  deployment: 0,
@@ -8397,12 +9561,64 @@ function planDestroyProjectContext(ctx) {
8397
9561
  const resources = [...ctx.state.listResources()].sort(
8398
9562
  (a, b) => (destroyOrder[a.address.type] ?? 99) - (destroyOrder[b.address.type] ?? 99)
8399
9563
  );
8400
- return { resources, executionContext: ctx };
9564
+ const identityName = ctx.config.defaults?.identity;
9565
+ const defaultMemoryStores = [];
9566
+ for (const [agentName, agent] of Object.entries(ctx.config.agents ?? {})) {
9567
+ if (!agent.default_memory_store || agent.delivery?.qoder?.type !== "forward") continue;
9568
+ if (agent.provider && agent.provider !== "qoder") continue;
9569
+ const identityId = identityName ? ctx.state.getResource({ type: "identity", name: identityName, provider: "qoder" })?.remote_id ?? null : null;
9570
+ const templateId = ctx.state.getResource({ type: "template", name: agentName, provider: "qoder" })?.remote_id ?? null;
9571
+ if (!identityId && !templateId) continue;
9572
+ defaultMemoryStores.push({
9573
+ agentName,
9574
+ provider: "qoder",
9575
+ identityId,
9576
+ templateId,
9577
+ deleteOnDestroy: agent.default_memory_store.delete_on_destroy ?? false
9578
+ });
9579
+ }
9580
+ for (const pending of ctx.state.getStateFile().pending_default_memory_store_cleanups ?? []) {
9581
+ const existing = defaultMemoryStores.find(
9582
+ (item) => item.agentName === pending.agent_name && item.provider === pending.provider
9583
+ );
9584
+ if (existing) {
9585
+ existing.memoryStoreId = pending.remote_id;
9586
+ existing.deleteOnDestroy = true;
9587
+ } else {
9588
+ defaultMemoryStores.push({
9589
+ agentName: pending.agent_name,
9590
+ provider: pending.provider,
9591
+ identityId: pending.identity_id ?? null,
9592
+ templateId: pending.template_id ?? null,
9593
+ deleteOnDestroy: true,
9594
+ memoryStoreId: pending.remote_id
9595
+ });
9596
+ }
9597
+ }
9598
+ return { resources, defaultMemoryStores, executionContext: ctx };
8401
9599
  }
8402
9600
  async function destroyPlannedProjectResources(planned, options = {}) {
8403
9601
  const results = [];
8404
- let stateChanged = false;
9602
+ const capturedDefaults = await captureDefaultMemoryStores(planned);
8405
9603
  const ctx = planned.executionContext;
9604
+ if (capturedDefaults.some((item) => item.error)) {
9605
+ const defaultMemoryStoreResults2 = capturedDefaults.map(preflightFailureResult);
9606
+ for (const resource of planned.resources) {
9607
+ const result = {
9608
+ resource,
9609
+ status: "blocked",
9610
+ reason: "skipped",
9611
+ error: "Destroy aborted because the default Memory Store preflight failed."
9612
+ };
9613
+ results.push(result);
9614
+ options.onResourceResult?.(result);
9615
+ }
9616
+ return { ...planned, results, defaultMemoryStoreResults: defaultMemoryStoreResults2, destroyed: 0, partial: true };
9617
+ }
9618
+ if (await persistCapturedDefaultMemoryStores(ctx, capturedDefaults)) {
9619
+ await ctx.state.save();
9620
+ }
9621
+ let stateChanged = false;
8406
9622
  for (const resource of planned.resources) {
8407
9623
  options.onResourceStart?.(resource);
8408
9624
  const result = await destroyOneResource(ctx, resource, options);
@@ -8413,14 +9629,171 @@ async function destroyPlannedProjectResources(planned, options = {}) {
8413
9629
  if (stateChanged) {
8414
9630
  await ctx.state.save();
8415
9631
  }
9632
+ const defaultMemoryStoreResults = await finalizeDefaultMemoryStores(planned, capturedDefaults, options);
9633
+ if (recordFailedDefaultMemoryStoreCleanups(ctx, defaultMemoryStoreResults)) {
9634
+ await ctx.state.save();
9635
+ }
9636
+ if (clearCompletedDefaultMemoryStoreCleanups(ctx, defaultMemoryStoreResults)) {
9637
+ await ctx.state.save();
9638
+ }
8416
9639
  const destroyed = results.filter((result) => result.status === "success").length;
8417
9640
  return {
8418
9641
  ...planned,
8419
9642
  results,
9643
+ defaultMemoryStoreResults,
8420
9644
  destroyed,
8421
- partial: destroyed !== planned.resources.length
9645
+ partial: destroyed !== planned.resources.length || defaultMemoryStoreResults.some((result) => result.status === "failed")
9646
+ };
9647
+ }
9648
+ async function persistCapturedDefaultMemoryStores(ctx, captured) {
9649
+ const state = ctx.state.getStateFile();
9650
+ if (!state.pending_default_memory_store_cleanups) state.pending_default_memory_store_cleanups = [];
9651
+ const pending = state.pending_default_memory_store_cleanups;
9652
+ let changed = false;
9653
+ for (const item of captured) {
9654
+ if (!item.plan.deleteOnDestroy || !item.memoryStoreId) continue;
9655
+ if (pending.some((entry) => entry.provider === item.plan.provider && entry.remote_id === item.memoryStoreId))
9656
+ continue;
9657
+ pending.push({
9658
+ agent_name: item.plan.agentName,
9659
+ provider: item.plan.provider,
9660
+ remote_id: item.memoryStoreId,
9661
+ ...item.plan.identityId ? { identity_id: item.plan.identityId } : {},
9662
+ ...item.plan.templateId ? { template_id: item.plan.templateId } : {}
9663
+ });
9664
+ changed = true;
9665
+ }
9666
+ return changed;
9667
+ }
9668
+ function clearCompletedDefaultMemoryStoreCleanups(ctx, results) {
9669
+ const state = ctx.state.getStateFile();
9670
+ const completedIds = new Set(
9671
+ results.filter((item) => item.status === "deleted" || item.status === "already_gone").map((item) => item.memoryStoreId).filter((id) => Boolean(id))
9672
+ );
9673
+ if (completedIds.size === 0 || !state.pending_default_memory_store_cleanups?.length) return false;
9674
+ const remaining = state.pending_default_memory_store_cleanups.filter((item) => !completedIds.has(item.remote_id));
9675
+ if (remaining.length === state.pending_default_memory_store_cleanups.length) return false;
9676
+ state.pending_default_memory_store_cleanups = remaining;
9677
+ return true;
9678
+ }
9679
+ function recordFailedDefaultMemoryStoreCleanups(ctx, results) {
9680
+ const pending = ctx.state.getStateFile().pending_default_memory_store_cleanups;
9681
+ if (!pending?.length) return false;
9682
+ let changed = false;
9683
+ for (const result of results) {
9684
+ if (result.status !== "failed" || !result.memoryStoreId) continue;
9685
+ const entry = pending.find((item) => item.remote_id === result.memoryStoreId);
9686
+ if (entry && entry.last_error !== result.error) {
9687
+ entry.last_error = result.error;
9688
+ changed = true;
9689
+ }
9690
+ }
9691
+ return changed;
9692
+ }
9693
+ function preflightFailureResult(item) {
9694
+ if (!item.plan.deleteOnDestroy) return { ...item.plan, status: "retained" };
9695
+ return {
9696
+ ...item.plan,
9697
+ status: "failed",
9698
+ ...item.memoryStoreId ? { memoryStoreId: item.memoryStoreId } : {},
9699
+ error: item.error ?? "Destroy aborted because another default Memory Store preflight failed."
8422
9700
  };
8423
9701
  }
9702
+ async function captureDefaultMemoryStores(planned) {
9703
+ return Promise.all(
9704
+ planned.defaultMemoryStores.map(async (item) => {
9705
+ if (!item.deleteOnDestroy) return { plan: item };
9706
+ if (item.memoryStoreId) return { plan: item, memoryStoreId: item.memoryStoreId };
9707
+ if (!item.identityId || !item.templateId) {
9708
+ return { plan: item, error: "Cannot resolve the Identity and Template before destroy." };
9709
+ }
9710
+ try {
9711
+ const provider = getRuntimeProvider(planned.executionContext, item.provider);
9712
+ if (!provider.findDefaultMemoryStoreId || !provider.deleteDefaultMemoryStore) {
9713
+ return { plan: item, error: `Provider '${item.provider}' cannot delete a default memory store.` };
9714
+ }
9715
+ const memoryStoreId = await provider.findDefaultMemoryStoreId(item.identityId, item.templateId);
9716
+ return { plan: item, ...memoryStoreId ? { memoryStoreId } : {} };
9717
+ } catch (error) {
9718
+ return { plan: item, error: error instanceof Error ? error.message : String(error) };
9719
+ }
9720
+ })
9721
+ );
9722
+ }
9723
+ async function finalizeDefaultMemoryStores(planned, captured, options) {
9724
+ const output = [];
9725
+ for (const item of captured) {
9726
+ if (!item.plan.deleteOnDestroy) {
9727
+ output.push({ ...item.plan, status: "retained" });
9728
+ continue;
9729
+ }
9730
+ if (item.error) {
9731
+ output.push({ ...item.plan, status: "failed", error: item.error });
9732
+ continue;
9733
+ }
9734
+ if (!item.memoryStoreId) {
9735
+ output.push({ ...item.plan, status: "already_gone" });
9736
+ continue;
9737
+ }
9738
+ try {
9739
+ const provider = getRuntimeProvider(planned.executionContext, item.plan.provider);
9740
+ await deleteDefaultMemoryStoreWithArchiveFallback(
9741
+ provider,
9742
+ item.memoryStoreId,
9743
+ options.defaultMemoryStoreRetryDelaysMs ?? [1e3, 2e3, 4e3, 8e3]
9744
+ );
9745
+ output.push({ ...item.plan, status: "deleted", memoryStoreId: item.memoryStoreId });
9746
+ } catch (error) {
9747
+ if (ApiError.isNotFound(error)) {
9748
+ output.push({ ...item.plan, status: "already_gone", memoryStoreId: item.memoryStoreId });
9749
+ } else {
9750
+ output.push({
9751
+ ...item.plan,
9752
+ status: "failed",
9753
+ memoryStoreId: item.memoryStoreId,
9754
+ error: error instanceof Error ? error.message : String(error)
9755
+ });
9756
+ }
9757
+ }
9758
+ }
9759
+ return output;
9760
+ }
9761
+ async function deleteDefaultMemoryStoreWithArchiveFallback(provider, memoryStoreId, retryDelaysMs) {
9762
+ try {
9763
+ await retryDefaultMemoryStoreOperation(() => provider.deleteDefaultMemoryStore(memoryStoreId), retryDelaysMs);
9764
+ } catch (error) {
9765
+ if (isAlreadyArchivedConflict(error) && provider.deleteMemoryStore) {
9766
+ await retryDefaultMemoryStoreOperation(() => provider.deleteMemoryStore(memoryStoreId), retryDelaysMs);
9767
+ return;
9768
+ }
9769
+ if (!isStillMountedConflict(error) || !provider.archiveMemoryStore || !provider.deleteMemoryStore) throw error;
9770
+ await retryDefaultMemoryStoreOperation(() => provider.archiveMemoryStore(memoryStoreId), retryDelaysMs);
9771
+ await retryDefaultMemoryStoreOperation(() => provider.deleteMemoryStore(memoryStoreId), retryDelaysMs);
9772
+ }
9773
+ }
9774
+ async function retryDefaultMemoryStoreOperation(operation, delaysMs) {
9775
+ for (let attempt = 0; ; attempt++) {
9776
+ try {
9777
+ await operation();
9778
+ return;
9779
+ } catch (error) {
9780
+ if (!isRetryableDefaultMemoryStoreError(error) || attempt >= delaysMs.length) throw error;
9781
+ await delay(delaysMs[attempt]);
9782
+ }
9783
+ }
9784
+ }
9785
+ function isRetryableDefaultMemoryStoreError(error) {
9786
+ return error instanceof ApiError && (isStillMountedConflict(error) || isAlreadyArchivedConflict(error) || error.statusCode === 429 || [500, 502, 503].includes(error.statusCode));
9787
+ }
9788
+ function isStillMountedConflict(error) {
9789
+ return error instanceof ApiError && error.statusCode === 409 && error.responseBody.includes("still mounted");
9790
+ }
9791
+ function isAlreadyArchivedConflict(error) {
9792
+ return error instanceof ApiError && error.statusCode === 409 && error.responseBody.toLowerCase().includes("already archived");
9793
+ }
9794
+ function delay(ms) {
9795
+ return new Promise((resolve13) => setTimeout(resolve13, ms));
9796
+ }
8424
9797
  async function destroyOneResource(ctx, resource, options) {
8425
9798
  if (isExternalReference(ctx, resource)) {
8426
9799
  ctx.state.removeResource(resource.address);
@@ -8441,8 +9814,18 @@ async function destroyOneResource(ctx, resource, options) {
8441
9814
  ctx.state.removeResource(resource.address);
8442
9815
  return successResult(resource, "destroyed");
8443
9816
  }
9817
+ const apiMode = resource.api_mode === "auto" ? void 0 : resource.api_mode;
8444
9818
  try {
8445
- await deleteRemoteResource(provider, resource.address.type, resource.remote_id, options.cascade);
9819
+ await deleteRemoteResource(
9820
+ provider,
9821
+ resource.address.type,
9822
+ resource.remote_id,
9823
+ options.cascade,
9824
+ apiMode,
9825
+ ctx.state.listResources().filter(
9826
+ (candidate) => candidate.address.provider === resource.address.provider && candidate.address.type === "memory_store" && candidate.api_mode === "forward" && typeof candidate.remote_id === "string"
9827
+ ).map((candidate) => candidate.remote_id)
9828
+ );
8446
9829
  ctx.state.removeResource(resource.address);
8447
9830
  emitRuntimeFeedback(options.onFeedback, {
8448
9831
  type: "resource_action_success",
@@ -8471,7 +9854,7 @@ async function destroyOneResource(ctx, resource, options) {
8471
9854
  };
8472
9855
  if (await options.onCascadeRequired?.(blocked)) {
8473
9856
  try {
8474
- await provider.deleteEnvironment(resource.remote_id, true);
9857
+ await provider.deleteEnvironment(resource.remote_id, true, apiMode);
8475
9858
  ctx.state.removeResource(resource.address);
8476
9859
  return {
8477
9860
  ...successResult(resource, "destroyed"),
@@ -8507,29 +9890,29 @@ function failureResult(resource, error) {
8507
9890
  error: error instanceof Error ? error.message : String(error)
8508
9891
  };
8509
9892
  }
8510
- async function deleteRemoteResource(provider, type, id, cascade) {
9893
+ async function deleteRemoteResource(provider, type, id, cascade, mode, ownedMemoryStoreIds = []) {
8511
9894
  switch (type) {
8512
9895
  case "agent":
8513
9896
  await provider.deleteAgent(id);
8514
9897
  return;
8515
9898
  case "template":
8516
9899
  if (!provider.archiveTemplate) throw new UserError(`Provider does not support templates`);
8517
- await provider.archiveTemplate(id);
9900
+ await provider.archiveTemplate(id, ownedMemoryStoreIds);
8518
9901
  return;
8519
9902
  case "skill":
8520
- await provider.deleteSkill(id);
9903
+ await provider.deleteSkill(id, mode);
8521
9904
  return;
8522
9905
  case "memory_store":
8523
9906
  if (!provider.deleteMemoryStore) {
8524
9907
  throw new UserError(`Provider does not support memory stores`);
8525
9908
  }
8526
- await provider.deleteMemoryStore(id);
9909
+ await provider.deleteMemoryStore(id, mode);
8527
9910
  return;
8528
9911
  case "vault":
8529
- await provider.deleteVault(id);
9912
+ await provider.deleteVault(id, mode);
8530
9913
  return;
8531
9914
  case "environment":
8532
- await provider.deleteEnvironment(id, cascade);
9915
+ await provider.deleteEnvironment(id, cascade, mode);
8533
9916
  return;
8534
9917
  case "deployment":
8535
9918
  await provider.deleteDeployment(id);
@@ -8543,7 +9926,7 @@ async function deleteRemoteResource(provider, type, id, cascade) {
8543
9926
  await provider.deleteChannel(id);
8544
9927
  return;
8545
9928
  case "file":
8546
- await provider.deleteFile(id);
9929
+ await provider.deleteFile(id, mode);
8547
9930
  return;
8548
9931
  }
8549
9932
  }
@@ -8703,6 +10086,7 @@ function buildAgentDecl(base, input) {
8703
10086
  });
8704
10087
  const agent = {
8705
10088
  ...base ?? {},
10089
+ name: input.name ?? base?.name,
8706
10090
  description: input.description ?? base?.description,
8707
10091
  model,
8708
10092
  instructions: input.instructions ?? base?.instructions ?? "",
@@ -8939,28 +10323,36 @@ async function listAgentsWithReadiness(ctx, options = {}) {
8939
10323
  }
8940
10324
  async function planAgentResources(ctx, agentId, options = {}) {
8941
10325
  const agent = getAgent(ctx, agentId);
10326
+ const rootAddress = collectAgentAddresses(ctx.config, agent.agentName, agent.provider)[0];
8942
10327
  const planned = await planProjectContext(ctx, {
8943
10328
  provider: agent.provider,
10329
+ scope: { roots: [rootAddress] },
10330
+ mode: options.mode,
8944
10331
  refresh: options.refresh,
8945
10332
  quiet: options.quiet ?? true
8946
10333
  });
8947
- const actions = filterAgentActions(ctx, agent, planned.plan);
10334
+ const actions = planned.plan.actions;
10335
+ const diagnostics = planned.plan.diagnostics;
8948
10336
  return {
8949
10337
  agentId,
8950
10338
  provider: agent.provider,
8951
10339
  actions,
8952
- diagnostics: filterAgentDiagnostics(ctx, agent, planned.plan),
10340
+ diagnostics,
8953
10341
  destructiveActions: selectDestructive(actions),
8954
10342
  planned
8955
10343
  };
8956
10344
  }
10345
+ async function planAgentResourcesWithStateBackend(input, agentId, options = {}) {
10346
+ return readProjectRuntime(input, (ctx) => planAgentResources(ctx, agentId, options));
10347
+ }
8957
10348
  async function syncAgentResources(ctx, agentId, options = {}) {
8958
10349
  return runAgentSync(ctx, agentId, options);
8959
10350
  }
8960
10351
  async function runAgentSync(ctx, agentId, options) {
8961
10352
  const fullPlan = await planAgentResources(ctx, agentId, {
8962
10353
  refresh: options.refresh,
8963
- quiet: options.quiet
10354
+ quiet: options.quiet,
10355
+ mode: options.mode
8964
10356
  });
8965
10357
  const actions = fullPlan.actions;
8966
10358
  const destructiveActions = fullPlan.destructiveActions;
@@ -8994,11 +10386,7 @@ async function runAgentSync(ctx, agentId, options) {
8994
10386
  };
8995
10387
  }
8996
10388
  try {
8997
- const scopedPlan = {
8998
- diagnostics: fullPlan.diagnostics,
8999
- actions: scopePlanActions(fullPlan.planned.plan, actions)
9000
- };
9001
- const execution = await executePlannedProject(replaceResourcePlan(fullPlan.planned, scopedPlan), {
10389
+ const execution = await executePlannedProject(fullPlan.planned, {
9002
10390
  policy: "force"
9003
10391
  });
9004
10392
  const results = toAgentSyncResults(execution);
@@ -9102,29 +10490,6 @@ function getAgentReadinessFromPlan(ctx, agentId, plan) {
9102
10490
  plannedActions: relevantActions
9103
10491
  };
9104
10492
  }
9105
- function filterAgentActions(ctx, agent, plan) {
9106
- const relevantKeys = agentAddressKeys(ctx, agent);
9107
- return plan.actions.filter(
9108
- (action) => relevantKeys.has(addressKey(action.address)) || action.dependencies.some((dependency) => relevantKeys.has(addressKey(dependency)))
9109
- );
9110
- }
9111
- function filterAgentDiagnostics(ctx, agent, plan) {
9112
- const relevantKeys = agentAddressKeys(ctx, agent);
9113
- return plan.diagnostics.filter(
9114
- (diagnostic) => !diagnostic.resource || relevantKeys.has(addressKey(diagnostic.resource))
9115
- );
9116
- }
9117
- function agentAddressKeys(ctx, agent) {
9118
- return new Set(collectAgentAddresses(ctx.config, agent.agentName, agent.provider).map(addressKey));
9119
- }
9120
- function scopePlanActions(fullPlan, agentActions) {
9121
- const allowedKeys = new Set(agentActions.filter((action) => action.action !== "no-op").map(actionKey));
9122
- return fullPlan.actions.filter((action) => action.action === "no-op" || allowedKeys.has(actionKey(action)));
9123
- }
9124
- function actionKey(action) {
9125
- const address = action.address;
9126
- return `${action.action}:${address.provider}:${address.type}:${address.name}`;
9127
- }
9128
10493
  function isNonBlockingAgentDrift(action) {
9129
10494
  if (action.action === "no-op") return true;
9130
10495
  return action.readinessImpact === "non_blocking";
@@ -9136,33 +10501,13 @@ function collectAgentAddresses(config, agentName, provider) {
9136
10501
  }
9137
10502
  const resolvedProvider = provider ?? resolveSessionProvider(agentName, config, void 0);
9138
10503
  const materialization = resolveAgentMaterialization(resolvedProvider, agent);
9139
- const addresses = [
9140
- { type: materialization.resourceType, name: agentName, provider: resolvedProvider }
9141
- ];
9142
- if (agent.environment) {
9143
- addresses.push({
9144
- type: "environment",
9145
- name: agent.environment,
9146
- provider: resolvedProvider
9147
- });
9148
- }
9149
- if (agent.vault) {
9150
- addresses.push({ type: "vault", name: agent.vault, provider: resolvedProvider });
9151
- }
9152
- for (const name of agent.memory_stores ?? []) {
9153
- addresses.push({ type: "memory_store", name, provider: resolvedProvider });
9154
- }
9155
- for (const skill of agent.skills ?? []) {
9156
- if (typeof skill === "string") {
9157
- addresses.push({ type: "skill", name: skill, provider: resolvedProvider });
9158
- }
9159
- }
9160
- for (const subAgent of agent.multiagent?.agents ?? []) {
9161
- const subDecl = config.agents?.[subAgent];
9162
- const subType = subDecl ? resolveAgentMaterialization(resolvedProvider, subDecl).resourceType : "agent";
9163
- addresses.push({ type: subType, name: subAgent, provider: resolvedProvider });
9164
- }
9165
- return addresses;
10504
+ const rootAddress = {
10505
+ type: materialization.resourceType,
10506
+ name: agentName,
10507
+ provider: resolvedProvider
10508
+ };
10509
+ const graph = buildDependencyGraph(config, [resolvedProvider]);
10510
+ return collectDependencyClosure(graph, [rootAddress]);
9166
10511
  }
9167
10512
  function toAgentDefinition(config, agentName, agent) {
9168
10513
  return {
@@ -9308,7 +10653,7 @@ async function collectEventsUntilTerminal(adapter2, sessionId, options = {}) {
9308
10653
  terminalStatus = terminalEvent.status;
9309
10654
  break;
9310
10655
  }
9311
- await delay(currentIntervalMs);
10656
+ await delay2(currentIntervalMs);
9312
10657
  currentIntervalMs = Math.min(currentIntervalMs * 2, maxPollIntervalMs);
9313
10658
  }
9314
10659
  } else {
@@ -9319,7 +10664,7 @@ async function collectEventsUntilTerminal(adapter2, sessionId, options = {}) {
9319
10664
  terminalStatus = session.status;
9320
10665
  break;
9321
10666
  }
9322
- await delay(currentIntervalMs);
10667
+ await delay2(currentIntervalMs);
9323
10668
  currentIntervalMs = Math.min(currentIntervalMs * 2, maxPollIntervalMs);
9324
10669
  }
9325
10670
  result = await adapter2.listSessionEvents(sessionId, { limit: 100 });
@@ -9389,12 +10734,20 @@ async function listSessionEvents(ctx, sessionId, options = {}) {
9389
10734
  const listOptions = {};
9390
10735
  if (options.limit !== void 0) listOptions.limit = options.limit;
9391
10736
  if (options.order !== void 0) listOptions.order = options.order;
10737
+ if (options.types !== void 0) listOptions.types = options.types;
10738
+ if (options.created_at_gt !== void 0) listOptions.created_at_gt = options.created_at_gt;
10739
+ if (options.created_at_gte !== void 0) listOptions.created_at_gte = options.created_at_gte;
10740
+ if (options.created_at_lt !== void 0) listOptions.created_at_lt = options.created_at_lt;
10741
+ if (options.created_at_lte !== void 0) listOptions.created_at_lte = options.created_at_lte;
9392
10742
  const pageToken = options.page_token ?? options.page;
9393
10743
  if (pageToken !== void 0) listOptions.page_token = pageToken;
9394
- return resolveDirectAdapter(ctx, options.provider).listSessionEvents(
10744
+ const result = await resolveDirectAdapter(ctx, options.provider).listSessionEvents(
9395
10745
  sessionId,
9396
10746
  Object.keys(listOptions).length > 0 ? listOptions : void 0
9397
10747
  );
10748
+ if (!options.types || options.types.length === 0) return result;
10749
+ const allowedTypes = new Set(options.types);
10750
+ return { ...result, events: result.events.filter((event) => allowedTypes.has(event.raw_type)) };
9398
10751
  }
9399
10752
  async function uploadFile(ctx, content, filename, options = {}) {
9400
10753
  const adapter2 = resolveDirectAdapter(ctx, options.provider);
@@ -9444,12 +10797,89 @@ async function deleteSkill(ctx, id, options = {}) {
9444
10797
  await resolveDirectAdapter(ctx, options.provider).deleteSkill(id);
9445
10798
  }
9446
10799
  function streamSessionEvents(ctx, sessionId, options = {}) {
10800
+ const adapter2 = resolveDirectAdapter(ctx, options.provider);
10801
+ if (options.after_id && !adapter2.eventResume) {
10802
+ return replaySessionEventsByPolling(adapter2, sessionId, options.after_id);
10803
+ }
9447
10804
  const streamOptions = {};
9448
10805
  if (options.after_id !== void 0) streamOptions.after_id = options.after_id;
9449
- return resolveDirectAdapter(ctx, options.provider).streamSessionEvents(
9450
- sessionId,
9451
- Object.keys(streamOptions).length > 0 ? streamOptions : void 0
9452
- );
10806
+ return adapter2.streamSessionEvents(sessionId, Object.keys(streamOptions).length > 0 ? streamOptions : void 0);
10807
+ }
10808
+ async function* replaySessionEventsByPolling(adapter2, sessionId, afterId) {
10809
+ const history = await listAllSessionEventHistory(adapter2, sessionId);
10810
+ const markerIndex = history.findIndex((event) => event.id === afterId);
10811
+ if (markerIndex < 0) {
10812
+ throw new UserError(`Session event '${afterId}' was not found; list session events and choose a valid event id.`);
10813
+ }
10814
+ const knownEventKeys = new Set(history.slice(0, markerIndex + 1).map(sessionEventKey));
10815
+ for (const event of history.slice(markerIndex + 1)) {
10816
+ const eventKey = sessionEventKey(event);
10817
+ if (knownEventKeys.has(eventKey)) continue;
10818
+ knownEventKeys.add(eventKey);
10819
+ yield event;
10820
+ if (event.type === "status" && isTerminalSessionStatus(event.status)) return;
10821
+ }
10822
+ while (true) {
10823
+ const newEvents = await listNewSessionEvents(adapter2, sessionId, knownEventKeys);
10824
+ for (const event of newEvents) {
10825
+ const eventKey = sessionEventKey(event);
10826
+ if (knownEventKeys.has(eventKey)) continue;
10827
+ knownEventKeys.add(eventKey);
10828
+ yield event;
10829
+ if (event.type === "status" && isTerminalSessionStatus(event.status)) return;
10830
+ }
10831
+ const session = await adapter2.getSession(sessionId);
10832
+ if (isTerminalSessionStatus(session.status)) return;
10833
+ await delay2(DEFAULT_POLL_INTERVAL_MS);
10834
+ }
10835
+ }
10836
+ async function listAllSessionEventHistory(adapter2, sessionId) {
10837
+ const events = [];
10838
+ const seenPageTokens = /* @__PURE__ */ new Set();
10839
+ let pageToken;
10840
+ while (true) {
10841
+ const result = await adapter2.listSessionEvents(sessionId, {
10842
+ limit: 100,
10843
+ order: "asc",
10844
+ ...pageToken ? { page_token: pageToken } : {}
10845
+ });
10846
+ events.push(...result.events);
10847
+ if (!result.next_page) return events;
10848
+ if (seenPageTokens.has(result.next_page)) {
10849
+ throw new UserError("Session event pagination returned a repeated cursor.");
10850
+ }
10851
+ seenPageTokens.add(result.next_page);
10852
+ pageToken = result.next_page;
10853
+ }
10854
+ }
10855
+ async function listNewSessionEvents(adapter2, sessionId, knownEventKeys) {
10856
+ const descendingEvents = [];
10857
+ const seenPageTokens = /* @__PURE__ */ new Set();
10858
+ let pageToken;
10859
+ while (true) {
10860
+ const result = await adapter2.listSessionEvents(sessionId, {
10861
+ limit: 100,
10862
+ order: "desc",
10863
+ ...pageToken ? { page_token: pageToken } : {}
10864
+ });
10865
+ let reachedKnownEvent = false;
10866
+ for (const event of result.events) {
10867
+ if (knownEventKeys.has(sessionEventKey(event))) {
10868
+ reachedKnownEvent = true;
10869
+ break;
10870
+ }
10871
+ descendingEvents.push(event);
10872
+ }
10873
+ if (reachedKnownEvent || !result.next_page) return descendingEvents.reverse();
10874
+ if (seenPageTokens.has(result.next_page)) {
10875
+ throw new UserError("Session event pagination returned a repeated cursor.");
10876
+ }
10877
+ seenPageTokens.add(result.next_page);
10878
+ pageToken = result.next_page;
10879
+ }
10880
+ }
10881
+ function sessionEventKey(event) {
10882
+ return event.id ?? `raw:${event.raw_type}:${JSON.stringify(event.raw)}`;
9453
10883
  }
9454
10884
  function resolveDirectAdapter(ctx, overrideProvider) {
9455
10885
  if (overrideProvider) return getRuntimeProvider(ctx, overrideProvider);
@@ -9486,7 +10916,7 @@ async function* streamWithResume(adapter2, sessionId, message) {
9486
10916
  }
9487
10917
  }
9488
10918
  if (!reachedTerminal) {
9489
- await delay(reconnectIntervalMs);
10919
+ await delay2(reconnectIntervalMs);
9490
10920
  reconnectIntervalMs = Math.min(reconnectIntervalMs * 2, DEFAULT_POLL_INTERVAL_MS);
9491
10921
  }
9492
10922
  }
@@ -9514,7 +10944,7 @@ function assertNotTimedOut(start, timeoutMs) {
9514
10944
  throw new UserError(`Session did not complete within the timeout (${Math.floor(timeoutMs / 1e3)} seconds).`);
9515
10945
  }
9516
10946
  }
9517
- function delay(ms) {
10947
+ function delay2(ms) {
9518
10948
  return new Promise((resolve13) => setTimeout(resolve13, ms));
9519
10949
  }
9520
10950
 
@@ -9700,6 +11130,7 @@ var StateManager = class _StateManager {
9700
11130
  address: r.address,
9701
11131
  remote_id: r.remote_id,
9702
11132
  externally_managed: r.externally_managed === true ? true : void 0,
11133
+ api_mode: r.api_mode === "forward" ? "forward" : r.api_mode === "managed" ? "managed" : void 0,
9703
11134
  version: r.version,
9704
11135
  content_hash: r.content_hash ?? r.desired_hash ?? "",
9705
11136
  desired_hash: r.desired_hash ?? r.content_hash ?? "",
@@ -9711,7 +11142,11 @@ var StateManager = class _StateManager {
9711
11142
  drift_paths: r.drift_paths,
9712
11143
  drift_status: r.drift_status
9713
11144
  }));
9714
- return new _StateManager({ resources }, path);
11145
+ const pending = Array.isArray(data.pending_default_memory_store_cleanups) ? data.pending_default_memory_store_cleanups : void 0;
11146
+ return new _StateManager(
11147
+ { resources, ...pending ? { pending_default_memory_store_cleanups: pending } : {} },
11148
+ path
11149
+ );
9715
11150
  } catch (err) {
9716
11151
  if (err && typeof err === "object" && "code" in err && err.code === "ENOENT") {
9717
11152
  return _StateManager.initialize(path);
@@ -9976,7 +11411,8 @@ var CloudAgentSchema = z6.object({
9976
11411
  workspace_id: z6.string().optional(),
9977
11412
  created_at: z6.string().optional(),
9978
11413
  updated_at: z6.string().optional(),
9979
- archived_at: z6.string().nullish()
11414
+ archived_at: z6.string().nullish(),
11415
+ attributes: z6.record(z6.string(), z6.unknown()).optional()
9980
11416
  });
9981
11417
  var ListCloudAgentsResponseSchema = z6.object({
9982
11418
  agents: z6.array(CloudAgentSchema)
@@ -9993,7 +11429,8 @@ var CloudEnvironmentSchema = z6.object({
9993
11429
  workspace_id: z6.string().optional(),
9994
11430
  created_at: z6.string().optional(),
9995
11431
  updated_at: z6.string().optional(),
9996
- archived_at: z6.string().nullish()
11432
+ archived_at: z6.string().nullish(),
11433
+ attributes: z6.record(z6.string(), z6.unknown()).optional()
9997
11434
  });
9998
11435
  var ListCloudEnvironmentsResponseSchema = z6.object({
9999
11436
  environments: z6.array(CloudEnvironmentSchema)
@@ -10005,7 +11442,8 @@ var CloudVaultSchema = z6.object({
10005
11442
  type: z6.string().optional(),
10006
11443
  created_at: z6.string().nullish(),
10007
11444
  updated_at: z6.string().nullish(),
10008
- archived_at: z6.string().nullish()
11445
+ archived_at: z6.string().nullish(),
11446
+ attributes: z6.record(z6.string(), z6.unknown()).optional()
10009
11447
  });
10010
11448
  var ListCloudVaultsResponseSchema = z6.object({
10011
11449
  vaults: z6.array(CloudVaultSchema)
@@ -10185,6 +11623,7 @@ export {
10185
11623
  applyProviderConfigToEnv,
10186
11624
  archiveCloudAgent,
10187
11625
  archiveMemoryStore,
11626
+ archiveRemoteSession,
10188
11627
  areRuntimeCredentialsReady,
10189
11628
  batchCreateMemories,
10190
11629
  bootstrapRuntimeCredentials,
@@ -10198,6 +11637,8 @@ export {
10198
11637
  createProjectRuntime,
10199
11638
  createSessionForAgent,
10200
11639
  createSkillFromFileId,
11640
+ createVaultCredential,
11641
+ createVaultCredentialWithStateBackend,
10201
11642
  decideDestructive,
10202
11643
  deleteCloudEnvironment,
10203
11644
  deleteCloudVault,
@@ -10207,6 +11648,8 @@ export {
10207
11648
  deleteSession,
10208
11649
  deleteSkill,
10209
11650
  destroyPlannedProjectResources,
11651
+ downloadRemoteFile,
11652
+ downloadRemoteSkill,
10210
11653
  executePlannedProject,
10211
11654
  extractSkillZipFiles,
10212
11655
  getAgent,
@@ -10214,13 +11657,23 @@ export {
10214
11657
  getDeploymentRuntimeProviderForContext,
10215
11658
  getFileDownloadUrl,
10216
11659
  getFileInfo,
11660
+ getManagedAgentProviderCapabilities,
10217
11661
  getMemory,
10218
11662
  getMemoryProviderCapabilities,
10219
11663
  getMemoryStore,
10220
11664
  getMemoryVersion,
11665
+ getRemoteAgent,
11666
+ getRemoteDeployment,
11667
+ getRemoteDeploymentRun,
11668
+ getRemoteEnvironment,
11669
+ getRemoteSkill,
11670
+ getRemoteSkillDownloadInfo,
11671
+ getRemoteSkillVersion,
11672
+ getRemoteVault,
10221
11673
  getSession,
10222
11674
  getSkillInfo,
10223
11675
  importResource,
11676
+ inspectSkillSource,
10224
11677
  isTerminalSessionStatus,
10225
11678
  listAgentsWithReadiness,
10226
11679
  listCloudAgents,
@@ -10233,7 +11686,16 @@ export {
10233
11686
  listMemoryVersions,
10234
11687
  listProviderModelsForContext,
10235
11688
  listProviderNames,
11689
+ listRemoteAgentVersions,
11690
+ listRemoteAgents,
11691
+ listRemoteDeploymentRuns,
11692
+ listRemoteDeployments,
10236
11693
  listRemoteDeploymentsForContext,
11694
+ listRemoteEnvironments,
11695
+ listRemoteFiles,
11696
+ listRemoteSkillVersions,
11697
+ listRemoteSkills,
11698
+ listRemoteVaults,
10237
11699
  listSessionEvents,
10238
11700
  listSessionSummaries,
10239
11701
  listSkills,
@@ -10243,8 +11705,13 @@ export {
10243
11705
  migrateConfig,
10244
11706
  parseStateAddress,
10245
11707
  pauseDeploymentForContext,
11708
+ planAgentResources,
11709
+ planAgentResourcesWithStateBackend,
10246
11710
  planDestroyProjectContext,
10247
11711
  planProjectContext,
11712
+ planProjectWithStateBackend,
11713
+ planVaultCredentialCreate,
11714
+ planVaultCredentialCreateWithStateBackend,
10248
11715
  prepareInitialSessionPrompt,
10249
11716
  preparePromptForProvider,
10250
11717
  prependFileHint,
@@ -10260,9 +11727,12 @@ export {
10260
11727
  resolveSyncProvider,
10261
11728
  rewriteFileMentions,
10262
11729
  runDeploymentForContext,
11730
+ runRemoteDeployment,
11731
+ sendRemoteSessionEvents,
10263
11732
  sendSessionMessagePolling,
10264
11733
  sendSessionMessageStreaming,
10265
11734
  setDefaultFetch,
11735
+ setRemoteDeploymentPaused,
10266
11736
  startSessionRun,
10267
11737
  startSessionRunPolling,
10268
11738
  streamSessionEvents,
@@ -10272,6 +11742,7 @@ export {
10272
11742
  syncProviderResourcesFromEnv,
10273
11743
  updateMemory,
10274
11744
  updateMemoryStore,
11745
+ updateRemoteSession,
10275
11746
  uploadFile,
10276
11747
  validateProjectConfig,
10277
11748
  writeProjectRuntime