@openagentpack/sdk 0.3.0-beta-fb9e73b-20260721 → 0.3.0-beta-e537ab3-20260722
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +54 -1
- package/dist/index.js +567 -124
- package/dist/session-events.js +21 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -298,6 +298,7 @@ var BaseApiClient = class {
|
|
|
298
298
|
buffer = buffer.slice(boundary + 2);
|
|
299
299
|
boundary = buffer.indexOf("\n\n");
|
|
300
300
|
const dataLines = [];
|
|
301
|
+
let sseId;
|
|
301
302
|
for (const line of frame.split("\n")) {
|
|
302
303
|
if (line.startsWith(":")) continue;
|
|
303
304
|
if (line.startsWith("event:") && line.slice(6).trim() === "heartbeat") {
|
|
@@ -307,11 +308,18 @@ var BaseApiClient = class {
|
|
|
307
308
|
if (line.startsWith("data:")) {
|
|
308
309
|
dataLines.push(line.slice(5).trimStart());
|
|
309
310
|
}
|
|
311
|
+
if (line.startsWith("id:")) {
|
|
312
|
+
sseId = line.slice(3).trimStart();
|
|
313
|
+
}
|
|
310
314
|
}
|
|
311
315
|
if (dataLines.length === 0) continue;
|
|
312
316
|
const json = dataLines.join("\n");
|
|
313
317
|
try {
|
|
314
|
-
|
|
318
|
+
const parsed = JSON.parse(json);
|
|
319
|
+
if (sseId !== void 0 && parsed.id === void 0) {
|
|
320
|
+
parsed.id = sseId;
|
|
321
|
+
}
|
|
322
|
+
yield parsed;
|
|
315
323
|
} catch {
|
|
316
324
|
}
|
|
317
325
|
}
|
|
@@ -849,8 +857,193 @@ function stripAgentsMetadata(value) {
|
|
|
849
857
|
return Object.keys(out).length > 0 ? out : void 0;
|
|
850
858
|
}
|
|
851
859
|
|
|
860
|
+
// src/internal/utils/sandbox-mount.ts
|
|
861
|
+
var PROVIDER_MOUNT_PREFIXES = {
|
|
862
|
+
qoder: "/data",
|
|
863
|
+
claude: "/workspace",
|
|
864
|
+
bailian: "/mnt",
|
|
865
|
+
ark: "/mnt"
|
|
866
|
+
};
|
|
867
|
+
function joinAbsolute(prefix, sub) {
|
|
868
|
+
const left = prefix.replace(/\/+$/, "");
|
|
869
|
+
const right = sub.replace(/^\/+/, "");
|
|
870
|
+
return `${left}/${right}`;
|
|
871
|
+
}
|
|
872
|
+
function quoteShellWord(value) {
|
|
873
|
+
return `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
874
|
+
}
|
|
875
|
+
function stripUrlQueryAndFragment(value) {
|
|
876
|
+
const queryIndex = value.indexOf("?");
|
|
877
|
+
const fragmentIndex = value.indexOf("#");
|
|
878
|
+
if (queryIndex === -1) {
|
|
879
|
+
return fragmentIndex === -1 ? value : value.slice(0, fragmentIndex);
|
|
880
|
+
}
|
|
881
|
+
if (fragmentIndex === -1) return value.slice(0, queryIndex);
|
|
882
|
+
return value.slice(0, Math.min(queryIndex, fragmentIndex));
|
|
883
|
+
}
|
|
884
|
+
function stripGitSuffix(value) {
|
|
885
|
+
return value.toLowerCase().endsWith(".git") ? value.slice(0, -4) : value;
|
|
886
|
+
}
|
|
887
|
+
function lastRemotePathSegment(value) {
|
|
888
|
+
const lastSlash = value.lastIndexOf("/");
|
|
889
|
+
const lastColon = value.lastIndexOf(":");
|
|
890
|
+
return value.slice(Math.max(lastSlash, lastColon) + 1).trim();
|
|
891
|
+
}
|
|
892
|
+
function providerMountPrefix(provider) {
|
|
893
|
+
return PROVIDER_MOUNT_PREFIXES[provider];
|
|
894
|
+
}
|
|
895
|
+
function resolveSandboxMountPath(provider, mountPath) {
|
|
896
|
+
const prefix = providerMountPrefix(provider);
|
|
897
|
+
if (!prefix) return mountPath;
|
|
898
|
+
if (mountPath === prefix || mountPath.startsWith(`${prefix}/`)) return mountPath;
|
|
899
|
+
if (mountPath.startsWith("/")) {
|
|
900
|
+
throw new UserError(`${provider} mount_path must start with '${prefix}/'; received '${mountPath}'.`);
|
|
901
|
+
}
|
|
902
|
+
return joinAbsolute(prefix, mountPath);
|
|
903
|
+
}
|
|
904
|
+
function resolveRepositoryMountPath(provider, resource) {
|
|
905
|
+
const prefix = providerMountPrefix(provider);
|
|
906
|
+
if (!prefix) throw new UserError(`Provider '${provider}' has no declared mount path prefix.`);
|
|
907
|
+
if (resource.mount_path) {
|
|
908
|
+
if (resource.mount_path !== prefix && !resource.mount_path.startsWith(`${prefix}/`)) {
|
|
909
|
+
throw new UserError(`${provider} Git repository Session resource mount_path must start with '${prefix}/'.`);
|
|
910
|
+
}
|
|
911
|
+
return resource.mount_path;
|
|
912
|
+
}
|
|
913
|
+
const repositoryName = stripGitSuffix(lastRemotePathSegment(stripUrlQueryAndFragment(resource.url)));
|
|
914
|
+
if (!repositoryName) {
|
|
915
|
+
throw new UserError(`Cannot derive a ${provider} Git repository mount path from URL '${resource.url}'.`);
|
|
916
|
+
}
|
|
917
|
+
return provider === "qoder" ? `${prefix}/workspace/${repositoryName}` : `${prefix}/${repositoryName}`;
|
|
918
|
+
}
|
|
919
|
+
function composeFileMountHint(files, provider) {
|
|
920
|
+
if (!files || files.length === 0) return "";
|
|
921
|
+
const lines = files.map((f) => `- ${resolveSandboxMountPath(provider, f.mount_path)}`);
|
|
922
|
+
return [
|
|
923
|
+
"The user uploaded files. They are available at the following sandbox paths:",
|
|
924
|
+
...lines,
|
|
925
|
+
"Read them from these paths when relevant."
|
|
926
|
+
].join("\n");
|
|
927
|
+
}
|
|
928
|
+
function prependFileHint(prompt, files, provider) {
|
|
929
|
+
const hint = composeFileMountHint(files, provider);
|
|
930
|
+
if (!hint) return prompt;
|
|
931
|
+
return `${hint}
|
|
932
|
+
|
|
933
|
+
${prompt}`;
|
|
934
|
+
}
|
|
935
|
+
var FILE_MENTION_START = "\u27E6file:";
|
|
936
|
+
var FILE_MENTION_END = "\u27E7";
|
|
937
|
+
function rewriteFileMentions(prompt, provider) {
|
|
938
|
+
let cursor = 0;
|
|
939
|
+
let rewritten = "";
|
|
940
|
+
while (cursor < prompt.length) {
|
|
941
|
+
const start = prompt.indexOf(FILE_MENTION_START, cursor);
|
|
942
|
+
if (start === -1) {
|
|
943
|
+
rewritten += prompt.slice(cursor);
|
|
944
|
+
break;
|
|
945
|
+
}
|
|
946
|
+
const mountPathStart = start + FILE_MENTION_START.length;
|
|
947
|
+
const end = prompt.indexOf(FILE_MENTION_END, mountPathStart);
|
|
948
|
+
if (end === -1) {
|
|
949
|
+
rewritten += prompt.slice(cursor);
|
|
950
|
+
break;
|
|
951
|
+
}
|
|
952
|
+
rewritten += prompt.slice(cursor, start);
|
|
953
|
+
rewritten += resolveSandboxMountPath(provider, prompt.slice(mountPathStart, end));
|
|
954
|
+
cursor = end + FILE_MENTION_END.length;
|
|
955
|
+
}
|
|
956
|
+
return rewritten;
|
|
957
|
+
}
|
|
958
|
+
function preparePromptForProvider(prompt, files, provider) {
|
|
959
|
+
return prependFileHint(rewriteFileMentions(prompt, provider), files, provider);
|
|
960
|
+
}
|
|
961
|
+
function prepareInitialSessionPrompt(prompt, bindings, provider) {
|
|
962
|
+
const prepared = preparePromptForProvider(prompt, bindings.files, provider);
|
|
963
|
+
const repositories = (bindings.resources ?? []).filter(
|
|
964
|
+
(resource) => resource.type === "github_repository"
|
|
965
|
+
);
|
|
966
|
+
if (repositories.length === 0) return prepared;
|
|
967
|
+
const paths = repositories.map((resource) => resolveRepositoryMountPath(provider, resource));
|
|
968
|
+
if (paths.length === 1) {
|
|
969
|
+
const path = paths[0];
|
|
970
|
+
return [
|
|
971
|
+
`The Git working tree for this task is mounted at \`${path}\`.`,
|
|
972
|
+
"Work only inside this directory unless the user explicitly requests otherwise.",
|
|
973
|
+
"Prefix every shell command with:",
|
|
974
|
+
`cd -- ${quoteShellWord(path)} &&`,
|
|
975
|
+
`Use absolute paths under \`${path}\` for non-shell file tools.`,
|
|
976
|
+
"",
|
|
977
|
+
prepared
|
|
978
|
+
].join("\n");
|
|
979
|
+
}
|
|
980
|
+
const lines = ["Git working trees for this task are mounted at:", ...paths.map((path) => `- ${path}`)];
|
|
981
|
+
lines.push("Choose the appropriate working tree for the task before inspecting or modifying files.");
|
|
982
|
+
return `${lines.join("\n")}
|
|
983
|
+
|
|
984
|
+
${prepared}`;
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
// src/internal/utils/tool-permissions.ts
|
|
988
|
+
function canonicalToolName(name) {
|
|
989
|
+
return name.trim().replace(/[^a-zA-Z0-9]+/g, "").toLowerCase();
|
|
990
|
+
}
|
|
991
|
+
function resolveBuiltinTools(tools, options = {}) {
|
|
992
|
+
const permissionByName = /* @__PURE__ */ new Map();
|
|
993
|
+
for (const [name, permission] of Object.entries(tools.permissions ?? {})) {
|
|
994
|
+
permissionByName.set(canonicalToolName(name), permission);
|
|
995
|
+
}
|
|
996
|
+
const supportedByName = options.supportedWireNames ? new Map([...options.supportedWireNames].map((name) => [canonicalToolName(name), name])) : void 0;
|
|
997
|
+
return tools.builtin.flatMap((configuredName) => {
|
|
998
|
+
const candidate = options.toWireName?.(configuredName) ?? configuredName;
|
|
999
|
+
const wireName = supportedByName?.get(canonicalToolName(candidate)) ?? (supportedByName ? void 0 : candidate);
|
|
1000
|
+
if (!wireName) return [];
|
|
1001
|
+
return [
|
|
1002
|
+
{
|
|
1003
|
+
configuredName,
|
|
1004
|
+
wireName,
|
|
1005
|
+
permission: permissionByName.get(canonicalToolName(configuredName)) ?? tools.default_permission ?? "allow"
|
|
1006
|
+
}
|
|
1007
|
+
];
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
1010
|
+
function toPermissionPolicy(permission) {
|
|
1011
|
+
return { type: permission === "ask" ? "always_ask" : "always_allow" };
|
|
1012
|
+
}
|
|
1013
|
+
function permissionOverridesFromWire(configs, toConfigName = (name) => name) {
|
|
1014
|
+
const permissions = {};
|
|
1015
|
+
for (const config of configs) {
|
|
1016
|
+
if (config.enabled === false) continue;
|
|
1017
|
+
const rawPolicy = config.permission_policy;
|
|
1018
|
+
const type = typeof rawPolicy === "string" ? rawPolicy : rawPolicy && typeof rawPolicy === "object" ? rawPolicy.type : void 0;
|
|
1019
|
+
if (type === "always_ask") permissions[toConfigName(config.name)] = "ask";
|
|
1020
|
+
else if (type === "always_allow") permissions[toConfigName(config.name)] = "allow";
|
|
1021
|
+
}
|
|
1022
|
+
return Object.keys(permissions).length ? permissions : void 0;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
// src/internal/providers/session-resource-mapper.ts
|
|
1026
|
+
function resolveGithubRepositoryMountPath(provider, resource) {
|
|
1027
|
+
return resolveRepositoryMountPath(provider, resource);
|
|
1028
|
+
}
|
|
1029
|
+
function mapGithubRepositorySessionResource(resource, options = {}) {
|
|
1030
|
+
const entry = {
|
|
1031
|
+
type: "github_repository",
|
|
1032
|
+
url: options.mapUrl?.(resource.url) ?? resource.url,
|
|
1033
|
+
authorization_token: resource.authorization_token
|
|
1034
|
+
};
|
|
1035
|
+
if (resource.checkout?.branch) entry.checkout = { type: "branch", name: resource.checkout.branch };
|
|
1036
|
+
else if (resource.checkout?.commit) entry.checkout = { type: "commit", sha: resource.checkout.commit };
|
|
1037
|
+
const mountPath = options.mapMountPath?.(resource) ?? resource.mount_path;
|
|
1038
|
+
if (mountPath) entry.mount_path = mountPath;
|
|
1039
|
+
return entry;
|
|
1040
|
+
}
|
|
1041
|
+
|
|
852
1042
|
// src/internal/providers/claude/mapper.ts
|
|
853
1043
|
var CLAUDE_BUILTINS = /* @__PURE__ */ new Set(["read", "write", "edit", "bash", "glob", "grep", "web_search", "web_fetch"]);
|
|
1044
|
+
function normalizeGithubRepositoryUrlForClaude(url) {
|
|
1045
|
+
return url.replace(/\.git\/?$/, "");
|
|
1046
|
+
}
|
|
854
1047
|
function credToDecl(raw, vaultName) {
|
|
855
1048
|
const auth = raw.auth ?? {};
|
|
856
1049
|
const name = raw.display_name || raw.id || "credential";
|
|
@@ -921,6 +1114,7 @@ function agentToDecl(raw) {
|
|
|
921
1114
|
const skills = raw.skills;
|
|
922
1115
|
const multiagent = raw.multiagent;
|
|
923
1116
|
let builtinTools;
|
|
1117
|
+
let builtinPermissions;
|
|
924
1118
|
let allToolsEnabled = false;
|
|
925
1119
|
if (tools?.length) {
|
|
926
1120
|
const toolset = tools.find((t) => t.type === "agent_toolset_20260401");
|
|
@@ -929,6 +1123,7 @@ function agentToDecl(raw) {
|
|
|
929
1123
|
const configs = toolset.configs ?? [];
|
|
930
1124
|
if (configs.length > 0) {
|
|
931
1125
|
builtinTools = configs.filter((c) => c.enabled !== false).map((c) => c.name);
|
|
1126
|
+
builtinPermissions = permissionOverridesFromWire(configs);
|
|
932
1127
|
} else if (defaultConfig?.enabled) {
|
|
933
1128
|
allToolsEnabled = true;
|
|
934
1129
|
}
|
|
@@ -955,7 +1150,7 @@ function agentToDecl(raw) {
|
|
|
955
1150
|
}
|
|
956
1151
|
let toolsDecl;
|
|
957
1152
|
if (builtinTools?.length) {
|
|
958
|
-
toolsDecl = { builtin: builtinTools };
|
|
1153
|
+
toolsDecl = { builtin: builtinTools, permissions: builtinPermissions };
|
|
959
1154
|
} else if (allToolsEnabled) {
|
|
960
1155
|
toolsDecl = {
|
|
961
1156
|
builtin: ["read", "write", "edit", "bash", "glob", "grep", "web_search", "web_fetch"]
|
|
@@ -1015,16 +1210,11 @@ function mapAgent(name, decl, refs, version, projectName) {
|
|
|
1015
1210
|
body.metadata = decl.metadata;
|
|
1016
1211
|
}
|
|
1017
1212
|
if (decl.tools) {
|
|
1018
|
-
const toolConfigs = decl.tools
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
permission_policy: {
|
|
1024
|
-
type: permission === "ask" ? "always_ask" : "always_allow"
|
|
1025
|
-
}
|
|
1026
|
-
};
|
|
1027
|
-
});
|
|
1213
|
+
const toolConfigs = resolveBuiltinTools(decl.tools, { supportedWireNames: CLAUDE_BUILTINS }).map((tool) => ({
|
|
1214
|
+
name: tool.wireName,
|
|
1215
|
+
enabled: true,
|
|
1216
|
+
permission_policy: toPermissionPolicy(tool.permission)
|
|
1217
|
+
}));
|
|
1028
1218
|
body.tools = [
|
|
1029
1219
|
{
|
|
1030
1220
|
type: "agent_toolset_20260401",
|
|
@@ -1090,6 +1280,23 @@ function mapDeployment(name, decl, refs, projectName, uploadedFiles) {
|
|
|
1090
1280
|
}
|
|
1091
1281
|
return body;
|
|
1092
1282
|
}
|
|
1283
|
+
function mapDeploymentUpdate(name, decl, refs, projectName, uploadedFiles, existingMetadata) {
|
|
1284
|
+
const body = mapDeployment(name, decl, refs, projectName, uploadedFiles);
|
|
1285
|
+
body.vault_ids = refs.vault_ids;
|
|
1286
|
+
body.resources = mapDeploymentResources(decl, refs, uploadedFiles);
|
|
1287
|
+
if (decl.schedule) {
|
|
1288
|
+
body.schedule = { type: "cron", expression: decl.schedule.expression, timezone: decl.schedule.timezone };
|
|
1289
|
+
}
|
|
1290
|
+
body.description = decl.description ?? "";
|
|
1291
|
+
const desiredMetadata = projectName ? injectMetadata(decl.metadata, projectName, name) : decl.metadata ?? {};
|
|
1292
|
+
body.metadata = {
|
|
1293
|
+
...Object.fromEntries(
|
|
1294
|
+
Object.keys(existingMetadata ?? {}).filter((key) => !(key in desiredMetadata)).map((key) => [key, null])
|
|
1295
|
+
),
|
|
1296
|
+
...desiredMetadata
|
|
1297
|
+
};
|
|
1298
|
+
return body;
|
|
1299
|
+
}
|
|
1093
1300
|
function mapInitialEvents(events) {
|
|
1094
1301
|
return events.map((ev) => {
|
|
1095
1302
|
if (ev.type === "user.message" || ev.type === "system.message") {
|
|
@@ -1123,7 +1330,7 @@ function mapDeploymentResources(decl, refs, uploadedFiles) {
|
|
|
1123
1330
|
} else if (r.type === "github_repository") {
|
|
1124
1331
|
const entry = {
|
|
1125
1332
|
type: "github_repository",
|
|
1126
|
-
url: r.url
|
|
1333
|
+
url: normalizeGithubRepositoryUrlForClaude(r.url)
|
|
1127
1334
|
};
|
|
1128
1335
|
if (r.authorization_token) entry.authorization_token = r.authorization_token;
|
|
1129
1336
|
if (r.checkout?.branch) {
|
|
@@ -1252,8 +1459,16 @@ function mapSession(bindings) {
|
|
|
1252
1459
|
resources.push({
|
|
1253
1460
|
type: "file",
|
|
1254
1461
|
file_id: f.file_id,
|
|
1255
|
-
mount_path: f.mount_path
|
|
1462
|
+
mount_path: resolveSandboxMountPath("claude", f.mount_path)
|
|
1256
1463
|
});
|
|
1464
|
+
for (const resource of bindings.resources ?? []) {
|
|
1465
|
+
resources.push(
|
|
1466
|
+
mapGithubRepositorySessionResource(resource, {
|
|
1467
|
+
mapUrl: normalizeGithubRepositoryUrlForClaude,
|
|
1468
|
+
mapMountPath: (item) => resolveGithubRepositoryMountPath("claude", item)
|
|
1469
|
+
})
|
|
1470
|
+
);
|
|
1471
|
+
}
|
|
1257
1472
|
if (resources.length) body.resources = resources;
|
|
1258
1473
|
return body;
|
|
1259
1474
|
}
|
|
@@ -1504,7 +1719,20 @@ var ClaudeAdapter = class _ClaudeAdapter {
|
|
|
1504
1719
|
}
|
|
1505
1720
|
async updateDeployment(id, name, decl, refs, basePath) {
|
|
1506
1721
|
const uploaded = await this.uploadDeploymentFiles(decl, basePath);
|
|
1507
|
-
const
|
|
1722
|
+
const current = await this.client.get(`/deployments/${id}`);
|
|
1723
|
+
if (current.schedule && !decl.schedule) {
|
|
1724
|
+
throw new UserError(
|
|
1725
|
+
`Deployment '${name}' cannot remove its schedule through the documented Claude update API; archive and recreate it as a manual deployment.`
|
|
1726
|
+
);
|
|
1727
|
+
}
|
|
1728
|
+
const body = mapDeploymentUpdate(
|
|
1729
|
+
name,
|
|
1730
|
+
decl,
|
|
1731
|
+
refs,
|
|
1732
|
+
this.projectName,
|
|
1733
|
+
uploaded,
|
|
1734
|
+
current.metadata
|
|
1735
|
+
);
|
|
1508
1736
|
const res = await this.client.post(`/deployments/${id}`, body);
|
|
1509
1737
|
return toRemoteResource(res);
|
|
1510
1738
|
}
|
|
@@ -1556,6 +1784,36 @@ var ClaudeAdapter = class _ClaudeAdapter {
|
|
|
1556
1784
|
attributes: res
|
|
1557
1785
|
};
|
|
1558
1786
|
}
|
|
1787
|
+
async listDeployments(filter) {
|
|
1788
|
+
const params = new URLSearchParams();
|
|
1789
|
+
if (filter?.agent_id) params.set("agent_id", filter.agent_id);
|
|
1790
|
+
if (filter?.status) params.set("status", filter.status);
|
|
1791
|
+
if (filter?.include_archived) params.set("include_archived", "true");
|
|
1792
|
+
if (filter?.limit) params.set("limit", String(filter.limit));
|
|
1793
|
+
if (filter?.page) params.set("page", filter.page);
|
|
1794
|
+
if (filter?.created_at_gte) params.set("created_at[gte]", filter.created_at_gte);
|
|
1795
|
+
if (filter?.created_at_lte) params.set("created_at[lte]", filter.created_at_lte);
|
|
1796
|
+
const query2 = params.toString();
|
|
1797
|
+
const res = await this.client.get(`/deployments${query2 ? `?${query2}` : ""}`);
|
|
1798
|
+
const nextPage = res.next_page ?? void 0;
|
|
1799
|
+
return {
|
|
1800
|
+
deployments: (res.data ?? []).map(toDeploymentInfo),
|
|
1801
|
+
has_more: nextPage !== void 0,
|
|
1802
|
+
next_page: nextPage
|
|
1803
|
+
};
|
|
1804
|
+
}
|
|
1805
|
+
async pauseDeployment(ctx) {
|
|
1806
|
+
return this.setDeploymentPaused(ctx, true);
|
|
1807
|
+
}
|
|
1808
|
+
async unpauseDeployment(ctx) {
|
|
1809
|
+
return this.setDeploymentPaused(ctx, false);
|
|
1810
|
+
}
|
|
1811
|
+
async setDeploymentPaused(ctx, paused) {
|
|
1812
|
+
if (!ctx.id) throw new UserError(`Deployment '${ctx.name}' has no remote id; run \`agents apply\` first.`);
|
|
1813
|
+
const action = paused ? "pause" : "unpause";
|
|
1814
|
+
const res = await this.client.post(`/deployments/${ctx.id}/${action}`, {});
|
|
1815
|
+
return toDeploymentInfo(res);
|
|
1816
|
+
}
|
|
1559
1817
|
async createSession(bindings) {
|
|
1560
1818
|
if (bindings.delivery === "forward") throw new UserError("Claude does not support Forward sessions.");
|
|
1561
1819
|
const body = mapSession(bindings);
|
|
@@ -1627,6 +1885,16 @@ var ClaudeAdapter = class _ClaudeAdapter {
|
|
|
1627
1885
|
await this.client.delete(`/files/${id}`);
|
|
1628
1886
|
}
|
|
1629
1887
|
};
|
|
1888
|
+
function toDeploymentInfo(res) {
|
|
1889
|
+
const sched = res.schedule;
|
|
1890
|
+
return {
|
|
1891
|
+
id: res.id ?? null,
|
|
1892
|
+
status: res.status ?? "unknown",
|
|
1893
|
+
paused_reason: res.paused_reason ?? void 0,
|
|
1894
|
+
schedule: sched ? { expression: sched.expression, timezone: sched.timezone } : void 0,
|
|
1895
|
+
attributes: res
|
|
1896
|
+
};
|
|
1897
|
+
}
|
|
1630
1898
|
function toSessionInfo(res) {
|
|
1631
1899
|
return buildSessionInfo(
|
|
1632
1900
|
res,
|
|
@@ -1679,6 +1947,7 @@ registerProvider({
|
|
|
1679
1947
|
name: "claude",
|
|
1680
1948
|
configSchema: claudeConfigSchema,
|
|
1681
1949
|
capabilities: CLAUDE_CAPABILITIES,
|
|
1950
|
+
features: { tool_permissions: true, session_resources: ["github_repository"] },
|
|
1682
1951
|
createAdapter: (config, projectName) => {
|
|
1683
1952
|
const c = config;
|
|
1684
1953
|
return new ClaudeAdapter(c.api_key, c.beta, projectName);
|
|
@@ -1687,7 +1956,7 @@ registerProvider({
|
|
|
1687
1956
|
|
|
1688
1957
|
// src/internal/providers/qoder/adapter.ts
|
|
1689
1958
|
import { readFileSync as readFileSync2 } from "fs";
|
|
1690
|
-
import { basename as
|
|
1959
|
+
import { basename as basename2, dirname as dirname2, resolve as resolve2 } from "path";
|
|
1691
1960
|
import JSZip2 from "jszip";
|
|
1692
1961
|
|
|
1693
1962
|
// src/internal/providers/qoder/client.ts
|
|
@@ -1712,57 +1981,6 @@ var QoderClient = class extends BaseApiClient {
|
|
|
1712
1981
|
}
|
|
1713
1982
|
};
|
|
1714
1983
|
|
|
1715
|
-
// src/internal/utils/sandbox-mount.ts
|
|
1716
|
-
var AGENTS_SESSION_PREFIX = "/mnt/session";
|
|
1717
|
-
function joinAbsolute(prefix, sub) {
|
|
1718
|
-
const left = prefix.replace(/\/+$/, "");
|
|
1719
|
-
const right = sub.replace(/^\/+/, "");
|
|
1720
|
-
return `${left}/${right}`;
|
|
1721
|
-
}
|
|
1722
|
-
function basename2(p) {
|
|
1723
|
-
const trimmed = p.replace(/\/+$/, "");
|
|
1724
|
-
const idx = trimmed.lastIndexOf("/");
|
|
1725
|
-
return idx === -1 ? trimmed : trimmed.slice(idx + 1);
|
|
1726
|
-
}
|
|
1727
|
-
function resolveSandboxMountPath(provider, mountPath) {
|
|
1728
|
-
switch (provider) {
|
|
1729
|
-
case "ark":
|
|
1730
|
-
case "bailian":
|
|
1731
|
-
case "claude":
|
|
1732
|
-
return joinAbsolute(AGENTS_SESSION_PREFIX, mountPath);
|
|
1733
|
-
case "qoder":
|
|
1734
|
-
return joinAbsolute("/data", basename2(mountPath));
|
|
1735
|
-
default:
|
|
1736
|
-
return mountPath;
|
|
1737
|
-
}
|
|
1738
|
-
}
|
|
1739
|
-
function composeFileMountHint(files, provider) {
|
|
1740
|
-
if (!files || files.length === 0) return "";
|
|
1741
|
-
const lines = files.map((f) => `- ${resolveSandboxMountPath(provider, f.mount_path)}`);
|
|
1742
|
-
return [
|
|
1743
|
-
"The user uploaded files. They are available at the following sandbox paths:",
|
|
1744
|
-
...lines,
|
|
1745
|
-
"Read them from these paths when relevant."
|
|
1746
|
-
].join("\n");
|
|
1747
|
-
}
|
|
1748
|
-
function prependFileHint(prompt, files, provider) {
|
|
1749
|
-
const hint = composeFileMountHint(files, provider);
|
|
1750
|
-
if (!hint) return prompt;
|
|
1751
|
-
return `${hint}
|
|
1752
|
-
|
|
1753
|
-
${prompt}`;
|
|
1754
|
-
}
|
|
1755
|
-
var FILE_MENTION_SENTINEL_RE = /\u27E6file:(.+?)\u27E7/g;
|
|
1756
|
-
function rewriteFileMentions(prompt, provider) {
|
|
1757
|
-
return prompt.replace(
|
|
1758
|
-
FILE_MENTION_SENTINEL_RE,
|
|
1759
|
-
(_match, mountPath) => resolveSandboxMountPath(provider, mountPath)
|
|
1760
|
-
);
|
|
1761
|
-
}
|
|
1762
|
-
function preparePromptForProvider(prompt, files, provider) {
|
|
1763
|
-
return prependFileHint(rewriteFileMentions(prompt, provider), files, provider);
|
|
1764
|
-
}
|
|
1765
|
-
|
|
1766
1984
|
// src/internal/providers/qoder/mapper.ts
|
|
1767
1985
|
function toPascalCase(name) {
|
|
1768
1986
|
return name.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[^a-zA-Z0-9]+/g, " ").trim().split(/\s+/).map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join("");
|
|
@@ -1875,6 +2093,7 @@ function agentToDecl2(raw) {
|
|
|
1875
2093
|
const mcpServers = raw.mcp_servers;
|
|
1876
2094
|
const skills = raw.skills;
|
|
1877
2095
|
let builtinTools;
|
|
2096
|
+
let builtinPermissions;
|
|
1878
2097
|
if (tools?.length) {
|
|
1879
2098
|
const toolset = tools.find((t) => t.type === "agent_toolset_20260401");
|
|
1880
2099
|
if (toolset && Array.isArray(toolset.enabled_tools)) {
|
|
@@ -1882,6 +2101,7 @@ function agentToDecl2(raw) {
|
|
|
1882
2101
|
} else if (toolset) {
|
|
1883
2102
|
const configs = toolset.configs ?? [];
|
|
1884
2103
|
builtinTools = configs.filter((c) => c.enabled !== false).map((c) => normalizeToolNameFromQoder(c.name));
|
|
2104
|
+
builtinPermissions = permissionOverridesFromWire(configs, normalizeToolNameFromQoder);
|
|
1885
2105
|
}
|
|
1886
2106
|
}
|
|
1887
2107
|
let mcpServerDecls;
|
|
@@ -1903,7 +2123,7 @@ function agentToDecl2(raw) {
|
|
|
1903
2123
|
description: raw.description,
|
|
1904
2124
|
model: raw.model,
|
|
1905
2125
|
instructions: raw.system,
|
|
1906
|
-
tools: builtinTools?.length ? { builtin: builtinTools } : void 0,
|
|
2126
|
+
tools: builtinTools?.length ? { builtin: builtinTools, permissions: builtinPermissions } : void 0,
|
|
1907
2127
|
mcp_servers: mcpServerDecls,
|
|
1908
2128
|
skills: skillDecls,
|
|
1909
2129
|
metadata: stripAgentsMetadata(raw.metadata)
|
|
@@ -1934,6 +2154,7 @@ function mapDeployment2(name, decl, refs, projectName, uploadedFiles) {
|
|
|
1934
2154
|
};
|
|
1935
2155
|
}
|
|
1936
2156
|
if (decl.description) body.description = decl.description;
|
|
2157
|
+
if (decl.environment_variables !== void 0) body.environment_variables = decl.environment_variables;
|
|
1937
2158
|
if (projectName) {
|
|
1938
2159
|
body.metadata = injectMetadata(decl.metadata, projectName, name);
|
|
1939
2160
|
} else if (decl.metadata) {
|
|
@@ -1941,6 +2162,24 @@ function mapDeployment2(name, decl, refs, projectName, uploadedFiles) {
|
|
|
1941
2162
|
}
|
|
1942
2163
|
return body;
|
|
1943
2164
|
}
|
|
2165
|
+
function mapDeploymentUpdate2(name, decl, refs, projectName, uploadedFiles, existingMetadata) {
|
|
2166
|
+
const body = mapDeployment2(name, decl, refs, projectName, uploadedFiles);
|
|
2167
|
+
body.vault_ids = refs.vault_ids;
|
|
2168
|
+
body.resources = mapDeploymentResources2(decl, refs, uploadedFiles);
|
|
2169
|
+
if (decl.schedule) {
|
|
2170
|
+
body.schedule = { type: "cron", expression: decl.schedule.expression, timezone: decl.schedule.timezone };
|
|
2171
|
+
}
|
|
2172
|
+
body.description = decl.description ?? "";
|
|
2173
|
+
body.environment_variables = decl.environment_variables ?? null;
|
|
2174
|
+
const desiredMetadata = projectName ? injectMetadata(decl.metadata, projectName, name) : decl.metadata ?? {};
|
|
2175
|
+
body.metadata = {
|
|
2176
|
+
...Object.fromEntries(
|
|
2177
|
+
Object.keys(existingMetadata ?? {}).filter((key) => !(key in desiredMetadata)).map((key) => [key, null])
|
|
2178
|
+
),
|
|
2179
|
+
...desiredMetadata
|
|
2180
|
+
};
|
|
2181
|
+
return body;
|
|
2182
|
+
}
|
|
1944
2183
|
function mapDeploymentInitialEvents(events) {
|
|
1945
2184
|
return events.map((ev) => {
|
|
1946
2185
|
if (ev.type === "user.message" || ev.type === "system.message") {
|
|
@@ -2017,11 +2256,14 @@ function mapAgent2(name, decl, refs, version, projectName) {
|
|
|
2017
2256
|
body.metadata = decl.metadata;
|
|
2018
2257
|
}
|
|
2019
2258
|
if (decl.tools) {
|
|
2020
|
-
const enabledTools = decl.tools.builtin.map((t) => normalizeToolNameForQoder(t));
|
|
2021
2259
|
body.tools = [
|
|
2022
2260
|
{
|
|
2023
2261
|
type: "agent_toolset_20260401",
|
|
2024
|
-
|
|
2262
|
+
configs: resolveBuiltinTools(decl.tools, { toWireName: normalizeToolNameForQoder }).map((tool) => ({
|
|
2263
|
+
name: tool.wireName,
|
|
2264
|
+
enabled: true,
|
|
2265
|
+
permission_policy: toPermissionPolicy(tool.permission)
|
|
2266
|
+
}))
|
|
2025
2267
|
}
|
|
2026
2268
|
];
|
|
2027
2269
|
} else {
|
|
@@ -2079,19 +2321,14 @@ function mapForwardTemplate(name, decl, refs, projectName) {
|
|
|
2079
2321
|
if (projectName) body.metadata = injectMetadata(decl.metadata, projectName, name);
|
|
2080
2322
|
else body.metadata = decl.metadata ?? {};
|
|
2081
2323
|
if (decl.tools) {
|
|
2082
|
-
const permissions = decl.tools.permissions ?? {};
|
|
2083
2324
|
body.tools = [
|
|
2084
2325
|
{
|
|
2085
2326
|
type: "agent_toolset_20260401",
|
|
2086
|
-
configs: decl.tools.
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
enabled: true,
|
|
2092
|
-
...policy ? { permission_policy: { type: policy === "ask" ? "always_ask" : "always_allow" } } : {}
|
|
2093
|
-
};
|
|
2094
|
-
})
|
|
2327
|
+
configs: resolveBuiltinTools(decl.tools, { toWireName: normalizeToolNameForQoder }).map((tool) => ({
|
|
2328
|
+
name: tool.wireName,
|
|
2329
|
+
enabled: true,
|
|
2330
|
+
permission_policy: toPermissionPolicy(tool.permission)
|
|
2331
|
+
}))
|
|
2095
2332
|
}
|
|
2096
2333
|
];
|
|
2097
2334
|
} else {
|
|
@@ -2147,6 +2384,7 @@ function toSessionEvent3(raw) {
|
|
|
2147
2384
|
const rawType = raw.type ?? "";
|
|
2148
2385
|
const type = QODER_EVENT_MAP[rawType] ?? "unknown";
|
|
2149
2386
|
const event = { type, raw_type: rawType, raw };
|
|
2387
|
+
if (typeof raw.id === "string") event.id = raw.id;
|
|
2150
2388
|
if (typeof raw.role === "string") event.role = raw.role;
|
|
2151
2389
|
if (type === "message") {
|
|
2152
2390
|
event.role = roleFromType2(rawType, raw.role);
|
|
@@ -2157,12 +2395,15 @@ function toSessionEvent3(raw) {
|
|
|
2157
2395
|
} else if (type === "tool_result") {
|
|
2158
2396
|
event.content = extractContentText2(raw);
|
|
2159
2397
|
} else if (type === "status") {
|
|
2398
|
+
const stopReason = extractStopReason2(raw.stop_reason);
|
|
2160
2399
|
if (rawType === "session.thread_status_idle") {
|
|
2161
2400
|
event.status = "running";
|
|
2401
|
+
} else if (rawType === "session.status_idle" && stopReason === "requires_action") {
|
|
2402
|
+
event.status = "running";
|
|
2162
2403
|
} else {
|
|
2163
2404
|
event.status = rawType.includes("idle") ? "idle" : rawType.includes("terminated") ? "terminated" : "running";
|
|
2164
2405
|
}
|
|
2165
|
-
event.stop_reason =
|
|
2406
|
+
event.stop_reason = stopReason;
|
|
2166
2407
|
} else if (type === "error") {
|
|
2167
2408
|
event.content = extractErrorMessage2(raw);
|
|
2168
2409
|
}
|
|
@@ -2224,6 +2465,13 @@ function mapSession2(bindings) {
|
|
|
2224
2465
|
for (const id of bindings.memory_store_ids) resources.push({ type: "memory_store", memory_store_id: id });
|
|
2225
2466
|
for (const f of bindings.files ?? [])
|
|
2226
2467
|
resources.push({ type: "file", file_id: f.file_id, mount_path: resolveSandboxMountPath("qoder", f.mount_path) });
|
|
2468
|
+
for (const resource of bindings.resources ?? []) {
|
|
2469
|
+
resources.push(
|
|
2470
|
+
mapGithubRepositorySessionResource(resource, {
|
|
2471
|
+
mapMountPath: (item) => resolveGithubRepositoryMountPath("qoder", item)
|
|
2472
|
+
})
|
|
2473
|
+
);
|
|
2474
|
+
}
|
|
2227
2475
|
if (resources.length) body.resources = resources;
|
|
2228
2476
|
return body;
|
|
2229
2477
|
}
|
|
@@ -2234,6 +2482,16 @@ function deriveForwardGateway(cloudGateway) {
|
|
|
2234
2482
|
const trimmed = cloudGateway.replace(/\/$/, "");
|
|
2235
2483
|
return trimmed.endsWith("/cloud") ? `${trimmed.slice(0, -"/cloud".length)}/forward` : `${trimmed}/forward`;
|
|
2236
2484
|
}
|
|
2485
|
+
function toDeploymentInfo2(res) {
|
|
2486
|
+
const sched = res.schedule;
|
|
2487
|
+
return {
|
|
2488
|
+
id: res.id ?? null,
|
|
2489
|
+
status: res.status ?? "unknown",
|
|
2490
|
+
paused_reason: res.paused_reason ?? void 0,
|
|
2491
|
+
schedule: sched ? { expression: sched.expression, timezone: sched.timezone } : void 0,
|
|
2492
|
+
attributes: res
|
|
2493
|
+
};
|
|
2494
|
+
}
|
|
2237
2495
|
var QoderAdapter = class _QoderAdapter {
|
|
2238
2496
|
name = "qoder";
|
|
2239
2497
|
eventResume = true;
|
|
@@ -2279,8 +2537,8 @@ var QoderAdapter = class _QoderAdapter {
|
|
|
2279
2537
|
vault: "/vaults",
|
|
2280
2538
|
skill: "/skills",
|
|
2281
2539
|
memory_store: "/memory_stores",
|
|
2282
|
-
file: "/files"
|
|
2283
|
-
|
|
2540
|
+
file: "/files",
|
|
2541
|
+
deployment: "/deployments"
|
|
2284
2542
|
};
|
|
2285
2543
|
async findResource(type, name, id) {
|
|
2286
2544
|
if (type === "template") {
|
|
@@ -2704,7 +2962,20 @@ var QoderAdapter = class _QoderAdapter {
|
|
|
2704
2962
|
}
|
|
2705
2963
|
async updateDeployment(id, name, decl, refs, basePath) {
|
|
2706
2964
|
const uploaded = await this.uploadDeploymentFiles(decl, basePath);
|
|
2707
|
-
const
|
|
2965
|
+
const current = await this.client.get(`/deployments/${id}`);
|
|
2966
|
+
if (current.schedule && !decl.schedule) {
|
|
2967
|
+
throw new UserError(
|
|
2968
|
+
`Deployment '${name}' cannot remove its schedule through the documented Qoder update API; archive and recreate it as a manual deployment.`
|
|
2969
|
+
);
|
|
2970
|
+
}
|
|
2971
|
+
const body = mapDeploymentUpdate2(
|
|
2972
|
+
name,
|
|
2973
|
+
decl,
|
|
2974
|
+
refs,
|
|
2975
|
+
this.projectName,
|
|
2976
|
+
uploaded,
|
|
2977
|
+
current.metadata
|
|
2978
|
+
);
|
|
2708
2979
|
const res = await this.client.post(`/deployments/${id}`, body);
|
|
2709
2980
|
return toRemoteResource(res);
|
|
2710
2981
|
}
|
|
@@ -2739,6 +3010,35 @@ var QoderAdapter = class _QoderAdapter {
|
|
|
2739
3010
|
attributes: res
|
|
2740
3011
|
};
|
|
2741
3012
|
}
|
|
3013
|
+
async listDeployments(filter) {
|
|
3014
|
+
const params = new URLSearchParams();
|
|
3015
|
+
if (filter?.agent_id) params.set("agent_id", filter.agent_id);
|
|
3016
|
+
if (filter?.status) params.set("status", filter.status);
|
|
3017
|
+
if (filter?.include_archived) params.set("include_archived", "true");
|
|
3018
|
+
if (filter?.limit) params.set("limit", String(filter.limit));
|
|
3019
|
+
if (filter?.page) params.set("page", filter.page);
|
|
3020
|
+
if (filter?.created_at_gte) params.set("created_at[gte]", filter.created_at_gte);
|
|
3021
|
+
if (filter?.created_at_lte) params.set("created_at[lte]", filter.created_at_lte);
|
|
3022
|
+
const query2 = params.toString();
|
|
3023
|
+
const res = await this.client.get(`/deployments${query2 ? `?${query2}` : ""}`);
|
|
3024
|
+
return {
|
|
3025
|
+
deployments: (res.data ?? []).map(toDeploymentInfo2),
|
|
3026
|
+
has_more: Boolean(res.has_more),
|
|
3027
|
+
next_page: res.next_page ?? void 0
|
|
3028
|
+
};
|
|
3029
|
+
}
|
|
3030
|
+
async pauseDeployment(ctx) {
|
|
3031
|
+
return this.setDeploymentPaused(ctx, true);
|
|
3032
|
+
}
|
|
3033
|
+
async unpauseDeployment(ctx) {
|
|
3034
|
+
return this.setDeploymentPaused(ctx, false);
|
|
3035
|
+
}
|
|
3036
|
+
async setDeploymentPaused(ctx, paused) {
|
|
3037
|
+
if (!ctx.id) throw new UserError(`Deployment '${ctx.name}' has no remote id; run \`agents apply\` first.`);
|
|
3038
|
+
const action = paused ? "pause" : "unpause";
|
|
3039
|
+
const res = await this.client.post(`/deployments/${ctx.id}/${action}`, {});
|
|
3040
|
+
return toDeploymentInfo2(res);
|
|
3041
|
+
}
|
|
2742
3042
|
async uploadDeploymentFiles(decl, basePath) {
|
|
2743
3043
|
const map = /* @__PURE__ */ new Map();
|
|
2744
3044
|
for (const r of decl.resources ?? []) {
|
|
@@ -2752,7 +3052,7 @@ var QoderAdapter = class _QoderAdapter {
|
|
|
2752
3052
|
const fullPath = resolve2(dirname2(basePath), source);
|
|
2753
3053
|
const content = readFileSync2(fullPath);
|
|
2754
3054
|
const formData = new FormData();
|
|
2755
|
-
formData.append("file", new File([new Uint8Array(content)],
|
|
3055
|
+
formData.append("file", new File([new Uint8Array(content)], basename2(fullPath)));
|
|
2756
3056
|
formData.append("purpose", "session_resource");
|
|
2757
3057
|
const res = await this.client.postFormData("/files", formData);
|
|
2758
3058
|
return res.file_id ?? res.id;
|
|
@@ -2925,7 +3225,7 @@ var QoderAdapter = class _QoderAdapter {
|
|
|
2925
3225
|
async uploadFile(filePath, options) {
|
|
2926
3226
|
const resolved = resolve2(filePath);
|
|
2927
3227
|
const content = readFileSync2(resolved);
|
|
2928
|
-
const fileName = options?.name ??
|
|
3228
|
+
const fileName = options?.name ?? basename2(resolved);
|
|
2929
3229
|
return this.uploadFileContent(new Uint8Array(content), fileName, {
|
|
2930
3230
|
purpose: options?.purpose
|
|
2931
3231
|
});
|
|
@@ -3050,6 +3350,7 @@ registerProvider({
|
|
|
3050
3350
|
name: "qoder",
|
|
3051
3351
|
configSchema: qoderConfigSchema,
|
|
3052
3352
|
capabilities: QODER_CAPABILITIES,
|
|
3353
|
+
features: { tool_permissions: true, session_resources: ["github_repository"] },
|
|
3053
3354
|
createAdapter: (config, projectName) => {
|
|
3054
3355
|
const c = config;
|
|
3055
3356
|
return new QoderAdapter(c.api_key, c.gateway, projectName, c.forward_gateway);
|
|
@@ -3058,7 +3359,7 @@ registerProvider({
|
|
|
3058
3359
|
|
|
3059
3360
|
// src/internal/providers/bailian/adapter.ts
|
|
3060
3361
|
import { readFileSync as readFileSync3 } from "fs";
|
|
3061
|
-
import { basename as
|
|
3362
|
+
import { basename as basename3, dirname as dirname3, extname, resolve as resolve3 } from "path";
|
|
3062
3363
|
import JSZip3 from "jszip";
|
|
3063
3364
|
|
|
3064
3365
|
// src/internal/providers/bailian/client.ts
|
|
@@ -3252,8 +3553,8 @@ function mapAgent3(name, decl, refs, version, projectName, skillVersions) {
|
|
|
3252
3553
|
}
|
|
3253
3554
|
const BAILIAN_BUILTINS = /* @__PURE__ */ new Set(["bash", "read", "write", "edit", "glob", "grep", "download_file"]);
|
|
3254
3555
|
if (decl.tools) {
|
|
3255
|
-
const toolConfigs = decl.tools
|
|
3256
|
-
name:
|
|
3556
|
+
const toolConfigs = resolveBuiltinTools(decl.tools, { supportedWireNames: BAILIAN_BUILTINS }).map((tool) => ({
|
|
3557
|
+
name: tool.wireName,
|
|
3257
3558
|
enabled: true
|
|
3258
3559
|
}));
|
|
3259
3560
|
body.tools = [
|
|
@@ -3315,7 +3616,13 @@ function mapSession3(bindings) {
|
|
|
3315
3616
|
if (bindings.metadata) body.metadata = bindings.metadata;
|
|
3316
3617
|
if (bindings.vault_ids.length) body.vault_ids = bindings.vault_ids;
|
|
3317
3618
|
const resources = [];
|
|
3318
|
-
for (const f of bindings.files ?? [])
|
|
3619
|
+
for (const f of bindings.files ?? []) {
|
|
3620
|
+
resources.push({
|
|
3621
|
+
type: "file",
|
|
3622
|
+
file_id: f.file_id,
|
|
3623
|
+
mount_path: resolveSandboxMountPath("bailian", f.mount_path)
|
|
3624
|
+
});
|
|
3625
|
+
}
|
|
3319
3626
|
if (resources.length) body.resources = resources;
|
|
3320
3627
|
if (bindings.memory_store_ids.length) body.memory_store_ids = bindings.memory_store_ids;
|
|
3321
3628
|
return body;
|
|
@@ -3763,7 +4070,7 @@ var BailianAdapter = class _BailianAdapter {
|
|
|
3763
4070
|
const fullPath = resolve3(dirname3(basePath), source);
|
|
3764
4071
|
const content = readFileSync3(fullPath);
|
|
3765
4072
|
const formData = new FormData();
|
|
3766
|
-
formData.append("file", new File([new Uint8Array(content)],
|
|
4073
|
+
formData.append("file", new File([new Uint8Array(content)], basename3(fullPath)));
|
|
3767
4074
|
const res = await this.client.postFormData("/files", formData);
|
|
3768
4075
|
const fileId = res.id;
|
|
3769
4076
|
await this.waitForFileAvailable(fileId);
|
|
@@ -3828,7 +4135,7 @@ var BailianAdapter = class _BailianAdapter {
|
|
|
3828
4135
|
async uploadFile(filePath, options) {
|
|
3829
4136
|
const resolved = resolve3(filePath);
|
|
3830
4137
|
const content = readFileSync3(resolved);
|
|
3831
|
-
const fileName = options?.name ??
|
|
4138
|
+
const fileName = options?.name ?? basename3(resolved);
|
|
3832
4139
|
return this.uploadFileContent(new Uint8Array(content), fileName, {
|
|
3833
4140
|
purpose: options?.purpose
|
|
3834
4141
|
});
|
|
@@ -3973,6 +4280,7 @@ registerProvider({
|
|
|
3973
4280
|
name: "bailian",
|
|
3974
4281
|
configSchema: bailianConfigSchema,
|
|
3975
4282
|
capabilities: BAILIAN_CAPABILITIES,
|
|
4283
|
+
features: { tool_permissions: false, session_resources: [] },
|
|
3976
4284
|
createAdapter: (config, projectName) => {
|
|
3977
4285
|
const c = config;
|
|
3978
4286
|
return new BailianAdapter(c.api_key, c.workspace_id, c.base_url, projectName);
|
|
@@ -3981,7 +4289,7 @@ registerProvider({
|
|
|
3981
4289
|
|
|
3982
4290
|
// src/internal/providers/ark/adapter.ts
|
|
3983
4291
|
import { readFileSync as readFileSync4 } from "fs";
|
|
3984
|
-
import { basename as
|
|
4292
|
+
import { basename as basename4, dirname as dirname4, resolve as resolve4 } from "path";
|
|
3985
4293
|
import JSZip4 from "jszip";
|
|
3986
4294
|
|
|
3987
4295
|
// src/internal/providers/resource-naming.ts
|
|
@@ -4106,6 +4414,7 @@ function agentToDecl4(raw) {
|
|
|
4106
4414
|
const skills = raw.skills;
|
|
4107
4415
|
const multiagent = raw.multiagent;
|
|
4108
4416
|
let builtinTools;
|
|
4417
|
+
let builtinPermissions;
|
|
4109
4418
|
let allToolsEnabled = false;
|
|
4110
4419
|
if (tools?.length) {
|
|
4111
4420
|
const toolset = tools.find((t) => t.type === "agent_toolset_20260701");
|
|
@@ -4114,6 +4423,7 @@ function agentToDecl4(raw) {
|
|
|
4114
4423
|
const configs = toolset.configs ?? [];
|
|
4115
4424
|
if (configs.length > 0) {
|
|
4116
4425
|
builtinTools = configs.filter((c) => c.enabled !== false).map((c) => c.name);
|
|
4426
|
+
builtinPermissions = permissionOverridesFromWire(configs);
|
|
4117
4427
|
} else if (defaultConfig?.enabled) {
|
|
4118
4428
|
allToolsEnabled = true;
|
|
4119
4429
|
}
|
|
@@ -4144,7 +4454,7 @@ function agentToDecl4(raw) {
|
|
|
4144
4454
|
}
|
|
4145
4455
|
let toolsDecl;
|
|
4146
4456
|
if (builtinTools?.length) {
|
|
4147
|
-
toolsDecl = { builtin: builtinTools };
|
|
4457
|
+
toolsDecl = { builtin: builtinTools, permissions: builtinPermissions };
|
|
4148
4458
|
} else if (allToolsEnabled) {
|
|
4149
4459
|
toolsDecl = {
|
|
4150
4460
|
builtin: ["read", "write", "edit", "bash", "glob", "grep", "web_search", "web_fetch"]
|
|
@@ -4205,16 +4515,11 @@ function mapAgent4(name, decl, refs, version, projectName) {
|
|
|
4205
4515
|
body.metadata = decl.metadata;
|
|
4206
4516
|
}
|
|
4207
4517
|
if (decl.tools) {
|
|
4208
|
-
const toolConfigs = decl.tools
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
permission_policy: {
|
|
4214
|
-
type: permission === "ask" ? "always_ask" : "always_allow"
|
|
4215
|
-
}
|
|
4216
|
-
};
|
|
4217
|
-
});
|
|
4518
|
+
const toolConfigs = resolveBuiltinTools(decl.tools, { supportedWireNames: ARK_BUILTINS }).map((tool) => ({
|
|
4519
|
+
name: tool.wireName,
|
|
4520
|
+
enabled: true,
|
|
4521
|
+
permission_policy: toPermissionPolicy(tool.permission)
|
|
4522
|
+
}));
|
|
4218
4523
|
body.tools = [
|
|
4219
4524
|
{
|
|
4220
4525
|
type: "agent_toolset_20260701",
|
|
@@ -4369,7 +4674,7 @@ function mapSession4(bindings) {
|
|
|
4369
4674
|
resources.push({
|
|
4370
4675
|
type: "file",
|
|
4371
4676
|
file_id: f.file_id,
|
|
4372
|
-
mount_path: f.mount_path
|
|
4677
|
+
mount_path: resolveSandboxMountPath("ark", f.mount_path)
|
|
4373
4678
|
});
|
|
4374
4679
|
if (resources.length) body.resources = resources;
|
|
4375
4680
|
return body;
|
|
@@ -4643,7 +4948,7 @@ var ArkAdapter = class _ArkAdapter {
|
|
|
4643
4948
|
const fullPath = resolve4(dirname4(basePath), source);
|
|
4644
4949
|
const content = readFileSync4(fullPath);
|
|
4645
4950
|
const formData = new FormData();
|
|
4646
|
-
formData.append("file", new File([new Uint8Array(content)],
|
|
4951
|
+
formData.append("file", new File([new Uint8Array(content)], basename4(fullPath)));
|
|
4647
4952
|
formData.append("purpose", "agent");
|
|
4648
4953
|
const res = await this.client.postFormData("/files", formData);
|
|
4649
4954
|
return res.file_id ?? res.id;
|
|
@@ -4692,7 +4997,7 @@ var ArkAdapter = class _ArkAdapter {
|
|
|
4692
4997
|
async uploadFile(filePath, options) {
|
|
4693
4998
|
const resolved = resolve4(filePath);
|
|
4694
4999
|
const content = readFileSync4(resolved);
|
|
4695
|
-
const fileName = options?.name ??
|
|
5000
|
+
const fileName = options?.name ?? basename4(resolved);
|
|
4696
5001
|
return this.uploadFileContent(new Uint8Array(content), fileName, {
|
|
4697
5002
|
purpose: options?.purpose
|
|
4698
5003
|
});
|
|
@@ -4773,6 +5078,7 @@ registerProvider({
|
|
|
4773
5078
|
name: "ark",
|
|
4774
5079
|
configSchema: arkConfigSchema,
|
|
4775
5080
|
capabilities: ARK_CAPABILITIES,
|
|
5081
|
+
features: { tool_permissions: true, session_resources: [] },
|
|
4776
5082
|
createAdapter: (config, projectName) => {
|
|
4777
5083
|
const c = config;
|
|
4778
5084
|
return new ArkAdapter(c.api_key, projectName);
|
|
@@ -4885,7 +5191,7 @@ async function resolveFileReferences(config, configPath) {
|
|
|
4885
5191
|
}
|
|
4886
5192
|
|
|
4887
5193
|
// src/internal/parser/resolve-project-config.ts
|
|
4888
|
-
import { basename as
|
|
5194
|
+
import { basename as basename5, dirname as dirname7, resolve as resolve7 } from "path";
|
|
4889
5195
|
|
|
4890
5196
|
// src/internal/parser/schema.ts
|
|
4891
5197
|
import { z as z5 } from "zod";
|
|
@@ -5030,8 +5336,32 @@ var mcpToolkitSchema = z5.object({
|
|
|
5030
5336
|
}));
|
|
5031
5337
|
var toolsSchema = z5.object({
|
|
5032
5338
|
builtin: z5.array(z5.string()),
|
|
5339
|
+
default_permission: z5.enum(["allow", "ask"]).optional(),
|
|
5033
5340
|
mcp: z5.array(mcpToolkitSchema).optional(),
|
|
5034
5341
|
permissions: z5.record(z5.string(), z5.enum(["allow", "ask"])).optional()
|
|
5342
|
+
}).superRefine((tools, ctx) => {
|
|
5343
|
+
const enabled = new Set(tools.builtin.map(canonicalToolName));
|
|
5344
|
+
const seen = /* @__PURE__ */ new Map();
|
|
5345
|
+
for (const key of Object.keys(tools.permissions ?? {})) {
|
|
5346
|
+
const canonical = canonicalToolName(key);
|
|
5347
|
+
const previous = seen.get(canonical);
|
|
5348
|
+
if (previous) {
|
|
5349
|
+
ctx.addIssue({
|
|
5350
|
+
code: "custom",
|
|
5351
|
+
path: ["permissions", key],
|
|
5352
|
+
message: `duplicates permission key '${previous}' after tool-name normalization`
|
|
5353
|
+
});
|
|
5354
|
+
} else {
|
|
5355
|
+
seen.set(canonical, key);
|
|
5356
|
+
}
|
|
5357
|
+
if (!enabled.has(canonical)) {
|
|
5358
|
+
ctx.addIssue({
|
|
5359
|
+
code: "custom",
|
|
5360
|
+
path: ["permissions", key],
|
|
5361
|
+
message: `references tool '${key}' which is not enabled in tools.builtin`
|
|
5362
|
+
});
|
|
5363
|
+
}
|
|
5364
|
+
}
|
|
5035
5365
|
});
|
|
5036
5366
|
var multiagentSchema = z5.object({
|
|
5037
5367
|
type: z5.literal("coordinator"),
|
|
@@ -5052,6 +5382,15 @@ var agentSkillRefSchema = z5.object({
|
|
|
5052
5382
|
var agentDeliverySchema = z5.object({
|
|
5053
5383
|
type: z5.enum(["managed", "forward"])
|
|
5054
5384
|
});
|
|
5385
|
+
var sessionGithubRepoResourceSchema = z5.object({
|
|
5386
|
+
type: z5.literal("github_repository"),
|
|
5387
|
+
url: z5.string().url(),
|
|
5388
|
+
checkout: z5.object({ branch: z5.string().min(1).optional(), commit: z5.string().min(1).optional() }).refine((value) => !(value.branch && value.commit), {
|
|
5389
|
+
message: "checkout accepts either branch or commit, not both"
|
|
5390
|
+
}).optional(),
|
|
5391
|
+
mount_path: z5.string().optional(),
|
|
5392
|
+
authorization_token: z5.string().min(1)
|
|
5393
|
+
});
|
|
5055
5394
|
var agentSchema = z5.object({
|
|
5056
5395
|
name: z5.string().optional(),
|
|
5057
5396
|
description: z5.string().optional(),
|
|
@@ -5065,6 +5404,7 @@ var agentSchema = z5.object({
|
|
|
5065
5404
|
skills: z5.array(z5.union([z5.string(), agentSkillRefSchema])).optional(),
|
|
5066
5405
|
vault: z5.string().optional(),
|
|
5067
5406
|
memory_stores: z5.array(z5.string()).optional(),
|
|
5407
|
+
resources: z5.array(sessionGithubRepoResourceSchema).optional(),
|
|
5068
5408
|
multiagent: multiagentSchema.optional(),
|
|
5069
5409
|
metadata: z5.record(z5.string(), z5.string()).optional(),
|
|
5070
5410
|
delivery: z5.record(z5.string(), agentDeliverySchema).optional()
|
|
@@ -5132,7 +5472,8 @@ var deploymentSchema = z5.object({
|
|
|
5132
5472
|
schedule: scheduleSchema.optional(),
|
|
5133
5473
|
description: z5.string().optional(),
|
|
5134
5474
|
provider: z5.string().optional(),
|
|
5135
|
-
metadata: z5.record(z5.string(), z5.string()).optional()
|
|
5475
|
+
metadata: z5.record(z5.string(), z5.string()).optional(),
|
|
5476
|
+
environment_variables: z5.string().optional()
|
|
5136
5477
|
});
|
|
5137
5478
|
var projectConfigSchema = z5.object({
|
|
5138
5479
|
version: z5.string(),
|
|
@@ -5203,7 +5544,7 @@ async function loadConfig(filePath, resolveEnv = false) {
|
|
|
5203
5544
|
// src/internal/parser/resolve-project-config.ts
|
|
5204
5545
|
async function resolveProjectConfig(filePath, options = {}) {
|
|
5205
5546
|
const configPath = resolve7(filePath);
|
|
5206
|
-
const projectName = options.projectName ??
|
|
5547
|
+
const projectName = options.projectName ?? basename5(dirname7(configPath));
|
|
5207
5548
|
const { config: parsed, errors } = await loadConfig(configPath, options.resolveEnv ?? true);
|
|
5208
5549
|
if (errors.length > 0) {
|
|
5209
5550
|
throw new UserError(errors.join("\n"));
|
|
@@ -6463,6 +6804,43 @@ function collectProviderCapabilities(config, providers, diagnostics) {
|
|
|
6463
6804
|
for (const [name, agent] of Object.entries(config.agents ?? {})) {
|
|
6464
6805
|
if (agent.provider && agent.provider !== providerName) continue;
|
|
6465
6806
|
const delivery = agent.delivery?.[providerName]?.type ?? "managed";
|
|
6807
|
+
const address = {
|
|
6808
|
+
type: delivery === "forward" ? "template" : "agent",
|
|
6809
|
+
name,
|
|
6810
|
+
provider: providerName
|
|
6811
|
+
};
|
|
6812
|
+
const asksForApproval = agent.tools?.default_permission === "ask" || Object.values(agent.tools?.permissions ?? {}).some((permission) => permission === "ask");
|
|
6813
|
+
if (asksForApproval && !def.features.tool_permissions) {
|
|
6814
|
+
diagnostics.error(
|
|
6815
|
+
`${providerName}.agent.tool_permissions.unsupported`,
|
|
6816
|
+
`agent.${name}: provider '${providerName}' cannot enforce interactive tool permission 'ask'.`,
|
|
6817
|
+
address
|
|
6818
|
+
);
|
|
6819
|
+
}
|
|
6820
|
+
for (const resource of agent.resources ?? []) {
|
|
6821
|
+
if (!def.features.session_resources.includes(resource.type)) {
|
|
6822
|
+
diagnostics.error(
|
|
6823
|
+
`${providerName}.agent.session_resource.${resource.type}.unsupported`,
|
|
6824
|
+
`agent.${name}: provider '${providerName}' does not support Session resource type '${resource.type}'.`,
|
|
6825
|
+
address
|
|
6826
|
+
);
|
|
6827
|
+
}
|
|
6828
|
+
const mountPrefix = providerMountPrefix(providerName);
|
|
6829
|
+
if (mountPrefix && resource.mount_path && resource.mount_path !== mountPrefix && !resource.mount_path.startsWith(`${mountPrefix}/`)) {
|
|
6830
|
+
diagnostics.error(
|
|
6831
|
+
`${providerName}.agent.session_resource.mount_path.invalid`,
|
|
6832
|
+
`agent.${name}: ${providerName} Session resource mount_path must start with '${mountPrefix}/'.`,
|
|
6833
|
+
address
|
|
6834
|
+
);
|
|
6835
|
+
}
|
|
6836
|
+
}
|
|
6837
|
+
if (delivery === "forward" && agent.resources?.length) {
|
|
6838
|
+
diagnostics.error(
|
|
6839
|
+
`${providerName}.template.session_resources.unsupported`,
|
|
6840
|
+
`agent.${name}: Forward delivery cannot attach Agent Session resources; use managed delivery.`,
|
|
6841
|
+
address
|
|
6842
|
+
);
|
|
6843
|
+
}
|
|
6466
6844
|
if (delivery === "forward" && !isSupported(caps, "template")) {
|
|
6467
6845
|
diagnostics.error(
|
|
6468
6846
|
`${providerName}.agent.delivery.forward.unsupported`,
|
|
@@ -6536,6 +6914,14 @@ function collectProviderCapabilities(config, providers, diagnostics) {
|
|
|
6536
6914
|
}
|
|
6537
6915
|
}
|
|
6538
6916
|
for (const [name, deployment] of Object.entries(config.deployments ?? {})) {
|
|
6917
|
+
if (deployment.provider && deployment.provider !== providerName) continue;
|
|
6918
|
+
if (deployment.environment_variables !== void 0) {
|
|
6919
|
+
diagnostics.error(
|
|
6920
|
+
`${providerName}.deployment.environment_variables.unsupported`,
|
|
6921
|
+
`deployment.${name}: environment_variables is supported only by Qoder deployments; remove it or pin this deployment to the qoder provider.`,
|
|
6922
|
+
{ type: "deployment", name, provider: providerName }
|
|
6923
|
+
);
|
|
6924
|
+
}
|
|
6539
6925
|
if (deployment.tunnel && (!deployment.provider || deployment.provider === providerName)) {
|
|
6540
6926
|
diagnostics.error(
|
|
6541
6927
|
`${providerName}.deployment.tunnel.unsupported`,
|
|
@@ -7498,6 +7884,12 @@ async function readYaml(path) {
|
|
|
7498
7884
|
}
|
|
7499
7885
|
|
|
7500
7886
|
// src/internal/core/deployment-runtime.ts
|
|
7887
|
+
async function listRemoteDeploymentsForContext(ctx, provider, filter) {
|
|
7888
|
+
const adapter2 = getRuntimeProvider(ctx, provider);
|
|
7889
|
+
if (!adapter2.listDeployments)
|
|
7890
|
+
throw new UserError(`Provider '${provider}' does not support remote deployment listing.`);
|
|
7891
|
+
return adapter2.listDeployments(filter);
|
|
7892
|
+
}
|
|
7501
7893
|
function listDeploymentsForContext(ctx, providerFilter) {
|
|
7502
7894
|
let rows = ctx.state.listResources().filter((resource) => resource.address.type === "deployment");
|
|
7503
7895
|
if (providerFilter) {
|
|
@@ -7542,6 +7934,14 @@ async function runDeploymentForContext(ctx, name, adapter2, resolvedProvider) {
|
|
|
7542
7934
|
result: await effectiveAdapter.runDeployment(depCtx)
|
|
7543
7935
|
};
|
|
7544
7936
|
}
|
|
7937
|
+
async function pauseDeploymentForContext(ctx, name, paused, resolvedProvider) {
|
|
7938
|
+
const provider = resolvedProvider ?? resolveDeploymentProvider(name, ctx.config);
|
|
7939
|
+
const adapter2 = getRuntimeProvider(ctx, provider);
|
|
7940
|
+
const operation = paused ? adapter2.pauseDeployment : adapter2.unpauseDeployment;
|
|
7941
|
+
if (!operation)
|
|
7942
|
+
throw new UserError(`Provider '${provider}' does not support ${paused ? "pausing" : "unpausing"} deployments.`);
|
|
7943
|
+
return operation.call(adapter2, buildDeploymentContext(ctx, name, provider));
|
|
7944
|
+
}
|
|
7545
7945
|
function getDeploymentRuntimeProviderForContext(ctx, name, overrideProvider) {
|
|
7546
7946
|
return resolveDeploymentProvider(name, ctx.config, overrideProvider);
|
|
7547
7947
|
}
|
|
@@ -7943,7 +8343,21 @@ function buildSessionBindings(agentName, config, provider, state, options = {})
|
|
|
7943
8343
|
const available = Object.keys(config.agents ?? {}).join(", ");
|
|
7944
8344
|
throw new UserError(`Agent '${agentName}' not found in config. Available agents: ${available || "(none)"}`);
|
|
7945
8345
|
}
|
|
8346
|
+
const sessionResources = options.resources ?? agent.resources;
|
|
8347
|
+
const providerFeatures = getProvider(provider)?.features;
|
|
8348
|
+
for (const resource of sessionResources ?? []) {
|
|
8349
|
+
if (!providerFeatures?.session_resources.includes(resource.type)) {
|
|
8350
|
+
throw new UserError(
|
|
8351
|
+
`Provider '${provider}' does not support Session resource type '${resource.type}' for agent '${agentName}'.`
|
|
8352
|
+
);
|
|
8353
|
+
}
|
|
8354
|
+
}
|
|
7946
8355
|
if (resolveAgentMaterialization(provider, agent).resourceType === "template") {
|
|
8356
|
+
if (sessionResources?.length) {
|
|
8357
|
+
throw new UserError(
|
|
8358
|
+
`Forward session for '${agentName}' cannot attach Agent resources. Use managed delivery for GitHub repositories.`
|
|
8359
|
+
);
|
|
8360
|
+
}
|
|
7947
8361
|
const templateId = requireRef(state, { type: "template", name: agentName, provider });
|
|
7948
8362
|
const defaultIdentity = config.defaults?.identity;
|
|
7949
8363
|
const identityId = options.identityId ?? (defaultIdentity ? requireRef(state, { type: "identity", name: defaultIdentity, provider }) : void 0);
|
|
@@ -8001,6 +8415,7 @@ function buildSessionBindings(agentName, config, provider, state, options = {})
|
|
|
8001
8415
|
vault_ids: vaultIds,
|
|
8002
8416
|
memory_store_ids: memoryStoreIds,
|
|
8003
8417
|
files: (options.files ?? []).map((f) => ({ file_id: f.fileId, mount_path: f.mountPath })),
|
|
8418
|
+
resources: sessionResources,
|
|
8004
8419
|
title: options.title,
|
|
8005
8420
|
metadata: options.metadata
|
|
8006
8421
|
};
|
|
@@ -8370,6 +8785,7 @@ function toAgentSkillRef(skill) {
|
|
|
8370
8785
|
var TERMINAL_SESSION_STATUSES = /* @__PURE__ */ new Set(["idle", "completed", "failed", "terminated", "deleted"]);
|
|
8371
8786
|
var DEFAULT_POLL_INTERVAL_MS = 2e3;
|
|
8372
8787
|
var DEFAULT_POLL_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
8788
|
+
var POLL_INITIAL_INTERVAL_MS = 300;
|
|
8373
8789
|
function resolveAgentName(agents, agentName) {
|
|
8374
8790
|
if (agentName) return agentName;
|
|
8375
8791
|
const names = Object.keys(agents ?? {});
|
|
@@ -8400,6 +8816,7 @@ async function createSessionForAgent(ctx, options = {}) {
|
|
|
8400
8816
|
vaultIds: options.vaultIds,
|
|
8401
8817
|
memoryStores: options.memoryStores,
|
|
8402
8818
|
files: options.files,
|
|
8819
|
+
resources: options.resources,
|
|
8403
8820
|
title: options.title,
|
|
8404
8821
|
metadata: options.metadata
|
|
8405
8822
|
});
|
|
@@ -8418,6 +8835,7 @@ async function startSessionRun(ctx, prompt, options = {}) {
|
|
|
8418
8835
|
vaultIds: options.vaultIds,
|
|
8419
8836
|
memoryStores: options.memoryStores,
|
|
8420
8837
|
files: options.files,
|
|
8838
|
+
resources: options.resources,
|
|
8421
8839
|
title: options.title,
|
|
8422
8840
|
metadata: options.metadata
|
|
8423
8841
|
});
|
|
@@ -8426,7 +8844,7 @@ async function startSessionRun(ctx, prompt, options = {}) {
|
|
|
8426
8844
|
agentName,
|
|
8427
8845
|
provider,
|
|
8428
8846
|
session,
|
|
8429
|
-
events: streamMessageEvents(adapter2, session.id,
|
|
8847
|
+
events: streamMessageEvents(adapter2, session.id, prepareInitialSessionPrompt(prompt, bindings, provider))
|
|
8430
8848
|
};
|
|
8431
8849
|
}
|
|
8432
8850
|
function streamMessageEvents(adapter2, sessionId, message) {
|
|
@@ -8440,15 +8858,12 @@ async function sendSessionMessageStreaming(ctx, sessionId, message, options = {}
|
|
|
8440
8858
|
return streamMessageEvents(adapter2, sessionId, message);
|
|
8441
8859
|
}
|
|
8442
8860
|
async function startSessionRunPolling(ctx, prompt, options = {}) {
|
|
8443
|
-
const
|
|
8444
|
-
const
|
|
8445
|
-
const
|
|
8446
|
-
|
|
8447
|
-
|
|
8448
|
-
|
|
8449
|
-
);
|
|
8450
|
-
const collected = await sendSessionMessageAndCollectEvents(adapter2, run.session.id, hintedPrompt, options);
|
|
8451
|
-
return { ...run, ...collected };
|
|
8861
|
+
const { agentName, provider, adapter: adapter2 } = resolveSessionRuntime(ctx, options);
|
|
8862
|
+
const bindings = buildSessionBindings(agentName, ctx.config, provider, ctx.state, options);
|
|
8863
|
+
const session = await adapter2.createSession(bindings);
|
|
8864
|
+
const initialPrompt = prepareInitialSessionPrompt(prompt, bindings, provider);
|
|
8865
|
+
const collected = await sendSessionMessageAndCollectEvents(adapter2, session.id, initialPrompt, options);
|
|
8866
|
+
return { agentName, provider, session, ...collected };
|
|
8452
8867
|
}
|
|
8453
8868
|
async function sendSessionMessageAndCollectEvents(adapter2, sessionId, message, options = {}) {
|
|
8454
8869
|
const eventId = await adapter2.sendSessionMessage(sessionId, message);
|
|
@@ -8464,8 +8879,9 @@ async function sendSessionMessagePolling(ctx, sessionId, message, options = {})
|
|
|
8464
8879
|
}
|
|
8465
8880
|
async function collectEventsUntilTerminal(adapter2, sessionId, options = {}) {
|
|
8466
8881
|
const start = Date.now();
|
|
8467
|
-
const
|
|
8882
|
+
const maxPollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
8468
8883
|
const pollTimeoutMs = options.pollTimeoutMs ?? DEFAULT_POLL_TIMEOUT_MS;
|
|
8884
|
+
let currentIntervalMs = Math.min(POLL_INITIAL_INTERVAL_MS, maxPollIntervalMs);
|
|
8469
8885
|
let terminalStatus = "idle";
|
|
8470
8886
|
let result;
|
|
8471
8887
|
if (options.afterId) {
|
|
@@ -8482,7 +8898,8 @@ async function collectEventsUntilTerminal(adapter2, sessionId, options = {}) {
|
|
|
8482
8898
|
terminalStatus = terminalEvent.status;
|
|
8483
8899
|
break;
|
|
8484
8900
|
}
|
|
8485
|
-
await delay(
|
|
8901
|
+
await delay(currentIntervalMs);
|
|
8902
|
+
currentIntervalMs = Math.min(currentIntervalMs * 2, maxPollIntervalMs);
|
|
8486
8903
|
}
|
|
8487
8904
|
} else {
|
|
8488
8905
|
while (true) {
|
|
@@ -8492,7 +8909,8 @@ async function collectEventsUntilTerminal(adapter2, sessionId, options = {}) {
|
|
|
8492
8909
|
terminalStatus = session.status;
|
|
8493
8910
|
break;
|
|
8494
8911
|
}
|
|
8495
|
-
await delay(
|
|
8912
|
+
await delay(currentIntervalMs);
|
|
8913
|
+
currentIntervalMs = Math.min(currentIntervalMs * 2, maxPollIntervalMs);
|
|
8496
8914
|
}
|
|
8497
8915
|
result = await adapter2.listSessionEvents(sessionId, { limit: 100 });
|
|
8498
8916
|
}
|
|
@@ -8640,7 +9058,28 @@ function buildAgentNameByRemoteId(ctx, provider) {
|
|
|
8640
9058
|
}
|
|
8641
9059
|
async function* streamWithResume(adapter2, sessionId, message) {
|
|
8642
9060
|
const eventId = await adapter2.sendSessionMessage(sessionId, message);
|
|
8643
|
-
|
|
9061
|
+
let lastEventId = eventId;
|
|
9062
|
+
let reachedTerminal = false;
|
|
9063
|
+
let reconnectIntervalMs = POLL_INITIAL_INTERVAL_MS;
|
|
9064
|
+
const start = Date.now();
|
|
9065
|
+
while (!reachedTerminal) {
|
|
9066
|
+
assertNotTimedOut(start, DEFAULT_POLL_TIMEOUT_MS);
|
|
9067
|
+
for await (const event of adapter2.streamSessionEvents(
|
|
9068
|
+
sessionId,
|
|
9069
|
+
lastEventId ? { after_id: lastEventId } : void 0
|
|
9070
|
+
)) {
|
|
9071
|
+
if (event.id) lastEventId = event.id;
|
|
9072
|
+
yield event;
|
|
9073
|
+
if (event.type === "status" && isTerminalSessionStatus(event.status)) {
|
|
9074
|
+
reachedTerminal = true;
|
|
9075
|
+
break;
|
|
9076
|
+
}
|
|
9077
|
+
}
|
|
9078
|
+
if (!reachedTerminal) {
|
|
9079
|
+
await delay(reconnectIntervalMs);
|
|
9080
|
+
reconnectIntervalMs = Math.min(reconnectIntervalMs * 2, DEFAULT_POLL_INTERVAL_MS);
|
|
9081
|
+
}
|
|
9082
|
+
}
|
|
8644
9083
|
}
|
|
8645
9084
|
async function* streamConnectBeforeSend(adapter2, sessionId, message) {
|
|
8646
9085
|
const iterator = adapter2.streamSessionEvents(sessionId)[Symbol.asyncIterator]();
|
|
@@ -9375,6 +9814,7 @@ export {
|
|
|
9375
9814
|
listMemoryVersions,
|
|
9376
9815
|
listProviderModelsForContext,
|
|
9377
9816
|
listProviderNames,
|
|
9817
|
+
listRemoteDeploymentsForContext,
|
|
9378
9818
|
listSessionEvents,
|
|
9379
9819
|
listSessionSummaries,
|
|
9380
9820
|
listSkills,
|
|
@@ -9383,8 +9823,10 @@ export {
|
|
|
9383
9823
|
loadProviderConfigIntoEnvSync,
|
|
9384
9824
|
migrateConfig,
|
|
9385
9825
|
parseStateAddress,
|
|
9826
|
+
pauseDeploymentForContext,
|
|
9386
9827
|
planDestroyProjectContext,
|
|
9387
9828
|
planProjectContext,
|
|
9829
|
+
prepareInitialSessionPrompt,
|
|
9388
9830
|
preparePromptForProvider,
|
|
9389
9831
|
prependFileHint,
|
|
9390
9832
|
providerConfigPath,
|
|
@@ -9394,6 +9836,7 @@ export {
|
|
|
9394
9836
|
resolveProjectConfig,
|
|
9395
9837
|
resolveProjectConfigFromObject,
|
|
9396
9838
|
resolveProviderConfigFromEnv,
|
|
9839
|
+
resolveRepositoryMountPath,
|
|
9397
9840
|
resolveSessionProvider,
|
|
9398
9841
|
resolveSyncProvider,
|
|
9399
9842
|
rewriteFileMentions,
|