@openagentpack/sdk 0.7.0 → 0.7.2

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.
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  UserError,
3
3
  inspectProjectSource
4
- } from "./chunk-ZBJDMUJT.js";
4
+ } from "./chunk-HLZOSZ7B.js";
5
5
 
6
6
  // src/internal/project-versions/directory.ts
7
7
  import { createHash, randomUUID } from "crypto";
@@ -1361,6 +1361,13 @@ function injectMetadata(userMetadata, projectName, resourceName) {
1361
1361
  };
1362
1362
  return { ...injected, ...userMetadata };
1363
1363
  }
1364
+ function injectManagedResourceMetadata(userMetadata, projectName, resourceName) {
1365
+ return {
1366
+ ...userMetadata,
1367
+ "agents.project": projectName,
1368
+ "agents.resource": resourceName
1369
+ };
1370
+ }
1364
1371
  function slug(value, fallback) {
1365
1372
  const out = (value ?? "").trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
1366
1373
  return out || fallback;
@@ -2574,6 +2581,7 @@ function normalizeEnvironmentPackages(value) {
2574
2581
  return Object.keys(packages).length > 0 ? packages : void 0;
2575
2582
  }
2576
2583
  function mapEnvironment2(name, decl, projectName) {
2584
+ const displayName = decl.name ?? name;
2577
2585
  const envType = decl.config.type ?? "cloud";
2578
2586
  const config = { type: envType };
2579
2587
  if (decl.config.networking) config.networking = decl.config.networking;
@@ -2582,10 +2590,10 @@ function mapEnvironment2(name, decl, projectName) {
2582
2590
  if (packages) config.packages = packages;
2583
2591
  if (decl.config.setup_script !== void 0) config.setup_script = decl.config.setup_script;
2584
2592
  return {
2585
- name,
2593
+ name: displayName,
2586
2594
  description: decl.description ?? "",
2587
2595
  config,
2588
- metadata: injectMetadata(decl.metadata, projectName, name)
2596
+ metadata: injectManagedResourceMetadata(decl.metadata, projectName, displayName)
2589
2597
  };
2590
2598
  }
2591
2599
  function mapForwardEnvironment(name, decl, projectName) {
@@ -2836,15 +2844,16 @@ function mapAgent2(name, decl, refs, version, projectName) {
2836
2844
  if (!qoderModel) throw new UserError(`No Qoder model specified for agent '${name}'`);
2837
2845
  model = typeof qoderModel === "string" ? qoderModel : qoderModel.id;
2838
2846
  }
2847
+ const displayName = decl.name ?? name;
2839
2848
  const body = {
2840
- name: decl.name ?? name,
2849
+ name: displayName,
2841
2850
  model,
2842
2851
  system: decl.instructions
2843
2852
  };
2844
2853
  if (version !== void 0) body.version = version;
2845
2854
  if (decl.description) body.description = decl.description;
2846
2855
  if (projectName) {
2847
- body.metadata = injectMetadata(decl.metadata, projectName, name);
2856
+ body.metadata = injectManagedResourceMetadata(decl.metadata, projectName, displayName);
2848
2857
  } else if (decl.metadata) {
2849
2858
  body.metadata = decl.metadata;
2850
2859
  }
@@ -3230,7 +3239,7 @@ var QoderAdapter = class _QoderAdapter {
3230
3239
  if (type === "deployment") return "unsupported";
3231
3240
  return _QoderAdapter.ENDPOINT_MAP[type] ? "existence" : "unsupported";
3232
3241
  }
3233
- async readComparableResource(type, id, name) {
3242
+ async readComparableResource(type, id, name, decl) {
3234
3243
  if (type !== "agent" && type !== "environment" && type !== "template" && type !== "identity" && type !== "channel")
3235
3244
  return null;
3236
3245
  if (type === "identity" || type === "channel") {
@@ -3242,15 +3251,22 @@ var QoderAdapter = class _QoderAdapter {
3242
3251
  const comparable2 = this.normalizeRemote(type, raw2);
3243
3252
  return { id: remote.id, type, comparable: comparable2, snapshot: comparable2 };
3244
3253
  }
3245
- const isTemplate = type === "template";
3246
- const endpoint = type === "agent" ? "/agents" : type === "environment" ? "/environments" : "/templates";
3247
- const raw = await locateRemote(
3248
- isTemplate ? this.forwardClient : this.client,
3249
- endpoint,
3250
- name,
3251
- id,
3252
- isTemplate ? (item) => item.status !== "archived" : notArchived
3253
- );
3254
+ let raw;
3255
+ if ((type === "agent" || type === "environment") && decl !== void 0 && this.projectName) {
3256
+ const declaredName = decl.name;
3257
+ const displayName = typeof declaredName === "string" ? declaredName : name;
3258
+ raw = await this.readManagedResourceByIdentity(type, id, displayName);
3259
+ } else {
3260
+ const isTemplate = type === "template";
3261
+ const endpoint = type === "agent" ? "/agents" : type === "environment" ? "/environments" : "/templates";
3262
+ raw = await locateRemote(
3263
+ isTemplate ? this.forwardClient : this.client,
3264
+ endpoint,
3265
+ name,
3266
+ id,
3267
+ isTemplate ? (item) => item.status !== "archived" : notArchived
3268
+ );
3269
+ }
3254
3270
  if (!raw) return null;
3255
3271
  const comparable = this.normalizeRemote(type, raw);
3256
3272
  return {
@@ -3261,6 +3277,38 @@ var QoderAdapter = class _QoderAdapter {
3261
3277
  snapshot: comparable
3262
3278
  };
3263
3279
  }
3280
+ async readManagedResourceByIdentity(type, id, displayName) {
3281
+ const endpoint = type === "agent" ? "/agents" : "/environments";
3282
+ if (id) {
3283
+ try {
3284
+ const raw = await this.client.get(`${endpoint}/${id}`);
3285
+ return this.matchesManagedResourceIdentity(type, raw, displayName) ? raw : null;
3286
+ } catch (error) {
3287
+ if (ApiError.isNotFound(error)) return null;
3288
+ throw error;
3289
+ }
3290
+ }
3291
+ const matches = (await this.client.getAllPaged(endpoint)).filter(
3292
+ (raw) => this.matchesManagedResourceIdentity(type, raw, displayName)
3293
+ );
3294
+ if (matches.length !== 1) return null;
3295
+ const matchedId = matches[0]?.id;
3296
+ if (typeof matchedId !== "string") return null;
3297
+ try {
3298
+ const raw = await this.client.get(`${endpoint}/${matchedId}`);
3299
+ return this.matchesManagedResourceIdentity(type, raw, displayName) ? raw : null;
3300
+ } catch (error) {
3301
+ if (ApiError.isNotFound(error)) return null;
3302
+ throw error;
3303
+ }
3304
+ }
3305
+ matchesManagedResourceIdentity(type, raw, displayName) {
3306
+ if (!notArchived(raw) || raw.name !== displayName) return false;
3307
+ if (typeof raw.type === "string" && raw.type !== type) return false;
3308
+ const metadata = raw.metadata;
3309
+ if (!metadata || typeof metadata !== "object") return false;
3310
+ return metadata["agents.project"] === this.projectName && metadata["agents.resource"] === displayName;
3311
+ }
3264
3312
  normalizeDesiredResource(type, name, decl) {
3265
3313
  if (type === "environment") {
3266
3314
  return this.normalizeRemote(
@@ -3342,7 +3390,7 @@ var QoderAdapter = class _QoderAdapter {
3342
3390
  }
3343
3391
  return compactDeep({
3344
3392
  name: raw.name,
3345
- description: raw.description,
3393
+ description: raw.description === "" ? void 0 : raw.description,
3346
3394
  model: normalizeModel(raw.model),
3347
3395
  instructions: raw.system,
3348
3396
  tools: normalizeQoderTools(raw.tools),
@@ -14,7 +14,7 @@ import {
14
14
  resolveFetch,
15
15
  resolveTargetProviders,
16
16
  skillNameFromFiles
17
- } from "./chunk-ZBJDMUJT.js";
17
+ } from "./chunk-HLZOSZ7B.js";
18
18
 
19
19
  // src/internal/core/project-runtime.ts
20
20
  function createProjectRuntime(input) {
@@ -403,11 +403,11 @@ function structurallyEqual(left, right) {
403
403
  function supportsFullDrift(adapter, type) {
404
404
  return adapter.getDriftSupport?.(type) === "full" && typeof adapter.readComparableResource === "function";
405
405
  }
406
- async function readComparableIfSupported(adapter, type, id, name) {
406
+ async function readComparableIfSupported(adapter, type, id, name, decl) {
407
407
  if (!supportsFullDrift(adapter, type)) return null;
408
408
  if (typeof adapter.readComparableResource !== "function") return null;
409
409
  try {
410
- return await adapter.readComparableResource(type, id, name);
410
+ return await adapter.readComparableResource(type, id, name, decl);
411
411
  } catch {
412
412
  return null;
413
413
  }
@@ -1232,7 +1232,13 @@ async function executeActionInner(action, provider, ctx) {
1232
1232
  const comparableHash = computeComparableDesiredHash(address, ctx.config, provider);
1233
1233
  let remoteHash = comparableHash;
1234
1234
  let remoteSnapshot;
1235
- const remote = await readComparableIfSupported(provider, type, result.id, name);
1235
+ const remote = await readComparableIfSupported(
1236
+ provider,
1237
+ type,
1238
+ result.id,
1239
+ name,
1240
+ getResourceDeclaration(address, ctx.config) ?? void 0
1241
+ );
1236
1242
  if (remote) {
1237
1243
  remoteHash = contentHash(remote.comparable);
1238
1244
  remoteSnapshot = remote.snapshot ?? remote.comparable;
@@ -1845,7 +1851,13 @@ async function refreshState(state, providers, options = {}) {
1845
1851
  try {
1846
1852
  const support = provider.getDriftSupport?.(res.address.type) ?? "existence";
1847
1853
  if (supportsFullDrift(provider, res.address.type) && provider.normalizeDesiredResource) {
1848
- const remote2 = await provider.readComparableResource?.(res.address.type, res.remote_id, res.address.name);
1854
+ const decl = options.config ? getResourceDeclaration(res.address, options.config) : null;
1855
+ const remote2 = await provider.readComparableResource?.(
1856
+ res.address.type,
1857
+ res.remote_id,
1858
+ res.address.name,
1859
+ decl ?? void 0
1860
+ );
1849
1861
  if (!remote2) {
1850
1862
  if (!options.quiet) {
1851
1863
  emitRuntimeFeedback(options.onFeedback, {
@@ -1861,7 +1873,6 @@ async function refreshState(state, providers, options = {}) {
1861
1873
  continue;
1862
1874
  }
1863
1875
  const remoteHash = contentHash(remote2.comparable);
1864
- const decl = options.config ? getResourceDeclaration(res.address, options.config) : null;
1865
1876
  const desiredComparable = decl ? provider.normalizeDesiredResource(res.address.type, res.address.name, decl) : null;
1866
1877
  const desiredComparableHash = desiredComparable === null ? void 0 : contentHash(desiredComparable);
1867
1878
  const baselineHash = res.desired_comparable_hash ?? desiredComparableHash ?? remoteHash;
@@ -2011,7 +2022,13 @@ async function importResource(ctx, address, remoteId, options = {}) {
2011
2022
  throw new UserError(`Planned ${address.type}.${address.name} is missing a content hash.`);
2012
2023
  }
2013
2024
  const provider = ctx.providers.get(address.provider);
2014
- const remote = provider ? await readComparableIfSupported(provider, address.type, remoteId, address.name) : null;
2025
+ const remote = provider ? await readComparableIfSupported(
2026
+ provider,
2027
+ address.type,
2028
+ remoteId,
2029
+ address.name,
2030
+ getResourceDeclaration(address, ctx.config) ?? void 0
2031
+ ) : null;
2015
2032
  const remoteHash = remote ? contentHash(remote.comparable) : void 0;
2016
2033
  const resource = {
2017
2034
  address,
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { U as UserError } from './errors-BcVE1wZB.js';
2
- import { P as ProjectConfig, S as SkillFile, R as ResolvedProjectConfig, a as ProjectRuntimeContext, D as DeploymentContext, b as DeploymentRunResult$1, c as DeploymentInfo$1, d as DeploymentListFilter, e as DeploymentListResult, f as ResourceState, g as ProviderSessionInfo, M as ManagedAgentProviderCapabilities, h as DeploymentRunInfo, i as ProviderSkillInfo, j as SkillDownloadInfo, k as SkillVersionInfo, A as AgentVersionListOptions, l as AgentPage, m as AgentListOptions, n as DeploymentRunPage, E as EnvironmentListOptions, o as EnvironmentPage, F as FileListOptions, p as FilePage, q as SkillVersionListOptions, r as SkillVersionPage, s as SkillListOptions, t as SkillPage, V as VaultListOptions, u as VaultPage, v as SessionEventInput, w as SessionEventSendResult, x as SessionUpdateInput, B as BackendRuntimeInput, y as RuntimeFeedbackSink, z as ModelInfo, C as ProviderAdapter, G as MemoryStoreInfo, H as BatchCreateMemoryInput, I as BatchCreateMemoryResult, J as CreateMemoryInput, K as MemoryInfo, L as CreateMemoryStoreInput, N as MemoryProviderCapabilities, O as MemoryVersionInfo, Q as MemoryListOptions, T as MemoryPage, U as MemoryListItem, W as MemoryStoreListOptions, X as MemoryVersionListOptions, Y as UpdateMemoryInput, Z as UpdateMemoryStoreInput, _ as AgentDecl, $ as SkillDecl, a0 as ResourcePlanResult, a1 as ResourceSyncMode, a2 as DestructivePolicy, a3 as EnvironmentDecl, a4 as RemoteResource, a5 as VaultDecl, a6 as SessionResourceDecl, a7 as SessionFilter, a8 as SessionBindings, a9 as SessionGithubRepositoryResource, aa as StateBackend, ab as StateScope, ac as IStateManager } from './resource-runtime-DZDY45_Q.js';
3
- export { ad as CredentialDecl, ae as CredentialInjectionLocation, af as CredentialNetworking, ag as CursorListOptions, ah as CursorPage, ai as DeploymentDecl, aj as LoadedProjectConfig, ak as ManagedAgentOperationAuth, al as ManagedAgentOperationCapability, am as MemoryPrefixInfo, an as ResourceActionResult, ao as ResourceExecutionResult, ap as ResourcePlanScope, aq as ResourceRefreshResult, ar as ResourceRuntimeOptions, as as ResourceSyncRun, at as RuntimeFeedbackEvent, au as SessionListResult, av as StateManager, aw as VaultCredentialInfo, ax as createProjectRuntime, ay as decideDestructive, az as executePlannedProject, aA as importResource, aB as planProjectContext, aC as planProjectWithStateBackend, aD as readProjectRuntime, aE as resolveProjectConfig, aF as resolveProjectConfigFromObject, aG as syncProjectResourcesWithStateBackend, aH as writeProjectRuntime } from './resource-runtime-DZDY45_Q.js';
2
+ import { P as ProjectConfig, S as SkillFile, R as ResolvedProjectConfig, a as ProjectRuntimeContext, D as DeploymentContext, b as DeploymentRunResult$1, c as DeploymentInfo$1, d as DeploymentListFilter, e as DeploymentListResult, f as ResourceState, g as ProviderSessionInfo, M as ManagedAgentProviderCapabilities, h as DeploymentRunInfo, i as ProviderSkillInfo, j as SkillDownloadInfo, k as SkillVersionInfo, A as AgentVersionListOptions, l as AgentPage, m as AgentListOptions, n as DeploymentRunPage, E as EnvironmentListOptions, o as EnvironmentPage, F as FileListOptions, p as FilePage, q as SkillVersionListOptions, r as SkillVersionPage, s as SkillListOptions, t as SkillPage, V as VaultListOptions, u as VaultPage, v as SessionEventInput, w as SessionEventSendResult, x as SessionUpdateInput, B as BackendRuntimeInput, y as RuntimeFeedbackSink, z as ModelInfo, C as ProviderAdapter, G as MemoryStoreInfo, H as BatchCreateMemoryInput, I as BatchCreateMemoryResult, J as CreateMemoryInput, K as MemoryInfo, L as CreateMemoryStoreInput, N as MemoryProviderCapabilities, O as MemoryVersionInfo, Q as MemoryListOptions, T as MemoryPage, U as MemoryListItem, W as MemoryStoreListOptions, X as MemoryVersionListOptions, Y as UpdateMemoryInput, Z as UpdateMemoryStoreInput, _ as AgentDecl, $ as SkillDecl, a0 as ResourcePlanResult, a1 as ResourceSyncMode, a2 as DestructivePolicy, a3 as EnvironmentDecl, a4 as RemoteResource, a5 as VaultDecl, a6 as SessionResourceDecl, a7 as SessionFilter, a8 as SessionBindings, a9 as SessionGithubRepositoryResource, aa as StateBackend, ab as StateScope, ac as IStateManager } from './resource-runtime-DZsBWDjg.js';
3
+ export { ad as CredentialDecl, ae as CredentialInjectionLocation, af as CredentialNetworking, ag as CursorListOptions, ah as CursorPage, ai as DeploymentDecl, aj as LoadedProjectConfig, ak as ManagedAgentOperationAuth, al as ManagedAgentOperationCapability, am as MemoryPrefixInfo, an as ResourceActionResult, ao as ResourceExecutionResult, ap as ResourcePlanScope, aq as ResourceRefreshResult, ar as ResourceRuntimeOptions, as as ResourceSyncRun, at as RuntimeFeedbackEvent, au as SessionListResult, av as StateManager, aw as VaultCredentialInfo, ax as createProjectRuntime, ay as decideDestructive, az as executePlannedProject, aA as importResource, aB as planProjectContext, aC as planProjectWithStateBackend, aD as readProjectRuntime, aE as resolveProjectConfig, aF as resolveProjectConfigFromObject, aG as syncProjectResourcesWithStateBackend, aH as writeProjectRuntime } from './resource-runtime-DZsBWDjg.js';
4
4
  import { D as Diagnostic, R as ResourceType, P as PlannedAction, A as AgentDefinition, a as AgentReadiness, b as AgentWithReadiness, C as CloudAgent, c as CloudEnvironment, d as CloudVault, e as AgentSyncRun, f as ResourceAddress } from './dto-BT1Q1Ii6.js';
5
5
  export { g as ActionType, h as ActionTypeSchema, i as AgentDefinitionSchema, j as AgentDriftSeverity, k as AgentDriftSeveritySchema, l as AgentModel, m as AgentModelSchema, n as AgentReadinessSchema, o as AgentReadinessStatus, p as AgentReadinessStatusSchema, q as AgentRecoveryAction, r as AgentRecoveryActionSchema, s as AgentSkillRef, t as AgentSkillRefSchema, u as AgentSyncReason, v as AgentSyncReasonSchema, w as AgentSyncResult, x as AgentSyncResultSchema, y as AgentSyncRunSchema, z as AgentSyncStatus, B as AgentSyncStatusSchema, E as AgentWithReadinessSchema, F as CloudAgentSchema, G as CloudEnvironmentSchema, H as CloudVaultSchema, I as CreateSessionRequest, J as CreateSessionRequestSchema, K as CreateSessionResponse, L as CreateSessionResponseSchema, M as DiagnosticSchema, N as DiagnosticSeverity, O as DiagnosticSeveritySchema, Q as DriftKind, S as DriftKindSchema, T as GetSessionRequest, U as GetSessionRequestSchema, V as KNOWN_SESSION_EVENT_TYPES, W as KnownSessionEventType, X as ListCloudAgentsResponse, Y as ListCloudAgentsResponseSchema, Z as ListCloudEnvironmentsResponse, _ as ListCloudEnvironmentsResponseSchema, $ as ListSessionEventsRequest, a0 as ListSessionEventsRequestSchema, a1 as ListSessionEventsResponse, a2 as ListSessionEventsResponseSchema, a3 as ListSessionsRequest, a4 as ListSessionsRequestSchema, a5 as ListSessionsResponse, a6 as ListSessionsResponseSchema, a7 as PlanReadinessImpact, a8 as PlanReadinessImpactSchema, a9 as PlannedActionSchema, aa as ResourceAddressSchema, ab as ResourceTypeSchema, ac as SendEventRequest, ad as SendEventRequestSchema, ae as SendEventResponse, af as SendEventResponseSchema, ag as Session, ah as SessionAgent, ai as SessionAgentSchema, aj as SessionContentBlock, ak as SessionContentBlockSchema, al as SessionEvent, am as SessionEventSchema, an as SessionEventType, ao as SessionEventTypeName, ap as SessionEventTypeSchema, aq as SessionSchema } from './dto-BT1Q1Ii6.js';
6
6
  import { P as ProviderFileInfo } from './file-Cj5-Vx27.js';
package/dist/index.js CHANGED
@@ -23,7 +23,7 @@ import {
23
23
  selectDestructive,
24
24
  syncProjectResourcesWithStateBackend,
25
25
  writeProjectRuntime
26
- } from "./chunk-HIK5DY4I.js";
26
+ } from "./chunk-LJQMLMAT.js";
27
27
  import {
28
28
  ApiError,
29
29
  ConflictError,
@@ -49,7 +49,7 @@ import {
49
49
  rewriteFileMentions,
50
50
  setDefaultFetch,
51
51
  validateProjectConfig
52
- } from "./chunk-ZBJDMUJT.js";
52
+ } from "./chunk-HLZOSZ7B.js";
53
53
  import "./chunk-6PDVAFLK.js";
54
54
  import {
55
55
  defaultFileUploadPurpose,
@@ -13,8 +13,8 @@ import {
13
13
  readProjectVersionSource,
14
14
  releasePreparedProjectVersion,
15
15
  restoreProjectVersion
16
- } from "./chunk-56BB46YT.js";
17
- import "./chunk-ZBJDMUJT.js";
16
+ } from "./chunk-7L73W3DL.js";
17
+ import "./chunk-HLZOSZ7B.js";
18
18
  import "./chunk-6PDVAFLK.js";
19
19
  import "./chunk-CHGDM6TX.js";
20
20
  export {
@@ -1,4 +1,4 @@
1
- import { aj as LoadedProjectConfig, a0 as ResourcePlanResult, as as ResourceSyncRun, y as RuntimeFeedbackSink } from './resource-runtime-DZDY45_Q.js';
1
+ import { aj as LoadedProjectConfig, a0 as ResourcePlanResult, as as ResourceSyncRun, y as RuntimeFeedbackSink } from './resource-runtime-DZsBWDjg.js';
2
2
  import { U as UserError } from './errors-BcVE1wZB.js';
3
3
  import { D as Diagnostic, P as PlannedAction } from './dto-BT1Q1Ii6.js';
4
4
  import { e as DirectoryProjectVersionService } from './directory-nY2Slsfi.js';
@@ -4,17 +4,17 @@ import {
4
4
  planProjectContext,
5
5
  planProjectWithStateBackend,
6
6
  writeProjectRuntime
7
- } from "./chunk-HIK5DY4I.js";
7
+ } from "./chunk-LJQMLMAT.js";
8
8
  import {
9
9
  createDirectoryProjectVersionService
10
- } from "./chunk-56BB46YT.js";
10
+ } from "./chunk-7L73W3DL.js";
11
11
  import {
12
12
  UserError,
13
13
  inspectProjectSource,
14
14
  resolveProjectConfig,
15
15
  resolveProjectConfigFromObject,
16
16
  validateProjectConfig
17
- } from "./chunk-ZBJDMUJT.js";
17
+ } from "./chunk-HLZOSZ7B.js";
18
18
  import "./chunk-6PDVAFLK.js";
19
19
  import "./chunk-CHGDM6TX.js";
20
20
 
@@ -77,11 +77,11 @@ Use this Skill when the user asks to summarize text.
77
77
  the directory is the upload source. Do not put secrets in these files.
78
78
  \`SKILL.md\` \u662F Skill \u6307\u4EE4\uFF0C\u9700\u8981\u7684\u811A\u672C\u548C\u7D20\u6750\u4E5F\u653E\u5728\u6B64\u76EE\u5F55\uFF1B\u6574\u4E2A\u76EE\u5F55\u4F5C\u4E3A\u4E0A\u4F20\u6E90\uFF0C\u8BF7\u52FF\u653E\u5165\u5BC6\u94A5\u3002
79
79
  - This example is ignored by Build/Publish. Copy it from \`skills/_examples/example-skill/\`
80
- to \`skills/example-skill/\`, then add \`"skills": ["example-skill"]\` to \`agent.json\`.
81
- \u6B64\u793A\u4F8B\u4E0D\u53C2\u4E0E\u6784\u5EFA/\u53D1\u5E03\u3002\u590D\u5236\u5230 \`skills/example-skill/\` \u540E\uFF0C\u518D\u5728 Agent \u4E2D\u6DFB\u52A0\u4E0A\u8FF0\u5F15\u7528\u3002
80
+ to \`skills/example-skill/\`, then Build adds \`"example-skill"\` to \`agent.json.skills\` automatically.
81
+ \u6B64\u793A\u4F8B\u4E0D\u53C2\u4E0E\u6784\u5EFA/\u53D1\u5E03\u3002\u590D\u5236\u5230 \`skills/example-skill/\` \u540E\uFF0CBuild \u4F1A\u81EA\u52A8\u8865\u9F50 Agent \u5F15\u7528\u3002
82
82
  - To add another Skill, copy this directory, change the directory name and \`skill.json.id\`,
83
- then add its ID to \`agent.json.skills\`. A new directory with only \`SKILL.md\` is also discovered by Build.
84
- \u65B0\u589E Skill \u65F6\u590D\u5236\u6B64\u76EE\u5F55\u3001\u4FEE\u6539\u76EE\u5F55\u540D\u548C ID\uFF0C\u518D\u5728 Agent \u4E2D\u5F15\u7528\uFF1B\u53EA\u653E \`SKILL.md\` \u7684\u65B0\u76EE\u5F55\u4E5F\u80FD\u7531 Build \u81EA\u52A8\u5173\u8054\u3002
83
+ then run Build to add its ID to \`agent.json.skills\`. A new directory with only \`SKILL.md\` is also discovered by Build.
84
+ \u65B0\u589E Skill \u65F6\u590D\u5236\u6B64\u76EE\u5F55\u3001\u4FEE\u6539\u76EE\u5F55\u540D\u548C ID\uFF0C\u518D\u8FD0\u884C Build \u81EA\u52A8\u5173\u8054\uFF1B\u53EA\u653E \`SKILL.md\` \u7684\u65B0\u76EE\u5F55\u4E5F\u80FD\u7531 Build \u81EA\u52A8\u5173\u8054\u3002
85
85
  - Delete this ignored example directory if not needed. For an enabled Skill, also remove its Agent reference.
86
86
  \u4E0D\u9700\u8981\u65F6\u53EF\u76F4\u63A5\u5220\u9664\u672C\u793A\u4F8B\u76EE\u5F55\uFF1B\u82E5\u5DF2\u7ECF\u542F\u7528\uFF0C\u8FD8\u9700\u5220\u9664 Agent \u5F15\u7528\u3002
87
87
  `,
@@ -106,8 +106,8 @@ at \`/mnt/example.md\` in agent.json.
106
106
  - \`source\` is relative to this resource directory. Keep \`id\` equal to the directory name.
107
107
  \`source\` \u76F8\u5BF9\u6B64\u8D44\u6E90\u76EE\u5F55\u89E3\u6790\uFF0C\`id\` \u5E94\u4E0E\u76EE\u5F55\u540D\u4E00\u81F4\u3002
108
108
  - Build/Publish ignore this example. Copy \`files/_examples/example-file/\` to \`files/example-file/\`
109
- to enable its declaration; add \`"files": [{"file": "example-file", "mount_path": "/mnt/example.md"}]\` to \`agent.json\`.
110
- \u6B64\u793A\u4F8B\u4E0D\u53C2\u4E0E\u6784\u5EFA/\u53D1\u5E03\u3002\u590D\u5236\u5230 \`files/example-file/\` \u540E\u542F\u7528\u58F0\u660E\uFF0C\u518D\u6DFB\u52A0\u4E0A\u8FF0\u6302\u8F7D\u5F15\u7528\uFF1B\u6302\u8F7D\u8DEF\u5F84\u5FC5\u987B\u5728 \`/mnt/\` \u4E0B\u3002
109
+ to enable its declaration; Build adds \`{"file": "example-file", "mount_path": "/mnt/example.md"}\` to \`agent.json.files\`.
110
+ \u6B64\u793A\u4F8B\u4E0D\u53C2\u4E0E\u6784\u5EFA/\u53D1\u5E03\u3002\u590D\u5236\u5230 \`files/example-file/\` \u540E\uFF0CBuild \u81EA\u52A8\u6DFB\u52A0\u4E0A\u8FF0\u6302\u8F7D\u5F15\u7528\uFF1B\u5DF2\u6709\u81EA\u5B9A\u4E49\u6302\u8F7D\u8DEF\u5F84\u4F1A\u4FDD\u7559\uFF0C\u6302\u8F7D\u8DEF\u5F84\u5FC5\u987B\u5728 \`/mnt/\` \u4E0B\u3002
111
111
  - Uploading a File does not permanently attach it to the remote Agent. These declarations
112
112
  supply default mounts for new Sessions; existing Sessions are unchanged.
113
113
  \u4E0A\u4F20 File \u4E0D\u7B49\u4E8E\u6C38\u4E45\u7ED1\u5B9A\u5230\u8FDC\u7AEF Agent\uFF1B\u8FD9\u91CC\u58F0\u660E\u7684\u662F\u65B0 Session \u7684\u9ED8\u8BA4\u6302\u8F7D\uFF0C\u4E0D\u4FEE\u6539\u5DF2\u6709 Session\u3002
@@ -133,9 +133,10 @@ at \`/mnt/example.md\` in agent.json.
133
133
 
134
134
  Build/Publish ignore this directory; no example secret is required to open Workbench.
135
135
  Copy \`vaults/_examples/example-vault/\` to \`vaults/example-vault/\` to enable the declaration,
136
- then add \`"vault": "example-vault"\` to \`agent.json\` and supply the secret.
136
+ then supply the secret and run Build. If \`agent.json.vault\` is unset, Build selects the sole local Vault automatically.
137
+ With multiple local Vaults, set \`"vault": "example-vault"\` explicitly; Build never overwrites an existing selection.
137
138
  \u6B64\u793A\u4F8B\u4E0D\u53C2\u4E0E\u6784\u5EFA/\u53D1\u5E03\uFF0C\u4E0D\u9700\u8981\u914D\u7F6E\u5BC6\u94A5\u5373\u53EF\u6253\u5F00 Workbench\u3002
138
- \u542F\u7528\u65F6\uFF0C\u590D\u5236\u5230 \`vaults/example-vault/\`\uFF0C\u5728 Agent \u4E2D\u6DFB\u52A0\u4E0A\u8FF0\u5F15\u7528\uFF0C\u5E76\u914D\u7F6E\u5BC6\u94A5\u3002
139
+ \u542F\u7528\u65F6\uFF0C\u590D\u5236\u5230 \`vaults/example-vault/\`\uFF0C\u914D\u7F6E\u5BC6\u94A5\u540E\u8FD0\u884C Build\u3002\u672A\u6307\u5B9A Vault \u65F6\u81EA\u52A8\u5173\u8054\u552F\u4E00\u5019\u9009\uFF1B\u591A\u4E2A\u5019\u9009\u9700\u663E\u5F0F\u9009\u62E9\uFF0C\u5DF2\u6709\u5F15\u7528\u4E0D\u8986\u76D6\u3002
139
140
 
140
141
  The example \`vault.json\` contains:
141
142
  \u793A\u4F8B \`vault.json\` \u7684\u5B8C\u6574\u914D\u7F6E\u5982\u4E0B\uFF1A
@@ -184,8 +185,9 @@ ${JSON.stringify(
184
185
  [`${agentRoot}/environments/${RESOURCE_EXAMPLES_DIRECTORY}/example-env/README.md`]: `# Environment example / Environment \u914D\u7F6E\u793A\u4F8B
185
186
 
186
187
  - This is an ignored managed cloud environment example. Copy \`environments/_examples/example-env/\`
187
- to \`environments/example-env/\` to enable it, then add \`"environment": "example-env"\` to \`agent.json\`.
188
- \u8FD9\u662F\u4E0D\u53C2\u4E0E\u6784\u5EFA/\u53D1\u5E03\u7684\u6258\u7BA1\u4E91\u73AF\u5883\u793A\u4F8B\u3002\u590D\u5236\u5230 \`environments/example-env/\` \u540E\u542F\u7528\uFF0C\u518D\u5728 Agent \u4E2D\u6DFB\u52A0\u4E0A\u8FF0\u5F15\u7528\u3002
188
+ to \`environments/example-env/\`, then run Build. An unset \`agent.json.environment\` is linked to the sole local Environment.
189
+ With multiple local Environments, set \`"environment": "example-env"\` explicitly; existing selections are preserved.
190
+ \u8FD9\u662F\u4E0D\u53C2\u4E0E\u6784\u5EFA/\u53D1\u5E03\u7684\u6258\u7BA1\u4E91\u73AF\u5883\u793A\u4F8B\u3002\u590D\u5236\u5230 \`environments/example-env/\` \u540E\u8FD0\u884C Build\uFF1B\u672A\u6307\u5B9A\u73AF\u5883\u65F6\u81EA\u52A8\u5173\u8054\u552F\u4E00\u5019\u9009\uFF0C\u591A\u4E2A\u5019\u9009\u9700\u663E\u5F0F\u9009\u62E9\uFF0C\u5DF2\u6709\u5F15\u7528\u4E0D\u8986\u76D6\u3002
189
191
  Keep \`id\` equal to the directory name. / ID \u5E94\u4E0E\u76EE\u5F55\u540D\u4E00\u81F4\u3002
190
192
  - Optional \`config\` fields include \`networking\`, \`packages\`, and \`setup_script\`.
191
193
  \`config\` \u53EF\u6309\u9700\u589E\u52A0\u7F51\u7EDC\u7B56\u7565\u3001\u4F9D\u8D56\u5305\u548C\u521D\u59CB\u5316\u811A\u672C\uFF0C\u4F8B\u5982\uFF1A
@@ -198,8 +200,8 @@ ${JSON.stringify({ type: "cloud", packages: { pip: ["requests"] }, setup_script:
198
200
  packages/scripts take effect on the remote platform, not on your computer during Init/Build.
199
201
  \u4E0A\u9762\u7684\u7247\u6BB5\u53EA\u66FF\u6362 \`config\`\u3002Init/Build \u4E0D\u4F1A\u5728\u672C\u673A\u5B89\u88C5\u4F9D\u8D56\u6216\u6267\u884C\u811A\u672C\uFF1B\u8FDC\u7AEF\u662F\u5426\u652F\u6301\u4EE5 Provider \u4E3A\u51C6\u3002
200
202
  - Init leaves \`agent.json\` unchanged and only creates ignored resource examples.
201
- Moving a declaration outside \`_examples/\` enables it for Build/Publish, even without an Agent reference.
202
- Init \u4E0D\u6DFB\u52A0 Agent \u8D44\u6E90\u5F15\u7528\u3002\u5C06\u58F0\u660E\u79FB\u5230 \`_examples/\` \u5916\u5373\u4F1A\u8FDB\u5165\u6784\u5EFA/\u53D1\u5E03\u8303\u56F4\uFF0C\u5373\u4F7F\u5C1A\u672A\u914D\u7F6E Agent \u5F15\u7528\u3002
203
+ Moving a declaration outside \`_examples/\` enables it for Build/Publish; Build also fills in the owning Agent's missing reference.
204
+ Init \u4E0D\u6DFB\u52A0 Agent \u8D44\u6E90\u5F15\u7528\u3002\u5C06\u58F0\u660E\u79FB\u5230 \`_examples/\` \u5916\u540E\uFF0CBuild \u4F1A\u8865\u9F50\u6240\u5C5E Agent \u7684\u5F15\u7528\u5E76\u7EB3\u5165\u6784\u5EFA/\u53D1\u5E03\u3002
203
205
  - Delete this ignored example directory if not needed. For an enabled Environment, also remove its Agent reference.
204
206
  \u4E0D\u9700\u8981\u65F6\u53EF\u76F4\u63A5\u5220\u9664\u672C\u793A\u4F8B\u76EE\u5F55\uFF1B\u82E5\u5DF2\u7ECF\u542F\u7528\uFF0C\u8FD8\u9700\u5220\u9664 Agent \u7684 Environment \u5F15\u7528\u3002
205
207
  `
@@ -438,6 +440,23 @@ async function resolveDirectoryProjectRoot(input = ".") {
438
440
  const root = resolve2(input);
439
441
  const details = await stat(root).catch(() => null);
440
442
  if (!details?.isDirectory()) throw new UserError(`Project directory does not exist: ${root}`);
443
+ if (!await pathExists(resolve2(root, PROJECT_METADATA_FILE))) {
444
+ let ancestor = dirname(root);
445
+ while (ancestor !== root) {
446
+ if (await pathExists(resolve2(ancestor, PROJECT_METADATA_FILE))) {
447
+ const quotedRoot = `'${ancestor.replaceAll("'", "'\\''")}'`;
448
+ throw new UserError(
449
+ `Not a project root: ${root} (${PROJECT_METADATA_FILE} is missing).
450
+ Project root: ${ancestor}
451
+ Run from the project root: cd ${quotedRoot}
452
+ Or specify the project directory: --project ${quotedRoot}`
453
+ );
454
+ }
455
+ const parent = dirname(ancestor);
456
+ if (parent === ancestor) break;
457
+ ancestor = parent;
458
+ }
459
+ }
441
460
  return root;
442
461
  }
443
462
  async function inspectDirectoryProject(projectDirectory = ".") {
@@ -804,7 +823,7 @@ async function assembleProject(projectRoot, sourceFiles, metadataOverrides) {
804
823
  for (const skill of skills) {
805
824
  if (skillById.has(skill.id)) throw new UserError(`Duplicate local skill id: ${skill.id}`);
806
825
  skillById.set(skill.id, skill);
807
- if (skill.ownerAgent && skill.inferred) {
826
+ if (skill.ownerAgent) {
808
827
  autoAssociateSkill(skill, projectRoot, agents, agentSources, autoAssociations);
809
828
  }
810
829
  }
@@ -850,9 +869,7 @@ async function assembleProject(projectRoot, sourceFiles, metadataOverrides) {
850
869
  const key = `${resource.type}:${resource.id}`;
851
870
  if (resourceKeys.has(key)) throw new UserError(`Duplicate ${resource.type} id: ${resource.id}`);
852
871
  resourceKeys.add(key);
853
- if (resource.type === "file" && resource.owner_agent && resource.inferred) {
854
- autoAssociateFile(resource, projectRoot, agents, agentSources, autoAssociations);
855
- }
872
+ autoAssociateDirectoryResource(resource, resources, projectRoot, agents, agentSources, autoAssociations);
856
873
  if (resource.owner_agent && isDirectoryResourceShared(resource.type, resource.id, resource.owner_agent, agents, project)) {
857
874
  const spec = DIRECTORY_RESOURCE_SPECS[resource.type];
858
875
  moves.push({
@@ -1120,6 +1137,43 @@ function autoAssociateSkill(skill, projectRoot, agents, agentSources, autoAssoci
1120
1137
  message: `Skill '${skill.id}' will be added to agents/${ownerAgent}/agent.json.`
1121
1138
  });
1122
1139
  }
1140
+ function autoAssociateDirectoryResource(resource, resources, projectRoot, agents, agentSources, autoAssociations) {
1141
+ if (resource.type === "file") {
1142
+ autoAssociateFile(resource, projectRoot, agents, agentSources, autoAssociations);
1143
+ return;
1144
+ }
1145
+ const ownerAgent = resource.owner_agent;
1146
+ if (!ownerAgent) return;
1147
+ const agent = agents[ownerAgent];
1148
+ const agentSource = agentSources.get(ownerAgent);
1149
+ if (!agent || !agentSource) return;
1150
+ const agentPath = `agents/${ownerAgent}/agent.json`;
1151
+ if (resource.type === "memory_store") {
1152
+ if (agent.memory_stores !== void 0 && !Array.isArray(agent.memory_stores)) return;
1153
+ const references = Array.isArray(agent.memory_stores) ? agent.memory_stores : [];
1154
+ if (references.includes(resource.id)) return;
1155
+ agent.memory_stores = [...references, resource.id];
1156
+ agentSource.memory_stores = structuredClone(agent.memory_stores);
1157
+ } else {
1158
+ if (agent[resource.type] !== void 0) return;
1159
+ const candidates = resources.filter(
1160
+ (candidate) => candidate.owner_agent === ownerAgent && candidate.type === resource.type
1161
+ );
1162
+ if (candidates.length > 1) {
1163
+ throw new UserError(
1164
+ `${agentPath}: multiple local ${resource.type} resources (${candidates.map((candidate) => candidate.id).join(", ")}). Set '${resource.type}' explicitly to choose one.`
1165
+ );
1166
+ }
1167
+ agent[resource.type] = resource.id;
1168
+ agentSource[resource.type] = resource.id;
1169
+ }
1170
+ planJsonWrite(autoAssociations, projectRoot, resolve2(projectRoot, agentPath), agentSource);
1171
+ autoAssociations.warnings.push({
1172
+ severity: "warning",
1173
+ code: `project.${resource.type}.agent_link.inferred`,
1174
+ message: `${resource.type} '${resource.id}' will be added to ${agentPath}.`
1175
+ });
1176
+ }
1123
1177
  function autoAssociateFile(resource, projectRoot, agents, agentSources, autoAssociations) {
1124
1178
  const ownerAgent = resource.owner_agent;
1125
1179
  if (!ownerAgent) return;
@@ -809,7 +809,7 @@ interface ProviderAdapter {
809
809
  listVaultResources?(options?: VaultListOptions): Promise<VaultPage>;
810
810
  getRemoteVault?(id: string): Promise<CloudVault>;
811
811
  getDriftSupport?(type: ResourceType): DriftSupport;
812
- readComparableResource?(type: ResourceType, id: string | null, name: string): Promise<ComparableRemoteResource | null>;
812
+ readComparableResource?(type: ResourceType, id: string | null, name: string, decl?: unknown): Promise<ComparableRemoteResource | null>;
813
813
  normalizeDesiredResource?(type: ResourceType, name: string, decl: unknown): unknown | null;
814
814
  /**
815
815
  * Reverse-map remote resources of a given type into `agents.yaml` declarations
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openagentpack/sdk",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "description": "OpenAgentPack SDK (Node-compatible runtime)",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [