@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/{chunk-GAAU67HX.js → chunk-6PDVAFLK.js} +13 -0
- package/dist/{file-URqwlxLf.d.ts → file-Cj5-Vx27.d.ts} +5 -0
- package/dist/file-lifecycle.d.ts +1 -1
- package/dist/index.d.ts +359 -47
- package/dist/index.js +1982 -511
- package/dist/{session-event-mzuENtyH.d.ts → session-event-DHLkM9iF.d.ts} +20 -8
- package/dist/session-events.d.ts +1 -1
- package/dist/session-events.js +2 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
toSessionEvent
|
|
3
|
-
} from "./chunk-
|
|
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
|
-
|
|
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
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
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
|
|
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
|
|
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
|
|
2901
|
+
const res = await client.post("/vaults", body);
|
|
2834
2902
|
const vaultId = res.id;
|
|
2835
2903
|
for (const cred of decl.credentials ?? []) {
|
|
2836
|
-
await
|
|
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(
|
|
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
|
-
|
|
2859
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2944
|
-
|
|
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
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
3300
|
-
|
|
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 =
|
|
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
|
-
|
|
3537
|
+
fileField,
|
|
3377
3538
|
new File([new Uint8Array(zipContent)], `${name}.zip`, {
|
|
3378
3539
|
type: "application/zip"
|
|
3379
3540
|
})
|
|
3380
3541
|
);
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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,
|
|
4080
|
-
|
|
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(
|
|
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({
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
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 (
|
|
6486
|
-
result = await provider.
|
|
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(
|
|
6524
|
-
|
|
6525
|
-
|
|
6526
|
-
|
|
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(
|
|
6542
|
-
|
|
6543
|
-
|
|
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 (
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
7015
|
-
|
|
7016
|
-
|
|
7017
|
-
|
|
7018
|
-
|
|
7019
|
-
|
|
7020
|
-
|
|
7021
|
-
|
|
7022
|
-
|
|
7023
|
-
|
|
7024
|
-
|
|
7025
|
-
|
|
7026
|
-
|
|
7027
|
-
|
|
7028
|
-
|
|
7029
|
-
|
|
7030
|
-
|
|
7031
|
-
|
|
7032
|
-
|
|
7033
|
-
|
|
7034
|
-
|
|
7035
|
-
|
|
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.
|
|
7125
|
-
`agent.${name}: memory_stores
|
|
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 (
|
|
7487
|
-
|
|
7488
|
-
|
|
7489
|
-
|
|
7490
|
-
|
|
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
|
-
|
|
7497
|
-
|
|
7498
|
-
|
|
7499
|
-
|
|
7500
|
-
|
|
7501
|
-
|
|
7502
|
-
|
|
7503
|
-
|
|
7504
|
-
|
|
7505
|
-
|
|
7506
|
-
|
|
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(
|
|
7545
|
-
collectReferenceDiagnostics(
|
|
7546
|
-
collectProviderCapabilities(
|
|
7547
|
-
const graph = buildDependencyGraph(
|
|
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
|
|
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
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
9140
|
-
|
|
9141
|
-
|
|
9142
|
-
|
|
9143
|
-
|
|
9144
|
-
|
|
9145
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
9450
|
-
|
|
9451
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|