@openagentpack/sdk 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  toSessionEvent
3
- } from "./chunk-GAAU67HX.js";
3
+ } from "./chunk-6PDVAFLK.js";
4
4
  import {
5
5
  defaultFileUploadPurpose,
6
6
  enrichProviderFileInfo
@@ -628,6 +628,13 @@ async function listSessionEventsPaged(client, sessionId, options, toEvent, confi
628
628
  const params = new URLSearchParams();
629
629
  if (options?.limit) params.set("limit", String(options.limit));
630
630
  if (options?.order) params.set("order", options.order);
631
+ if (config?.forwardTypes !== false) {
632
+ for (const type of options?.types ?? []) params.append("types", type);
633
+ }
634
+ if (options?.created_at_gt) params.set("created_at[gt]", options.created_at_gt);
635
+ if (options?.created_at_gte) params.set("created_at[gte]", options.created_at_gte);
636
+ if (options?.created_at_lt) params.set("created_at[lt]", options.created_at_lt);
637
+ if (options?.created_at_lte) params.set("created_at[lte]", options.created_at_lte);
631
638
  const pageCursor = options?.page_token ?? options?.page;
632
639
  if (pageCursor) params.set("page", pageCursor);
633
640
  if (config?.forwardAfterId && options?.after_id) params.set("after_id", options.after_id);
@@ -794,7 +801,8 @@ function toCloudAgent(raw) {
794
801
  workspace_id: raw.workspace_id,
795
802
  created_at: raw.created_at,
796
803
  updated_at: raw.updated_at,
797
- archived_at: raw.archived_at ?? null
804
+ archived_at: raw.archived_at ?? null,
805
+ attributes: raw
798
806
  };
799
807
  }
800
808
  function toCloudEnvironment(raw) {
@@ -810,7 +818,8 @@ function toCloudEnvironment(raw) {
810
818
  workspace_id: raw.workspace_id,
811
819
  created_at: raw.created_at,
812
820
  updated_at: raw.updated_at,
813
- archived_at: raw.archived_at ?? null
821
+ archived_at: raw.archived_at ?? null,
822
+ attributes: raw
814
823
  };
815
824
  }
816
825
  function toCloudVault(raw) {
@@ -821,7 +830,8 @@ function toCloudVault(raw) {
821
830
  type: raw.type,
822
831
  created_at: raw.created_at ?? null,
823
832
  updated_at: raw.updated_at ?? null,
824
- archived_at: raw.archived_at ?? null
833
+ archived_at: raw.archived_at ?? null,
834
+ attributes: raw
825
835
  };
826
836
  }
827
837
  function toRestFileInfo(res) {
@@ -833,7 +843,9 @@ function toRestFileInfo(res) {
833
843
  created_at: res.created_at,
834
844
  downloadable: res.downloadable,
835
845
  status: res.status,
836
- purpose: res.purpose
846
+ purpose: res.purpose,
847
+ scope: res.scope,
848
+ attributes: res
837
849
  };
838
850
  }
839
851
  function toRestSkillInfo(res) {
@@ -846,7 +858,8 @@ function toRestSkillInfo(res) {
846
858
  status: "active",
847
859
  latest_version: res.latest_version,
848
860
  created_at: res.created_at,
849
- updated_at: res.updated_at
861
+ updated_at: res.updated_at,
862
+ attributes: res
850
863
  };
851
864
  }
852
865
 
@@ -1238,7 +1251,7 @@ function mapAgent(name, decl, refs, version, projectName) {
1238
1251
  }
1239
1252
  }
1240
1253
  const body = {
1241
- name,
1254
+ name: decl.name ?? name,
1242
1255
  model: modelValue,
1243
1256
  system: decl.instructions
1244
1257
  };
@@ -1297,7 +1310,7 @@ function mapAgent(name, decl, refs, version, projectName) {
1297
1310
  }
1298
1311
  function mapDeployment(name, decl, refs, projectName, uploadedFiles) {
1299
1312
  const body = {
1300
- name,
1313
+ name: decl.name ?? name,
1301
1314
  agent: refs.agent_version !== void 0 ? { id: refs.agent_id, type: "agent", version: refs.agent_version } : refs.agent_id,
1302
1315
  environment_id: refs.environment_id,
1303
1316
  initial_events: mapInitialEvents(decl.initial_events)
@@ -2183,6 +2196,7 @@ function agentToDecl2(raw) {
2183
2196
  }));
2184
2197
  }
2185
2198
  return compactDeep({
2199
+ name: raw.name,
2186
2200
  description: raw.description,
2187
2201
  model: raw.model,
2188
2202
  instructions: raw.system,
@@ -2201,7 +2215,7 @@ function mapMemoryStore2(name, decl) {
2201
2215
  }
2202
2216
  function mapDeployment2(name, decl, refs, projectName, uploadedFiles) {
2203
2217
  const body = {
2204
- name,
2218
+ name: decl.name ?? name,
2205
2219
  agent: refs.agent_version !== void 0 ? { id: refs.agent_id, type: "agent", version: refs.agent_version } : refs.agent_id,
2206
2220
  environment_id: refs.environment_id,
2207
2221
  initial_events: mapDeploymentInitialEvents(decl.initial_events)
@@ -2307,7 +2321,7 @@ function mapAgent2(name, decl, refs, version, projectName) {
2307
2321
  model = typeof qoderModel === "string" ? qoderModel : qoderModel.id;
2308
2322
  }
2309
2323
  const body = {
2310
- name,
2324
+ name: decl.name ?? name,
2311
2325
  model,
2312
2326
  system: decl.instructions
2313
2327
  };
@@ -2811,6 +2825,7 @@ var QoderAdapter = class _QoderAdapter {
2811
2825
  return compactDeep(normalized);
2812
2826
  }
2813
2827
  return compactDeep({
2828
+ name: raw.name,
2814
2829
  description: raw.description,
2815
2830
  model: normalizeModel(raw.model),
2816
2831
  instructions: raw.system,
@@ -2831,7 +2846,7 @@ var QoderAdapter = class _QoderAdapter {
2831
2846
  const currentMetadata = current.metadata ?? {};
2832
2847
  const metadata = { ...body.metadata ?? {} };
2833
2848
  for (const key of Object.keys(currentMetadata)) {
2834
- if (!key.startsWith("agents.") && !(key in metadata)) metadata[key] = null;
2849
+ if (key !== "created_by" && !key.startsWith("agents.") && !(key in metadata)) metadata[key] = null;
2835
2850
  }
2836
2851
  body.metadata = metadata;
2837
2852
  const res = await client.post(`/environments/${id}`, body);
@@ -2839,8 +2854,20 @@ var QoderAdapter = class _QoderAdapter {
2839
2854
  }
2840
2855
  async deleteEnvironment(id, cascade = false, mode = "managed") {
2841
2856
  if (mode === "forward") {
2842
- await this.forwardClient.delete(`/environments/${id}`);
2843
- return;
2857
+ try {
2858
+ await this.forwardClient.delete(`/environments/${id}`);
2859
+ return;
2860
+ } catch (err) {
2861
+ const isConflict = err instanceof ApiError && (err.statusCode === 409 || err.responseBody.includes("in use"));
2862
+ if (!isConflict) throw err;
2863
+ if (!cascade) {
2864
+ throw new UserError(
2865
+ `Environment ${id} is referenced by one or more Forward sessions. Use --cascade to archive the environment.`
2866
+ );
2867
+ }
2868
+ await this.forwardClient.post(`/environments/${id}/archive`, {});
2869
+ return;
2870
+ }
2844
2871
  }
2845
2872
  try {
2846
2873
  await this.client.delete(`/environments/${id}`);
@@ -3630,25 +3657,26 @@ function mapVault2(name, decl, projectName) {
3630
3657
  return body;
3631
3658
  }
3632
3659
  function mapCredential2(cred) {
3633
- if (cred.type === "environment_variable") {
3634
- return {
3635
- auth: {
3636
- type: "environment_variable",
3637
- secret_name: cred.secret_name,
3638
- secret_value: cred.secret_value,
3639
- networking: cred.networking ?? { type: "unrestricted" }
3640
- },
3641
- display_name: cred.name
3642
- };
3660
+ if (cred.type !== "environment_variable") {
3661
+ throw new UserError(
3662
+ `credential '${cred.name}': Bailian only supports credential type 'environment_variable', but '${cred.type}' was declared.`
3663
+ );
3643
3664
  }
3644
- return {
3665
+ if (cred.networking?.type === "limited" && cred.networking.allowed_hosts === void 0) {
3666
+ throw new UserError(`credential '${cred.name}': Bailian limited networking requires networking.allowed_hosts.`);
3667
+ }
3668
+ const body = {
3645
3669
  auth: {
3646
- type: cred.type,
3647
- token: cred.access_token,
3648
- mcp_server_url: cred.mcp_server_url
3670
+ type: "environment_variable",
3671
+ secret_name: cred.secret_name,
3672
+ secret_value: cred.secret_value,
3673
+ networking: { allowed_hosts: cred.networking?.allowed_hosts ?? ["*"] },
3674
+ injection_location: cred.injection_location ?? { header: true, body: false }
3649
3675
  },
3650
3676
  display_name: cred.name
3651
3677
  };
3678
+ if (cred.metadata) body.metadata = cred.metadata;
3679
+ return body;
3652
3680
  }
3653
3681
  function credToDecl3(raw, vaultName) {
3654
3682
  const auth = raw.auth ?? {};
@@ -3658,17 +3686,21 @@ function credToDecl3(raw, vaultName) {
3658
3686
  return {
3659
3687
  name,
3660
3688
  type: "static_bearer",
3689
+ metadata: stripAgentsMetadata(raw.metadata),
3661
3690
  mcp_server_url: auth.mcp_server_url ?? "",
3662
3691
  access_token: placeholder
3663
3692
  };
3664
3693
  }
3665
3694
  const networking = auth.networking;
3695
+ const injectionLocation = auth.injection_location;
3666
3696
  return {
3667
3697
  name,
3668
3698
  type: "environment_variable",
3699
+ metadata: stripAgentsMetadata(raw.metadata),
3669
3700
  secret_name: auth.secret_name ?? name,
3670
3701
  secret_value: placeholder,
3671
- networking: networking ?? { type: "unrestricted" }
3702
+ networking: networking ?? { type: "unrestricted" },
3703
+ ...injectionLocation ? { injection_location: injectionLocation } : {}
3672
3704
  };
3673
3705
  }
3674
3706
  function vaultToDecl3(raw, rawCredentials, resourceName) {
@@ -3733,6 +3765,7 @@ function agentToDecl3(raw) {
3733
3765
  const model = raw.model;
3734
3766
  const modelValue = typeof model === "object" && model ? model.id : model;
3735
3767
  return compactDeep({
3768
+ name: raw.name,
3736
3769
  description: raw.description,
3737
3770
  model: modelValue,
3738
3771
  instructions: raw.system,
@@ -3752,7 +3785,7 @@ function mapAgent3(name, decl, refs, version, projectName, skillVersions) {
3752
3785
  modelId = typeof bailianModel === "string" ? bailianModel : bailianModel.id;
3753
3786
  }
3754
3787
  const body = {
3755
- name,
3788
+ name: decl.name ?? name,
3756
3789
  model: { id: modelId },
3757
3790
  system: decl.instructions
3758
3791
  };
@@ -3845,7 +3878,7 @@ function mapDeployment3(name, decl, refs, projectName, uploadedFiles) {
3845
3878
  const agent = { id: refs.agent_id };
3846
3879
  if (refs.agent_version !== void 0) agent.version = refs.agent_version;
3847
3880
  const body = {
3848
- name,
3881
+ name: decl.name ?? name,
3849
3882
  agent,
3850
3883
  environment_id: refs.environment_id,
3851
3884
  initial_events: mapMessageEvents(decl.initial_events)
@@ -3983,6 +4016,7 @@ var BailianAdapter = class _BailianAdapter {
3983
4016
  });
3984
4017
  }
3985
4018
  return compactDeep({
4019
+ name: raw.name,
3986
4020
  description: raw.description,
3987
4021
  model: normalizeBailianModel(raw.model),
3988
4022
  instructions: raw.system,
@@ -4014,6 +4048,18 @@ var BailianAdapter = class _BailianAdapter {
4014
4048
  async deleteEnvironment(id) {
4015
4049
  await this.client.delete(`/environments/${id}`);
4016
4050
  }
4051
+ async listEnvironmentResources(options) {
4052
+ const params = cursorParams(options);
4053
+ if (options?.include_archived !== void 0) {
4054
+ params.set("include_archived", String(options.include_archived));
4055
+ }
4056
+ const res = await this.client.get(withQuery("/environments", params));
4057
+ return cursorPage(res, toCloudEnvironment);
4058
+ }
4059
+ async getRemoteEnvironment(id) {
4060
+ const res = await this.client.get(`/environments/${id}`);
4061
+ return toCloudEnvironment(res);
4062
+ }
4017
4063
  // --- Agent ---
4018
4064
  async createAgent(name, decl, refs) {
4019
4065
  const skillVersions = await this.fetchSkillVersions(refs);
@@ -4062,6 +4108,25 @@ var BailianAdapter = class _BailianAdapter {
4062
4108
  async deleteAgent(id) {
4063
4109
  await this.client.post(`/agents/${id}/archive`, {});
4064
4110
  }
4111
+ async listAgentResources(options) {
4112
+ const params = cursorParams(options);
4113
+ if (options?.include_archived !== void 0) {
4114
+ params.set("include_archived", String(options.include_archived));
4115
+ }
4116
+ const res = await this.client.get(withQuery("/agents", params));
4117
+ return cursorPage(res, toCloudAgent);
4118
+ }
4119
+ async getRemoteAgent(id, version) {
4120
+ const params = new URLSearchParams();
4121
+ if (version !== void 0) params.set("version", String(version));
4122
+ const res = await this.client.get(withQuery(`/agents/${id}`, params));
4123
+ return toCloudAgent(res);
4124
+ }
4125
+ async listAgentVersions(id, options) {
4126
+ const params = cursorParams(options);
4127
+ const res = await this.client.get(withQuery(`/agents/${id}/versions`, params));
4128
+ return cursorPage(res, toCloudAgent);
4129
+ }
4065
4130
  // --- Skill (2-step: Files API → Skills API) ---
4066
4131
  async createSkill(name, decl, files) {
4067
4132
  const fileId = await this.uploadSkillZip(name, decl, files);
@@ -4160,10 +4225,31 @@ var BailianAdapter = class _BailianAdapter {
4160
4225
  const all = await this.client.getAllPaged(path);
4161
4226
  return all.map(toBailianSkillInfo);
4162
4227
  }
4228
+ async listSkillResources(options) {
4229
+ const params = cursorParams(options);
4230
+ if (options?.source === "official") params.set("source", "official");
4231
+ if (options?.source === "custom") params.set("source", "customer");
4232
+ const res = await this.client.get(withQuery("/skills", params));
4233
+ return cursorPage(res, toBailianSkillInfo);
4234
+ }
4163
4235
  async getSkillInfo(id) {
4164
4236
  const res = await this.client.get(`/skills/${id}`);
4165
4237
  return toBailianSkillInfo(res);
4166
4238
  }
4239
+ async listSkillVersions(id, options) {
4240
+ const params = cursorParams(options);
4241
+ const res = await this.client.get(withQuery(`/skills/${id}/versions`, params));
4242
+ return cursorPage(res, toSkillVersionInfo);
4243
+ }
4244
+ async getSkillVersion(id, version) {
4245
+ const res = await this.client.get(`/skills/${id}/versions/${encodeURIComponent(version)}`);
4246
+ return toSkillVersionInfo(res);
4247
+ }
4248
+ async getSkillDownloadInfo(id, version) {
4249
+ return await this.client.get(
4250
+ `/skills/${id}/versions/${encodeURIComponent(version)}/content`
4251
+ );
4252
+ }
4167
4253
  // Non-blocking create: file already uploaded → POST /skills with retry for residual OSS
4168
4254
  // replication lag (postSkillWithRetry covers SKILL_FILE_NOT_FOUND for a few seconds), and return
4169
4255
  // the initial status WITHOUT waiting for the security scan. Callers MUST ensure the file has
@@ -4223,6 +4309,7 @@ var BailianAdapter = class _BailianAdapter {
4223
4309
  // thin wrappers over the AgentStudio endpoints, exposed so callers/tests can
4224
4310
  // exercise the full surface through real project code rather than raw fetch.
4225
4311
  async createVault(name, decl) {
4312
+ for (const credential of decl.credentials ?? []) mapCredential2(credential);
4226
4313
  const body = mapVault2(name, decl, this.projectName);
4227
4314
  const res = await this.client.post("/vaults", body);
4228
4315
  const vaultId = res.id;
@@ -4235,6 +4322,18 @@ var BailianAdapter = class _BailianAdapter {
4235
4322
  const all = await this.client.getAllPaged("/vaults");
4236
4323
  return all.map(toCloudVault);
4237
4324
  }
4325
+ async listVaultResources(options) {
4326
+ const params = cursorParams(options);
4327
+ if (options?.include_archived !== void 0) {
4328
+ params.set("include_archived", String(options.include_archived));
4329
+ }
4330
+ const res = await this.client.get(withQuery("/vaults", params));
4331
+ return cursorPage(res, toCloudVault);
4332
+ }
4333
+ async getRemoteVault(id) {
4334
+ const res = await this.client.get(`/vaults/${id}`);
4335
+ return toCloudVault(res);
4336
+ }
4238
4337
  async getVault(id) {
4239
4338
  return await this.client.get(`/vaults/${id}`);
4240
4339
  }
@@ -4256,7 +4355,24 @@ var BailianAdapter = class _BailianAdapter {
4256
4355
  }
4257
4356
  async listCredentials(vaultId) {
4258
4357
  const all = await this.client.getAllPaged(`/vaults/${vaultId}/credentials`);
4259
- return all.map(toRemoteResource);
4358
+ return all.map((raw) => {
4359
+ const auth = raw.auth ?? {};
4360
+ const networking = auth.networking;
4361
+ const metadata = raw.metadata;
4362
+ return {
4363
+ id: raw.id,
4364
+ display_name: raw.display_name ?? raw.id,
4365
+ auth_type: auth.type ?? "",
4366
+ secret_name: auth.secret_name,
4367
+ mcp_server_url: auth.mcp_server_url,
4368
+ networking_type: networking?.type,
4369
+ networking,
4370
+ injection_location: auth.injection_location,
4371
+ metadata: metadata ? Object.fromEntries(
4372
+ Object.entries(metadata).filter((entry) => typeof entry[1] === "string")
4373
+ ) : void 0
4374
+ };
4375
+ });
4260
4376
  }
4261
4377
  async getCredential(vaultId, credentialId) {
4262
4378
  return await this.client.get(`/vaults/${vaultId}/credentials/${credentialId}`);
@@ -4306,11 +4422,7 @@ var BailianAdapter = class _BailianAdapter {
4306
4422
  throw new UserError(`Deployment '${ctx.name}' has no remote id; run \`agents apply\` first.`);
4307
4423
  }
4308
4424
  const res = await this.client.post(`/deployments/${ctx.id}/run`, {});
4309
- return {
4310
- run_id: res.id,
4311
- session_id: res.session_id ?? null,
4312
- error: res.error ?? void 0
4313
- };
4425
+ return toDeploymentRunResult(res);
4314
4426
  }
4315
4427
  async getDeployment(ctx) {
4316
4428
  if (!ctx.id) {
@@ -4322,6 +4434,7 @@ var BailianAdapter = class _BailianAdapter {
4322
4434
  async listDeployments(filter) {
4323
4435
  const params = new URLSearchParams();
4324
4436
  if (filter?.agent_id) params.set("agent_id", filter.agent_id);
4437
+ if (filter?.keyword) params.set("keyword", filter.keyword);
4325
4438
  if (filter?.status) params.set("status", filter.status);
4326
4439
  if (filter?.include_archived) params.set("include_archived", "true");
4327
4440
  if (filter?.limit) params.set("limit", String(filter.limit));
@@ -4337,6 +4450,32 @@ var BailianAdapter = class _BailianAdapter {
4337
4450
  next_page: nextPage
4338
4451
  };
4339
4452
  }
4453
+ async getDeploymentById(id) {
4454
+ const res = await this.client.get(`/deployments/${id}`);
4455
+ return toDeploymentInfo3(res);
4456
+ }
4457
+ async runDeploymentById(id) {
4458
+ const res = await this.client.post(`/deployments/${id}/run`, {});
4459
+ return toDeploymentRunResult(res);
4460
+ }
4461
+ async pauseDeploymentById(id) {
4462
+ const res = await this.client.post(`/deployments/${id}/pause`, {});
4463
+ return toDeploymentInfo3(res);
4464
+ }
4465
+ async unpauseDeploymentById(id) {
4466
+ const res = await this.client.post(`/deployments/${id}/unpause`, {});
4467
+ return toDeploymentInfo3(res);
4468
+ }
4469
+ async listDeploymentRuns(deploymentId, options) {
4470
+ const res = await this.client.get(
4471
+ withQuery(`/deployments/${deploymentId}/runs`, cursorParams(options))
4472
+ );
4473
+ return cursorPage(res, toDeploymentRunInfo);
4474
+ }
4475
+ async getDeploymentRun(runId) {
4476
+ const res = await this.client.get(`/deployment_runs/${runId}`);
4477
+ return toDeploymentRunInfo(res);
4478
+ }
4340
4479
  async pauseDeployment(ctx) {
4341
4480
  return this.setDeploymentPaused(ctx, true);
4342
4481
  }
@@ -4391,6 +4530,9 @@ var BailianAdapter = class _BailianAdapter {
4391
4530
  async listSessions(filter) {
4392
4531
  const params = new URLSearchParams();
4393
4532
  if (filter?.agent_id) params.set("agent_id", filter.agent_id);
4533
+ for (const status of filter?.statuses ?? []) params.append("statuses[]", status);
4534
+ if (filter?.created_at_gte) params.set("created_at[gte]", filter.created_at_gte);
4535
+ if (filter?.created_at_lte) params.set("created_at[lte]", filter.created_at_lte);
4394
4536
  if (filter?.limit) params.set("limit", String(filter.limit));
4395
4537
  if (filter?.page) params.set("page", filter.page);
4396
4538
  const qs = params.toString();
@@ -4407,6 +4549,15 @@ var BailianAdapter = class _BailianAdapter {
4407
4549
  const res = await this.client.get(`/sessions/${id}`);
4408
4550
  return toSessionInfo3(res);
4409
4551
  }
4552
+ async updateSession(id, input) {
4553
+ const res = await this.client.post(`/sessions/${id}`, input);
4554
+ if (!res.agent || !res.environment_id) return this.getSession(id);
4555
+ return toSessionInfo3(res);
4556
+ }
4557
+ async archiveSession(id) {
4558
+ const res = await this.client.post(`/sessions/${id}/archive`, {});
4559
+ return toSessionInfo3(res);
4560
+ }
4410
4561
  async deleteSession(id) {
4411
4562
  await this.client.delete(`/sessions/${id}`);
4412
4563
  }
@@ -4415,13 +4566,20 @@ var BailianAdapter = class _BailianAdapter {
4415
4566
  const res = await this.client.post(`/sessions/${sessionId}/events`, body);
4416
4567
  return extractCreatedEventId(res);
4417
4568
  }
4569
+ async sendSessionEvents(sessionId, events) {
4570
+ const res = await this.client.post(`/sessions/${sessionId}/events`, { input: events });
4571
+ return {
4572
+ event_ids: extractCreatedEventIds(res),
4573
+ attributes: res
4574
+ };
4575
+ }
4418
4576
  async *streamSessionEvents(sessionId, _options) {
4419
4577
  for await (const raw of this.client.sse(`/sessions/${sessionId}/events/stream`)) {
4420
4578
  yield toSessionEvent(raw);
4421
4579
  }
4422
4580
  }
4423
4581
  async listSessionEvents(sessionId, options) {
4424
- return listSessionEventsPaged(this.client, sessionId, options, toSessionEvent);
4582
+ return listSessionEventsPaged(this.client, sessionId, options, toSessionEvent, { forwardTypes: false });
4425
4583
  }
4426
4584
  // --- Files ---
4427
4585
  async uploadFile(filePath, options) {
@@ -4447,6 +4605,15 @@ var BailianAdapter = class _BailianAdapter {
4447
4605
  const all = await this.client.getAllPaged("/files");
4448
4606
  return all.map(toRestFileInfo);
4449
4607
  }
4608
+ async listFileResources(options) {
4609
+ const params = cursorParams(options);
4610
+ if (options?.scope_id) params.set("scope_id", options.scope_id);
4611
+ const res = await this.client.get(withQuery("/files", params));
4612
+ return cursorPage(res, toRestFileInfo);
4613
+ }
4614
+ async downloadFileContent(id) {
4615
+ return new Uint8Array(await this.client.getBuffer(`/files/${id}/content`));
4616
+ }
4450
4617
  async deleteFile(id) {
4451
4618
  await this.client.delete(`/files/${id}`);
4452
4619
  }
@@ -4481,9 +4648,77 @@ function toBailianSkillInfo(res) {
4481
4648
  status: skillStatusFromString(res.status),
4482
4649
  latest_version: res.latest_version,
4483
4650
  created_at: res.created_at,
4484
- updated_at: res.updated_at
4651
+ updated_at: res.updated_at,
4652
+ attributes: res
4653
+ };
4654
+ }
4655
+ function cursorParams(options) {
4656
+ const params = new URLSearchParams();
4657
+ if (options?.limit !== void 0) params.set("limit", String(options.limit));
4658
+ if (options?.page) params.set("page", options.page);
4659
+ return params;
4660
+ }
4661
+ function withQuery(path, params) {
4662
+ const query2 = params.toString();
4663
+ return query2 ? `${path}?${query2}` : path;
4664
+ }
4665
+ function cursorPage(res, mapper) {
4666
+ const nextPage = res.next_page ?? void 0;
4667
+ return {
4668
+ data: (res.data ?? []).map(mapper),
4669
+ has_more: res.has_more ?? nextPage !== void 0,
4670
+ next_page: nextPage
4671
+ };
4672
+ }
4673
+ function toSkillVersionInfo(res) {
4674
+ return {
4675
+ id: res.id,
4676
+ skill_id: res.skill_id ?? "",
4677
+ type: res.type ?? "skill_version",
4678
+ name: res.name,
4679
+ description: res.description,
4680
+ version: res.version ?? "",
4681
+ status: res.status,
4682
+ created_at: res.created_at,
4683
+ updated_at: res.updated_at,
4684
+ additional_properties: res.additional_properties,
4685
+ attributes: res
4686
+ };
4687
+ }
4688
+ function toDeploymentRunResult(res) {
4689
+ return {
4690
+ run_id: res.id,
4691
+ session_id: res.session_id ?? null,
4692
+ error: res.error ?? void 0
4693
+ };
4694
+ }
4695
+ function toDeploymentRunInfo(res) {
4696
+ return {
4697
+ id: res.id ?? "",
4698
+ deployment_id: res.deployment_id,
4699
+ session_id: res.session_id ?? void 0,
4700
+ status: res.status,
4701
+ error: res.error ?? void 0,
4702
+ created_at: res.created_at,
4703
+ updated_at: res.updated_at,
4704
+ attributes: res
4485
4705
  };
4486
4706
  }
4707
+ function extractCreatedEventIds(res) {
4708
+ const ids = /* @__PURE__ */ new Set();
4709
+ const topLevel = extractCreatedEventId(res);
4710
+ if (topLevel) ids.add(topLevel);
4711
+ for (const key of ["data", "events"]) {
4712
+ const items = res[key];
4713
+ if (!Array.isArray(items)) continue;
4714
+ for (const item of items) {
4715
+ if (!item || typeof item !== "object") continue;
4716
+ const id = item.id;
4717
+ if (typeof id === "string") ids.add(id);
4718
+ }
4719
+ }
4720
+ return Array.from(ids);
4721
+ }
4487
4722
  function normalizeBailianModel(value) {
4488
4723
  if (value && typeof value === "object" && "id" in value) {
4489
4724
  return value.id;
@@ -4548,7 +4783,7 @@ function guessMimeType(fileName) {
4548
4783
  // src/internal/providers/bailian/capabilities.ts
4549
4784
  var BAILIAN_CAPABILITIES = {
4550
4785
  environment: { tier: "native", reason: "environments API" },
4551
- vault: { tier: "native", reason: "vaults + credentials API (static_bearer MCP credentials)" },
4786
+ vault: { tier: "native", reason: "vaults + environment_variable credentials API" },
4552
4787
  skill: { tier: "native", reason: "skills API with 2-step zip upload via Files API" },
4553
4788
  agent: { tier: "native", reason: "agents API with versioned updates" },
4554
4789
  template: { tier: "unsupported", reason: "no Forward Template equivalent on Bailian" },
@@ -4809,7 +5044,7 @@ function mapAgent4(name, decl, refs, version, projectName) {
4809
5044
  if (!arkModel) throw new UserError(`No Ark model specified for agent '${name}'`);
4810
5045
  const modelValue = typeof arkModel === "string" ? { id: arkModel } : { id: arkModel.id };
4811
5046
  const body = {
4812
- name,
5047
+ name: decl.name ?? name,
4813
5048
  model: modelValue,
4814
5049
  system: decl.instructions
4815
5050
  };
@@ -5499,6 +5734,30 @@ async function resolveFileReferences(config, configPath) {
5499
5734
  // src/internal/parser/resolve-project-config.ts
5500
5735
  import { basename as basename5, dirname as dirname7, resolve as resolve7 } from "path";
5501
5736
 
5737
+ // src/internal/utils/env.ts
5738
+ var ENV_VAR_PATTERN = /\$\{([^}]+)\}/g;
5739
+ function interpolateEnvVars(value, resolve13 = false, environment = process.env) {
5740
+ return value.replace(ENV_VAR_PATTERN, (match, varName) => {
5741
+ if (!resolve13) return match;
5742
+ const resolvedValue = environment[varName];
5743
+ if (resolvedValue === void 0) {
5744
+ throw new UserError(`Environment variable '${varName}' is not set`);
5745
+ }
5746
+ return resolvedValue;
5747
+ });
5748
+ }
5749
+ function interpolateObjectEnv(value, environment = process.env) {
5750
+ if (typeof value === "string") return interpolateEnvVars(value, true, environment);
5751
+ if (Array.isArray(value)) return value.map((entry) => interpolateObjectEnv(entry, environment));
5752
+ if (!value || typeof value !== "object") return value;
5753
+ return Object.fromEntries(
5754
+ Object.entries(value).map(([key, entry]) => [
5755
+ key,
5756
+ interpolateObjectEnv(entry, environment)
5757
+ ])
5758
+ );
5759
+ }
5760
+
5502
5761
  // src/internal/parser/schema.ts
5503
5762
  import { z as z5 } from "zod";
5504
5763
  var networkingSchema = z5.object({
@@ -5543,6 +5802,7 @@ var coerceString = z5.union([z5.string(), z5.number()]).transform(String);
5543
5802
  var staticBearerCredentialSchema = z5.object({
5544
5803
  name: z5.string(),
5545
5804
  type: z5.literal("static_bearer"),
5805
+ metadata: z5.record(z5.string(), z5.string()).optional(),
5546
5806
  mcp_server_url: z5.string(),
5547
5807
  access_token: coerceString,
5548
5808
  protocol: z5.enum(["sse", "streamable_http"]).optional()
@@ -5550,9 +5810,17 @@ var staticBearerCredentialSchema = z5.object({
5550
5810
  var environmentVariableCredentialSchema = z5.object({
5551
5811
  name: z5.string(),
5552
5812
  type: z5.literal("environment_variable"),
5813
+ metadata: z5.record(z5.string(), z5.string()).optional(),
5553
5814
  secret_name: z5.string(),
5554
5815
  secret_value: coerceString,
5555
- networking: z5.object({ type: z5.enum(["unrestricted", "limited"]) }).optional()
5816
+ networking: z5.object({
5817
+ type: z5.enum(["unrestricted", "limited"]).optional(),
5818
+ allowed_hosts: z5.array(z5.string()).optional()
5819
+ }).optional(),
5820
+ injection_location: z5.object({
5821
+ header: z5.boolean().optional(),
5822
+ body: z5.boolean().optional()
5823
+ }).optional()
5556
5824
  });
5557
5825
  var credentialSchema = z5.discriminatedUnion("type", [
5558
5826
  staticBearerCredentialSchema,
@@ -5692,6 +5960,10 @@ var agentSkillRefSchema = z5.object({
5692
5960
  var agentDeliverySchema = z5.object({
5693
5961
  type: z5.enum(["managed", "forward"])
5694
5962
  });
5963
+ var agentFileMountSchema = z5.object({
5964
+ file: z5.string().min(1),
5965
+ mount_path: z5.string().min(1)
5966
+ });
5695
5967
  var managedToolConfigSchema = z5.object({
5696
5968
  enabled_tools: z5.array(z5.string().min(1))
5697
5969
  });
@@ -5716,8 +5988,8 @@ var agentSchema = z5.object({
5716
5988
  mcp_servers: z5.array(mcpServerSchema).optional(),
5717
5989
  skills: z5.array(z5.union([z5.string(), agentSkillRefSchema])).optional(),
5718
5990
  vault: z5.string().optional(),
5719
- files: z5.array(z5.string()).optional(),
5720
5991
  memory_stores: z5.array(z5.string()).optional(),
5992
+ files: z5.array(z5.union([z5.string().min(1), agentFileMountSchema])).optional(),
5721
5993
  default_memory_store: z5.object({
5722
5994
  name: z5.string().trim().min(1).max(255),
5723
5995
  description: z5.string().max(1024).optional(),
@@ -5783,6 +6055,7 @@ var scheduleSchema = z5.object({
5783
6055
  timezone: z5.string()
5784
6056
  });
5785
6057
  var deploymentSchema = z5.object({
6058
+ name: z5.string().optional(),
5786
6059
  agent: z5.string(),
5787
6060
  agent_version: z5.number().int().optional(),
5788
6061
  environment: z5.string().optional(),
@@ -5819,22 +6092,7 @@ var projectConfigSchema = z5.object({
5819
6092
  // src/internal/parser/yaml-loader.ts
5820
6093
  import { readFile as readFile3 } from "fs/promises";
5821
6094
  import { parse as parseYaml } from "yaml";
5822
-
5823
- // src/internal/utils/env.ts
5824
- var ENV_VAR_PATTERN = /\$\{([^}]+)\}/g;
5825
- function interpolateEnvVars(value, resolve13 = false) {
5826
- return value.replace(ENV_VAR_PATTERN, (match, varName) => {
5827
- if (!resolve13) return match;
5828
- const val = process.env[varName];
5829
- if (val === void 0) {
5830
- throw new UserError(`Environment variable '${varName}' is not set`);
5831
- }
5832
- return val;
5833
- });
5834
- }
5835
-
5836
- // src/internal/parser/yaml-loader.ts
5837
- async function loadConfig(filePath, resolveEnv = false) {
6095
+ async function loadConfig(filePath, resolveEnv = false, environment) {
5838
6096
  let raw;
5839
6097
  try {
5840
6098
  raw = await readFile3(filePath, "utf8");
@@ -5845,7 +6103,7 @@ async function loadConfig(filePath, resolveEnv = false) {
5845
6103
  const msg = err instanceof Error ? err.message : String(err);
5846
6104
  return { config: null, errors: [`Failed to read file: ${msg}`] };
5847
6105
  }
5848
- if (resolveEnv) {
6106
+ if (resolveEnv && !environment) {
5849
6107
  raw = interpolateEnvVars(raw, true);
5850
6108
  }
5851
6109
  let parsed;
@@ -5855,6 +6113,7 @@ async function loadConfig(filePath, resolveEnv = false) {
5855
6113
  const msg = e instanceof Error ? e.message : String(e);
5856
6114
  return { config: null, errors: [`YAML parse error: ${msg}`] };
5857
6115
  }
6116
+ if (resolveEnv && environment) parsed = interpolateObjectEnv(parsed, environment);
5858
6117
  const result = projectConfigSchema.safeParse(parsed);
5859
6118
  if (!result.success) {
5860
6119
  const errors = result.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`);
@@ -5867,27 +6126,73 @@ async function loadConfig(filePath, resolveEnv = false) {
5867
6126
  async function resolveProjectConfig(filePath, options = {}) {
5868
6127
  const configPath = resolve7(filePath);
5869
6128
  const projectName = options.projectName ?? basename5(dirname7(configPath));
5870
- const { config: parsed, errors } = await loadConfig(configPath, options.resolveEnv ?? true);
6129
+ const { config: parsed, errors } = await loadConfig(
6130
+ configPath,
6131
+ options.resolveEnv ?? true,
6132
+ options.environment ? { ...options.environment, ...process.env } : void 0
6133
+ );
5871
6134
  if (errors.length > 0) {
5872
6135
  throw new UserError(errors.join("\n"));
5873
6136
  }
5874
- const config = await resolveFileReferences(parsed, configPath);
5875
- return { configPath, projectName, config };
6137
+ const sourcePaths = collectProjectSourcePaths(parsed, configPath, true);
6138
+ let config;
6139
+ try {
6140
+ config = await resolveFileReferences(parsed, configPath);
6141
+ } catch (error) {
6142
+ if (error && typeof error === "object") {
6143
+ Object.assign(error, { sourcePaths });
6144
+ }
6145
+ throw error;
6146
+ }
6147
+ return { configPath, projectName, config, sourcePaths };
5876
6148
  }
5877
6149
  async function resolveProjectConfigFromObject(rawConfig, options) {
5878
6150
  const basePath = resolve7(options.basePath ?? process.cwd());
5879
- const result = projectConfigSchema.safeParse(rawConfig);
6151
+ const input = options.resolveEnv ? interpolateObjectEnv(rawConfig, { ...options.environment, ...process.env }) : rawConfig;
6152
+ const result = projectConfigSchema.safeParse(input);
5880
6153
  if (!result.success) {
5881
6154
  const errors = result.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`);
5882
6155
  throw new UserError(errors.join("\n"));
5883
6156
  }
5884
6157
  const anchor = resolve7(basePath, "__in_memory_config__");
5885
- const config = await resolveFileReferences(result.data, anchor);
5886
- return { configPath: basePath, projectName: options.projectName, config };
6158
+ const parsed = result.data;
6159
+ const sourcePaths = collectProjectSourcePaths(parsed, anchor, false);
6160
+ const config = await resolveFileReferences(parsed, anchor);
6161
+ return { configPath: basePath, projectName: options.projectName, config, sourcePaths };
6162
+ }
6163
+ function collectProjectSourcePaths(config, configPath, includeConfigPath) {
6164
+ const baseDirectory = dirname7(configPath);
6165
+ const paths = /* @__PURE__ */ new Set();
6166
+ if (includeConfigPath) paths.add(configPath);
6167
+ const addLocalPath = (value, requirePathSyntax = false) => {
6168
+ if (!value || /^https?:\/\//i.test(value)) return;
6169
+ if (requirePathSyntax && !isLocalPathReference(value)) return;
6170
+ paths.add(resolve7(baseDirectory, value));
6171
+ };
6172
+ for (const agent of Object.values(config.agents ?? {})) {
6173
+ addLocalPath(agent.instructions, true);
6174
+ }
6175
+ for (const store of Object.values(config.memory_stores ?? {})) {
6176
+ for (const entry of store.entries ?? []) addLocalPath(entry.content, true);
6177
+ }
6178
+ for (const skill of Object.values(config.skills ?? {})) addLocalPath(skill.source);
6179
+ for (const file of Object.values(config.files ?? {})) addLocalPath(file.source);
6180
+ for (const deployment of Object.values(config.deployments ?? {})) {
6181
+ for (const resource of deployment.resources ?? []) {
6182
+ if (resource.type === "file") addLocalPath(resource.source);
6183
+ }
6184
+ for (const event of deployment.initial_events ?? []) {
6185
+ if (event.type === "user.define_outcome") addLocalPath(event.rubric_file, true);
6186
+ }
6187
+ }
6188
+ return [...paths].sort();
6189
+ }
6190
+ function isLocalPathReference(value) {
6191
+ return value.startsWith("./") || value.startsWith("../") || value.startsWith("/");
5887
6192
  }
5888
6193
 
5889
6194
  // src/internal/executor/executor.ts
5890
- import { dirname as dirname10, resolve as resolve11 } from "path";
6195
+ import { basename as basename7, dirname as dirname10, resolve as resolve11 } from "path";
5891
6196
 
5892
6197
  // src/internal/utils/hash.ts
5893
6198
  import { createHash } from "crypto";
@@ -6001,8 +6306,9 @@ async function computeResourceHash(address, config, basePath, state) {
6001
6306
  }
6002
6307
  if (address.type === "template") {
6003
6308
  const refs = resolveTemplateReferenceIds(decl, config, address.provider, state);
6004
- return contentHash({ decl, refs });
6309
+ return contentHash({ decl: withoutLocalSessionFileMounts(decl), refs });
6005
6310
  }
6311
+ if (address.type === "agent") return contentHash(withoutLocalSessionFileMounts(decl));
6006
6312
  if (address.type === "channel") {
6007
6313
  const refs = resolveChannelReferenceIds(
6008
6314
  decl,
@@ -6014,6 +6320,12 @@ async function computeResourceHash(address, config, basePath, state) {
6014
6320
  }
6015
6321
  return contentHash(decl);
6016
6322
  }
6323
+ function withoutLocalSessionFileMounts(decl) {
6324
+ if (!decl || typeof decl !== "object" || Array.isArray(decl)) return decl;
6325
+ const { files, ...remoteDeclaration } = decl;
6326
+ const templateFiles = Array.isArray(files) ? files.filter((file) => typeof file === "string") : [];
6327
+ return templateFiles.length ? { ...remoteDeclaration, files: templateFiles } : remoteDeclaration;
6328
+ }
6017
6329
  function resolveQoderApiMode(type, name, provider, config) {
6018
6330
  if (provider !== "qoder") return void 0;
6019
6331
  if (type === "environment" && config.environments?.[name]?.environment_id) return "auto";
@@ -6021,7 +6333,7 @@ function resolveQoderApiMode(type, name, provider, config) {
6021
6333
  if (agent.provider && agent.provider !== provider) continue;
6022
6334
  const referenced = type === "environment" ? agent.environment === name : type === "skill" ? agent.skills?.some(
6023
6335
  (skill) => typeof skill === "string" ? skill === name : skill.type === "custom" && skill.skill_id === name
6024
- ) : type === "vault" ? agent.vault === name : type === "memory_store" ? agent.memory_stores?.includes(name) : agent.files?.includes(name);
6336
+ ) : type === "vault" ? agent.vault === name : type === "memory_store" ? agent.memory_stores?.includes(name) : agent.files?.some((file) => (typeof file === "string" ? file : file.file) === name);
6025
6337
  if (referenced && agent.delivery?.qoder?.type === "forward") return "forward";
6026
6338
  }
6027
6339
  return "managed";
@@ -6062,9 +6374,7 @@ function resolveTemplateReferenceIds(decl, config, provider, state) {
6062
6374
  memory_store_ids: (decl.memory_stores ?? []).map(
6063
6375
  (memoryStore) => state?.getResource({ type: "memory_store", name: memoryStore, provider })?.remote_id ?? memoryStore
6064
6376
  ),
6065
- file_ids: (decl.files ?? []).map(
6066
- (file) => state?.getResource({ type: "file", name: file, provider })?.remote_id ?? file
6067
- ),
6377
+ file_ids: (decl.files ?? []).filter((file) => typeof file === "string").map((file) => state?.getResource({ type: "file", name: file, provider })?.remote_id ?? file),
6068
6378
  identity_id: decl.memory_stores?.length && config.defaults?.identity ? state?.getResource({ type: "identity", name: config.defaults.identity, provider })?.remote_id : void 0
6069
6379
  };
6070
6380
  }
@@ -6254,7 +6564,7 @@ function resolveTemplateRefs(agentName, config, provider, state) {
6254
6564
  environment_id: environment.environment_id ?? requireRef(state, { type: "environment", name: agent.environment, provider }),
6255
6565
  ...agent.tunnel ? { tunnel_id: resolveTunnelIdFromConfig(config, agent.tunnel, provider) } : {},
6256
6566
  vault_ids: agent.vault ? [requireRef(state, { type: "vault", name: agent.vault, provider })] : [],
6257
- file_ids: (agent.files ?? []).map((file) => requireRef(state, { type: "file", name: file, provider })),
6567
+ file_ids: (agent.files ?? []).filter((file) => typeof file === "string").map((file) => requireRef(state, { type: "file", name: file, provider })),
6258
6568
  memory_store_ids: memoryStoreIds,
6259
6569
  owned_memory_store_ids: state.listResources().filter(
6260
6570
  (resource) => resource.address.provider === provider && resource.address.type === "memory_store" && resource.api_mode === "forward" && typeof resource.remote_id === "string"
@@ -6350,8 +6660,61 @@ function resolveTunnelIdFromConfig(config, tunnelName, provider) {
6350
6660
  }
6351
6661
 
6352
6662
  // src/internal/executor/skill-resolver.ts
6663
+ import { dirname as dirname9 } from "path";
6664
+
6665
+ // src/internal/core/skill-source.ts
6353
6666
  import { readFileSync as readFileSync7, statSync as statSync3 } from "fs";
6354
- import { dirname as dirname9, resolve as resolve10 } from "path";
6667
+ import { basename as basename6, resolve as resolve10 } from "path";
6668
+ import { parse } from "yaml";
6669
+ async function inspectSkillSource(source, options = {}) {
6670
+ if (/^https?:\/\//i.test(source)) {
6671
+ throw new UserError("Skill source inspection only accepts a local directory, zip, or SKILL.md file.");
6672
+ }
6673
+ const sourcePath = resolve10(options.basePath ?? process.cwd(), source);
6674
+ const sourceStat = statSync3(sourcePath, { throwIfNoEntry: false });
6675
+ if (!sourceStat) throw new UserError(`Skill source not found: ${source}`);
6676
+ let files;
6677
+ if (sourceStat.isDirectory()) {
6678
+ files = collectFiles(sourcePath, "");
6679
+ } else if (sourceStat.isFile() && sourcePath.toLowerCase().endsWith(".zip")) {
6680
+ files = await extractSkillZipFiles(readFileSync7(sourcePath));
6681
+ } else if (sourceStat.isFile() && basename6(sourcePath).toLowerCase() === "skill.md") {
6682
+ files = [{ relativePath: "SKILL.md", content: readFileSync7(sourcePath) }];
6683
+ } else {
6684
+ throw new UserError("Skill source must be a directory, .zip archive, or SKILL.md file.");
6685
+ }
6686
+ const normalizedFiles = normalizeSkillRoot(files);
6687
+ const manifest = normalizedFiles.find((file) => file.relativePath === "SKILL.md");
6688
+ const name = parseSkillManifestName(manifest.content);
6689
+ return { name, sourcePath, files: normalizedFiles };
6690
+ }
6691
+ function normalizeSkillRoot(files) {
6692
+ if (files.some((file) => file.relativePath === "SKILL.md")) return files;
6693
+ const manifests = files.filter((file) => file.relativePath.endsWith("/SKILL.md"));
6694
+ if (manifests.length === 0) throw new UserError("Skill source does not contain SKILL.md.");
6695
+ if (manifests.length > 1) {
6696
+ throw new UserError("Skill source contains multiple SKILL.md files and has no unambiguous root.");
6697
+ }
6698
+ const prefix = manifests[0].relativePath.slice(0, -"SKILL.md".length);
6699
+ return files.filter((file) => file.relativePath.startsWith(prefix)).map((file) => ({ ...file, relativePath: file.relativePath.slice(prefix.length) }));
6700
+ }
6701
+ function parseSkillManifestName(content) {
6702
+ const text = content.toString("utf8");
6703
+ const frontmatter = text.match(/^---\s*\r?\n([\s\S]*?)\r?\n---(?:\s*\r?\n|$)/);
6704
+ if (!frontmatter) throw new UserError("SKILL.md must start with YAML frontmatter containing a name.");
6705
+ let manifest;
6706
+ try {
6707
+ manifest = parse(frontmatter[1]);
6708
+ } catch (error) {
6709
+ throw new UserError(`Invalid SKILL.md frontmatter: ${error instanceof Error ? error.message : String(error)}`);
6710
+ }
6711
+ const rawName = manifest && typeof manifest === "object" ? manifest.name : void 0;
6712
+ const name = typeof rawName === "string" ? rawName.trim() : "";
6713
+ if (!name) throw new UserError("SKILL.md frontmatter must contain a non-empty name.");
6714
+ return name;
6715
+ }
6716
+
6717
+ // src/internal/executor/skill-resolver.ts
6355
6718
  async function resolveSkillFiles(decl, ctx) {
6356
6719
  if (/^https?:\/\//i.test(decl.source)) {
6357
6720
  const res = await resolveFetch()(decl.source);
@@ -6359,19 +6722,7 @@ async function resolveSkillFiles(decl, ctx) {
6359
6722
  return extractSkillZipFiles(Buffer.from(await res.arrayBuffer()));
6360
6723
  }
6361
6724
  if (!ctx.configPath) return [];
6362
- const sourcePath = resolve10(dirname9(ctx.configPath), decl.source);
6363
- const stat = statSync3(sourcePath, { throwIfNoEntry: false });
6364
- if (stat?.isDirectory()) {
6365
- return collectFiles(sourcePath, "");
6366
- }
6367
- if (stat?.isFile()) {
6368
- if (sourcePath.endsWith(".zip")) {
6369
- return extractSkillZipFiles(readFileSync7(sourcePath));
6370
- }
6371
- const content = readFileSync7(sourcePath);
6372
- return [{ relativePath: "SKILL.md", content }];
6373
- }
6374
- return [];
6725
+ return (await inspectSkillSource(decl.source, { basePath: dirname9(ctx.configPath) })).files;
6375
6726
  }
6376
6727
 
6377
6728
  // src/internal/executor/executor.ts
@@ -6449,7 +6800,9 @@ async function executePlan(plan, ctx, options = {}) {
6449
6800
  await runWithConcurrency(level, concurrency, runAction);
6450
6801
  await ctx.state.save();
6451
6802
  }
6452
- await reconcileDefaultMemoryStores(ctx, new Set(plan.actions.map((action) => action.address.provider)));
6803
+ if (!ctx.createOnly) {
6804
+ await reconcileDefaultMemoryStores(ctx, new Set(plan.actions.map((action) => action.address.provider)));
6805
+ }
6453
6806
  for (const action of deletions) {
6454
6807
  await runAction(action);
6455
6808
  await ctx.state.save();
@@ -6661,6 +7014,7 @@ async function executeActionInner(action, provider, ctx) {
6661
7014
  } catch (err) {
6662
7015
  result = await adoptOnConflict(err, address, provider, ctx.onFeedback, {
6663
7016
  mode: apiMode,
7017
+ createOnly: ctx.createOnly,
6664
7018
  onExisting: (existing) => provider.updateEnvironment(existing.id, remoteName, decl, apiMode)
6665
7019
  });
6666
7020
  adopted = true;
@@ -6680,6 +7034,7 @@ async function executeActionInner(action, provider, ctx) {
6680
7034
  } catch (err) {
6681
7035
  result = await adoptOnConflict(err, address, provider, ctx.onFeedback, {
6682
7036
  mode: apiMode,
7037
+ createOnly: ctx.createOnly,
6683
7038
  onExisting: (existing) => provider.updateEnvironment(existing.id, remoteName, decl, apiMode)
6684
7039
  });
6685
7040
  adopted = true;
@@ -6706,6 +7061,7 @@ async function executeActionInner(action, provider, ctx) {
6706
7061
  } catch (err) {
6707
7062
  result = await adoptOnConflict(err, address, provider, ctx.onFeedback, {
6708
7063
  mode: apiMode,
7064
+ createOnly: ctx.createOnly,
6709
7065
  onExisting: async (existing) => {
6710
7066
  await provider.deleteVault(existing.id, apiMode);
6711
7067
  return provider.createVault(name, decl, apiMode);
@@ -6742,6 +7098,7 @@ async function executeActionInner(action, provider, ctx) {
6742
7098
  const searchNames = manifestName && manifestName !== remoteName ? [remoteName, manifestName] : [remoteName];
6743
7099
  const existing = await findExistingByNames(provider, "skill", searchNames, apiMode);
6744
7100
  if (existing) {
7101
+ if (ctx.createOnly) throw createOnlyExistingResourceError(address, existing.name);
6745
7102
  result = existing.resource;
6746
7103
  emitRuntimeFeedback(ctx.onFeedback, {
6747
7104
  type: "resource_adopted",
@@ -6757,6 +7114,7 @@ async function executeActionInner(action, provider, ctx) {
6757
7114
  result = await adoptOnConflict(err, address, provider, ctx.onFeedback, {
6758
7115
  mode: apiMode,
6759
7116
  searchNames,
7117
+ createOnly: ctx.createOnly,
6760
7118
  onExisting: async (existing2) => existing2
6761
7119
  });
6762
7120
  adopted = true;
@@ -6823,6 +7181,7 @@ async function executeActionInner(action, provider, ctx) {
6823
7181
  } catch (err) {
6824
7182
  result = await adoptOnConflict(err, address, provider, ctx.onFeedback, {
6825
7183
  mode: apiMode,
7184
+ createOnly: ctx.createOnly,
6826
7185
  onExisting: async (existing) => reconcile(existing.id)
6827
7186
  });
6828
7187
  adopted = true;
@@ -6841,6 +7200,7 @@ async function executeActionInner(action, provider, ctx) {
6841
7200
  result = await provider.createAgent(remoteName, decl, refs);
6842
7201
  } catch (err) {
6843
7202
  result = await adoptOnConflict(err, address, provider, ctx.onFeedback, {
7203
+ createOnly: ctx.createOnly,
6844
7204
  onExisting: (existing) => provider.updateAgent(existing.id, remoteName, decl, refs)
6845
7205
  });
6846
7206
  adopted = true;
@@ -6864,6 +7224,7 @@ async function executeActionInner(action, provider, ctx) {
6864
7224
  result = await createTemplate(remoteName, decl, refs);
6865
7225
  } catch (err) {
6866
7226
  result = await adoptOnConflict(err, address, provider, ctx.onFeedback, {
7227
+ createOnly: ctx.createOnly,
6867
7228
  onExisting: (existing) => updateTemplate(existing.id, remoteName, decl, refs)
6868
7229
  });
6869
7230
  adopted = true;
@@ -6898,6 +7259,7 @@ async function executeActionInner(action, provider, ctx) {
6898
7259
  result = await createIdentity(name, decl);
6899
7260
  } catch (err) {
6900
7261
  if (!(err instanceof ConflictError)) throw err;
7262
+ if (ctx.createOnly) throw createOnlyExistingResourceError(address);
6901
7263
  const existing = await provider.findResource("identity", decl.external_id);
6902
7264
  if (!existing?.id) throw err;
6903
7265
  result = await updateIdentity(existing.id, name, decl);
@@ -6921,6 +7283,7 @@ async function executeActionInner(action, provider, ctx) {
6921
7283
  result = await createChannel(name, decl, refs);
6922
7284
  } catch (err) {
6923
7285
  result = await adoptOnConflict(err, address, provider, ctx.onFeedback, {
7286
+ createOnly: ctx.createOnly,
6924
7287
  onExisting: (existing) => updateChannel(existing.id, name, decl, refs)
6925
7288
  });
6926
7289
  adopted = true;
@@ -6940,6 +7303,7 @@ async function executeActionInner(action, provider, ctx) {
6940
7303
  } catch (err) {
6941
7304
  const preparedFiles = err instanceof DeploymentCreateConflictError ? err.preparedFiles : void 0;
6942
7305
  const existing = await adoptOnConflict(err, address, provider, ctx.onFeedback, {
7306
+ createOnly: ctx.createOnly,
6943
7307
  onExisting: (existing2) => provider.updateDeployment(existing2.id, name, decl, refs, ctx.configPath ?? "", preparedFiles)
6944
7308
  });
6945
7309
  adopted = true;
@@ -6951,6 +7315,7 @@ async function executeActionInner(action, provider, ctx) {
6951
7315
  } else {
6952
7316
  const existing = hasLocalFileSources ? await findExistingByNames(provider, "deployment", [name]) : null;
6953
7317
  if (existing) {
7318
+ if (ctx.createOnly) throw createOnlyExistingResourceError(address, existing.name);
6954
7319
  result = await provider.updateDeployment(existing.resource.id, name, decl, refs, ctx.configPath ?? "");
6955
7320
  emitRuntimeFeedback(ctx.onFeedback, {
6956
7321
  type: "resource_adopted",
@@ -6977,7 +7342,16 @@ async function executeActionInner(action, provider, ctx) {
6977
7342
  }
6978
7343
  }
6979
7344
  }
6980
- const info = await provider.uploadFile(filePath, { name: decl.name, purpose: decl.purpose }, apiMode);
7345
+ const info = await provider.uploadFile(
7346
+ filePath,
7347
+ {
7348
+ // Keep the source filename and extension; a declaration label must not
7349
+ // change the multipart filename or the provider's inferred MIME type.
7350
+ name: basename7(filePath),
7351
+ purpose: decl.purpose
7352
+ },
7353
+ apiMode
7354
+ );
6981
7355
  result = { id: info.id, type: "file" };
6982
7356
  break;
6983
7357
  }
@@ -7029,7 +7403,7 @@ function resolveResourceApiMode(type, name, provider, config) {
7029
7403
  if (agent.provider && agent.provider !== provider) continue;
7030
7404
  const referenced = type === "environment" ? agent.environment === name : type === "skill" ? agent.skills?.some(
7031
7405
  (skill) => typeof skill === "string" ? skill === name : skill.type === "custom" && skill.skill_id === name
7032
- ) : type === "vault" ? agent.vault === name : type === "memory_store" ? agent.memory_stores?.includes(name) : agent.files?.includes(name);
7406
+ ) : type === "vault" ? agent.vault === name : type === "memory_store" ? agent.memory_stores?.includes(name) : agent.files?.some((file) => (typeof file === "string" ? file : file.file) === name);
7033
7407
  if (!referenced) continue;
7034
7408
  if (agent.delivery?.qoder?.type === "forward") forward = true;
7035
7409
  else managed = true;
@@ -7051,6 +7425,7 @@ async function findExistingByNames(provider, type, names, mode) {
7051
7425
  async function adoptOnConflict(err, address, provider, onFeedback, opts) {
7052
7426
  if (!(err instanceof ConflictError)) throw err;
7053
7427
  const candidates = opts.searchNames?.length ? opts.searchNames : [address.name];
7428
+ if (opts.createOnly) throw createOnlyExistingResourceError(address, candidates.join('" / "'));
7054
7429
  const existing = await findExistingByNames(provider, address.type, candidates, opts.mode);
7055
7430
  if (!existing) throw nameReservedError(err, address, candidates.join('" / "'));
7056
7431
  emitRuntimeFeedback(onFeedback, {
@@ -7061,6 +7436,11 @@ async function adoptOnConflict(err, address, provider, onFeedback, opts) {
7061
7436
  });
7062
7437
  return opts.onExisting(existing.resource);
7063
7438
  }
7439
+ function createOnlyExistingResourceError(address, remoteName = address.name) {
7440
+ return new UserError(
7441
+ `Create-only cannot adopt or reconcile existing ${address.type} "${remoteName}" on provider '${address.provider}'. Choose a new name, or use a normal apply/import workflow to manage the existing resource.`
7442
+ );
7443
+ }
7064
7444
  function nameReservedError(err, address, searchName) {
7065
7445
  const detail = err instanceof ApiError ? err.message : String(err);
7066
7446
  if (address.type === "channel" && err instanceof ApiError && err.responseBody.includes("CHANNEL_CREDENTIAL_CONFLICT")) {
@@ -7073,73 +7453,6 @@ function nameReservedError(err, address, searchName) {
7073
7453
  );
7074
7454
  }
7075
7455
 
7076
- // src/internal/diagnostics/diagnostics.ts
7077
- var DiagnosticCollector = class {
7078
- items = [];
7079
- error(code, message, resource) {
7080
- this.items.push({ severity: "error", code, message, resource });
7081
- }
7082
- warning(code, message, resource) {
7083
- this.items.push({ severity: "warning", code, message, resource });
7084
- }
7085
- info(code, message, resource) {
7086
- this.items.push({ severity: "info", code, message, resource });
7087
- }
7088
- hasErrors() {
7089
- return this.items.some((d) => d.severity === "error");
7090
- }
7091
- getAll() {
7092
- return [...this.items];
7093
- }
7094
- format() {
7095
- if (this.items.length === 0) return "";
7096
- const lines = [];
7097
- for (const d of this.items) {
7098
- const icon = severityIcon(d.severity);
7099
- const addr = d.resource ? ` ${d.resource.type}.${d.resource.name} (${d.resource.provider})` : "";
7100
- lines.push(`${icon} ${d.code}`);
7101
- if (addr) lines.push(` Resource:${addr}`);
7102
- lines.push(` ${d.message}`);
7103
- lines.push("");
7104
- }
7105
- return lines.join("\n");
7106
- }
7107
- };
7108
- function severityIcon(s) {
7109
- switch (s) {
7110
- case "error":
7111
- return "\u2717";
7112
- case "warning":
7113
- return "\u26A0";
7114
- case "info":
7115
- return "\u2139";
7116
- }
7117
- }
7118
-
7119
- // src/internal/validation/bailian.ts
7120
- function findMissingBailianMcpToolConfigs(config, providerName = "bailian") {
7121
- if (providerName !== "bailian") return [];
7122
- const missing = [];
7123
- for (const [agentName, agent] of Object.entries(config.agents ?? {})) {
7124
- if (!agentTargetsProvider(config, agent.provider, providerName)) continue;
7125
- const configuredToolServers = new Set((agent.tools?.mcp ?? []).map((tool) => tool.mcp_server_name));
7126
- for (const server of agent.mcp_servers ?? []) {
7127
- if (!configuredToolServers.has(server.name)) {
7128
- missing.push({ agentName, serverName: server.name });
7129
- }
7130
- }
7131
- }
7132
- return missing;
7133
- }
7134
- function agentTargetsProvider(config, agentProvider, providerName) {
7135
- if (agentProvider) return agentProvider === providerName;
7136
- const defaultProvider = config.defaults?.provider;
7137
- if (defaultProvider && defaultProvider !== "all") {
7138
- return defaultProvider === providerName;
7139
- }
7140
- return Object.hasOwn(config.providers, providerName);
7141
- }
7142
-
7143
7456
  // src/internal/core/agent-materialization.ts
7144
7457
  function resolveAgentMaterialization(provider, agent) {
7145
7458
  const mode = agent.delivery?.[provider]?.type ?? "managed";
@@ -7147,7 +7460,298 @@ function resolveAgentMaterialization(provider, agent) {
7147
7460
  return { resourceType: "template", mode };
7148
7461
  }
7149
7462
 
7150
- // src/internal/core/validate-config.ts
7463
+ // src/internal/graph/dependency.ts
7464
+ function collectDependencyClosure(graph, roots) {
7465
+ const selected = /* @__PURE__ */ new Map();
7466
+ function visit2(address) {
7467
+ const key = addressKey(address);
7468
+ if (selected.has(key)) return;
7469
+ selected.set(key, graph.nodes.get(key) ?? address);
7470
+ for (const dependencyKey of graph.edges.get(key) ?? []) {
7471
+ const dependency = graph.nodes.get(dependencyKey);
7472
+ if (dependency) visit2(dependency);
7473
+ }
7474
+ }
7475
+ for (const root of roots) visit2(root);
7476
+ return [...selected.values()];
7477
+ }
7478
+ function buildDependencyGraph(config, targetProviders) {
7479
+ const nodes = /* @__PURE__ */ new Map();
7480
+ const edges = /* @__PURE__ */ new Map();
7481
+ function addNode(addr) {
7482
+ const key = addressKey(addr);
7483
+ nodes.set(key, addr);
7484
+ if (!edges.has(key)) edges.set(key, /* @__PURE__ */ new Set());
7485
+ }
7486
+ function addEdge(from, to) {
7487
+ const fromKey = addressKey(from);
7488
+ const toKey = addressKey(to);
7489
+ edges.get(fromKey)?.add(toKey);
7490
+ }
7491
+ for (const provider of targetProviders) {
7492
+ const def = getProvider(provider);
7493
+ const caps = def?.capabilities;
7494
+ if (config.environments) {
7495
+ for (const name of Object.keys(config.environments)) {
7496
+ const decl = config.environments[name];
7497
+ if (decl.provider && decl.provider !== provider) continue;
7498
+ addNode({ type: "environment", name, provider });
7499
+ }
7500
+ }
7501
+ if (config.memory_stores) {
7502
+ for (const name of Object.keys(config.memory_stores)) {
7503
+ const decl = config.memory_stores[name];
7504
+ if (decl.provider && decl.provider !== provider) continue;
7505
+ if (!isSupported(caps, "memory_store")) continue;
7506
+ addNode({ type: "memory_store", name, provider });
7507
+ }
7508
+ }
7509
+ if (config.vaults) {
7510
+ for (const name of Object.keys(config.vaults)) {
7511
+ const decl = config.vaults[name];
7512
+ if (decl.provider && decl.provider !== provider) continue;
7513
+ addNode({ type: "vault", name, provider });
7514
+ }
7515
+ }
7516
+ if (config.skills) {
7517
+ for (const name of Object.keys(config.skills)) {
7518
+ const decl = config.skills[name];
7519
+ if (decl.provider && decl.provider !== provider) continue;
7520
+ addNode({ type: "skill", name, provider });
7521
+ }
7522
+ }
7523
+ if (config.files) {
7524
+ for (const name of Object.keys(config.files)) {
7525
+ const decl = config.files[name];
7526
+ if (decl.provider && decl.provider !== provider) continue;
7527
+ addNode({ type: "file", name, provider });
7528
+ }
7529
+ }
7530
+ if (config.identities && isSupported(caps, "identity")) {
7531
+ for (const name of Object.keys(config.identities)) {
7532
+ const decl = config.identities[name];
7533
+ if (decl.provider && decl.provider !== provider) continue;
7534
+ addNode({ type: "identity", name, provider });
7535
+ }
7536
+ }
7537
+ if (config.agents) {
7538
+ for (const name of Object.keys(config.agents)) {
7539
+ const decl = config.agents[name];
7540
+ if (decl.provider && decl.provider !== provider) continue;
7541
+ const materialization = resolveAgentMaterialization(provider, decl);
7542
+ const agentAddr = { type: materialization.resourceType, name, provider };
7543
+ addNode(agentAddr);
7544
+ if ((decl.default_memory_store || decl.memory_stores?.length) && materialization.resourceType === "template") {
7545
+ const identityName = config.defaults?.identity;
7546
+ if (identityName) {
7547
+ const identityAddr = { type: "identity", name: identityName, provider };
7548
+ if (nodes.has(addressKey(identityAddr))) addEdge(agentAddr, identityAddr);
7549
+ }
7550
+ }
7551
+ if (decl.environment && config.environments?.[decl.environment]) {
7552
+ const envAddr = {
7553
+ type: "environment",
7554
+ name: decl.environment,
7555
+ provider
7556
+ };
7557
+ if (nodes.has(addressKey(envAddr))) {
7558
+ addEdge(agentAddr, envAddr);
7559
+ }
7560
+ }
7561
+ if (decl.skills) {
7562
+ for (const skillRef of decl.skills) {
7563
+ if (typeof skillRef !== "string") continue;
7564
+ const skillName = skillRef;
7565
+ const skillAddr = { type: "skill", name: skillName, provider };
7566
+ if (nodes.has(addressKey(skillAddr))) {
7567
+ addEdge(agentAddr, skillAddr);
7568
+ }
7569
+ }
7570
+ }
7571
+ if (decl.vault) {
7572
+ const vaultAddr = { type: "vault", name: decl.vault, provider };
7573
+ if (nodes.has(addressKey(vaultAddr))) {
7574
+ addEdge(agentAddr, vaultAddr);
7575
+ }
7576
+ }
7577
+ if (decl.files) {
7578
+ for (const file of decl.files) {
7579
+ const fileName = typeof file === "string" ? file : file.file;
7580
+ const fileAddr = { type: "file", name: fileName, provider };
7581
+ if (nodes.has(addressKey(fileAddr))) addEdge(agentAddr, fileAddr);
7582
+ }
7583
+ }
7584
+ if (decl.memory_stores) {
7585
+ for (const msName of decl.memory_stores) {
7586
+ const msAddr = {
7587
+ type: "memory_store",
7588
+ name: msName,
7589
+ provider
7590
+ };
7591
+ if (nodes.has(addressKey(msAddr))) {
7592
+ addEdge(agentAddr, msAddr);
7593
+ }
7594
+ }
7595
+ }
7596
+ if (decl.multiagent && isSupported(caps, "multiagent")) {
7597
+ for (const subName of decl.multiagent.agents) {
7598
+ const subDecl = config.agents[subName];
7599
+ const subType = subDecl ? resolveAgentMaterialization(provider, subDecl).resourceType : "agent";
7600
+ const subAddr = { type: subType, name: subName, provider };
7601
+ addEdge(agentAddr, subAddr);
7602
+ }
7603
+ }
7604
+ }
7605
+ }
7606
+ if (config.deployments) {
7607
+ for (const name of Object.keys(config.deployments)) {
7608
+ const decl = config.deployments[name];
7609
+ if (decl.provider && decl.provider !== provider) continue;
7610
+ const depAddr = { type: "deployment", name, provider };
7611
+ addNode(depAddr);
7612
+ const agentDecl = config.agents?.[decl.agent];
7613
+ const agentType = agentDecl ? resolveAgentMaterialization(provider, agentDecl).resourceType : "agent";
7614
+ const agentAddr = { type: agentType, name: decl.agent, provider };
7615
+ if (nodes.has(addressKey(agentAddr))) addEdge(depAddr, agentAddr);
7616
+ if (decl.environment) {
7617
+ const envAddr = { type: "environment", name: decl.environment, provider };
7618
+ if (nodes.has(addressKey(envAddr))) addEdge(depAddr, envAddr);
7619
+ }
7620
+ if (decl.vaults) {
7621
+ for (const vName of decl.vaults) {
7622
+ const vAddr = { type: "vault", name: vName, provider };
7623
+ if (nodes.has(addressKey(vAddr))) addEdge(depAddr, vAddr);
7624
+ }
7625
+ }
7626
+ if (decl.memory_stores) {
7627
+ for (const msName of decl.memory_stores) {
7628
+ const msAddr = { type: "memory_store", name: msName, provider };
7629
+ if (nodes.has(addressKey(msAddr))) addEdge(depAddr, msAddr);
7630
+ }
7631
+ }
7632
+ if (decl.resources) {
7633
+ for (const r of decl.resources) {
7634
+ if (r.type === "memory_store") {
7635
+ const msAddr = { type: "memory_store", name: r.memory_store, provider };
7636
+ if (nodes.has(addressKey(msAddr))) addEdge(depAddr, msAddr);
7637
+ }
7638
+ }
7639
+ }
7640
+ }
7641
+ }
7642
+ if (config.channels && isSupported(caps, "channel")) {
7643
+ for (const name of Object.keys(config.channels)) {
7644
+ const decl = config.channels[name];
7645
+ if (decl.provider && decl.provider !== provider) continue;
7646
+ const channelAddr = { type: "channel", name, provider };
7647
+ addNode(channelAddr);
7648
+ if (decl.mode === "pairing" || !decl.agent) continue;
7649
+ const agentDecl = config.agents?.[decl.agent];
7650
+ const agentType = agentDecl ? resolveAgentMaterialization(provider, agentDecl).resourceType : "agent";
7651
+ const agentAddr = { type: agentType, name: decl.agent, provider };
7652
+ if (nodes.has(addressKey(agentAddr))) addEdge(channelAddr, agentAddr);
7653
+ const identityName = decl.identity ?? config.defaults?.identity;
7654
+ if (identityName) {
7655
+ const identityAddr = { type: "identity", name: identityName, provider };
7656
+ if (nodes.has(addressKey(identityAddr))) addEdge(channelAddr, identityAddr);
7657
+ }
7658
+ }
7659
+ }
7660
+ }
7661
+ return { nodes, edges };
7662
+ }
7663
+ function topologicalSort(graph) {
7664
+ const visited = /* @__PURE__ */ new Set();
7665
+ const sorted = [];
7666
+ const visiting = /* @__PURE__ */ new Set();
7667
+ function visit2(key) {
7668
+ if (visited.has(key)) return;
7669
+ if (visiting.has(key)) {
7670
+ throw new UserError(`Circular dependency detected involving: ${key}`);
7671
+ }
7672
+ visiting.add(key);
7673
+ const deps = graph.edges.get(key) ?? /* @__PURE__ */ new Set();
7674
+ for (const dep of deps) {
7675
+ visit2(dep);
7676
+ }
7677
+ visiting.delete(key);
7678
+ visited.add(key);
7679
+ sorted.push(graph.nodes.get(key));
7680
+ }
7681
+ for (const key of graph.nodes.keys()) {
7682
+ visit2(key);
7683
+ }
7684
+ return sorted;
7685
+ }
7686
+
7687
+ // src/internal/diagnostics/diagnostics.ts
7688
+ var DiagnosticCollector = class {
7689
+ items = [];
7690
+ error(code, message, resource) {
7691
+ this.items.push({ severity: "error", code, message, resource });
7692
+ }
7693
+ warning(code, message, resource) {
7694
+ this.items.push({ severity: "warning", code, message, resource });
7695
+ }
7696
+ info(code, message, resource) {
7697
+ this.items.push({ severity: "info", code, message, resource });
7698
+ }
7699
+ hasErrors() {
7700
+ return this.items.some((d) => d.severity === "error");
7701
+ }
7702
+ getAll() {
7703
+ return [...this.items];
7704
+ }
7705
+ format() {
7706
+ if (this.items.length === 0) return "";
7707
+ const lines = [];
7708
+ for (const d of this.items) {
7709
+ const icon = severityIcon(d.severity);
7710
+ const addr = d.resource ? ` ${d.resource.type}.${d.resource.name} (${d.resource.provider})` : "";
7711
+ lines.push(`${icon} ${d.code}`);
7712
+ if (addr) lines.push(` Resource:${addr}`);
7713
+ lines.push(` ${d.message}`);
7714
+ lines.push("");
7715
+ }
7716
+ return lines.join("\n");
7717
+ }
7718
+ };
7719
+ function severityIcon(s) {
7720
+ switch (s) {
7721
+ case "error":
7722
+ return "\u2717";
7723
+ case "warning":
7724
+ return "\u26A0";
7725
+ case "info":
7726
+ return "\u2139";
7727
+ }
7728
+ }
7729
+
7730
+ // src/internal/validation/bailian.ts
7731
+ function findMissingBailianMcpToolConfigs(config, providerName = "bailian") {
7732
+ if (providerName !== "bailian") return [];
7733
+ const missing = [];
7734
+ for (const [agentName, agent] of Object.entries(config.agents ?? {})) {
7735
+ if (!agentTargetsProvider(config, agent.provider, providerName)) continue;
7736
+ const configuredToolServers = new Set((agent.tools?.mcp ?? []).map((tool) => tool.mcp_server_name));
7737
+ for (const server of agent.mcp_servers ?? []) {
7738
+ if (!configuredToolServers.has(server.name)) {
7739
+ missing.push({ agentName, serverName: server.name });
7740
+ }
7741
+ }
7742
+ }
7743
+ return missing;
7744
+ }
7745
+ function agentTargetsProvider(config, agentProvider, providerName) {
7746
+ if (agentProvider) return agentProvider === providerName;
7747
+ const defaultProvider = config.defaults?.provider;
7748
+ if (defaultProvider && defaultProvider !== "all") {
7749
+ return defaultProvider === providerName;
7750
+ }
7751
+ return Object.hasOwn(config.providers, providerName);
7752
+ }
7753
+
7754
+ // src/internal/core/validate-config.ts
7151
7755
  function validateProjectConfig(config, options = {}) {
7152
7756
  const collector = new DiagnosticCollector();
7153
7757
  collectReferenceDiagnostics(config, collector);
@@ -7202,8 +7806,9 @@ function collectReferenceDiagnostics(config, diagnostics) {
7202
7806
  diagnostics.error("config.agent.vault.unknown", `agent.${name}: references unknown vault '${agent.vault}'`);
7203
7807
  }
7204
7808
  for (const file of agent.files ?? []) {
7205
- if (!fileNames.has(file)) {
7206
- diagnostics.error("config.agent.file.unknown", `agent.${name}: references unknown file '${file}'`);
7809
+ const fileName = typeof file === "string" ? file : file.file;
7810
+ if (!fileNames.has(fileName)) {
7811
+ diagnostics.error("config.agent.file.unknown", `agent.${name}: references unknown file '${fileName}'`);
7207
7812
  }
7208
7813
  }
7209
7814
  for (const memory of agent.memory_stores ?? []) {
@@ -7268,6 +7873,16 @@ function collectProviderCapabilities(config, providers, diagnostics) {
7268
7873
  continue;
7269
7874
  }
7270
7875
  const caps = def.capabilities;
7876
+ for (const [name, vault] of Object.entries(config.vaults ?? {})) {
7877
+ if (vault.provider && vault.provider !== providerName) continue;
7878
+ if (providerName !== "bailian" && vault.credentials.some((credential) => credential.injection_location !== void 0)) {
7879
+ diagnostics.error(
7880
+ `${providerName}.vault.injection_location.unsupported`,
7881
+ `vault.${name}: provider '${providerName}' does not support credential injection_location; pin this vault to bailian.`,
7882
+ { type: "vault", name, provider: providerName }
7883
+ );
7884
+ }
7885
+ }
7271
7886
  for (const [name, environment] of Object.entries(config.environments ?? {})) {
7272
7887
  if (environment.provider && environment.provider !== providerName) continue;
7273
7888
  if (environment.environment_id) continue;
@@ -7387,7 +8002,7 @@ function collectProviderCapabilities(config, providers, diagnostics) {
7387
8002
  ),
7388
8003
  ...agent.vault ? [`vault:${agent.vault}`] : [],
7389
8004
  ...(agent.memory_stores ?? []).map((store) => `memory_store:${store}`),
7390
- ...(agent.files ?? []).map((file) => `file:${file}`)
8005
+ ...(agent.files ?? []).map((file) => `file:${typeof file === "string" ? file : file.file}`)
7391
8006
  ];
7392
8007
  for (const ref of refs) {
7393
8008
  const modes = domains.get(ref) ?? /* @__PURE__ */ new Set();
@@ -7407,7 +8022,7 @@ function collectProviderCapabilities(config, providers, diagnostics) {
7407
8022
  }
7408
8023
  for (const [name, agent] of Object.entries(config.agents ?? {})) {
7409
8024
  if (agent.provider && agent.provider !== providerName) continue;
7410
- if (agent.files?.length && (providerName !== "qoder" || agent.delivery?.qoder?.type !== "forward")) {
8025
+ if (agent.files?.some((file) => typeof file === "string") && (providerName !== "qoder" || agent.delivery?.qoder?.type !== "forward")) {
7411
8026
  diagnostics.error(
7412
8027
  "config.agent.files.unsupported",
7413
8028
  `agent.${name}: files are supported only by Qoder Forward Templates.`,
@@ -7431,6 +8046,30 @@ function collectProviderCapabilities(config, providers, diagnostics) {
7431
8046
  address
7432
8047
  );
7433
8048
  }
8049
+ const normalizedFileMountPaths = /* @__PURE__ */ new Set();
8050
+ for (const file of agent.files ?? []) {
8051
+ if (typeof file === "string") continue;
8052
+ let normalizedMountPath;
8053
+ try {
8054
+ normalizedMountPath = resolveSandboxMountPath(providerName, file.mount_path);
8055
+ } catch (error) {
8056
+ diagnostics.error(
8057
+ `${providerName}.agent.file.mount_path.invalid`,
8058
+ `agent.${name}: ${error instanceof Error ? error.message : String(error)}`,
8059
+ address
8060
+ );
8061
+ continue;
8062
+ }
8063
+ if (normalizedFileMountPaths.has(normalizedMountPath)) {
8064
+ diagnostics.error(
8065
+ `${providerName}.agent.file.mount_path.duplicate`,
8066
+ `agent.${name}: file mount_path '${normalizedMountPath}' is duplicated after normalization.`,
8067
+ address
8068
+ );
8069
+ } else {
8070
+ normalizedFileMountPaths.add(normalizedMountPath);
8071
+ }
8072
+ }
7434
8073
  for (const resource of agent.resources ?? []) {
7435
8074
  if (!def.features.session_resources.includes(resource.type)) {
7436
8075
  diagnostics.error(
@@ -7591,370 +8230,164 @@ function collectProviderCapabilities(config, providers, diagnostics) {
7591
8230
  `${providerName}.deployment.file.mount_path.invalid`,
7592
8231
  `deployment.${name}: Bailian file mount_path must start with '${mountPrefix}/'.`,
7593
8232
  addr
7594
- );
7595
- continue;
7596
- }
7597
- const normalizedMountPath = resolveSandboxMountPath(providerName, resource.mount_path);
7598
- if (normalizedMountPaths.has(normalizedMountPath)) {
7599
- diagnostics.error(
7600
- `${providerName}.deployment.file.mount_path.duplicate`,
7601
- `deployment.${name}: Bailian file mount_path '${normalizedMountPath}' is duplicated after normalization.`,
7602
- addr
7603
- );
7604
- } else {
7605
- normalizedMountPaths.add(normalizedMountPath);
7606
- }
7607
- }
7608
- }
7609
- }
7610
- if (providerName !== "qoder") {
7611
- for (const [name, env] of Object.entries(config.environments ?? {})) {
7612
- if (env.environment_id) continue;
7613
- if (env.config.type === "self_hosted" && (!env.provider || env.provider === providerName)) {
7614
- diagnostics.error(
7615
- `${providerName}.environment.self_hosted.unsupported`,
7616
- `environment.${name}: self_hosted environments are supported only by Qoder BYOC; use type 'cloud' or pin this environment to the qoder provider.`,
7617
- { type: "environment", name, provider: providerName }
7618
- );
7619
- }
7620
- }
7621
- for (const [name, agent] of Object.entries(config.agents ?? {})) {
7622
- if (agent.environment_variables && (!agent.provider || agent.provider === providerName)) {
7623
- diagnostics.error(
7624
- `${providerName}.agent.environment_variables.unsupported`,
7625
- `agent.${name}: environment_variables is supported only by Qoder; remove it or pin this agent to qoder.`,
7626
- { type: "agent", name, provider: providerName }
7627
- );
7628
- }
7629
- if (agent.managed_tool_config && (!agent.provider || agent.provider === providerName)) {
7630
- diagnostics.error(
7631
- `${providerName}.agent.managed_tool_config.unsupported`,
7632
- `agent.${name}: managed_tool_config is supported only by Qoder; remove it or pin this agent to qoder.`,
7633
- { type: "agent", name, provider: providerName }
7634
- );
7635
- }
7636
- if (agent.tunnel && (!agent.provider || agent.provider === providerName)) {
7637
- diagnostics.error(
7638
- `${providerName}.agent.tunnel.unsupported`,
7639
- "Tunnels are supported only by Qoder BYOC sessions.",
7640
- { type: "agent", name, provider: providerName }
7641
- );
7642
- }
7643
- }
7644
- for (const [name, deployment] of Object.entries(config.deployments ?? {})) {
7645
- if (deployment.provider && deployment.provider !== providerName) continue;
7646
- if (deployment.environment_variables !== void 0) {
7647
- diagnostics.error(
7648
- `${providerName}.deployment.environment_variables.unsupported`,
7649
- `deployment.${name}: environment_variables is supported only by Qoder deployments; remove it or pin this deployment to the qoder provider.`,
7650
- { type: "deployment", name, provider: providerName }
7651
- );
7652
- }
7653
- if (deployment.tunnel && (!deployment.provider || deployment.provider === providerName)) {
7654
- diagnostics.error(
7655
- `${providerName}.deployment.tunnel.unsupported`,
7656
- "Tunnels are supported only by Qoder BYOC sessions.",
7657
- { type: "deployment", name, provider: providerName }
7658
- );
7659
- }
7660
- }
7661
- }
7662
- for (const missing of findMissingBailianMcpToolConfigs(config, providerName)) {
7663
- diagnostics.error(
7664
- `${providerName}.agent.mcp_toolkit_missing`,
7665
- `Bailian MCP server '${missing.serverName}' requires a matching tools.mcp entry.`,
7666
- { type: "agent", name: missing.agentName, provider: providerName }
7667
- );
7668
- }
7669
- if (config.memory_stores && !isSupported(caps, "memory_store")) {
7670
- for (const [name, decl] of Object.entries(config.memory_stores)) {
7671
- if (!decl.provider || decl.provider === providerName) {
7672
- diagnostics.error(
7673
- `${providerName}.memory_store.unsupported`,
7674
- `${caps.memory_store.reason}. ${caps.memory_store.remediation ?? ""}`.trim(),
7675
- { type: "memory_store", name, provider: providerName }
7676
- );
7677
- }
7678
- }
7679
- }
7680
- if (config.agents && !isSupported(caps, "multiagent")) {
7681
- for (const [name, agent] of Object.entries(config.agents)) {
7682
- if (agent.multiagent) {
7683
- if (!agent.provider || agent.provider === providerName) {
7684
- diagnostics.error(
7685
- `${providerName}.multiagent.unsupported`,
7686
- `${caps.multiagent.reason}. ${caps.multiagent.remediation ?? ""}`.trim(),
7687
- { type: "agent", name, provider: providerName }
7688
- );
7689
- }
7690
- }
7691
- }
7692
- }
7693
- if (config.deployments && caps.deployment.tier === "emulated") {
7694
- for (const [name, dep] of Object.entries(config.deployments)) {
7695
- if (dep.provider && dep.provider !== providerName) continue;
7696
- const addr = {
7697
- type: "deployment",
7698
- name,
7699
- provider: providerName
7700
- };
7701
- if (dep.schedule) {
7702
- diagnostics.warning(
7703
- `${providerName}.deployment.schedule_unsupported`,
7704
- "Schedules are not enforced server-side on this provider; trigger runs via external cron/CI.",
7705
- addr
7706
- );
7707
- }
7708
- if (dep.initial_events?.some((e) => e.type === "user.define_outcome")) {
7709
- diagnostics.warning(
7710
- `${providerName}.deployment.define_outcome_unsupported`,
7711
- "Outcome rubrics (user.define_outcome) are not enforced server-side on this provider; the run executes without rubric grading.",
7712
- addr
7713
- );
7714
- }
7715
- if (dep.resources?.some((r) => r.type === "github_repository")) {
7716
- diagnostics.warning(
7717
- `${providerName}.deployment.github_repository_unsupported`,
7718
- "github_repository resources are not provisioned on this provider; clone the repository inside the session instead.",
7719
- addr
7720
- );
7721
- }
7722
- if (dep.resources?.some((r) => r.type === "memory_store" && (r.access === "read_only" || r.instructions))) {
7723
- diagnostics.warning(
7724
- `${providerName}.deployment.memory_store_options_unsupported`,
7725
- "Per-resource memory_store access/instructions are not honored on this provider; the store is attached with default access.",
7726
- addr
7727
- );
7728
- }
7729
- }
7730
- }
7731
- }
7732
- }
7733
-
7734
- // src/internal/graph/dependency.ts
7735
- function buildDependencyGraph(config, targetProviders) {
7736
- const nodes = /* @__PURE__ */ new Map();
7737
- const edges = /* @__PURE__ */ new Map();
7738
- function addNode(addr) {
7739
- const key = addressKey(addr);
7740
- nodes.set(key, addr);
7741
- if (!edges.has(key)) edges.set(key, /* @__PURE__ */ new Set());
7742
- }
7743
- function addEdge(from, to) {
7744
- const fromKey = addressKey(from);
7745
- const toKey = addressKey(to);
7746
- edges.get(fromKey)?.add(toKey);
7747
- }
7748
- for (const provider of targetProviders) {
7749
- const def = getProvider(provider);
7750
- const caps = def?.capabilities;
7751
- if (config.environments) {
7752
- for (const name of Object.keys(config.environments)) {
7753
- const decl = config.environments[name];
7754
- if (decl.provider && decl.provider !== provider) continue;
7755
- addNode({ type: "environment", name, provider });
7756
- }
7757
- }
7758
- if (config.memory_stores) {
7759
- for (const name of Object.keys(config.memory_stores)) {
7760
- const decl = config.memory_stores[name];
7761
- if (decl.provider && decl.provider !== provider) continue;
7762
- if (!isSupported(caps, "memory_store")) continue;
7763
- addNode({ type: "memory_store", name, provider });
7764
- }
7765
- }
7766
- if (config.vaults) {
7767
- for (const name of Object.keys(config.vaults)) {
7768
- const decl = config.vaults[name];
7769
- if (decl.provider && decl.provider !== provider) continue;
7770
- addNode({ type: "vault", name, provider });
7771
- }
7772
- }
7773
- if (config.skills) {
7774
- for (const name of Object.keys(config.skills)) {
7775
- const decl = config.skills[name];
7776
- if (decl.provider && decl.provider !== provider) continue;
7777
- addNode({ type: "skill", name, provider });
7778
- }
7779
- }
7780
- if (config.files) {
7781
- for (const name of Object.keys(config.files)) {
7782
- const decl = config.files[name];
7783
- if (decl.provider && decl.provider !== provider) continue;
7784
- addNode({ type: "file", name, provider });
7785
- }
7786
- }
7787
- if (config.identities && isSupported(caps, "identity")) {
7788
- for (const name of Object.keys(config.identities)) {
7789
- const decl = config.identities[name];
7790
- if (decl.provider && decl.provider !== provider) continue;
7791
- addNode({ type: "identity", name, provider });
7792
- }
7793
- }
7794
- if (config.agents) {
7795
- for (const name of Object.keys(config.agents)) {
7796
- const decl = config.agents[name];
7797
- if (decl.provider && decl.provider !== provider) continue;
7798
- const materialization = resolveAgentMaterialization(provider, decl);
7799
- const agentAddr = { type: materialization.resourceType, name, provider };
7800
- addNode(agentAddr);
7801
- if ((decl.default_memory_store || decl.memory_stores?.length) && materialization.resourceType === "template") {
7802
- const identityName = config.defaults?.identity;
7803
- if (identityName) {
7804
- const identityAddr = { type: "identity", name: identityName, provider };
7805
- if (nodes.has(addressKey(identityAddr))) addEdge(agentAddr, identityAddr);
7806
- }
7807
- }
7808
- if (decl.environment && config.environments?.[decl.environment]) {
7809
- const envAddr = {
7810
- type: "environment",
7811
- name: decl.environment,
7812
- provider
7813
- };
7814
- if (nodes.has(addressKey(envAddr))) {
7815
- addEdge(agentAddr, envAddr);
7816
- }
7817
- }
7818
- if (decl.skills) {
7819
- for (const skillRef of decl.skills) {
7820
- if (typeof skillRef !== "string") continue;
7821
- const skillName = skillRef;
7822
- const skillAddr = { type: "skill", name: skillName, provider };
7823
- if (nodes.has(addressKey(skillAddr))) {
7824
- addEdge(agentAddr, skillAddr);
7825
- }
7826
- }
7827
- }
7828
- if (decl.vault) {
7829
- const vaultAddr = { type: "vault", name: decl.vault, provider };
7830
- if (nodes.has(addressKey(vaultAddr))) {
7831
- addEdge(agentAddr, vaultAddr);
7832
- }
7833
- }
7834
- if (decl.files) {
7835
- for (const fileName of decl.files) {
7836
- const fileAddr = { type: "file", name: fileName, provider };
7837
- if (nodes.has(addressKey(fileAddr))) addEdge(agentAddr, fileAddr);
7838
- }
7839
- }
7840
- if (decl.memory_stores) {
7841
- for (const msName of decl.memory_stores) {
7842
- const msAddr = {
7843
- type: "memory_store",
7844
- name: msName,
7845
- provider
7846
- };
7847
- if (nodes.has(addressKey(msAddr))) {
7848
- addEdge(agentAddr, msAddr);
7849
- }
8233
+ );
8234
+ continue;
7850
8235
  }
7851
- }
7852
- if (decl.multiagent && isSupported(caps, "multiagent")) {
7853
- for (const subName of decl.multiagent.agents) {
7854
- const subDecl = config.agents[subName];
7855
- const subType = subDecl ? resolveAgentMaterialization(provider, subDecl).resourceType : "agent";
7856
- const subAddr = { type: subType, name: subName, provider };
7857
- addEdge(agentAddr, subAddr);
8236
+ const normalizedMountPath = resolveSandboxMountPath(providerName, resource.mount_path);
8237
+ if (normalizedMountPaths.has(normalizedMountPath)) {
8238
+ diagnostics.error(
8239
+ `${providerName}.deployment.file.mount_path.duplicate`,
8240
+ `deployment.${name}: Bailian file mount_path '${normalizedMountPath}' is duplicated after normalization.`,
8241
+ addr
8242
+ );
8243
+ } else {
8244
+ normalizedMountPaths.add(normalizedMountPath);
7858
8245
  }
7859
8246
  }
7860
8247
  }
7861
8248
  }
7862
- if (config.deployments) {
7863
- for (const name of Object.keys(config.deployments)) {
7864
- const decl = config.deployments[name];
7865
- if (decl.provider && decl.provider !== provider) continue;
7866
- const depAddr = { type: "deployment", name, provider };
7867
- addNode(depAddr);
7868
- const agentDecl = config.agents?.[decl.agent];
7869
- const agentType = agentDecl ? resolveAgentMaterialization(provider, agentDecl).resourceType : "agent";
7870
- const agentAddr = { type: agentType, name: decl.agent, provider };
7871
- if (nodes.has(addressKey(agentAddr))) addEdge(depAddr, agentAddr);
7872
- if (decl.environment) {
7873
- const envAddr = { type: "environment", name: decl.environment, provider };
7874
- if (nodes.has(addressKey(envAddr))) addEdge(depAddr, envAddr);
8249
+ if (providerName !== "qoder") {
8250
+ for (const [name, env] of Object.entries(config.environments ?? {})) {
8251
+ if (env.environment_id) continue;
8252
+ if (env.config.type === "self_hosted" && (!env.provider || env.provider === providerName)) {
8253
+ diagnostics.error(
8254
+ `${providerName}.environment.self_hosted.unsupported`,
8255
+ `environment.${name}: self_hosted environments are supported only by Qoder BYOC; use type 'cloud' or pin this environment to the qoder provider.`,
8256
+ { type: "environment", name, provider: providerName }
8257
+ );
7875
8258
  }
7876
- if (decl.vaults) {
7877
- for (const vName of decl.vaults) {
7878
- const vAddr = { type: "vault", name: vName, provider };
7879
- if (nodes.has(addressKey(vAddr))) addEdge(depAddr, vAddr);
7880
- }
8259
+ }
8260
+ for (const [name, agent] of Object.entries(config.agents ?? {})) {
8261
+ if (agent.environment_variables && (!agent.provider || agent.provider === providerName)) {
8262
+ diagnostics.error(
8263
+ `${providerName}.agent.environment_variables.unsupported`,
8264
+ `agent.${name}: environment_variables is supported only by Qoder; remove it or pin this agent to qoder.`,
8265
+ { type: "agent", name, provider: providerName }
8266
+ );
7881
8267
  }
7882
- if (decl.memory_stores) {
7883
- for (const msName of decl.memory_stores) {
7884
- const msAddr = { type: "memory_store", name: msName, provider };
7885
- if (nodes.has(addressKey(msAddr))) addEdge(depAddr, msAddr);
7886
- }
8268
+ if (agent.managed_tool_config && (!agent.provider || agent.provider === providerName)) {
8269
+ diagnostics.error(
8270
+ `${providerName}.agent.managed_tool_config.unsupported`,
8271
+ `agent.${name}: managed_tool_config is supported only by Qoder; remove it or pin this agent to qoder.`,
8272
+ { type: "agent", name, provider: providerName }
8273
+ );
7887
8274
  }
7888
- if (decl.resources) {
7889
- for (const r of decl.resources) {
7890
- if (r.type === "memory_store") {
7891
- const msAddr = { type: "memory_store", name: r.memory_store, provider };
7892
- if (nodes.has(addressKey(msAddr))) addEdge(depAddr, msAddr);
7893
- }
7894
- }
8275
+ if (agent.tunnel && (!agent.provider || agent.provider === providerName)) {
8276
+ diagnostics.error(
8277
+ `${providerName}.agent.tunnel.unsupported`,
8278
+ "Tunnels are supported only by Qoder BYOC sessions.",
8279
+ { type: "agent", name, provider: providerName }
8280
+ );
8281
+ }
8282
+ }
8283
+ for (const [name, deployment] of Object.entries(config.deployments ?? {})) {
8284
+ if (deployment.provider && deployment.provider !== providerName) continue;
8285
+ if (deployment.environment_variables !== void 0) {
8286
+ diagnostics.error(
8287
+ `${providerName}.deployment.environment_variables.unsupported`,
8288
+ `deployment.${name}: environment_variables is supported only by Qoder deployments; remove it or pin this deployment to the qoder provider.`,
8289
+ { type: "deployment", name, provider: providerName }
8290
+ );
8291
+ }
8292
+ if (deployment.tunnel && (!deployment.provider || deployment.provider === providerName)) {
8293
+ diagnostics.error(
8294
+ `${providerName}.deployment.tunnel.unsupported`,
8295
+ "Tunnels are supported only by Qoder BYOC sessions.",
8296
+ { type: "deployment", name, provider: providerName }
8297
+ );
7895
8298
  }
7896
8299
  }
7897
8300
  }
7898
- if (config.channels && isSupported(caps, "channel")) {
7899
- for (const name of Object.keys(config.channels)) {
7900
- const decl = config.channels[name];
7901
- if (decl.provider && decl.provider !== provider) continue;
7902
- const channelAddr = { type: "channel", name, provider };
7903
- addNode(channelAddr);
7904
- if (decl.mode === "pairing" || !decl.agent) continue;
7905
- const agentDecl = config.agents?.[decl.agent];
7906
- const agentType = agentDecl ? resolveAgentMaterialization(provider, agentDecl).resourceType : "agent";
7907
- const agentAddr = { type: agentType, name: decl.agent, provider };
7908
- if (nodes.has(addressKey(agentAddr))) addEdge(channelAddr, agentAddr);
7909
- const identityName = decl.identity ?? config.defaults?.identity;
7910
- if (identityName) {
7911
- const identityAddr = { type: "identity", name: identityName, provider };
7912
- if (nodes.has(addressKey(identityAddr))) addEdge(channelAddr, identityAddr);
8301
+ for (const missing of findMissingBailianMcpToolConfigs(config, providerName)) {
8302
+ diagnostics.error(
8303
+ `${providerName}.agent.mcp_toolkit_missing`,
8304
+ `Bailian MCP server '${missing.serverName}' requires a matching tools.mcp entry.`,
8305
+ { type: "agent", name: missing.agentName, provider: providerName }
8306
+ );
8307
+ }
8308
+ if (config.memory_stores && !isSupported(caps, "memory_store")) {
8309
+ for (const [name, decl] of Object.entries(config.memory_stores)) {
8310
+ if (!decl.provider || decl.provider === providerName) {
8311
+ diagnostics.error(
8312
+ `${providerName}.memory_store.unsupported`,
8313
+ `${caps.memory_store.reason}. ${caps.memory_store.remediation ?? ""}`.trim(),
8314
+ { type: "memory_store", name, provider: providerName }
8315
+ );
7913
8316
  }
7914
8317
  }
7915
8318
  }
7916
- }
7917
- return { nodes, edges };
7918
- }
7919
- function topologicalSort(graph) {
7920
- const visited = /* @__PURE__ */ new Set();
7921
- const sorted = [];
7922
- const visiting = /* @__PURE__ */ new Set();
7923
- function visit(key) {
7924
- if (visited.has(key)) return;
7925
- if (visiting.has(key)) {
7926
- throw new UserError(`Circular dependency detected involving: ${key}`);
8319
+ if (config.agents && !isSupported(caps, "multiagent")) {
8320
+ for (const [name, agent] of Object.entries(config.agents)) {
8321
+ if (agent.multiagent) {
8322
+ if (!agent.provider || agent.provider === providerName) {
8323
+ diagnostics.error(
8324
+ `${providerName}.multiagent.unsupported`,
8325
+ `${caps.multiagent.reason}. ${caps.multiagent.remediation ?? ""}`.trim(),
8326
+ { type: "agent", name, provider: providerName }
8327
+ );
8328
+ }
8329
+ }
8330
+ }
7927
8331
  }
7928
- visiting.add(key);
7929
- const deps = graph.edges.get(key) ?? /* @__PURE__ */ new Set();
7930
- for (const dep of deps) {
7931
- visit(dep);
8332
+ if (config.deployments && caps.deployment.tier === "emulated") {
8333
+ for (const [name, dep] of Object.entries(config.deployments)) {
8334
+ if (dep.provider && dep.provider !== providerName) continue;
8335
+ const addr = {
8336
+ type: "deployment",
8337
+ name,
8338
+ provider: providerName
8339
+ };
8340
+ if (dep.schedule) {
8341
+ diagnostics.warning(
8342
+ `${providerName}.deployment.schedule_unsupported`,
8343
+ "Schedules are not enforced server-side on this provider; trigger runs via external cron/CI.",
8344
+ addr
8345
+ );
8346
+ }
8347
+ if (dep.initial_events?.some((e) => e.type === "user.define_outcome")) {
8348
+ diagnostics.warning(
8349
+ `${providerName}.deployment.define_outcome_unsupported`,
8350
+ "Outcome rubrics (user.define_outcome) are not enforced server-side on this provider; the run executes without rubric grading.",
8351
+ addr
8352
+ );
8353
+ }
8354
+ if (dep.resources?.some((r) => r.type === "github_repository")) {
8355
+ diagnostics.warning(
8356
+ `${providerName}.deployment.github_repository_unsupported`,
8357
+ "github_repository resources are not provisioned on this provider; clone the repository inside the session instead.",
8358
+ addr
8359
+ );
8360
+ }
8361
+ if (dep.resources?.some((r) => r.type === "memory_store" && (r.access === "read_only" || r.instructions))) {
8362
+ diagnostics.warning(
8363
+ `${providerName}.deployment.memory_store_options_unsupported`,
8364
+ "Per-resource memory_store access/instructions are not honored on this provider; the store is attached with default access.",
8365
+ addr
8366
+ );
8367
+ }
8368
+ }
7932
8369
  }
7933
- visiting.delete(key);
7934
- visited.add(key);
7935
- sorted.push(graph.nodes.get(key));
7936
- }
7937
- for (const key of graph.nodes.keys()) {
7938
- visit(key);
7939
8370
  }
7940
- return sorted;
7941
8371
  }
7942
8372
 
7943
8373
  // src/internal/planner/planner.ts
7944
8374
  async function buildPlan(config, state, options = {}) {
8375
+ const scopedConfig = options.resourceAddresses ? selectProjectConfig(config, options.resourceAddresses) : config;
8376
+ const resourceKeys = options.resourceAddresses ? new Set(options.resourceAddresses.map(addressKey)) : void 0;
8377
+ const scopedState = resourceKeys ? { ...state, resources: state.resources.filter((resource) => resourceKeys.has(addressKey(resource.address))) } : state;
7945
8378
  const diagnostics = new DiagnosticCollector();
7946
8379
  const actions = [];
7947
- const targetProviders = options.providers ?? resolveTargetProviders(config);
7948
- collectReferenceDiagnostics(config, diagnostics);
7949
- collectProviderCapabilities(config, targetProviders, diagnostics);
7950
- const graph = buildDependencyGraph(config, targetProviders);
8380
+ const targetProviders = options.providers ?? resolveTargetProviders(scopedConfig);
8381
+ collectReferenceDiagnostics(scopedConfig, diagnostics);
8382
+ collectProviderCapabilities(scopedConfig, targetProviders, diagnostics);
8383
+ const graph = buildDependencyGraph(scopedConfig, targetProviders);
7951
8384
  const sorted = topologicalSort(graph);
7952
8385
  const stateIndex = /* @__PURE__ */ new Map();
7953
- for (const res of state.resources) {
8386
+ for (const res of scopedState.resources) {
7954
8387
  stateIndex.set(addressKey(res.address), res);
7955
8388
  }
7956
8389
  const remoteIdLookup = /* @__PURE__ */ new Map();
7957
- for (const res of state.resources) {
8390
+ for (const res of scopedState.resources) {
7958
8391
  remoteIdLookup.set(addressKey(res.address), res);
7959
8392
  }
7960
8393
  const hashStateLookup = { getResource: (addr) => remoteIdLookup.get(addressKey(addr)) };
@@ -8098,9 +8531,53 @@ async function buildPlan(config, state, options = {}) {
8098
8531
  dependencies: replacement ? [replacement] : []
8099
8532
  });
8100
8533
  }
8101
- coalesceChannelRenames(actions, config, state);
8534
+ coalesceChannelRenames(actions, scopedConfig, scopedState);
8102
8535
  return { actions, diagnostics: diagnostics.getAll() };
8103
8536
  }
8537
+ function selectProjectConfig(config, addresses) {
8538
+ const providers = new Set(addresses.map((address) => address.provider));
8539
+ const namesByType = /* @__PURE__ */ new Map();
8540
+ for (const address of addresses) {
8541
+ const names = namesByType.get(address.type) ?? /* @__PURE__ */ new Set();
8542
+ names.add(address.name);
8543
+ namesByType.set(address.type, names);
8544
+ }
8545
+ const pick = (record, names) => {
8546
+ if (!record || !names?.size) return void 0;
8547
+ const selected = Object.fromEntries(Object.entries(record).filter(([name]) => names.has(name)));
8548
+ return Object.keys(selected).length > 0 ? selected : void 0;
8549
+ };
8550
+ const agentNames = /* @__PURE__ */ new Set([...namesByType.get("agent") ?? [], ...namesByType.get("template") ?? []]);
8551
+ const selectedAgents = pick(config.agents, agentNames);
8552
+ const tunnelNames = /* @__PURE__ */ new Set();
8553
+ for (const agent of Object.values(selectedAgents ?? {})) {
8554
+ if (agent.tunnel) tunnelNames.add(agent.tunnel);
8555
+ }
8556
+ for (const deployment of Object.values(pick(config.deployments, namesByType.get("deployment")) ?? {})) {
8557
+ if (deployment.tunnel) tunnelNames.add(deployment.tunnel);
8558
+ }
8559
+ const identityNames = namesByType.get("identity");
8560
+ const selectedProviders = Object.fromEntries(
8561
+ Object.entries(config.providers).filter(([providerName]) => providers.has(providerName))
8562
+ );
8563
+ const defaultProvider = providers.size === 1 ? [...providers][0] : config.defaults?.provider;
8564
+ const defaultIdentity = config.defaults?.identity && identityNames?.has(config.defaults.identity) ? config.defaults.identity : void 0;
8565
+ return {
8566
+ ...config,
8567
+ providers: selectedProviders,
8568
+ defaults: defaultProvider || defaultIdentity ? { provider: defaultProvider, identity: defaultIdentity } : void 0,
8569
+ environments: pick(config.environments, namesByType.get("environment")),
8570
+ tunnels: pick(config.tunnels, tunnelNames),
8571
+ vaults: pick(config.vaults, namesByType.get("vault")),
8572
+ memory_stores: pick(config.memory_stores, namesByType.get("memory_store")),
8573
+ skills: pick(config.skills, namesByType.get("skill")),
8574
+ files: pick(config.files, namesByType.get("file")),
8575
+ identities: pick(config.identities, identityNames),
8576
+ agents: selectedAgents,
8577
+ channels: pick(config.channels, namesByType.get("channel")),
8578
+ deployments: pick(config.deployments, namesByType.get("deployment"))
8579
+ };
8580
+ }
8104
8581
  function coalesceChannelRenames(actions, config, state) {
8105
8582
  const creates = actions.filter((action) => action.action === "create" && action.address.type === "channel");
8106
8583
  const deletes = actions.filter((action) => action.action === "delete" && action.address.type === "channel");
@@ -8180,6 +8657,9 @@ async function refreshState(state, providers, options = {}) {
8180
8657
  const errors = [];
8181
8658
  let dirty = false;
8182
8659
  for (const res of resources) {
8660
+ if (options.resourceKeys && !options.resourceKeys.has(addressKey(res.address))) {
8661
+ continue;
8662
+ }
8183
8663
  if (options.targetProviders && !options.targetProviders.includes(res.address.provider)) {
8184
8664
  continue;
8185
8665
  }
@@ -8293,18 +8773,26 @@ async function refreshState(state, providers, options = {}) {
8293
8773
  }
8294
8774
 
8295
8775
  // src/internal/core/resource-runtime.ts
8776
+ async function planProjectWithStateBackend(input, options = {}) {
8777
+ return readProjectRuntime(input, (ctx) => planProjectContext(ctx, options));
8778
+ }
8296
8779
  async function syncProjectResourcesWithStateBackend(input, options = {}) {
8297
8780
  return writeProjectRuntime(input, async (ctx) => {
8298
8781
  const planned = await planProjectContext(ctx, options);
8299
8782
  if (options.refreshOnly) {
8300
8783
  return { planned };
8301
8784
  }
8785
+ if (options.mode === "create-only") {
8786
+ const errorDiagnostic = planned.plan.diagnostics.find((diagnostic) => diagnostic.severity === "error");
8787
+ if (errorDiagnostic) throw new UserError(errorDiagnostic.message);
8788
+ }
8302
8789
  return {
8303
8790
  planned,
8304
8791
  execution: await executePlannedProject(planned, {
8305
8792
  onFeedback: options.onFeedback,
8306
8793
  policy: options.policy,
8307
- confirm: options.confirm
8794
+ confirm: options.confirm,
8795
+ concurrency: options.concurrency
8308
8796
  })
8309
8797
  };
8310
8798
  });
@@ -8366,26 +8854,103 @@ async function importResource(ctx, address, remoteId, options = {}) {
8366
8854
  return resource;
8367
8855
  }
8368
8856
  async function planProjectContext(ctx, options = {}) {
8369
- const targetProviders = resolveTargetProviders2(options.provider);
8857
+ if (options.mode === "create-only" && !options.scope) {
8858
+ throw new UserError("Resource create-only mode requires an explicit resource scope.");
8859
+ }
8860
+ let targetProviders = resolveTargetProviders2(options.provider);
8861
+ if (!targetProviders && options.scope) {
8862
+ targetProviders = [...new Set(options.scope.roots.map((root) => root.provider))];
8863
+ }
8864
+ const selectedAddresses = options.scope ? resolvePlanScope(ctx, targetProviders ?? [], options.scope) : void 0;
8865
+ const resourceKeys = selectedAddresses ? new Set(selectedAddresses.map(addressKey)) : void 0;
8370
8866
  const refreshResult = options.refresh !== false && ctx.state.listResources().length > 0 ? await refreshState(ctx.state, ctx.providers, {
8371
8867
  targetProviders,
8868
+ resourceKeys,
8372
8869
  config: ctx.config,
8373
8870
  quiet: options.quiet ?? true,
8374
8871
  onFeedback: options.onFeedback
8375
8872
  }) : void 0;
8376
- const plan = await buildPlan(ctx.config, ctx.state.getStateFile(), {
8873
+ let plan = await buildPlan(ctx.config, ctx.state.getStateFile(), {
8377
8874
  providers: targetProviders,
8378
- configPath: ctx.configPath
8875
+ configPath: ctx.configPath,
8876
+ resourceAddresses: selectedAddresses
8379
8877
  });
8878
+ if (options.mode === "create-only" && options.scope) {
8879
+ plan = enforceCreateOnlyPlan(plan, options.scope, toResourceRefreshResult(refreshResult));
8880
+ }
8380
8881
  return {
8381
8882
  executionContext: ctx,
8382
8883
  plan,
8383
8884
  refreshResult: toResourceRefreshResult(refreshResult),
8384
8885
  targetProviders,
8385
- destructiveActions: selectDestructive(plan.actions)
8886
+ destructiveActions: selectDestructive(plan.actions),
8887
+ selectedAddresses,
8888
+ mode: options.mode
8889
+ };
8890
+ }
8891
+ function enforceCreateOnlyPlan(plan, scope, refreshResult) {
8892
+ const reasons = [];
8893
+ const rootKeys = new Set(scope.roots.map(addressKey));
8894
+ const refreshError = refreshResult?.errors[0];
8895
+ if (refreshError) {
8896
+ reasons.push(
8897
+ `Cannot verify scoped dependencies because refresh failed for ${addressKey(refreshError.resource.address)}: ${refreshError.error}`
8898
+ );
8899
+ }
8900
+ for (const root of scope.roots) {
8901
+ const rootKey = addressKey(root);
8902
+ const rootAction = plan.actions.find((action) => addressKey(action.address) === rootKey);
8903
+ if (!rootAction) {
8904
+ reasons.push(`Scoped plan did not contain target resource ${rootKey}.`);
8905
+ } else if (rootAction.action !== "create") {
8906
+ reasons.push(`Target resource ${rootKey} must be new, but the scoped plan requires '${rootAction.action}'.`);
8907
+ }
8908
+ }
8909
+ const dependencyChanges = plan.actions.filter(
8910
+ (action) => !rootKeys.has(addressKey(action.address)) && action.action !== "no-op"
8911
+ );
8912
+ if (dependencyChanges.length > 0) {
8913
+ const labels = dependencyChanges.map((action) => `${addressKey(action.address)} (${action.action})`).join(", ");
8914
+ reasons.push(`Create-only requires every scoped dependency to be up-to-date. Reconcile first: ${labels}.`);
8915
+ }
8916
+ if (reasons.length === 0) return plan;
8917
+ return {
8918
+ ...plan,
8919
+ diagnostics: [
8920
+ ...plan.diagnostics,
8921
+ {
8922
+ severity: "error",
8923
+ code: "resource.create_only.blocked",
8924
+ message: reasons.join(" "),
8925
+ resource: scope.roots[0]
8926
+ }
8927
+ ]
8386
8928
  };
8387
8929
  }
8930
+ function resolvePlanScope(ctx, targetProviders, scope) {
8931
+ if (scope.roots.length === 0) {
8932
+ throw new UserError("Resource plan scope requires at least one root address.");
8933
+ }
8934
+ for (const root of scope.roots) {
8935
+ if (!targetProviders.includes(root.provider)) {
8936
+ throw new UserError(
8937
+ `Scoped resource ${addressKey(root)} is outside the selected provider set: ${targetProviders.join(", ")}.`
8938
+ );
8939
+ }
8940
+ }
8941
+ const graph = buildDependencyGraph(ctx.config, targetProviders);
8942
+ for (const root of scope.roots) {
8943
+ if (!graph.nodes.has(addressKey(root))) {
8944
+ throw new UserError(`Scoped resource ${addressKey(root)} is not declared in the project config.`);
8945
+ }
8946
+ }
8947
+ return scope.includeDependencies === false ? [...scope.roots] : collectDependencyClosure(graph, scope.roots);
8948
+ }
8388
8949
  async function executePlannedProject(planned, options = {}) {
8950
+ if (planned.mode === "create-only") {
8951
+ const errorDiagnostic = planned.plan.diagnostics.find((diagnostic) => diagnostic.severity === "error");
8952
+ if (errorDiagnostic) throw new UserError(errorDiagnostic.message);
8953
+ }
8389
8954
  const decision = await decideDestructive(planned.destructiveActions, {
8390
8955
  policy: options.policy,
8391
8956
  confirm: options.confirm
@@ -8403,7 +8968,8 @@ async function executePlannedProject(planned, options = {}) {
8403
8968
  configPath: ctx.configPath,
8404
8969
  providers: ctx.providers,
8405
8970
  state: ctx.state,
8406
- onFeedback: options.onFeedback
8971
+ onFeedback: options.onFeedback,
8972
+ createOnly: planned.mode === "create-only"
8407
8973
  },
8408
8974
  { concurrency: options.concurrency }
8409
8975
  );
@@ -8428,13 +8994,6 @@ async function decideDestructive(destructiveActions, options = {}) {
8428
8994
  return "blocked";
8429
8995
  }
8430
8996
  }
8431
- function replaceResourcePlan(planned, plan) {
8432
- return {
8433
- ...planned,
8434
- plan,
8435
- destructiveActions: selectDestructive(plan.actions)
8436
- };
8437
- }
8438
8997
  function toResourceRefreshResult(result) {
8439
8998
  if (!result) return void 0;
8440
8999
  return {
@@ -8456,6 +9015,124 @@ function toResourceExecutionResult(result) {
8456
9015
  };
8457
9016
  }
8458
9017
 
9018
+ // src/internal/core/project-source-security.ts
9019
+ import { basename as basename8, dirname as dirname11 } from "path";
9020
+ import { isScalar, parseDocument, visit } from "yaml";
9021
+ var REDACTED = "[redacted]";
9022
+ var ENVIRONMENT_REFERENCE = /^\$\{[A-Za-z_][A-Za-z0-9_]*\}$/;
9023
+ var SENSITIVE_KEY = /(access[_-]?key(?:[_-]?id)?|api[_-]?key|authorization|credential|headers?|password|secret(?![_-]?name)|signature|token)/i;
9024
+ async function inspectProjectSource(source, configPath) {
9025
+ const document = parseDocument(source, { keepSourceTokens: true, prettyErrors: true });
9026
+ if (document.errors.length > 0) {
9027
+ return {
9028
+ diagnostics: document.errors.map(() => ({
9029
+ severity: "error",
9030
+ code: "project.config.invalid",
9031
+ message: "agents.yaml contains invalid YAML. Fix the syntax before creating or restoring a version."
9032
+ })),
9033
+ redacted_source: "# Invalid agents.yaml source omitted from the safe preview.\n",
9034
+ sensitive_literals: []
9035
+ };
9036
+ }
9037
+ const rawConfig = document.toJS({ mapAsMap: false });
9038
+ const displaySecrets = collectSensitiveScalars(rawConfig);
9039
+ const sensitiveLiterals = [...displaySecrets].filter((value) => !ENVIRONMENT_REFERENCE.test(value));
9040
+ let diagnostics;
9041
+ try {
9042
+ const loaded = await resolveProjectConfigFromObject(rawConfig, {
9043
+ projectName: basename8(dirname11(configPath)),
9044
+ basePath: dirname11(configPath)
9045
+ });
9046
+ diagnostics = validateProjectConfig(loaded.config);
9047
+ } catch (error) {
9048
+ diagnostics = [
9049
+ {
9050
+ severity: "error",
9051
+ code: "project.config.invalid",
9052
+ message: error instanceof Error ? error.message : String(error)
9053
+ }
9054
+ ];
9055
+ }
9056
+ if (sensitiveLiterals.length > 0) {
9057
+ diagnostics.push({
9058
+ severity: "error",
9059
+ code: "project.version.sensitive_literal",
9060
+ message: "agents.yaml contains a credential value in a sensitive field. Replace it with an environment variable reference before creating or restoring a version."
9061
+ });
9062
+ }
9063
+ return {
9064
+ diagnostics: redactDiagnostics(diagnostics, displaySecrets),
9065
+ redacted_source: redactDocumentSource(source, document, displaySecrets),
9066
+ sensitive_literals: sensitiveLiterals.map(() => REDACTED)
9067
+ };
9068
+ }
9069
+ function collectSensitiveScalars(value, result = /* @__PURE__ */ new Set(), key = "", ancestorSensitive = false) {
9070
+ if (Array.isArray(value)) {
9071
+ const nestedSensitive = ancestorSensitive || isSensitiveValueKey(key);
9072
+ for (const entry of value) collectSensitiveScalars(entry, result, key, nestedSensitive);
9073
+ return result;
9074
+ }
9075
+ if (isRecord2(value)) {
9076
+ const nestedSensitive = ancestorSensitive || isSensitiveContainerKey(key);
9077
+ for (const [entryKey, entry] of Object.entries(value)) {
9078
+ collectSensitiveScalars(entry, result, entryKey, nestedSensitive);
9079
+ }
9080
+ return result;
9081
+ }
9082
+ if ((ancestorSensitive || isSensitiveValueKey(key)) && (typeof value === "string" || typeof value === "number") && String(value).length > 0) {
9083
+ result.add(String(value));
9084
+ }
9085
+ return result;
9086
+ }
9087
+ function isSensitiveContainerKey(key) {
9088
+ return ["header", "headers", "authorization"].includes(key.toLowerCase().replaceAll("-", "_"));
9089
+ }
9090
+ function isSensitiveValueKey(key) {
9091
+ const normalized = key.toLowerCase().replaceAll("-", "_");
9092
+ if (normalized === "secret_name" || normalized === "credentials") return false;
9093
+ return SENSITIVE_KEY.test(normalized);
9094
+ }
9095
+ function redactDocumentSource(source, document, secrets) {
9096
+ if (secrets.size === 0) return source;
9097
+ const redactedDocument = document.clone();
9098
+ visit(redactedDocument, (_key, node) => {
9099
+ if (isScalar(node) && (typeof node.value === "string" || typeof node.value === "number")) {
9100
+ const value = String(node.value);
9101
+ const redacted = redactText(value, secrets);
9102
+ if (redacted !== value) {
9103
+ node.value = redacted;
9104
+ node.source = redacted;
9105
+ node.type = "PLAIN";
9106
+ }
9107
+ }
9108
+ redactComments(node, secrets);
9109
+ });
9110
+ redactComments(redactedDocument, secrets);
9111
+ return redactedDocument.toString();
9112
+ }
9113
+ function redactText(source, secrets) {
9114
+ let redacted = source;
9115
+ for (const secret of [...secrets].sort((left, right) => right.length - left.length)) {
9116
+ redacted = redacted.replaceAll(secret, REDACTED);
9117
+ }
9118
+ return redacted;
9119
+ }
9120
+ function redactComments(value, secrets) {
9121
+ if (!value || typeof value !== "object") return;
9122
+ const commented = value;
9123
+ if (commented.comment) commented.comment = redactText(commented.comment, secrets);
9124
+ if (commented.commentBefore) commented.commentBefore = redactText(commented.commentBefore, secrets);
9125
+ }
9126
+ function redactDiagnostics(diagnostics, secrets) {
9127
+ return diagnostics.map((diagnostic) => ({
9128
+ ...diagnostic,
9129
+ message: redactText(diagnostic.message, secrets)
9130
+ }));
9131
+ }
9132
+ function isRecord2(value) {
9133
+ return typeof value === "object" && value !== null && !Array.isArray(value);
9134
+ }
9135
+
8459
9136
  // src/internal/core/sync-runtime.ts
8460
9137
  import { stringify as stringifyYaml } from "yaml";
8461
9138
  var SYNCABLE_GROUP = {
@@ -8783,6 +9460,378 @@ function buildDeploymentContext(ctx, name, provider) {
8783
9460
  };
8784
9461
  }
8785
9462
 
9463
+ // src/internal/core/managed-api-runtime.ts
9464
+ function resolveAdapter(ctx, provider) {
9465
+ if (provider) return getRuntimeProvider(ctx, provider);
9466
+ const configured = Array.from(ctx.providers.keys());
9467
+ if (configured.length === 1) return getRuntimeProvider(ctx, configured[0]);
9468
+ throw new UserError("Multiple providers configured. Use --provider to specify one.");
9469
+ }
9470
+ function requiredMethod(value, provider, operation) {
9471
+ if (value) return value;
9472
+ throw new UserError(`Provider '${provider}' does not support ${operation}.`);
9473
+ }
9474
+ async function listRemoteAgents(ctx, options = {}) {
9475
+ const adapter2 = resolveAdapter(ctx, options.provider);
9476
+ const method2 = requiredMethod(adapter2.listAgentResources, adapter2.name, "agent listing");
9477
+ return method2.call(adapter2, options);
9478
+ }
9479
+ async function getRemoteAgent(ctx, id, options = {}) {
9480
+ const adapter2 = resolveAdapter(ctx, options.provider);
9481
+ const method2 = requiredMethod(adapter2.getRemoteAgent, adapter2.name, "agent lookup");
9482
+ return method2.call(adapter2, id, options.version);
9483
+ }
9484
+ async function listRemoteAgentVersions(ctx, id, options = {}) {
9485
+ const adapter2 = resolveAdapter(ctx, options.provider);
9486
+ const method2 = requiredMethod(adapter2.listAgentVersions, adapter2.name, "agent version listing");
9487
+ return method2.call(adapter2, id, options);
9488
+ }
9489
+ async function listRemoteEnvironments(ctx, options = {}) {
9490
+ const adapter2 = resolveAdapter(ctx, options.provider);
9491
+ const method2 = requiredMethod(adapter2.listEnvironmentResources, adapter2.name, "environment listing");
9492
+ return method2.call(adapter2, options);
9493
+ }
9494
+ async function getRemoteEnvironment(ctx, id, options = {}) {
9495
+ const adapter2 = resolveAdapter(ctx, options.provider);
9496
+ const method2 = requiredMethod(adapter2.getRemoteEnvironment, adapter2.name, "environment lookup");
9497
+ return method2.call(adapter2, id);
9498
+ }
9499
+ async function listRemoteVaults(ctx, options = {}) {
9500
+ const adapter2 = resolveAdapter(ctx, options.provider);
9501
+ const method2 = requiredMethod(adapter2.listVaultResources, adapter2.name, "vault listing");
9502
+ return method2.call(adapter2, options);
9503
+ }
9504
+ async function getRemoteVault(ctx, id, options = {}) {
9505
+ const adapter2 = resolveAdapter(ctx, options.provider);
9506
+ const method2 = requiredMethod(adapter2.getRemoteVault, adapter2.name, "vault lookup");
9507
+ return method2.call(adapter2, id);
9508
+ }
9509
+ async function listRemoteSkills(ctx, options = {}) {
9510
+ const adapter2 = resolveAdapter(ctx, options.provider);
9511
+ const method2 = requiredMethod(adapter2.listSkillResources, adapter2.name, "skill listing");
9512
+ return method2.call(adapter2, options);
9513
+ }
9514
+ async function getRemoteSkill(ctx, id, options = {}) {
9515
+ const adapter2 = resolveAdapter(ctx, options.provider);
9516
+ const method2 = requiredMethod(adapter2.getSkillInfo, adapter2.name, "skill lookup");
9517
+ return method2.call(adapter2, id);
9518
+ }
9519
+ async function listRemoteSkillVersions(ctx, id, options = {}) {
9520
+ const adapter2 = resolveAdapter(ctx, options.provider);
9521
+ const method2 = requiredMethod(adapter2.listSkillVersions, adapter2.name, "skill version listing");
9522
+ return method2.call(adapter2, id, options);
9523
+ }
9524
+ async function getRemoteSkillVersion(ctx, id, version, options = {}) {
9525
+ const adapter2 = resolveAdapter(ctx, options.provider);
9526
+ const method2 = requiredMethod(adapter2.getSkillVersion, adapter2.name, "skill version lookup");
9527
+ return method2.call(adapter2, id, version);
9528
+ }
9529
+ async function getRemoteSkillDownloadInfo(ctx, id, version, options = {}) {
9530
+ const adapter2 = resolveAdapter(ctx, options.provider);
9531
+ const method2 = requiredMethod(adapter2.getSkillDownloadInfo, adapter2.name, "skill version download");
9532
+ return method2.call(adapter2, id, version);
9533
+ }
9534
+ async function downloadRemoteSkill(ctx, id, version, options = {}) {
9535
+ const info = await getRemoteSkillDownloadInfo(ctx, id, version, options);
9536
+ const response = await resolveFetch()(info.file_url, { method: "GET" });
9537
+ if (!response.ok) {
9538
+ throw new ApiError(response.status, await response.text(), "Skill download failed");
9539
+ }
9540
+ return new Uint8Array(await response.arrayBuffer());
9541
+ }
9542
+ async function listRemoteFiles(ctx, options = {}) {
9543
+ const adapter2 = resolveAdapter(ctx, options.provider);
9544
+ const method2 = requiredMethod(adapter2.listFileResources, adapter2.name, "file listing");
9545
+ return method2.call(adapter2, options);
9546
+ }
9547
+ async function downloadRemoteFile(ctx, id, options = {}) {
9548
+ const adapter2 = resolveAdapter(ctx, options.provider);
9549
+ const method2 = requiredMethod(adapter2.downloadFileContent, adapter2.name, "file content download");
9550
+ return method2.call(adapter2, id);
9551
+ }
9552
+ async function updateRemoteSession(ctx, id, input, options = {}) {
9553
+ const adapter2 = resolveAdapter(ctx, options.provider);
9554
+ const method2 = requiredMethod(adapter2.updateSession, adapter2.name, "session update");
9555
+ return method2.call(adapter2, id, input);
9556
+ }
9557
+ async function archiveRemoteSession(ctx, id, options = {}) {
9558
+ const adapter2 = resolveAdapter(ctx, options.provider);
9559
+ const method2 = requiredMethod(adapter2.archiveSession, adapter2.name, "session archive");
9560
+ return method2.call(adapter2, id);
9561
+ }
9562
+ async function sendRemoteSessionEvents(ctx, id, events, options = {}) {
9563
+ const adapter2 = resolveAdapter(ctx, options.provider);
9564
+ const method2 = requiredMethod(adapter2.sendSessionEvents, adapter2.name, "generic session event sending");
9565
+ return method2.call(adapter2, id, events);
9566
+ }
9567
+ async function listRemoteDeployments(ctx, options = {}) {
9568
+ const adapter2 = resolveAdapter(ctx, options.provider);
9569
+ const method2 = requiredMethod(adapter2.listDeployments, adapter2.name, "deployment listing");
9570
+ return method2.call(adapter2, options);
9571
+ }
9572
+ async function getRemoteDeployment(ctx, id, options = {}) {
9573
+ const adapter2 = resolveAdapter(ctx, options.provider);
9574
+ const method2 = requiredMethod(adapter2.getDeploymentById, adapter2.name, "deployment lookup");
9575
+ return method2.call(adapter2, id);
9576
+ }
9577
+ async function runRemoteDeployment(ctx, id, options = {}) {
9578
+ const adapter2 = resolveAdapter(ctx, options.provider);
9579
+ const method2 = requiredMethod(adapter2.runDeploymentById, adapter2.name, "deployment run");
9580
+ return method2.call(adapter2, id);
9581
+ }
9582
+ async function setRemoteDeploymentPaused(ctx, id, paused, options = {}) {
9583
+ const adapter2 = resolveAdapter(ctx, options.provider);
9584
+ const method2 = paused ? adapter2.pauseDeploymentById : adapter2.unpauseDeploymentById;
9585
+ return requiredMethod(method2, adapter2.name, `${paused ? "pausing" : "unpausing"} deployments`).call(adapter2, id);
9586
+ }
9587
+ async function listRemoteDeploymentRuns(ctx, deploymentId, options = {}) {
9588
+ const adapter2 = resolveAdapter(ctx, options.provider);
9589
+ const method2 = requiredMethod(adapter2.listDeploymentRuns, adapter2.name, "deployment run listing");
9590
+ return method2.call(adapter2, deploymentId, options);
9591
+ }
9592
+ async function getRemoteDeploymentRun(ctx, runId, options = {}) {
9593
+ const adapter2 = resolveAdapter(ctx, options.provider);
9594
+ const method2 = requiredMethod(adapter2.getDeploymentRun, adapter2.name, "deployment run lookup");
9595
+ return method2.call(adapter2, runId);
9596
+ }
9597
+ var API_KEY = { supported: true, auth: "api_key" };
9598
+ var CLIENT_SEARCH = {
9599
+ supported: true,
9600
+ auth: "api_key",
9601
+ reason: "Client-side filtering over the corresponding list API."
9602
+ };
9603
+ var UNSUPPORTED_MODEL = {
9604
+ supported: false,
9605
+ auth: null,
9606
+ reason: "The public Managed Agents API does not expose a model catalog endpoint."
9607
+ };
9608
+ var UNSUPPORTED_THREAD = {
9609
+ supported: false,
9610
+ auth: null,
9611
+ reason: "Managed Agents exposes child-thread ids and lifecycle events through Session Events, but no independent Thread resource API."
9612
+ };
9613
+ var UNSUPPORTED_OAUTH = {
9614
+ supported: false,
9615
+ auth: null,
9616
+ reason: "The public Managed Agents data plane does not expose MCP OAuth login."
9617
+ };
9618
+ var BAILIAN_OPERATIONS = {
9619
+ "agent.create": { ...API_KEY, reason: "YAML declaration plus scoped create-only apply." },
9620
+ "agent.list": API_KEY,
9621
+ "agent.get": API_KEY,
9622
+ "agent.search": CLIENT_SEARCH,
9623
+ "agent.versions": API_KEY,
9624
+ "environment.create": { ...API_KEY, reason: "YAML declaration plus scoped create-only apply." },
9625
+ "environment.list": API_KEY,
9626
+ "environment.get": API_KEY,
9627
+ "environment.search": CLIENT_SEARCH,
9628
+ "skill.create": { ...API_KEY, reason: "YAML declaration plus scoped create-only apply." },
9629
+ "skill.list": API_KEY,
9630
+ "skill.get": API_KEY,
9631
+ "skill.search": CLIENT_SEARCH,
9632
+ "skill.versions": API_KEY,
9633
+ "skill.download": API_KEY,
9634
+ "vault.create": { ...API_KEY, reason: "YAML declaration plus scoped create-only apply." },
9635
+ "vault.credential.create": {
9636
+ ...API_KEY,
9637
+ reason: "YAML declaration plus scoped Vault transaction; Bailian supports environment_variable credentials only."
9638
+ },
9639
+ "vault.list": API_KEY,
9640
+ "vault.get": API_KEY,
9641
+ "vault.search": CLIENT_SEARCH,
9642
+ "deployment.create": { ...API_KEY, reason: "YAML declaration plus scoped create-only apply." },
9643
+ "deployment.list": API_KEY,
9644
+ "deployment.get": API_KEY,
9645
+ "deployment.search": { ...API_KEY, reason: "Maps to the server-side keyword parameter." },
9646
+ "deployment.runs.list": API_KEY,
9647
+ "deployment.runs.get": API_KEY,
9648
+ "deployment.run": API_KEY,
9649
+ "deployment.pause": API_KEY,
9650
+ "deployment.unpause": API_KEY,
9651
+ "session.create": API_KEY,
9652
+ "session.list": API_KEY,
9653
+ "session.get": API_KEY,
9654
+ "session.search": CLIENT_SEARCH,
9655
+ "session.update": API_KEY,
9656
+ "session.archive": API_KEY,
9657
+ "session.delete": API_KEY,
9658
+ "session.run": { ...API_KEY, reason: "Client composition of session create and event send/stream." },
9659
+ "session.event.send": API_KEY,
9660
+ "session.event.list": API_KEY,
9661
+ "session.event.stream": API_KEY,
9662
+ "session.debug": { ...API_KEY, reason: "Client-side aggregation of supported read APIs." },
9663
+ "session.export": { ...API_KEY, reason: "Client-side export of supported read APIs." },
9664
+ "file.upload": API_KEY,
9665
+ "file.list": API_KEY,
9666
+ "file.get": API_KEY,
9667
+ "file.search": CLIENT_SEARCH,
9668
+ "file.download": API_KEY,
9669
+ "file.delete": API_KEY,
9670
+ "model.list": UNSUPPORTED_MODEL,
9671
+ "model.search": UNSUPPORTED_MODEL,
9672
+ "session_thread.list": UNSUPPORTED_THREAD,
9673
+ "session_thread.get": UNSUPPORTED_THREAD,
9674
+ "session_thread.archive": UNSUPPORTED_THREAD,
9675
+ "session_thread.events": UNSUPPORTED_THREAD,
9676
+ "mcp.oauth_login": UNSUPPORTED_OAUTH
9677
+ };
9678
+ function getManagedAgentProviderCapabilities(provider) {
9679
+ if (provider === "bailian") {
9680
+ return { provider, operations: { ...BAILIAN_OPERATIONS } };
9681
+ }
9682
+ return {
9683
+ provider,
9684
+ operations: {
9685
+ "managed_agent.api": {
9686
+ supported: false,
9687
+ auth: null,
9688
+ reason: "The operation-level API command surface is currently implemented for Bailian only."
9689
+ }
9690
+ }
9691
+ };
9692
+ }
9693
+
9694
+ // src/internal/core/vault-credential-runtime.ts
9695
+ async function planVaultCredentialCreate(ctx, vaultName, credentialName, options = {}) {
9696
+ const prepared = await prepareVaultCredentialCreate(ctx, vaultName, credentialName, options);
9697
+ return {
9698
+ provider: prepared.provider,
9699
+ vault: vaultName,
9700
+ vaultRemoteId: prepared.vaultState.remote_id,
9701
+ credential: credentialName,
9702
+ remoteChecked: prepared.remoteChecked,
9703
+ reuseRemote: Boolean(prepared.remoteCredential),
9704
+ remoteCredentialId: prepared.remoteCredential?.id
9705
+ };
9706
+ }
9707
+ async function planVaultCredentialCreateWithStateBackend(input, vaultName, credentialName, options = {}) {
9708
+ return readProjectRuntime(input, (ctx) => planVaultCredentialCreate(ctx, vaultName, credentialName, options));
9709
+ }
9710
+ async function createVaultCredential(ctx, vaultName, credentialName, options = {}) {
9711
+ if (options.checkRemote === false) {
9712
+ throw new UserError("Vault Credential create requires the remote duplicate check.");
9713
+ }
9714
+ const prepared = await prepareVaultCredentialCreate(ctx, vaultName, credentialName, options);
9715
+ const remote = prepared.remoteCredential ?? await prepared.adapter.createCredential(prepared.vaultState.remote_id, prepared.credential);
9716
+ if (!remote.id) throw new UserError("Credential create returned no remote id.");
9717
+ const address = { type: "vault", name: vaultName, provider: prepared.provider };
9718
+ const desiredHash = await computeResourceHash(address, ctx.config, ctx.configPath, ctx.state);
9719
+ ctx.state.setResource({
9720
+ ...prepared.vaultState,
9721
+ content_hash: desiredHash,
9722
+ desired_hash: desiredHash,
9723
+ drift_paths: [],
9724
+ drift_status: "unchecked"
9725
+ });
9726
+ await ctx.state.save();
9727
+ return {
9728
+ provider: prepared.provider,
9729
+ vault: vaultName,
9730
+ vaultRemoteId: prepared.vaultState.remote_id,
9731
+ credential: credentialName,
9732
+ remoteChecked: prepared.remoteChecked,
9733
+ credentialId: remote.id,
9734
+ reuseRemote: Boolean(prepared.remoteCredential),
9735
+ remoteCredentialId: prepared.remoteCredential?.id,
9736
+ adopted: Boolean(prepared.remoteCredential)
9737
+ };
9738
+ }
9739
+ async function createVaultCredentialWithStateBackend(input, vaultName, credentialName, options = {}) {
9740
+ return writeProjectRuntime(input, (ctx) => createVaultCredential(ctx, vaultName, credentialName, options));
9741
+ }
9742
+ async function prepareVaultCredentialCreate(ctx, vaultName, credentialName, options) {
9743
+ const vault = ctx.config.vaults?.[vaultName];
9744
+ if (!vault) throw new UserError(`Vault '${vaultName}' is not declared in the project config.`);
9745
+ const provider = resolveVaultProvider(ctx, vault.provider, options.provider);
9746
+ const credential = vault.credentials.at(-1);
9747
+ if (!credential || credential.name !== credentialName) {
9748
+ throw new UserError(`Credential '${credentialName}' must be the final newly appended entry in vault.${vaultName}.`);
9749
+ }
9750
+ if (vault.credentials.slice(0, -1).some((entry) => entry.name === credentialName)) {
9751
+ throw new UserError(`Vault '${vaultName}' already declares a credential named '${credentialName}'.`);
9752
+ }
9753
+ if (provider === "bailian" && credential.type !== "environment_variable") {
9754
+ throw new UserError(
9755
+ `Credential '${credentialName}' uses '${credential.type}', but Bailian only supports 'environment_variable' credentials.`
9756
+ );
9757
+ }
9758
+ const address = { type: "vault", name: vaultName, provider };
9759
+ const priorConfig = structuredClone(ctx.config);
9760
+ priorConfig.vaults[vaultName] = {
9761
+ ...priorConfig.vaults[vaultName],
9762
+ credentials: priorConfig.vaults[vaultName].credentials.slice(0, -1)
9763
+ };
9764
+ const priorPlan = await planProjectContext(
9765
+ { ...ctx, config: priorConfig },
9766
+ {
9767
+ provider,
9768
+ scope: { roots: [address] },
9769
+ refresh: options.refresh,
9770
+ quiet: options.quiet ?? true
9771
+ }
9772
+ );
9773
+ const refreshError = priorPlan.refreshResult?.errors[0];
9774
+ if (refreshError) {
9775
+ throw new UserError(`Cannot verify vault.${vaultName} because refresh failed: ${refreshError.error}`);
9776
+ }
9777
+ const errorDiagnostic = priorPlan.plan.diagnostics.find((diagnostic) => diagnostic.severity === "error");
9778
+ if (errorDiagnostic) throw new UserError(errorDiagnostic.message);
9779
+ const vaultAction = priorPlan.plan.actions.find(
9780
+ (action) => action.address.type === "vault" && action.address.name === vaultName
9781
+ );
9782
+ if (vaultAction?.action !== "no-op") {
9783
+ throw new UserError(
9784
+ `vault.${vaultName} must be tracked and up-to-date before adding a credential; current action is '${vaultAction?.action ?? "missing"}'.`
9785
+ );
9786
+ }
9787
+ const vaultState = ctx.state.getResource(address);
9788
+ if (!vaultState?.remote_id) throw new UserError(`vault.${vaultName} has no tracked remote id.`);
9789
+ const adapter2 = getRuntimeProvider(ctx, provider);
9790
+ if (!adapter2.createCredential || !adapter2.listCredentials) {
9791
+ throw new UserError(`Provider '${provider}' does not support scoped Vault Credential create.`);
9792
+ }
9793
+ const remoteChecked = options.checkRemote !== false;
9794
+ const sameName = remoteChecked ? (await adapter2.listCredentials(vaultState.remote_id)).filter(
9795
+ (remoteCredential) => remoteCredential.display_name === credentialName
9796
+ ) : [];
9797
+ const exact = sameName.find((remoteCredential) => credentialMatches(remoteCredential, credential));
9798
+ if (sameName.length > 0 && !exact) {
9799
+ throw new UserError(`Vault '${vaultName}' already has a different remote credential named '${credentialName}'.`);
9800
+ }
9801
+ return { provider, credential, vaultState, adapter: adapter2, remoteChecked, remoteCredential: exact };
9802
+ }
9803
+ function resolveVaultProvider(ctx, declaredProvider, requestedProvider) {
9804
+ if (requestedProvider && declaredProvider && requestedProvider !== declaredProvider) {
9805
+ throw new UserError(
9806
+ `Vault provider '${declaredProvider}' does not match requested provider '${requestedProvider}'.`
9807
+ );
9808
+ }
9809
+ const provider = requestedProvider ?? declaredProvider ?? ctx.config.defaults?.provider;
9810
+ if (provider && provider !== "all") return provider;
9811
+ const configured = [...ctx.providers.keys()];
9812
+ if (configured.length === 1) return configured[0];
9813
+ throw new UserError("Cannot infer one provider for Vault Credential create.");
9814
+ }
9815
+ function credentialMatches(remote, desired) {
9816
+ if (remote.auth_type !== desired.type || !metadataMatches(remote.metadata, desired.metadata)) return false;
9817
+ if (desired.type === "static_bearer") return remote.mcp_server_url === desired.mcp_server_url;
9818
+ const desiredHosts = credentialHosts(desired.networking);
9819
+ const remoteHosts = credentialHosts(remote.networking ?? { type: remote.networking_type });
9820
+ const desiredLocation = desired.injection_location;
9821
+ const remoteLocation = remote.injection_location;
9822
+ if (desiredLocation && !remoteLocation) return false;
9823
+ return remote.secret_name === desired.secret_name && desiredHosts !== void 0 && remoteHosts !== void 0 && desiredHosts.length === remoteHosts.length && desiredHosts.every((host) => remoteHosts.includes(host)) && (desiredLocation?.header ?? true) === (remoteLocation?.header ?? true) && (desiredLocation?.body ?? false) === (remoteLocation?.body ?? false);
9824
+ }
9825
+ function credentialHosts(networking) {
9826
+ if (networking?.allowed_hosts !== void 0) return [...new Set(networking.allowed_hosts)];
9827
+ return networking?.type === "limited" ? void 0 : ["*"];
9828
+ }
9829
+ function metadataMatches(remote, desired) {
9830
+ const remoteEntries = Object.entries(remote ?? {});
9831
+ const desiredEntries = Object.entries(desired ?? {});
9832
+ return remoteEntries.length === desiredEntries.length && desiredEntries.every(([key, value]) => remote?.[key] === value);
9833
+ }
9834
+
8786
9835
  // src/internal/core/destroy-runtime.ts
8787
9836
  var destroyOrder = {
8788
9837
  deployment: 0,
@@ -8805,11 +9854,14 @@ function planDestroyProjectContext(ctx) {
8805
9854
  for (const [agentName, agent] of Object.entries(ctx.config.agents ?? {})) {
8806
9855
  if (!agent.default_memory_store || agent.delivery?.qoder?.type !== "forward") continue;
8807
9856
  if (agent.provider && agent.provider !== "qoder") continue;
9857
+ const identityId = identityName ? ctx.state.getResource({ type: "identity", name: identityName, provider: "qoder" })?.remote_id ?? null : null;
9858
+ const templateId = ctx.state.getResource({ type: "template", name: agentName, provider: "qoder" })?.remote_id ?? null;
9859
+ if (!identityId && !templateId) continue;
8808
9860
  defaultMemoryStores.push({
8809
9861
  agentName,
8810
9862
  provider: "qoder",
8811
- identityId: identityName ? ctx.state.getResource({ type: "identity", name: identityName, provider: "qoder" })?.remote_id ?? null : null,
8812
- templateId: ctx.state.getResource({ type: "template", name: agentName, provider: "qoder" })?.remote_id ?? null,
9863
+ identityId,
9864
+ templateId,
8813
9865
  deleteOnDestroy: agent.default_memory_store.delete_on_destroy ?? false
8814
9866
  });
8815
9867
  }
@@ -9322,6 +10374,7 @@ function buildAgentDecl(base, input) {
9322
10374
  });
9323
10375
  const agent = {
9324
10376
  ...base ?? {},
10377
+ name: input.name ?? base?.name,
9325
10378
  description: input.description ?? base?.description,
9326
10379
  model,
9327
10380
  instructions: input.instructions ?? base?.instructions ?? "",
@@ -9365,6 +10418,7 @@ function buildSessionBindings(agentName, config, provider, state, options = {})
9365
10418
  throw new UserError(`Agent '${agentName}' not found in config. Available agents: ${available || "(none)"}`);
9366
10419
  }
9367
10420
  const sessionResources = options.resources ?? agent.resources;
10421
+ const sessionFiles = resolveSessionFiles(agentName, agent, provider, state, options.files ?? []);
9368
10422
  const environmentVariables = options.environmentVariables ?? agent.environment_variables;
9369
10423
  if (environmentVariables && provider !== "qoder") {
9370
10424
  throw new UserError("Session environment variables are supported only by Qoder.");
@@ -9395,7 +10449,7 @@ function buildSessionBindings(agentName, config, provider, state, options = {})
9395
10449
  delivery: "forward",
9396
10450
  template_id: templateId,
9397
10451
  identity_id: identityId,
9398
- files: (options.files ?? []).map((file) => ({ file_id: file.fileId, mount_path: file.mountPath })),
10452
+ files: sessionFiles,
9399
10453
  title: options.title,
9400
10454
  metadata: options.metadata,
9401
10455
  environment_variables: environmentVariables
@@ -9440,13 +10494,41 @@ function buildSessionBindings(agentName, config, provider, state, options = {})
9440
10494
  tunnel_id: tunnelId,
9441
10495
  vault_ids: vaultIds,
9442
10496
  memory_store_ids: memoryStoreIds,
9443
- files: (options.files ?? []).map((f) => ({ file_id: f.fileId, mount_path: f.mountPath })),
10497
+ files: sessionFiles,
9444
10498
  resources: sessionResources,
9445
10499
  title: options.title,
9446
10500
  metadata: options.metadata,
9447
10501
  environment_variables: environmentVariables
9448
10502
  };
9449
10503
  }
10504
+ function resolveSessionFiles(agentName, agent, provider, state, explicitFiles) {
10505
+ const resolved = [];
10506
+ const mountOwners = /* @__PURE__ */ new Map();
10507
+ for (const file of agent.files ?? []) {
10508
+ if (typeof file === "string") continue;
10509
+ const mountPath = resolveSandboxMountPath(provider, file.mount_path);
10510
+ assertUniqueMountPath(mountOwners, mountPath, `declared file '${file.file}'`, agentName);
10511
+ resolved.push({
10512
+ file_id: requireRef(state, { type: "file", name: file.file, provider }),
10513
+ mount_path: mountPath
10514
+ });
10515
+ }
10516
+ for (const file of explicitFiles) {
10517
+ const mountPath = resolveSandboxMountPath(provider, file.mountPath);
10518
+ assertUniqueMountPath(mountOwners, mountPath, `Session file '${file.fileId}'`, agentName);
10519
+ resolved.push({ file_id: file.fileId, mount_path: mountPath });
10520
+ }
10521
+ return resolved;
10522
+ }
10523
+ function assertUniqueMountPath(mountOwners, mountPath, owner, agentName) {
10524
+ const existing = mountOwners.get(mountPath);
10525
+ if (existing) {
10526
+ throw new UserError(
10527
+ `Agent '${agentName}' cannot mount ${owner} at '${mountPath}'; the path is already used by ${existing}.`
10528
+ );
10529
+ }
10530
+ mountOwners.set(mountPath, owner);
10531
+ }
9450
10532
  function resolveTunnelId(agent, config, options, provider) {
9451
10533
  const tunnelName = options.tunnel ?? agent.tunnel;
9452
10534
  if (!options.tunnelId && !tunnelName) return void 0;
@@ -9466,6 +10548,74 @@ function validateResourceInConfig(name, type, resources) {
9466
10548
  }
9467
10549
  }
9468
10550
 
10551
+ // src/internal/state/backend.ts
10552
+ function cloneStateFile(state) {
10553
+ return structuredClone(state);
10554
+ }
10555
+
10556
+ // src/internal/state/in-memory-state-manager.ts
10557
+ var InMemoryStateManager = class _InMemoryStateManager {
10558
+ state;
10559
+ index;
10560
+ constructor(state) {
10561
+ this.state = state;
10562
+ this.index = this.buildIndex();
10563
+ }
10564
+ buildIndex() {
10565
+ const idx = /* @__PURE__ */ new Map();
10566
+ for (let i = 0; i < this.state.resources.length; i++) {
10567
+ idx.set(addressKey(this.state.resources[i].address), i);
10568
+ }
10569
+ return idx;
10570
+ }
10571
+ static fromJSON(data) {
10572
+ return new _InMemoryStateManager(structuredClone(data));
10573
+ }
10574
+ static empty() {
10575
+ return new _InMemoryStateManager({ resources: [] });
10576
+ }
10577
+ getResource(address) {
10578
+ const i = this.index.get(addressKey(address));
10579
+ return i !== void 0 ? this.state.resources[i] : void 0;
10580
+ }
10581
+ setResource(resource) {
10582
+ const key = addressKey(resource.address);
10583
+ const i = this.index.get(key);
10584
+ if (i !== void 0) {
10585
+ this.state.resources[i] = resource;
10586
+ } else {
10587
+ this.index.set(key, this.state.resources.length);
10588
+ this.state.resources.push(resource);
10589
+ }
10590
+ }
10591
+ removeResource(address) {
10592
+ const key = addressKey(address);
10593
+ const i = this.index.get(key);
10594
+ if (i === void 0) return;
10595
+ this.state.resources.splice(i, 1);
10596
+ this.index.delete(key);
10597
+ for (let j = i; j < this.state.resources.length; j++) {
10598
+ this.index.set(addressKey(this.state.resources[j].address), j);
10599
+ }
10600
+ }
10601
+ listResources() {
10602
+ return [...this.state.resources];
10603
+ }
10604
+ findResource(query2) {
10605
+ return this.state.resources.find((resource) => {
10606
+ const matchType = resource.address.type === query2.type;
10607
+ const matchName = resource.address.name === query2.name;
10608
+ const matchProvider = !query2.provider || resource.address.provider === query2.provider;
10609
+ return matchType && matchName && matchProvider;
10610
+ });
10611
+ }
10612
+ getStateFile() {
10613
+ return this.state;
10614
+ }
10615
+ async save() {
10616
+ }
10617
+ };
10618
+
9469
10619
  // src/internal/core/agent-runtime.ts
9470
10620
  function listAgents(ctx) {
9471
10621
  const agents = ctx.config.agents ?? {};
@@ -9556,34 +10706,64 @@ async function listAgentsWithReadiness(ctx, options = {}) {
9556
10706
  readiness: getAgentReadinessFromPlan(ctx, agent.id, planResult.plan)
9557
10707
  }));
9558
10708
  }
10709
+ function isAgentRunnable(readiness) {
10710
+ return readiness.status === "ready" || readiness.status === "drifted" && readiness.driftSeverity === "non_blocking";
10711
+ }
9559
10712
  async function planAgentResources(ctx, agentId, options = {}) {
9560
10713
  const agent = getAgent(ctx, agentId);
10714
+ const addresses = collectAgentAddresses(ctx.config, agent.agentName, agent.provider);
9561
10715
  const planned = await planProjectContext(ctx, {
9562
10716
  provider: agent.provider,
10717
+ scope: { roots: options.scope === "runtime" ? addresses : [addresses[0]] },
10718
+ mode: options.mode,
9563
10719
  refresh: options.refresh,
9564
- quiet: options.quiet ?? true
10720
+ quiet: options.quiet ?? true,
10721
+ onFeedback: options.onFeedback
9565
10722
  });
9566
- const actions = filterAgentActions(ctx, agent, planned.plan);
10723
+ const actions = planned.plan.actions;
10724
+ const diagnostics = planned.plan.diagnostics;
9567
10725
  return {
9568
10726
  agentId,
9569
10727
  provider: agent.provider,
10728
+ fingerprint: computeAgentPlanFingerprint(agentId, agent.provider, actions, diagnostics),
9570
10729
  actions,
9571
- diagnostics: filterAgentDiagnostics(ctx, agent, planned.plan),
10730
+ diagnostics,
9572
10731
  destructiveActions: selectDestructive(actions),
9573
10732
  planned
9574
10733
  };
9575
10734
  }
10735
+ async function planAgentResourcesWithStateBackend(input, agentId, options = {}) {
10736
+ return readProjectRuntime(input, (ctx) => planAgentResources(ctx, agentId, options));
10737
+ }
9576
10738
  async function syncAgentResources(ctx, agentId, options = {}) {
9577
10739
  return runAgentSync(ctx, agentId, options);
9578
10740
  }
9579
10741
  async function runAgentSync(ctx, agentId, options) {
9580
- const fullPlan = await planAgentResources(ctx, agentId, {
10742
+ const transactionalState = options.expectedPlanFingerprint ? InMemoryStateManager.fromJSON(cloneStateFile(ctx.state.getStateFile())) : void 0;
10743
+ const planningContext = transactionalState ? { ...ctx, state: transactionalState } : ctx;
10744
+ const fullPlan = await planAgentResources(planningContext, agentId, {
9581
10745
  refresh: options.refresh,
9582
- quiet: options.quiet
10746
+ quiet: options.quiet,
10747
+ onFeedback: options.onFeedback,
10748
+ scope: options.scope,
10749
+ mode: options.mode
9583
10750
  });
9584
10751
  const actions = fullPlan.actions;
9585
10752
  const destructiveActions = fullPlan.destructiveActions;
9586
10753
  const errorDiagnostic = fullPlan.diagnostics.find((diagnostic) => diagnostic.severity === "error");
10754
+ if (options.expectedPlanFingerprint && options.expectedPlanFingerprint !== fullPlan.fingerprint) {
10755
+ return {
10756
+ agentId,
10757
+ provider: fullPlan.provider,
10758
+ status: "blocked",
10759
+ reason: "plan_stale",
10760
+ actions,
10761
+ diagnostics: fullPlan.diagnostics,
10762
+ destructiveActions,
10763
+ results: [],
10764
+ error: "The project or remote resources changed after planning. Create a new plan before applying."
10765
+ };
10766
+ }
9587
10767
  const decision = await decideDestructive(destructiveActions, {
9588
10768
  policy: options.policy,
9589
10769
  confirm: options.confirm
@@ -9593,6 +10773,7 @@ async function runAgentSync(ctx, agentId, options) {
9593
10773
  agentId,
9594
10774
  provider: fullPlan.provider,
9595
10775
  status: "blocked",
10776
+ reason: decision === "cancelled" ? "cancelled" : "destructive_blocked",
9596
10777
  actions,
9597
10778
  diagnostics: fullPlan.diagnostics,
9598
10779
  destructiveActions,
@@ -9605,6 +10786,7 @@ async function runAgentSync(ctx, agentId, options) {
9605
10786
  agentId,
9606
10787
  provider: fullPlan.provider,
9607
10788
  status: "blocked",
10789
+ reason: "diagnostic_error",
9608
10790
  actions,
9609
10791
  diagnostics: fullPlan.diagnostics,
9610
10792
  destructiveActions,
@@ -9613,13 +10795,11 @@ async function runAgentSync(ctx, agentId, options) {
9613
10795
  };
9614
10796
  }
9615
10797
  try {
9616
- const scopedPlan = {
9617
- diagnostics: fullPlan.diagnostics,
9618
- actions: scopePlanActions(fullPlan.planned.plan, actions)
9619
- };
9620
- const execution = await executePlannedProject(replaceResourcePlan(fullPlan.planned, scopedPlan), {
10798
+ const execution = await executePlannedProject(fullPlan.planned, {
10799
+ onFeedback: options.onFeedback,
9621
10800
  policy: "force"
9622
10801
  });
10802
+ if (transactionalState) await replaceState(ctx.state, transactionalState);
9623
10803
  const results = toAgentSyncResults(execution);
9624
10804
  const failed = results.find((result) => result.status === "failed");
9625
10805
  return {
@@ -9633,6 +10813,7 @@ async function runAgentSync(ctx, agentId, options) {
9633
10813
  error: failed?.error
9634
10814
  };
9635
10815
  } catch (error) {
10816
+ if (transactionalState) await replaceState(ctx.state, transactionalState);
9636
10817
  return {
9637
10818
  agentId,
9638
10819
  provider: fullPlan.provider,
@@ -9645,6 +10826,11 @@ async function runAgentSync(ctx, agentId, options) {
9645
10826
  };
9646
10827
  }
9647
10828
  }
10829
+ async function replaceState(target, source) {
10830
+ for (const resource of target.listResources()) target.removeResource(resource.address);
10831
+ for (const resource of source.listResources()) target.setResource(resource);
10832
+ await target.save();
10833
+ }
9648
10834
  async function syncAgentResourcesWithStateBackend(input, agentId, options = {}) {
9649
10835
  return writeProjectRuntime(input, (ctx) => syncAgentResources(ctx, agentId, options));
9650
10836
  }
@@ -9721,25 +10907,6 @@ function getAgentReadinessFromPlan(ctx, agentId, plan) {
9721
10907
  plannedActions: relevantActions
9722
10908
  };
9723
10909
  }
9724
- function filterAgentActions(ctx, agent, plan) {
9725
- const relevantKeys = agentAddressKeys(ctx, agent);
9726
- return plan.actions.filter(
9727
- (action) => relevantKeys.has(addressKey(action.address)) || action.dependencies.some((dependency) => relevantKeys.has(addressKey(dependency)))
9728
- );
9729
- }
9730
- function filterAgentDiagnostics(ctx, agent, plan) {
9731
- const relevantKeys = agentAddressKeys(ctx, agent);
9732
- return plan.diagnostics.filter(
9733
- (diagnostic) => !diagnostic.resource || relevantKeys.has(addressKey(diagnostic.resource))
9734
- );
9735
- }
9736
- function agentAddressKeys(ctx, agent) {
9737
- return new Set(collectAgentAddresses(ctx.config, agent.agentName, agent.provider).map(addressKey));
9738
- }
9739
- function scopePlanActions(fullPlan, agentActions) {
9740
- const allowedKeys = new Set(agentActions.filter((action) => action.action !== "no-op").map(actionKey));
9741
- return fullPlan.actions.filter((action) => action.action === "no-op" || allowedKeys.has(actionKey(action)));
9742
- }
9743
10910
  function actionKey(action) {
9744
10911
  const address = action.address;
9745
10912
  return `${action.action}:${address.provider}:${address.type}:${address.name}`;
@@ -9755,33 +10922,48 @@ function collectAgentAddresses(config, agentName, provider) {
9755
10922
  }
9756
10923
  const resolvedProvider = provider ?? resolveSessionProvider(agentName, config, void 0);
9757
10924
  const materialization = resolveAgentMaterialization(resolvedProvider, agent);
9758
- const addresses = [
9759
- { type: materialization.resourceType, name: agentName, provider: resolvedProvider }
9760
- ];
9761
- if (agent.environment) {
9762
- addresses.push({
9763
- type: "environment",
9764
- name: agent.environment,
9765
- provider: resolvedProvider
9766
- });
9767
- }
9768
- if (agent.vault) {
9769
- addresses.push({ type: "vault", name: agent.vault, provider: resolvedProvider });
9770
- }
9771
- for (const name of agent.memory_stores ?? []) {
9772
- addresses.push({ type: "memory_store", name, provider: resolvedProvider });
9773
- }
9774
- for (const skill of agent.skills ?? []) {
9775
- if (typeof skill === "string") {
9776
- addresses.push({ type: "skill", name: skill, provider: resolvedProvider });
10925
+ const rootAddress = {
10926
+ type: materialization.resourceType,
10927
+ name: agentName,
10928
+ provider: resolvedProvider
10929
+ };
10930
+ const graph = buildDependencyGraph(config, [resolvedProvider]);
10931
+ const roots = [rootAddress];
10932
+ const visited = /* @__PURE__ */ new Set();
10933
+ function collectRuntimeRoots(name) {
10934
+ if (visited.has(name)) return;
10935
+ visited.add(name);
10936
+ const declaration = config.agents?.[name];
10937
+ if (!declaration) return;
10938
+ const type = resolveAgentMaterialization(resolvedProvider, declaration).resourceType;
10939
+ if (type === "template" && config.defaults?.identity) {
10940
+ roots.push({ type: "identity", name: config.defaults.identity, provider: resolvedProvider });
10941
+ }
10942
+ for (const subAgentName of declaration.multiagent?.agents ?? []) {
10943
+ const subAgent = config.agents?.[subAgentName];
10944
+ if (!subAgent) continue;
10945
+ roots.push({
10946
+ type: resolveAgentMaterialization(resolvedProvider, subAgent).resourceType,
10947
+ name: subAgentName,
10948
+ provider: resolvedProvider
10949
+ });
10950
+ collectRuntimeRoots(subAgentName);
9777
10951
  }
9778
10952
  }
9779
- for (const subAgent of agent.multiagent?.agents ?? []) {
9780
- const subDecl = config.agents?.[subAgent];
9781
- const subType = subDecl ? resolveAgentMaterialization(resolvedProvider, subDecl).resourceType : "agent";
9782
- addresses.push({ type: subType, name: subAgent, provider: resolvedProvider });
9783
- }
9784
- return addresses;
10953
+ collectRuntimeRoots(agentName);
10954
+ return collectDependencyClosure(graph, roots);
10955
+ }
10956
+ function computeAgentPlanFingerprint(agentId, provider, actions, diagnostics) {
10957
+ const normalizedActions = actions.map((action) => ({
10958
+ ...action,
10959
+ dependencies: [...action.dependencies].sort((left, right) => addressKey(left).localeCompare(addressKey(right)))
10960
+ })).sort((left, right) => actionKey(left).localeCompare(actionKey(right)));
10961
+ const normalizedDiagnostics = [...diagnostics].sort((left, right) => {
10962
+ const leftKey = `${left.resource ? addressKey(left.resource) : ""}:${left.severity}:${left.code}:${left.message}`;
10963
+ const rightKey = `${right.resource ? addressKey(right.resource) : ""}:${right.severity}:${right.code}:${right.message}`;
10964
+ return leftKey.localeCompare(rightKey);
10965
+ });
10966
+ return contentHash({ agentId, provider, actions: normalizedActions, diagnostics: normalizedDiagnostics });
9785
10967
  }
9786
10968
  function toAgentDefinition(config, agentName, agent) {
9787
10969
  return {
@@ -10008,12 +11190,20 @@ async function listSessionEvents(ctx, sessionId, options = {}) {
10008
11190
  const listOptions = {};
10009
11191
  if (options.limit !== void 0) listOptions.limit = options.limit;
10010
11192
  if (options.order !== void 0) listOptions.order = options.order;
11193
+ if (options.types !== void 0) listOptions.types = options.types;
11194
+ if (options.created_at_gt !== void 0) listOptions.created_at_gt = options.created_at_gt;
11195
+ if (options.created_at_gte !== void 0) listOptions.created_at_gte = options.created_at_gte;
11196
+ if (options.created_at_lt !== void 0) listOptions.created_at_lt = options.created_at_lt;
11197
+ if (options.created_at_lte !== void 0) listOptions.created_at_lte = options.created_at_lte;
10011
11198
  const pageToken = options.page_token ?? options.page;
10012
11199
  if (pageToken !== void 0) listOptions.page_token = pageToken;
10013
- return resolveDirectAdapter(ctx, options.provider).listSessionEvents(
11200
+ const result = await resolveDirectAdapter(ctx, options.provider).listSessionEvents(
10014
11201
  sessionId,
10015
11202
  Object.keys(listOptions).length > 0 ? listOptions : void 0
10016
11203
  );
11204
+ if (!options.types || options.types.length === 0) return result;
11205
+ const allowedTypes = new Set(options.types);
11206
+ return { ...result, events: result.events.filter((event) => allowedTypes.has(event.raw_type)) };
10017
11207
  }
10018
11208
  async function uploadFile(ctx, content, filename, options = {}) {
10019
11209
  const adapter2 = resolveDirectAdapter(ctx, options.provider);
@@ -10063,12 +11253,89 @@ async function deleteSkill(ctx, id, options = {}) {
10063
11253
  await resolveDirectAdapter(ctx, options.provider).deleteSkill(id);
10064
11254
  }
10065
11255
  function streamSessionEvents(ctx, sessionId, options = {}) {
11256
+ const adapter2 = resolveDirectAdapter(ctx, options.provider);
11257
+ if (options.after_id && !adapter2.eventResume) {
11258
+ return replaySessionEventsByPolling(adapter2, sessionId, options.after_id);
11259
+ }
10066
11260
  const streamOptions = {};
10067
11261
  if (options.after_id !== void 0) streamOptions.after_id = options.after_id;
10068
- return resolveDirectAdapter(ctx, options.provider).streamSessionEvents(
10069
- sessionId,
10070
- Object.keys(streamOptions).length > 0 ? streamOptions : void 0
10071
- );
11262
+ return adapter2.streamSessionEvents(sessionId, Object.keys(streamOptions).length > 0 ? streamOptions : void 0);
11263
+ }
11264
+ async function* replaySessionEventsByPolling(adapter2, sessionId, afterId) {
11265
+ const history = await listAllSessionEventHistory(adapter2, sessionId);
11266
+ const markerIndex = history.findIndex((event) => event.id === afterId);
11267
+ if (markerIndex < 0) {
11268
+ throw new UserError(`Session event '${afterId}' was not found; list session events and choose a valid event id.`);
11269
+ }
11270
+ const knownEventKeys = new Set(history.slice(0, markerIndex + 1).map(sessionEventKey));
11271
+ for (const event of history.slice(markerIndex + 1)) {
11272
+ const eventKey = sessionEventKey(event);
11273
+ if (knownEventKeys.has(eventKey)) continue;
11274
+ knownEventKeys.add(eventKey);
11275
+ yield event;
11276
+ if (event.type === "status" && isTerminalSessionStatus(event.status)) return;
11277
+ }
11278
+ while (true) {
11279
+ const newEvents = await listNewSessionEvents(adapter2, sessionId, knownEventKeys);
11280
+ for (const event of newEvents) {
11281
+ const eventKey = sessionEventKey(event);
11282
+ if (knownEventKeys.has(eventKey)) continue;
11283
+ knownEventKeys.add(eventKey);
11284
+ yield event;
11285
+ if (event.type === "status" && isTerminalSessionStatus(event.status)) return;
11286
+ }
11287
+ const session = await adapter2.getSession(sessionId);
11288
+ if (isTerminalSessionStatus(session.status)) return;
11289
+ await delay2(DEFAULT_POLL_INTERVAL_MS);
11290
+ }
11291
+ }
11292
+ async function listAllSessionEventHistory(adapter2, sessionId) {
11293
+ const events = [];
11294
+ const seenPageTokens = /* @__PURE__ */ new Set();
11295
+ let pageToken;
11296
+ while (true) {
11297
+ const result = await adapter2.listSessionEvents(sessionId, {
11298
+ limit: 100,
11299
+ order: "asc",
11300
+ ...pageToken ? { page_token: pageToken } : {}
11301
+ });
11302
+ events.push(...result.events);
11303
+ if (!result.next_page) return events;
11304
+ if (seenPageTokens.has(result.next_page)) {
11305
+ throw new UserError("Session event pagination returned a repeated cursor.");
11306
+ }
11307
+ seenPageTokens.add(result.next_page);
11308
+ pageToken = result.next_page;
11309
+ }
11310
+ }
11311
+ async function listNewSessionEvents(adapter2, sessionId, knownEventKeys) {
11312
+ const descendingEvents = [];
11313
+ const seenPageTokens = /* @__PURE__ */ new Set();
11314
+ let pageToken;
11315
+ while (true) {
11316
+ const result = await adapter2.listSessionEvents(sessionId, {
11317
+ limit: 100,
11318
+ order: "desc",
11319
+ ...pageToken ? { page_token: pageToken } : {}
11320
+ });
11321
+ let reachedKnownEvent = false;
11322
+ for (const event of result.events) {
11323
+ if (knownEventKeys.has(sessionEventKey(event))) {
11324
+ reachedKnownEvent = true;
11325
+ break;
11326
+ }
11327
+ descendingEvents.push(event);
11328
+ }
11329
+ if (reachedKnownEvent || !result.next_page) return descendingEvents.reverse();
11330
+ if (seenPageTokens.has(result.next_page)) {
11331
+ throw new UserError("Session event pagination returned a repeated cursor.");
11332
+ }
11333
+ seenPageTokens.add(result.next_page);
11334
+ pageToken = result.next_page;
11335
+ }
11336
+ }
11337
+ function sessionEventKey(event) {
11338
+ return event.id ?? `raw:${event.raw_type}:${JSON.stringify(event.raw)}`;
10072
11339
  }
10073
11340
  function resolveDirectAdapter(ctx, overrideProvider) {
10074
11341
  if (overrideProvider) return getRuntimeProvider(ctx, overrideProvider);
@@ -10141,7 +11408,7 @@ function delay2(ms) {
10141
11408
  import { readFileSync as readFileSync8 } from "fs";
10142
11409
  import { readFile as readFile5 } from "fs/promises";
10143
11410
  import { homedir } from "os";
10144
- import { dirname as dirname11, join } from "path";
11411
+ import { dirname as dirname12, join } from "path";
10145
11412
  var AGENTS_CONFIG_PROVIDERS = ["bailian", "qoder", "ark", "claude"];
10146
11413
  var AGENTS_PROVIDER_FIELDS = {
10147
11414
  bailian: [
@@ -10210,7 +11477,7 @@ function loadDotEnv(startDir = process.cwd()) {
10210
11477
  return envPath;
10211
11478
  } catch {
10212
11479
  }
10213
- const parent = dirname11(dir);
11480
+ const parent = dirname12(dir);
10214
11481
  if (parent === dir) break;
10215
11482
  dir = parent;
10216
11483
  }
@@ -10294,7 +11561,7 @@ function parseStateAddress(address, options = {}) {
10294
11561
 
10295
11562
  // src/internal/state/state-manager.ts
10296
11563
  import { mkdir, readFile as readFile6, rename, unlink, writeFile } from "fs/promises";
10297
- import { dirname as dirname12 } from "path";
11564
+ import { dirname as dirname13 } from "path";
10298
11565
  var StateManager = class _StateManager {
10299
11566
  state;
10300
11567
  path;
@@ -10385,7 +11652,7 @@ var StateManager = class _StateManager {
10385
11652
  return this.state;
10386
11653
  }
10387
11654
  async save() {
10388
- await mkdir(dirname12(this.path), { recursive: true });
11655
+ await mkdir(dirname13(this.path), { recursive: true });
10389
11656
  const tmpPath = `${this.path}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
10390
11657
  try {
10391
11658
  await writeFile(tmpPath, `${JSON.stringify(this.state, null, 2)}
@@ -10407,74 +11674,6 @@ function deriveStatePath(configPath) {
10407
11674
  return /\.ya?ml$/i.test(configPath) ? configPath.replace(/\.ya?ml$/i, ".state.json") : `${configPath}.state.json`;
10408
11675
  }
10409
11676
 
10410
- // src/internal/state/backend.ts
10411
- function cloneStateFile(state) {
10412
- return structuredClone(state);
10413
- }
10414
-
10415
- // src/internal/state/in-memory-state-manager.ts
10416
- var InMemoryStateManager = class _InMemoryStateManager {
10417
- state;
10418
- index;
10419
- constructor(state) {
10420
- this.state = state;
10421
- this.index = this.buildIndex();
10422
- }
10423
- buildIndex() {
10424
- const idx = /* @__PURE__ */ new Map();
10425
- for (let i = 0; i < this.state.resources.length; i++) {
10426
- idx.set(addressKey(this.state.resources[i].address), i);
10427
- }
10428
- return idx;
10429
- }
10430
- static fromJSON(data) {
10431
- return new _InMemoryStateManager(structuredClone(data));
10432
- }
10433
- static empty() {
10434
- return new _InMemoryStateManager({ resources: [] });
10435
- }
10436
- getResource(address) {
10437
- const i = this.index.get(addressKey(address));
10438
- return i !== void 0 ? this.state.resources[i] : void 0;
10439
- }
10440
- setResource(resource) {
10441
- const key = addressKey(resource.address);
10442
- const i = this.index.get(key);
10443
- if (i !== void 0) {
10444
- this.state.resources[i] = resource;
10445
- } else {
10446
- this.index.set(key, this.state.resources.length);
10447
- this.state.resources.push(resource);
10448
- }
10449
- }
10450
- removeResource(address) {
10451
- const key = addressKey(address);
10452
- const i = this.index.get(key);
10453
- if (i === void 0) return;
10454
- this.state.resources.splice(i, 1);
10455
- this.index.delete(key);
10456
- for (let j = i; j < this.state.resources.length; j++) {
10457
- this.index.set(addressKey(this.state.resources[j].address), j);
10458
- }
10459
- }
10460
- listResources() {
10461
- return [...this.state.resources];
10462
- }
10463
- findResource(query2) {
10464
- return this.state.resources.find((resource) => {
10465
- const matchType = resource.address.type === query2.type;
10466
- const matchName = resource.address.name === query2.name;
10467
- const matchProvider = !query2.provider || resource.address.provider === query2.provider;
10468
- return matchType && matchName && matchProvider;
10469
- });
10470
- }
10471
- getStateFile() {
10472
- return this.state;
10473
- }
10474
- async save() {
10475
- }
10476
- };
10477
-
10478
11677
  // src/internal/state/local-file-state-backend.ts
10479
11678
  var LocalFileStateBackend = class {
10480
11679
  configPath;
@@ -10600,7 +11799,8 @@ var CloudAgentSchema = z6.object({
10600
11799
  workspace_id: z6.string().optional(),
10601
11800
  created_at: z6.string().optional(),
10602
11801
  updated_at: z6.string().optional(),
10603
- archived_at: z6.string().nullish()
11802
+ archived_at: z6.string().nullish(),
11803
+ attributes: z6.record(z6.string(), z6.unknown()).optional()
10604
11804
  });
10605
11805
  var ListCloudAgentsResponseSchema = z6.object({
10606
11806
  agents: z6.array(CloudAgentSchema)
@@ -10617,7 +11817,8 @@ var CloudEnvironmentSchema = z6.object({
10617
11817
  workspace_id: z6.string().optional(),
10618
11818
  created_at: z6.string().optional(),
10619
11819
  updated_at: z6.string().optional(),
10620
- archived_at: z6.string().nullish()
11820
+ archived_at: z6.string().nullish(),
11821
+ attributes: z6.record(z6.string(), z6.unknown()).optional()
10621
11822
  });
10622
11823
  var ListCloudEnvironmentsResponseSchema = z6.object({
10623
11824
  environments: z6.array(CloudEnvironmentSchema)
@@ -10629,7 +11830,8 @@ var CloudVaultSchema = z6.object({
10629
11830
  type: z6.string().optional(),
10630
11831
  created_at: z6.string().nullish(),
10631
11832
  updated_at: z6.string().nullish(),
10632
- archived_at: z6.string().nullish()
11833
+ archived_at: z6.string().nullish(),
11834
+ attributes: z6.record(z6.string(), z6.unknown()).optional()
10633
11835
  });
10634
11836
  var ListCloudVaultsResponseSchema = z6.object({
10635
11837
  vaults: z6.array(CloudVaultSchema)
@@ -10644,6 +11846,7 @@ var SessionEventTypeSchema = z6.enum([
10644
11846
  "unknown"
10645
11847
  ]);
10646
11848
  var AgentSyncStatusSchema = z6.enum(["completed", "blocked", "failed"]);
11849
+ var AgentSyncReasonSchema = z6.enum(["destructive_blocked", "cancelled", "diagnostic_error", "plan_stale"]);
10647
11850
  var AgentSyncResultSchema = z6.object({
10648
11851
  action: PlannedActionSchema,
10649
11852
  status: z6.enum(["success", "failed", "skipped"]),
@@ -10653,6 +11856,7 @@ var AgentSyncRunSchema = z6.object({
10653
11856
  agentId: z6.string(),
10654
11857
  provider: z6.string().optional(),
10655
11858
  status: AgentSyncStatusSchema,
11859
+ reason: AgentSyncReasonSchema.optional(),
10656
11860
  actions: z6.array(PlannedActionSchema),
10657
11861
  diagnostics: z6.array(DiagnosticSchema),
10658
11862
  destructiveActions: z6.array(PlannedActionSchema),
@@ -10770,6 +11974,7 @@ export {
10770
11974
  AgentReadinessStatusSchema,
10771
11975
  AgentRecoveryActionSchema,
10772
11976
  AgentSkillRefSchema,
11977
+ AgentSyncReasonSchema,
10773
11978
  AgentSyncResultSchema,
10774
11979
  AgentSyncRunSchema,
10775
11980
  AgentSyncStatusSchema,
@@ -10809,6 +12014,7 @@ export {
10809
12014
  applyProviderConfigToEnv,
10810
12015
  archiveCloudAgent,
10811
12016
  archiveMemoryStore,
12017
+ archiveRemoteSession,
10812
12018
  areRuntimeCredentialsReady,
10813
12019
  batchCreateMemories,
10814
12020
  bootstrapRuntimeCredentials,
@@ -10822,6 +12028,8 @@ export {
10822
12028
  createProjectRuntime,
10823
12029
  createSessionForAgent,
10824
12030
  createSkillFromFileId,
12031
+ createVaultCredential,
12032
+ createVaultCredentialWithStateBackend,
10825
12033
  decideDestructive,
10826
12034
  deleteCloudEnvironment,
10827
12035
  deleteCloudVault,
@@ -10831,6 +12039,8 @@ export {
10831
12039
  deleteSession,
10832
12040
  deleteSkill,
10833
12041
  destroyPlannedProjectResources,
12042
+ downloadRemoteFile,
12043
+ downloadRemoteSkill,
10834
12044
  executePlannedProject,
10835
12045
  extractSkillZipFiles,
10836
12046
  getAgent,
@@ -10838,13 +12048,25 @@ export {
10838
12048
  getDeploymentRuntimeProviderForContext,
10839
12049
  getFileDownloadUrl,
10840
12050
  getFileInfo,
12051
+ getManagedAgentProviderCapabilities,
10841
12052
  getMemory,
10842
12053
  getMemoryProviderCapabilities,
10843
12054
  getMemoryStore,
10844
12055
  getMemoryVersion,
12056
+ getRemoteAgent,
12057
+ getRemoteDeployment,
12058
+ getRemoteDeploymentRun,
12059
+ getRemoteEnvironment,
12060
+ getRemoteSkill,
12061
+ getRemoteSkillDownloadInfo,
12062
+ getRemoteSkillVersion,
12063
+ getRemoteVault,
10845
12064
  getSession,
10846
12065
  getSkillInfo,
10847
12066
  importResource,
12067
+ inspectProjectSource,
12068
+ inspectSkillSource,
12069
+ isAgentRunnable,
10848
12070
  isTerminalSessionStatus,
10849
12071
  listAgentsWithReadiness,
10850
12072
  listCloudAgents,
@@ -10857,7 +12079,16 @@ export {
10857
12079
  listMemoryVersions,
10858
12080
  listProviderModelsForContext,
10859
12081
  listProviderNames,
12082
+ listRemoteAgentVersions,
12083
+ listRemoteAgents,
12084
+ listRemoteDeploymentRuns,
12085
+ listRemoteDeployments,
10860
12086
  listRemoteDeploymentsForContext,
12087
+ listRemoteEnvironments,
12088
+ listRemoteFiles,
12089
+ listRemoteSkillVersions,
12090
+ listRemoteSkills,
12091
+ listRemoteVaults,
10861
12092
  listSessionEvents,
10862
12093
  listSessionSummaries,
10863
12094
  listSkills,
@@ -10867,8 +12098,13 @@ export {
10867
12098
  migrateConfig,
10868
12099
  parseStateAddress,
10869
12100
  pauseDeploymentForContext,
12101
+ planAgentResources,
12102
+ planAgentResourcesWithStateBackend,
10870
12103
  planDestroyProjectContext,
10871
12104
  planProjectContext,
12105
+ planProjectWithStateBackend,
12106
+ planVaultCredentialCreate,
12107
+ planVaultCredentialCreateWithStateBackend,
10872
12108
  prepareInitialSessionPrompt,
10873
12109
  preparePromptForProvider,
10874
12110
  prependFileHint,
@@ -10884,9 +12120,12 @@ export {
10884
12120
  resolveSyncProvider,
10885
12121
  rewriteFileMentions,
10886
12122
  runDeploymentForContext,
12123
+ runRemoteDeployment,
12124
+ sendRemoteSessionEvents,
10887
12125
  sendSessionMessagePolling,
10888
12126
  sendSessionMessageStreaming,
10889
12127
  setDefaultFetch,
12128
+ setRemoteDeploymentPaused,
10890
12129
  startSessionRun,
10891
12130
  startSessionRunPolling,
10892
12131
  streamSessionEvents,
@@ -10896,6 +12135,7 @@ export {
10896
12135
  syncProviderResourcesFromEnv,
10897
12136
  updateMemory,
10898
12137
  updateMemoryStore,
12138
+ updateRemoteSession,
10899
12139
  uploadFile,
10900
12140
  validateProjectConfig,
10901
12141
  writeProjectRuntime