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