@autohq/cli 0.1.148 → 0.1.150

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
@@ -18510,8 +18510,8 @@ function isSafePathUnderHome(value, home) {
18510
18510
  if (!value.startsWith(prefix)) {
18511
18511
  return false;
18512
18512
  }
18513
- const relative = value.slice(prefix.length);
18514
- return relative.split("/").every((segment) => segment !== "" && segment !== "." && segment !== "..");
18513
+ const relative2 = value.slice(prefix.length);
18514
+ return relative2.split("/").every((segment) => segment !== "" && segment !== "." && segment !== "..");
18515
18515
  }
18516
18516
  function isSafeRelativePath(value) {
18517
18517
  if (!value || value.startsWith("/")) {
@@ -21306,7 +21306,7 @@ var init_package = __esm({
21306
21306
  "package.json"() {
21307
21307
  package_default = {
21308
21308
  name: "@autohq/cli",
21309
- version: "0.1.148",
21309
+ version: "0.1.150",
21310
21310
  license: "SEE LICENSE IN README.md",
21311
21311
  publishConfig: {
21312
21312
  access: "public"
@@ -21403,28 +21403,6 @@ function compileAgentFile(path2) {
21403
21403
  removals: context.removals
21404
21404
  };
21405
21405
  }
21406
- function compileAgentDocumentValue(document, path2) {
21407
- const context = { graph: /* @__PURE__ */ new Map(), removals: [] };
21408
- const compiled = finalizeAgentApplyShape(
21409
- compileAgentDocument(document, path2, [], context),
21410
- path2
21411
- );
21412
- const parsed = ProjectApplyResourceSchema.safeParse(compiled.resource);
21413
- if (!parsed.success) {
21414
- throw new Error(`Invalid compiled agent ${path2}: ${parsed.error.message}`);
21415
- }
21416
- if (parsed.data.kind !== RESOURCE_KIND_AGENT) {
21417
- throw new Error(
21418
- `Invalid compiled agent ${path2}: expected kind "agent", got "${parsed.data.kind}"`
21419
- );
21420
- }
21421
- return {
21422
- resource: parsed.data,
21423
- resources: [...compiled.resources, parsed.data],
21424
- graph: [...context.graph.values()],
21425
- removals: context.removals
21426
- };
21427
- }
21428
21406
  function renderCompiledAgentYaml(result) {
21429
21407
  return stringify(result.resource).trimEnd();
21430
21408
  }
@@ -21481,9 +21459,6 @@ function readLocalAgentAuthoringStatuses(input) {
21481
21459
  }
21482
21460
  });
21483
21461
  }
21484
- function validateAgentFragmentFile(path2) {
21485
- validateAgentFragmentDocument(readSingleDocument(path2), path2, []);
21486
- }
21487
21462
  function agentAuthoringFiles(directory) {
21488
21463
  let entries;
21489
21464
  try {
@@ -21566,29 +21541,6 @@ function compileAgentDocument(document, path2, stack, context) {
21566
21541
  []
21567
21542
  );
21568
21543
  }
21569
- function validateAgentFragmentDocument(document, path2, stack) {
21570
- const resolvedPath = resolve(path2);
21571
- if (stack.includes(resolvedPath)) {
21572
- throw new Error(
21573
- `Agent import cycle detected: ${[...stack, resolvedPath].join(" -> ")}`
21574
- );
21575
- }
21576
- if (!isRecord(document)) {
21577
- throw new Error(`Invalid agent fragment file ${path2}: expected object`);
21578
- }
21579
- for (const imported of importPaths(document).map(
21580
- (importPath) => resolveImportPath(importPath, resolvedPath)
21581
- )) {
21582
- validateAgentFragmentDocument(readSingleDocument(imported), imported, [
21583
- ...stack,
21584
- resolvedPath
21585
- ]);
21586
- }
21587
- for (const removal of removalDirectives(document, resolvedPath)) {
21588
- assertSupportedRemovalTarget(removal.target);
21589
- }
21590
- authoringDocumentApplyShape(document, resolvedPath);
21591
- }
21592
21544
  function readSingleDocument(path2) {
21593
21545
  const documents = readDocuments(path2);
21594
21546
  if (documents.length !== 1) {
@@ -22298,112 +22250,201 @@ var init_assets = __esm({
22298
22250
  }
22299
22251
  });
22300
22252
 
22301
- // src/commands/apply/files.ts
22302
- import { createHash as createHash3 } from "crypto";
22303
- import {
22304
- readFileSync as readFileSync4,
22305
- readdirSync as readdirSync3,
22306
- realpathSync,
22307
- statSync as statSync2
22308
- } from "fs";
22309
- import {
22310
- basename as basename3,
22311
- dirname as dirname5,
22312
- extname as extname2,
22313
- isAbsolute as isAbsolute2,
22314
- join as join5,
22315
- resolve as resolve2
22316
- } from "path";
22253
+ // ../../packages/schemas/src/project-apply-files/source.ts
22317
22254
  import { parseAllDocuments as parseYamlDocuments2 } from "yaml";
22318
- function readProjectApplyRequest(options) {
22319
- if (options.file && options.directory) {
22320
- throw new Error("Cannot use --file with --directory.");
22321
- }
22322
- if (options.file) {
22323
- const request = readApplyDocumentFile(options.file);
22324
- const resources2 = dedupeGeneratedResources(request.resourceRecords);
22325
- const assets2 = readApplyAssets(
22326
- resources2,
22327
- applyFileProjectRoot(options.file)
22255
+ function readDocumentsFromSource(file2) {
22256
+ const source = Buffer.from(file2.contentBase64, "base64").toString("utf8");
22257
+ try {
22258
+ const parsedDocuments = parseYamlDocuments2(source);
22259
+ const parseError = parsedDocuments.flatMap((document) => document.errors).at(0);
22260
+ if (parseError) {
22261
+ throw parseError;
22262
+ }
22263
+ return parsedDocuments.filter((document) => document.contents !== null).map((document) => document.toJSON());
22264
+ } catch (error51) {
22265
+ throw new Error(
22266
+ `Invalid apply file ${file2.path}: ${error51 instanceof Error ? error51.message : String(error51)}`
22328
22267
  );
22329
- return {
22330
- delete: request.delete,
22331
- dryRun: request.dryRun,
22332
- prune: request.prune,
22333
- resources: resources2,
22334
- assets: assets2
22268
+ }
22269
+ }
22270
+ function primaryApplyDirectory() {
22271
+ return APPLY_DIRECTORIES[RESOURCE_KIND_AGENT];
22272
+ }
22273
+ function isResourceFileUnderDirectory(path2, directory) {
22274
+ const normalizedPath = normalizeSourcePath(path2);
22275
+ const normalizedDirectory = normalizeSourcePath(directory);
22276
+ return normalizedPath.startsWith(`${normalizedDirectory}/`) && /\.(json|ya?ml)$/i.test(normalizedPath);
22277
+ }
22278
+ function sourcePathJoin(...parts) {
22279
+ return parts.map(normalizeSourcePath).filter(Boolean).join("/");
22280
+ }
22281
+ function normalizeSourcePath(path2) {
22282
+ return path2.replaceAll("\\", "/").replace(/^\/+|\/+$/g, "");
22283
+ }
22284
+ function sourceFileIndex(files) {
22285
+ return new Map(files.map((file2) => [normalizeSourcePath(file2.path), file2]));
22286
+ }
22287
+ function isAbsoluteSourcePath(path2) {
22288
+ return path2.startsWith("/");
22289
+ }
22290
+ function isRecord2(value) {
22291
+ return typeof value === "object" && value !== null && !Array.isArray(value);
22292
+ }
22293
+ var APPLY_DIRECTORIES, PROJECT_APPLY_RESOURCE_DIRECTORIES;
22294
+ var init_source = __esm({
22295
+ "../../packages/schemas/src/project-apply-files/source.ts"() {
22296
+ "use strict";
22297
+ init_agents();
22298
+ APPLY_DIRECTORIES = {
22299
+ [RESOURCE_KIND_AGENT]: "agents"
22335
22300
  };
22301
+ PROJECT_APPLY_RESOURCE_DIRECTORIES = Object.freeze([
22302
+ APPLY_DIRECTORIES[RESOURCE_KIND_AGENT]
22303
+ ]);
22336
22304
  }
22337
- const directory = options.directory ?? join5(process.cwd(), ".auto");
22338
- assertNoLegacySessionFiles(directory);
22339
- assertNoStandaloneResourceFiles(directory);
22340
- assertValidFragmentFiles(directory);
22341
- const files = applyFiles(directory);
22342
- if (files.length === 0) {
22343
- throw new Error(`No resource files found in ${directory}`);
22305
+ });
22306
+
22307
+ // ../../packages/schemas/src/project-apply-files/agent-document-merge.ts
22308
+ import { posix } from "path";
22309
+ function readSingleDocument2(path2, fileIndex) {
22310
+ const file2 = fileIndex.get(normalizeSourcePath(path2));
22311
+ if (!file2) {
22312
+ throw new Error(`Agent import not found: ${path2}`);
22313
+ }
22314
+ const documents = readDocumentsFromSource(file2);
22315
+ if (documents.length !== 1) {
22316
+ throw new Error(
22317
+ `Agent authoring file ${file2.path} must contain exactly one document`
22318
+ );
22344
22319
  }
22345
- const resourceRecords = [];
22346
- for (const { kind, path: path2 } of files) {
22347
- const request = readApplyDocumentFile(path2);
22348
- for (const { resource, generatedFromAgent } of request.resourceRecords) {
22349
- if (!isAllowedDirectoryResourceKind(kind, resource, generatedFromAgent)) {
22350
- throw new Error(
22351
- `Resource kind "${resource.kind}" in ${path2} does not match .auto/${primaryApplyDirectory(kind)}`
22352
- );
22353
- }
22354
- resourceRecords.push({ resource, generatedFromAgent });
22320
+ return documents[0];
22321
+ }
22322
+ function importPaths2(document) {
22323
+ const value = document.imports ?? document.import;
22324
+ if (value === void 0) {
22325
+ return [];
22326
+ }
22327
+ const values = Array.isArray(value) ? value : [value];
22328
+ return values.map((item) => {
22329
+ if (typeof item !== "string" || item.trim().length === 0) {
22330
+ throw new Error("Agent imports must be non-empty string paths");
22355
22331
  }
22332
+ return item.trim();
22333
+ });
22334
+ }
22335
+ function resolveImportPath2(importPath, importerPath, fileIndex) {
22336
+ if (isAbsoluteSourcePath(importPath) || /^[A-Za-z]+:\/\//.test(importPath)) {
22337
+ throw new Error(`Agent import must be a relative path: ${importPath}`);
22356
22338
  }
22357
- const resources = dedupeGeneratedResources(resourceRecords);
22358
- const assets = readApplyAssets(resources, applyProjectRoot(directory));
22339
+ const resolved = normalizeSourcePath(
22340
+ posix.normalize(posix.join(posix.dirname(importerPath), importPath))
22341
+ );
22342
+ if (!fileIndex.has(resolved)) {
22343
+ throw new Error(
22344
+ `Agent import not found: ${importPath} from ${importerPath}`
22345
+ );
22346
+ }
22347
+ return resolved;
22348
+ }
22349
+ function removalDirectives2(document, path2) {
22350
+ const raw = isRecord2(document.remove) ? document.remove : {};
22351
+ const directives = [];
22352
+ for (const [target, value] of Object.entries(raw)) {
22353
+ const names = stringList2(value, `remove.${target}`);
22354
+ if (names.length > 0) {
22355
+ directives.push({ path: path2, target, names });
22356
+ }
22357
+ }
22358
+ return directives;
22359
+ }
22360
+ function stringList2(value, label) {
22361
+ const values = Array.isArray(value) ? value : [value];
22362
+ return values.map((item) => {
22363
+ if (typeof item !== "string" || item.trim().length === 0) {
22364
+ throw new Error(`${label} entries must be non-empty strings`);
22365
+ }
22366
+ return item.trim();
22367
+ });
22368
+ }
22369
+ var init_agent_document_merge = __esm({
22370
+ "../../packages/schemas/src/project-apply-files/agent-document-merge.ts"() {
22371
+ "use strict";
22372
+ init_source();
22373
+ }
22374
+ });
22375
+
22376
+ // ../../packages/schemas/src/project-apply-files/agent-fields/file-backed-string.ts
22377
+ import { posix as posix2 } from "path";
22378
+ function fileBackedStringField() {
22359
22379
  return {
22360
- delete: [],
22361
- dryRun: false,
22362
- prune: true,
22363
- resources,
22364
- assets
22380
+ target: "spec",
22381
+ read: (value, context) => resolveFileBackedString2(value, context)
22365
22382
  };
22366
22383
  }
22367
- function isAllowedDirectoryResourceKind(directoryKind, resource, generatedFromAgent) {
22368
- if (resource.kind === directoryKind) {
22369
- return true;
22384
+ function resolveFileBackedString2(value, input) {
22385
+ if (!isRecord2(value) || !("file" in value)) {
22386
+ return value;
22387
+ }
22388
+ const file2 = value.file;
22389
+ if (typeof file2 !== "string" || file2.trim().length === 0) {
22390
+ throw new Error(
22391
+ `Invalid agent authoring file ${input.path}: ${input.field}.file must be a non-empty string`
22392
+ );
22393
+ }
22394
+ const filePath = file2.trim();
22395
+ if (isAbsoluteSourcePath(filePath) || /^[A-Za-z]+:\/\//.test(filePath)) {
22396
+ throw new Error(
22397
+ `Invalid agent authoring file ${input.path}: ${input.field}.file must be a relative path`
22398
+ );
22399
+ }
22400
+ const resolved = normalizeSourcePath(
22401
+ posix2.normalize(posix2.join(posix2.dirname(input.path), filePath))
22402
+ );
22403
+ const source = input.fileIndex.get(resolved);
22404
+ if (!source) {
22405
+ throw new Error(
22406
+ `Invalid agent authoring file ${input.path}: ${input.field}.file not found: ${filePath}`
22407
+ );
22370
22408
  }
22371
- return directoryKind === RESOURCE_KIND_AGENT && (resource.kind === RESOURCE_KIND_ENVIRONMENT || resource.kind === RESOURCE_KIND_IDENTITY) && generatedFromAgent;
22409
+ return Buffer.from(source.contentBase64, "base64").toString("utf8");
22372
22410
  }
22373
- function dedupeGeneratedResources(records) {
22374
- const recordsByKey = /* @__PURE__ */ new Map();
22375
- const deduped = [];
22376
- for (const record2 of records) {
22377
- const { resource } = record2;
22378
- const key = `${resource.kind}/${resource.metadata.name}`;
22379
- const existing = recordsByKey.get(key);
22380
- if (!existing) {
22381
- recordsByKey.set(key, record2);
22382
- deduped.push(record2);
22383
- continue;
22384
- }
22385
- if (!record2.generatedFromAgent && !existing.generatedFromAgent) {
22386
- deduped.push(record2);
22387
- continue;
22388
- }
22389
- if (stableResource(resource) !== stableResource(existing.resource)) {
22390
- throw new Error(
22391
- `Conflicting generated resource "${key}" from agent authoring. Inline generated resources must be identical when they share a name.`
22392
- );
22411
+ var init_file_backed_string = __esm({
22412
+ "../../packages/schemas/src/project-apply-files/agent-fields/file-backed-string.ts"() {
22413
+ "use strict";
22414
+ init_source();
22415
+ }
22416
+ });
22417
+
22418
+ // ../../packages/schemas/src/project-apply-files/agent-fields/helpers.ts
22419
+ function emptyAgentDraft() {
22420
+ return { metadata: {}, spec: {} };
22421
+ }
22422
+ function cloneAgentDraft(draft) {
22423
+ return structuredClone(draft);
22424
+ }
22425
+ function isMetadataFieldKey(key) {
22426
+ return AGENT_METADATA_FIELD_KEYS.includes(key);
22427
+ }
22428
+ function mergeValues3(base, override) {
22429
+ if (override === void 0) {
22430
+ return base;
22431
+ }
22432
+ if (isRecord2(base) && isRecord2(override)) {
22433
+ const merged = { ...base };
22434
+ for (const [key, value] of Object.entries(override)) {
22435
+ merged[key] = mergeValues3(merged[key], value);
22393
22436
  }
22437
+ return merged;
22394
22438
  }
22395
- return deduped.map((record2) => record2.resource);
22439
+ return override;
22396
22440
  }
22397
22441
  function stableResource(resource) {
22398
22442
  return JSON.stringify({
22399
22443
  kind: resource.kind,
22400
- metadata: metadataComparable(resource.metadata),
22444
+ metadata: sortJson(resource.metadata),
22401
22445
  spec: sortJson(resource.spec)
22402
22446
  });
22403
22447
  }
22404
- function metadataComparable(metadata) {
22405
- return sortJson(metadata);
22406
- }
22407
22448
  function sortJson(value) {
22408
22449
  if (Array.isArray(value)) {
22409
22450
  return value.map(sortJson);
@@ -22415,65 +22456,775 @@ function sortJson(value) {
22415
22456
  }
22416
22457
  return value;
22417
22458
  }
22418
- function appliedResourceKind(request, response, index) {
22419
- const plannedResources = response.plan.filter(
22420
- (item) => item.action !== "archive"
22421
- );
22422
- const kind = plannedResources[index]?.kind ?? request.resources[index]?.kind;
22423
- if (!kind) {
22459
+ var CONTROL_FIELDS, AGENT_METADATA_FIELD_KEYS;
22460
+ var init_helpers = __esm({
22461
+ "../../packages/schemas/src/project-apply-files/agent-fields/helpers.ts"() {
22462
+ "use strict";
22463
+ init_source();
22464
+ CONTROL_FIELDS = /* @__PURE__ */ new Set(["import", "imports", "remove"]);
22465
+ AGENT_METADATA_FIELD_KEYS = ["name", "labels", "annotations"];
22466
+ }
22467
+ });
22468
+
22469
+ // ../../packages/schemas/src/project-apply-files/agent-fields/inline-resource.ts
22470
+ function inlineEnvironmentField() {
22471
+ return {
22472
+ target: "spec",
22473
+ merge: (base, override) => mergeValues3(base, override),
22474
+ compile: (value, context) => {
22475
+ if (!isRecord2(value)) {
22476
+ return { resources: [], value };
22477
+ }
22478
+ const resource = inlineEnvironmentResource2(value, context.path);
22479
+ return { resources: [resource], value: resource.metadata.name };
22480
+ }
22481
+ };
22482
+ }
22483
+ function inlineIdentityField() {
22484
+ return {
22485
+ target: "spec",
22486
+ merge: (base, override) => mergeValues3(base, override),
22487
+ compile: (value, context) => {
22488
+ if (!isRecord2(value)) {
22489
+ return { resources: [], value };
22490
+ }
22491
+ const resource = inlineIdentityResource2(
22492
+ value,
22493
+ context.draft,
22494
+ context.path
22495
+ );
22496
+ return { resources: [resource], value: resource.metadata.name };
22497
+ }
22498
+ };
22499
+ }
22500
+ function assertAgentAuthoringDocument(document, path2) {
22501
+ if (!isRecord2(document) || !("kind" in document)) {
22502
+ return;
22503
+ }
22504
+ if (document.kind === "session") {
22424
22505
  throw new Error(
22425
- `Apply response did not include a resource kind for item ${index}`
22506
+ 'Legacy resource kind "session" is no longer supported. Use .auto/agents with the root-level Agent facade format.'
22426
22507
  );
22427
22508
  }
22428
- return kind;
22429
- }
22430
- function mcpOAuthAgentToolConnectionsFromApplyRequest(request) {
22431
- return request.resources.filter((resource) => resource.kind === RESOURCE_KIND_AGENT).flatMap((resource) => {
22432
- return mcpOAuthAgentToolConnectionsFromAgentTools({
22433
- agent: resource.metadata.name,
22434
- tools: resource.spec.tools
22435
- });
22509
+ if (document.kind === RESOURCE_KIND_ENVIRONMENT || document.kind === RESOURCE_KIND_IDENTITY) {
22510
+ throw standaloneResourceError(document.kind, path2);
22511
+ }
22512
+ if (document.kind !== RESOURCE_KIND_AGENT) {
22513
+ throw new Error(
22514
+ `Unsupported apply resource kind "${String(document.kind)}"; supported kind is "${RESOURCE_KIND_AGENT}"`
22515
+ );
22516
+ }
22517
+ const parsed = AgentApplyRequestSchema.safeParse({
22518
+ metadata: document.metadata,
22519
+ spec: document.spec
22436
22520
  });
22521
+ if (parsed.success) {
22522
+ throw new Error(
22523
+ `Legacy agent resource envelopes are no longer supported in ${path2}. Use the root-level Agent facade format under .auto/agents.`
22524
+ );
22525
+ }
22437
22526
  }
22438
- function mcpOAuthAgentToolConnectionsFromAppliedResources(resources) {
22439
- return resources.filter((item) => item.kind === RESOURCE_KIND_AGENT).flatMap((item) => {
22440
- const resource = item.resource;
22441
- return mcpOAuthAgentToolConnectionsFromAgentTools({
22442
- agent: resource.metadata.name,
22443
- tools: resource.spec.tools
22444
- });
22527
+ function parseAgentResource(draft, path2) {
22528
+ const parsed = AgentApplyRequestSchema.safeParse({
22529
+ metadata: draft.metadata,
22530
+ spec: draft.spec
22445
22531
  });
22446
- }
22447
- function applyFiles(root) {
22448
- const agentsRoot = join5(root, primaryApplyDirectory(RESOURCE_KIND_AGENT));
22449
- let entries;
22450
- try {
22451
- entries = readdirSync3(agentsRoot, { withFileTypes: true });
22452
- } catch {
22453
- return [];
22532
+ if (!parsed.success) {
22533
+ throw new Error(`Invalid compiled agent ${path2}: ${parsed.error.message}`);
22454
22534
  }
22455
- return resourceApplyFiles(agentsRoot, entries).map((path2) => ({
22535
+ return {
22456
22536
  kind: RESOURCE_KIND_AGENT,
22457
- path: path2
22458
- }));
22459
- }
22460
- function assertNoLegacySessionFiles(root) {
22461
- const path2 = join5(root, "sessions");
22462
- let entries;
22463
- try {
22464
- entries = readdirSync3(path2, { withFileTypes: true });
22465
- } catch {
22466
- return;
22537
+ metadata: parsed.data.metadata,
22538
+ spec: parsed.data.spec
22539
+ };
22540
+ }
22541
+ function inlineEnvironmentResource2(document, path2) {
22542
+ const parsed = EnvironmentApplyRequestSchema.safeParse(
22543
+ splitMetadataAndSpec(document)
22544
+ );
22545
+ if (!parsed.success) {
22546
+ throw new Error(
22547
+ `Invalid inline environment in ${path2}: ${parsed.error.message}`
22548
+ );
22549
+ }
22550
+ return {
22551
+ kind: RESOURCE_KIND_ENVIRONMENT,
22552
+ metadata: parsed.data.metadata,
22553
+ spec: parsed.data.spec
22554
+ };
22555
+ }
22556
+ function inlineIdentityResource2(document, agentDraft, path2) {
22557
+ const input = splitMetadataAndSpec(document);
22558
+ if (input.metadata.name === void 0 && typeof agentDraft.metadata.name === "string") {
22559
+ input.metadata.name = agentDraft.metadata.name;
22560
+ }
22561
+ const parsed = IdentityApplyRequestSchema.safeParse(input);
22562
+ if (!parsed.success) {
22563
+ throw new Error(
22564
+ `Invalid inline identity in ${path2}: ${parsed.error.message}`
22565
+ );
22566
+ }
22567
+ return {
22568
+ kind: RESOURCE_KIND_IDENTITY,
22569
+ metadata: parsed.data.metadata,
22570
+ spec: parsed.data.spec
22571
+ };
22572
+ }
22573
+ function splitMetadataAndSpec(document) {
22574
+ const metadata = {};
22575
+ const spec = {};
22576
+ for (const [key, value] of Object.entries(document)) {
22577
+ if (value === void 0) {
22578
+ continue;
22579
+ }
22580
+ if (isMetadataFieldKey(key)) {
22581
+ metadata[key] = value;
22582
+ continue;
22583
+ }
22584
+ spec[key] = value;
22585
+ }
22586
+ return { metadata, spec };
22587
+ }
22588
+ function standaloneResourceError(kind, path2) {
22589
+ if (kind === RESOURCE_KIND_ENVIRONMENT) {
22590
+ return new Error(
22591
+ `Standalone environment resources are no longer supported in ${path2}. Define environments inline in .auto/agents YAML, using fragment imports under .auto/fragments/environments for reused runtimes.`
22592
+ );
22593
+ }
22594
+ return new Error(
22595
+ `Standalone identity resources are no longer supported in ${path2}. Define identities inline on the owning .auto/agents YAML file.`
22596
+ );
22597
+ }
22598
+ var init_inline_resource = __esm({
22599
+ "../../packages/schemas/src/project-apply-files/agent-fields/inline-resource.ts"() {
22600
+ "use strict";
22601
+ init_agents();
22602
+ init_environments();
22603
+ init_identities();
22604
+ init_source();
22605
+ init_helpers();
22606
+ }
22607
+ });
22608
+
22609
+ // ../../packages/schemas/src/project-apply-files/agent-fields/named-array.ts
22610
+ function namedArrayField(options) {
22611
+ const remove = options.removable === false ? void 0 : removeNamedArray;
22612
+ return {
22613
+ target: "spec",
22614
+ merge: (base, override) => {
22615
+ if (!Array.isArray(base) || !Array.isArray(override)) {
22616
+ return mergeValues3(base, override);
22617
+ }
22618
+ return mergeNamedArray(base, override, options.itemKey);
22619
+ },
22620
+ remove: remove ? (value, names) => remove(value, names, options.itemKey) : void 0
22621
+ };
22622
+ }
22623
+ function mountsField() {
22624
+ return namedArrayField({
22625
+ itemKey: mountItemKey,
22626
+ removable: false
22627
+ });
22628
+ }
22629
+ function triggersField() {
22630
+ return {
22631
+ ...namedArrayField({ itemKey: triggerItemKey }),
22632
+ compile: (value) => {
22633
+ return {
22634
+ resources: [],
22635
+ value: removeAuthoringTriggerNames(value)
22636
+ };
22637
+ }
22638
+ };
22639
+ }
22640
+ function mountItemKey(item) {
22641
+ if (!isRecord2(item)) {
22642
+ return void 0;
22643
+ }
22644
+ if (typeof item.name === "string") {
22645
+ return item.name;
22646
+ }
22647
+ if (typeof item.mountPath === "string") {
22648
+ return item.mountPath;
22649
+ }
22650
+ return void 0;
22651
+ }
22652
+ function triggerItemKey(item) {
22653
+ if (!isRecord2(item)) {
22654
+ return void 0;
22655
+ }
22656
+ if (typeof item.name === "string") {
22657
+ return item.name;
22658
+ }
22659
+ if (typeof item.event === "string") {
22660
+ return item.event;
22661
+ }
22662
+ if (Array.isArray(item.events)) {
22663
+ return item.events.filter((event) => typeof event === "string").join(",");
22664
+ }
22665
+ if (typeof item.cron === "string") {
22666
+ return `cron:${item.cron}:${typeof item.timezone === "string" ? item.timezone : ""}`;
22667
+ }
22668
+ return void 0;
22669
+ }
22670
+ function mergeNamedArray(base, override, itemKey) {
22671
+ const merged = [...base];
22672
+ const indexByKey = /* @__PURE__ */ new Map();
22673
+ for (const [index, item] of merged.entries()) {
22674
+ const key = itemKey(item);
22675
+ if (key) {
22676
+ indexByKey.set(key, index);
22677
+ }
22678
+ }
22679
+ for (const item of override) {
22680
+ const key = itemKey(item);
22681
+ if (key && indexByKey.has(key)) {
22682
+ merged[indexByKey.get(key) ?? 0] = mergeValues3(
22683
+ merged[indexByKey.get(key) ?? 0],
22684
+ item
22685
+ );
22686
+ continue;
22687
+ }
22688
+ if (key) {
22689
+ indexByKey.set(key, merged.length);
22690
+ }
22691
+ merged.push(item);
22692
+ }
22693
+ return merged;
22694
+ }
22695
+ function removeNamedArray(value, names, itemKey) {
22696
+ if (!Array.isArray(value)) {
22697
+ return value;
22698
+ }
22699
+ return value.filter((item) => !names.includes(itemKey(item) ?? ""));
22700
+ }
22701
+ function removeAuthoringTriggerNames(value) {
22702
+ if (!Array.isArray(value)) {
22703
+ return value;
22704
+ }
22705
+ return value.map((trigger) => {
22706
+ if (!isRecord2(trigger) || !("name" in trigger)) {
22707
+ return trigger;
22708
+ }
22709
+ const next = { ...trigger };
22710
+ delete next.name;
22711
+ return next;
22712
+ });
22713
+ }
22714
+ var init_named_array = __esm({
22715
+ "../../packages/schemas/src/project-apply-files/agent-fields/named-array.ts"() {
22716
+ "use strict";
22717
+ init_source();
22718
+ init_helpers();
22719
+ }
22720
+ });
22721
+
22722
+ // ../../packages/schemas/src/project-apply-files/agent-fields/named-map.ts
22723
+ function namedMapField() {
22724
+ return {
22725
+ target: "spec",
22726
+ merge: (base, override) => mergeValues3(base, override),
22727
+ remove: (value, names) => {
22728
+ if (!isRecord2(value)) {
22729
+ return value;
22730
+ }
22731
+ const next = { ...value };
22732
+ for (const name of names) {
22733
+ delete next[name];
22734
+ }
22735
+ return next;
22736
+ }
22737
+ };
22738
+ }
22739
+ var init_named_map = __esm({
22740
+ "../../packages/schemas/src/project-apply-files/agent-fields/named-map.ts"() {
22741
+ "use strict";
22742
+ init_source();
22743
+ init_helpers();
22744
+ }
22745
+ });
22746
+
22747
+ // ../../packages/schemas/src/project-apply-files/agent-fields/scalar.ts
22748
+ function metadataField() {
22749
+ return { target: "metadata" };
22750
+ }
22751
+ function specField() {
22752
+ return { target: "spec" };
22753
+ }
22754
+ var init_scalar = __esm({
22755
+ "../../packages/schemas/src/project-apply-files/agent-fields/scalar.ts"() {
22756
+ "use strict";
22757
+ }
22758
+ });
22759
+
22760
+ // ../../packages/schemas/src/project-apply-files/agent-fields/index.ts
22761
+ function parseAgentDraft(document, path2, fileIndex) {
22762
+ assertAgentAuthoringDocument(document, path2);
22763
+ const sanitized = sanitizedAgentDocument2(document);
22764
+ assertNoLegacyEnvelopeFields(sanitized, path2);
22765
+ const draft = emptyAgentDraft();
22766
+ for (const [key, value] of Object.entries(sanitized)) {
22767
+ if (value === void 0) {
22768
+ continue;
22769
+ }
22770
+ const field = AGENT_FIELDS[key];
22771
+ if (!field) {
22772
+ continue;
22773
+ }
22774
+ const target = draft[field.target];
22775
+ assertNoDuplicateFacadeField2({
22776
+ path: path2,
22777
+ field: key,
22778
+ target: `${field.target}.${key}`,
22779
+ targetValue: target[key]
22780
+ });
22781
+ target[key] = field.read ? field.read(value, { path: path2, field: key, fileIndex }) : value;
22782
+ }
22783
+ return draft;
22784
+ }
22785
+ function mergeAgentDrafts(base, override) {
22786
+ return {
22787
+ metadata: mergeDraftTarget("metadata", base.metadata, override.metadata),
22788
+ spec: mergeDraftTarget("spec", base.spec, override.spec)
22789
+ };
22790
+ }
22791
+ function applyAgentDraftRemoval(draft, removal) {
22792
+ const field = AGENT_FIELDS[removal.target];
22793
+ if (!field?.remove) {
22794
+ assertSupportedAgentRemovalTarget(removal.target);
22795
+ return draft;
22796
+ }
22797
+ const next = cloneAgentDraft(draft);
22798
+ const target = next[field.target];
22799
+ const current = target[removal.target];
22800
+ const updated = field.remove(current, removal.names, {
22801
+ field: removal.target
22802
+ });
22803
+ if (updated !== void 0 || current !== void 0) {
22804
+ target[removal.target] = updated;
22805
+ }
22806
+ return next;
22807
+ }
22808
+ function assertSupportedAgentRemovalTarget(target) {
22809
+ const supported = supportedRemovalTargets();
22810
+ if (!supported.includes(target)) {
22811
+ throw new Error(
22812
+ `Unsupported agent remove target "${target}"; supported targets are ${supported.join(", ")}`
22813
+ );
22814
+ }
22815
+ }
22816
+ function compileAgentDraftResources(draft, path2) {
22817
+ const next = cloneAgentDraft(draft);
22818
+ const resources = [];
22819
+ for (const [key, field] of Object.entries(AGENT_FIELDS)) {
22820
+ if (field.target !== "spec") {
22821
+ continue;
22822
+ }
22823
+ const value = next.spec[key];
22824
+ if (value === void 0) {
22825
+ continue;
22826
+ }
22827
+ const context = { path: path2, draft: next };
22828
+ if (field.compile) {
22829
+ const compiled = field.compile(value, context);
22830
+ resources.push(...compiled.resources);
22831
+ next.spec[key] = compiled.value;
22832
+ }
22833
+ }
22834
+ const resource = parseAgentResource(next, path2);
22835
+ return { resource, resources: [...resources, resource] };
22836
+ }
22837
+ function sanitizedAgentDocument2(document) {
22838
+ return Object.fromEntries(
22839
+ Object.entries(document).filter(([key]) => !CONTROL_FIELDS.has(key))
22840
+ );
22841
+ }
22842
+ function assertNoLegacyEnvelopeFields(document, path2) {
22843
+ const legacyEnvelopeFields = ["kind", "metadata", "spec"].filter(
22844
+ (field) => field in document
22845
+ );
22846
+ if (legacyEnvelopeFields.length > 0) {
22847
+ throw new Error(
22848
+ `Invalid agent authoring file ${path2}: legacy resource envelope fields are no longer supported (${legacyEnvelopeFields.join(", ")}). Use root-level Agent facade fields instead.`
22849
+ );
22850
+ }
22851
+ }
22852
+ function mergeDraftTarget(target, base, override) {
22853
+ const merged = { ...base };
22854
+ for (const [key, value] of Object.entries(override)) {
22855
+ const field = AGENT_FIELDS[key];
22856
+ const merge2 = field?.target === target ? field.merge : void 0;
22857
+ merged[key] = merge2 ? merge2(merged[key], value, { field: key }) : mergeValues3(merged[key], value);
22858
+ }
22859
+ return merged;
22860
+ }
22861
+ function assertNoDuplicateFacadeField2(input) {
22862
+ if (input.targetValue !== void 0) {
22863
+ throw new Error(
22864
+ `Invalid agent authoring file ${input.path}: ${input.field} duplicates ${input.target}`
22865
+ );
22866
+ }
22867
+ }
22868
+ function supportedRemovalTargets() {
22869
+ return ["tools", "triggers"].filter((key) => AGENT_FIELDS[key]?.remove);
22870
+ }
22871
+ var AGENT_FIELDS;
22872
+ var init_agent_fields = __esm({
22873
+ "../../packages/schemas/src/project-apply-files/agent-fields/index.ts"() {
22874
+ "use strict";
22875
+ init_file_backed_string();
22876
+ init_helpers();
22877
+ init_inline_resource();
22878
+ init_named_array();
22879
+ init_named_map();
22880
+ init_scalar();
22881
+ AGENT_FIELDS = {
22882
+ name: metadataField(),
22883
+ labels: metadataField(),
22884
+ annotations: metadataField(),
22885
+ harness: specField(),
22886
+ systemPrompt: fileBackedStringField(),
22887
+ environment: inlineEnvironmentField(),
22888
+ identity: inlineIdentityField(),
22889
+ initialPrompt: fileBackedStringField(),
22890
+ env: specField(),
22891
+ mounts: mountsField(),
22892
+ triggers: triggersField(),
22893
+ workingDirectory: specField(),
22894
+ tools: namedMapField()
22895
+ };
22896
+ }
22897
+ });
22898
+
22899
+ // ../../packages/schemas/src/project-apply-files/agent-authoring.ts
22900
+ function readApplyDocument(path2, document, fileIndex) {
22901
+ assertAgentAuthoringDocument(document, path2);
22902
+ const result = compileAgentDocumentValue(document, path2, fileIndex);
22903
+ return result.resources.map((resource) => ({
22904
+ resource,
22905
+ generatedFromAgent: resource !== result.resource
22906
+ }));
22907
+ }
22908
+ function validateAgentFragmentDocument(document, path2, context) {
22909
+ const normalizedPath = normalizeSourcePath(path2);
22910
+ if (context.stack.includes(normalizedPath)) {
22911
+ throw new Error(
22912
+ `Agent import cycle detected: ${[...context.stack, normalizedPath].join(" -> ")}`
22913
+ );
22914
+ }
22915
+ if (!isRecord2(document)) {
22916
+ throw new Error(`Invalid agent fragment file ${path2}: expected object`);
22917
+ }
22918
+ for (const imported of importPaths2(document).map(
22919
+ (importPath) => resolveImportPath2(importPath, normalizedPath, context.fileIndex)
22920
+ )) {
22921
+ validateAgentFragmentDocument(
22922
+ readSingleDocument2(imported, context.fileIndex),
22923
+ imported,
22924
+ {
22925
+ fileIndex: context.fileIndex,
22926
+ stack: [...context.stack, normalizedPath]
22927
+ }
22928
+ );
22929
+ }
22930
+ for (const removal of removalDirectives2(document, normalizedPath)) {
22931
+ assertSupportedAgentRemovalTarget(removal.target);
22932
+ }
22933
+ parseAgentDraft(document, normalizedPath, context.fileIndex);
22934
+ }
22935
+ function dedupeGeneratedResources(records) {
22936
+ const recordsByKey = /* @__PURE__ */ new Map();
22937
+ const deduped = [];
22938
+ for (const record2 of records) {
22939
+ const { resource } = record2;
22940
+ const key = `${resource.kind}/${resource.metadata.name}`;
22941
+ const existing = recordsByKey.get(key);
22942
+ if (!existing) {
22943
+ recordsByKey.set(key, record2);
22944
+ deduped.push(record2);
22945
+ continue;
22946
+ }
22947
+ if (!record2.generatedFromAgent && !existing.generatedFromAgent) {
22948
+ deduped.push(record2);
22949
+ continue;
22950
+ }
22951
+ if (stableResource(resource) !== stableResource(existing.resource)) {
22952
+ throw new Error(
22953
+ `Conflicting generated resource "${key}" from agent authoring. Inline generated resources must be identical when they share a name.`
22954
+ );
22955
+ }
22956
+ }
22957
+ return deduped.map((record2) => record2.resource);
22958
+ }
22959
+ function compileAgentDocumentValue(document, path2, fileIndex) {
22960
+ return compileAgentDraftResources(
22961
+ compileAgentDocument2(document, path2, {
22962
+ fileIndex,
22963
+ stack: []
22964
+ }),
22965
+ path2
22966
+ );
22967
+ }
22968
+ function compileAgentDocument2(document, path2, context) {
22969
+ const normalizedPath = normalizeSourcePath(path2);
22970
+ if (context.stack.includes(normalizedPath)) {
22971
+ throw new Error(
22972
+ `Agent import cycle detected: ${[...context.stack, normalizedPath].join(" -> ")}`
22973
+ );
22974
+ }
22975
+ if (!isRecord2(document)) {
22976
+ throw new Error(`Invalid agent authoring file ${path2}: expected object`);
22977
+ }
22978
+ let merged = emptyAgentDraft();
22979
+ for (const imported of importPaths2(document).map(
22980
+ (importPath) => resolveImportPath2(importPath, normalizedPath, context.fileIndex)
22981
+ )) {
22982
+ merged = mergeAgentDrafts(
22983
+ merged,
22984
+ compileAgentDocument2(
22985
+ readSingleDocument2(imported, context.fileIndex),
22986
+ imported,
22987
+ {
22988
+ fileIndex: context.fileIndex,
22989
+ stack: [...context.stack, normalizedPath]
22990
+ }
22991
+ )
22992
+ );
22993
+ }
22994
+ for (const removal of removalDirectives2(document, normalizedPath)) {
22995
+ merged = applyAgentDraftRemoval(merged, removal);
22996
+ }
22997
+ return mergeAgentDrafts(
22998
+ merged,
22999
+ parseAgentDraft(document, normalizedPath, context.fileIndex)
23000
+ );
23001
+ }
23002
+ var init_agent_authoring = __esm({
23003
+ "../../packages/schemas/src/project-apply-files/agent-authoring.ts"() {
23004
+ "use strict";
23005
+ init_agent_document_merge();
23006
+ init_agent_fields();
23007
+ init_source();
23008
+ }
23009
+ });
23010
+
23011
+ // ../../packages/schemas/src/project-apply-files/apply-result.ts
23012
+ function appliedResourceKind(request, response, index) {
23013
+ const plannedResources = response.plan.filter(
23014
+ (item) => item.action !== "archive" && isProjectApplyResourceKind(item.kind)
23015
+ );
23016
+ const kind = plannedResources[index]?.kind ?? request.resources[index]?.kind;
23017
+ if (!kind) {
23018
+ throw new Error(
23019
+ `Apply response did not include a resource kind for item ${index}`
23020
+ );
23021
+ }
23022
+ return kind;
23023
+ }
23024
+ function mcpOAuthAgentToolConnectionsFromApplyRequest(request) {
23025
+ return request.resources.filter((resource) => resource.kind === RESOURCE_KIND_AGENT).flatMap((resource) => {
23026
+ return mcpOAuthAgentToolConnectionsFromAgentTools({
23027
+ agent: resource.metadata.name,
23028
+ tools: resource.spec.tools
23029
+ });
23030
+ });
23031
+ }
23032
+ function mcpOAuthAgentToolConnectionsFromAppliedResources(resources) {
23033
+ return resources.filter((item) => item.kind === RESOURCE_KIND_AGENT).flatMap((item) => {
23034
+ const resource = item.resource;
23035
+ return mcpOAuthAgentToolConnectionsFromAgentTools({
23036
+ agent: resource.metadata.name,
23037
+ tools: resource.spec.tools
23038
+ });
23039
+ });
23040
+ }
23041
+ function isProjectApplyResourceKind(kind) {
23042
+ return kind === RESOURCE_KIND_IDENTITY || kind === RESOURCE_KIND_ENVIRONMENT || kind === RESOURCE_KIND_AGENT;
23043
+ }
23044
+ function mcpOAuthAgentToolConnectionsFromAgentTools(input) {
23045
+ return Object.entries(input.tools).flatMap(([alias, tool]) => {
23046
+ if (tool.kind !== "mcp_remote" || tool.disabled || tool.auth.kind !== "mcp_oauth") {
23047
+ return [];
23048
+ }
23049
+ return [
23050
+ {
23051
+ agent: input.agent,
23052
+ tool: alias,
23053
+ connection: tool.auth.connection
23054
+ }
23055
+ ];
23056
+ });
23057
+ }
23058
+ var init_apply_result = __esm({
23059
+ "../../packages/schemas/src/project-apply-files/apply-result.ts"() {
23060
+ "use strict";
23061
+ init_agents();
23062
+ init_environments();
23063
+ init_identities();
23064
+ }
23065
+ });
23066
+
23067
+ // ../../packages/schemas/src/project-apply-files/assets.ts
23068
+ import { createHash as createHash3 } from "crypto";
23069
+ import { extname as extname2 } from "path";
23070
+ function readApplyAssets(resources, readAsset) {
23071
+ const assets = {};
23072
+ for (const resource of resources) {
23073
+ const target = avatarAssetTarget(resource);
23074
+ if (!target || assets[target.asset]) {
23075
+ continue;
23076
+ }
23077
+ if (!isAvatarAssetPathShapeValid(target.asset)) {
23078
+ throw new Error(
23079
+ `Invalid identity avatar asset for "${target.resourceName}": asset path must be under .auto/assets`
23080
+ );
23081
+ }
23082
+ const source = readAsset(target);
23083
+ if (!source) {
23084
+ throw new Error(
23085
+ `Invalid identity avatar asset for "${target.resourceName}": ${target.asset} does not exist`
23086
+ );
23087
+ }
23088
+ assets[target.asset] = projectApplyAssetFromSource({
23089
+ resourceName: target.resourceName,
23090
+ source
23091
+ });
23092
+ }
23093
+ return assets;
23094
+ }
23095
+ function projectApplyAssetFromSource(input) {
23096
+ const bytes = Buffer.from(input.source.bytes);
23097
+ if (bytes.length === 0 || bytes.length > MAX_AVATAR_ASSET_BYTES) {
23098
+ throw new Error(
23099
+ `Invalid identity avatar asset for "${input.resourceName}": asset must be ${MAX_AVATAR_ASSET_BYTES} bytes or smaller`
23100
+ );
23101
+ }
23102
+ const extension = extname2(input.source.path).toLowerCase();
23103
+ if (!ALLOWED_AVATAR_EXTENSIONS.has(extension)) {
23104
+ throw new Error(
23105
+ `Invalid identity avatar asset for "${input.resourceName}": asset must be a PNG or JPEG image`
23106
+ );
23107
+ }
23108
+ const dimensionsProblem = avatarAssetDimensionsProblem(bytes);
23109
+ if (dimensionsProblem) {
23110
+ throw new Error(
23111
+ `Invalid identity avatar asset for "${input.resourceName}": ${dimensionsProblem}`
23112
+ );
23113
+ }
23114
+ return {
23115
+ sha256: createHash3("sha256").update(bytes).digest("hex"),
23116
+ contentType: extension === ".png" ? "image/png" : "image/jpeg",
23117
+ dataBase64: bytes.toString("base64")
23118
+ };
23119
+ }
23120
+ function avatarAssetTarget(resource) {
23121
+ if (resource.kind === RESOURCE_KIND_IDENTITY) {
23122
+ const asset = resource.spec.avatar?.asset;
23123
+ return asset ? { asset, resourceName: resource.metadata.name } : void 0;
23124
+ }
23125
+ if (resource.kind === RESOURCE_KIND_AGENT && typeof resource.spec.identity === "object" && resource.spec.identity !== null && !Array.isArray(resource.spec.identity)) {
23126
+ const asset = resource.spec.identity.avatar?.asset;
23127
+ return asset ? { asset, resourceName: resource.metadata.name } : void 0;
23128
+ }
23129
+ return void 0;
23130
+ }
23131
+ var ALLOWED_AVATAR_EXTENSIONS;
23132
+ var init_assets2 = __esm({
23133
+ "../../packages/schemas/src/project-apply-files/assets.ts"() {
23134
+ "use strict";
23135
+ init_agents();
23136
+ init_identities();
23137
+ ALLOWED_AVATAR_EXTENSIONS = /* @__PURE__ */ new Set([".jpg", ".jpeg", ".png"]);
23138
+ }
23139
+ });
23140
+
23141
+ // ../../packages/schemas/src/project-apply-files/index.ts
23142
+ function readProjectApplyDirectorySource(input) {
23143
+ const resourceRoot = normalizeSourcePath(input.resourceRoot ?? "");
23144
+ const displayResourceRoot2 = input.displayResourceRoot ?? (resourceRoot || ".auto");
23145
+ const fileIndex = sourceFileIndex(input.files);
23146
+ assertNoLegacySessionSourceFiles(
23147
+ input.files,
23148
+ resourceRoot,
23149
+ displayResourceRoot2
23150
+ );
23151
+ assertNoStandaloneSourceFiles(input.files, resourceRoot, displayResourceRoot2);
23152
+ assertValidFragmentSourceFiles(input.files, resourceRoot, fileIndex);
23153
+ const agentFiles = input.files.filter(
23154
+ (file2) => isResourceFileUnderDirectory(
23155
+ file2.path,
23156
+ sourcePathJoin(resourceRoot, primaryApplyDirectory())
23157
+ )
23158
+ ).sort((left, right) => left.path.localeCompare(right.path));
23159
+ const resourceRecords = [];
23160
+ for (const file2 of agentFiles) {
23161
+ const request = readProjectApplyDocumentSourceFile(file2, { fileIndex });
23162
+ resourceRecords.push(
23163
+ ...request.resources.map((resource) => ({
23164
+ resource,
23165
+ generatedFromAgent: resource.kind !== RESOURCE_KIND_AGENT
23166
+ }))
23167
+ );
23168
+ }
23169
+ const resources = dedupeGeneratedResources(resourceRecords);
23170
+ if (agentFiles.length === 0 && !input.allowEmpty) {
23171
+ throw new Error(input.emptyMessage ?? "No resource files found");
23172
+ }
23173
+ return ProjectApplyRequestSchema.parse({
23174
+ delete: [],
23175
+ dryRun: input.dryRun ?? false,
23176
+ prune: input.prune ?? true,
23177
+ resources,
23178
+ assets: readApplyAssets(resources, input.readAsset)
23179
+ });
23180
+ }
23181
+ function readProjectApplyFileSource(input) {
23182
+ const request = readProjectApplyDocumentSourceFile(input.file, {
23183
+ fileIndex: sourceFileIndex(input.files ?? [input.file])
23184
+ });
23185
+ return ProjectApplyRequestSchema.parse({
23186
+ ...request,
23187
+ assets: readApplyAssets(request.resources, input.readAsset)
23188
+ });
23189
+ }
23190
+ function readProjectApplyDocumentSourceFile(file2, options = {}) {
23191
+ const fileIndex = options.fileIndex ?? sourceFileIndex([file2]);
23192
+ const documents = readDocumentsFromSource(file2);
23193
+ if (documents.length === 0) {
23194
+ throw new Error(`Invalid apply file: ${file2.path} is empty`);
23195
+ }
23196
+ if (documents.length === 1) {
23197
+ const system = ProjectApplySystemConfigSchema.safeParse(documents[0]);
23198
+ if (system.success) {
23199
+ return ProjectApplyRequestSchema.parse(system.data.spec);
23200
+ }
22467
23201
  }
22468
- const files = resourceApplyFiles(path2, entries);
22469
- if (files.length === 0) {
23202
+ const resourceRecords = documents.flatMap(
23203
+ (document) => readApplyDocument(file2.path, document, fileIndex)
23204
+ );
23205
+ return ProjectApplyRequestSchema.parse({
23206
+ delete: [],
23207
+ dryRun: false,
23208
+ prune: false,
23209
+ resources: dedupeGeneratedResources(resourceRecords),
23210
+ assets: {}
23211
+ });
23212
+ }
23213
+ function assertNoLegacySessionSourceFiles(files, resourceRoot, displayResourceRoot2) {
23214
+ const legacyFiles = files.filter(
23215
+ (file2) => isResourceFileUnderDirectory(
23216
+ file2.path,
23217
+ sourcePathJoin(resourceRoot, "sessions")
23218
+ )
23219
+ );
23220
+ if (legacyFiles.length === 0) {
22470
23221
  return;
22471
23222
  }
22472
23223
  throw new Error(
22473
- `Legacy .auto/sessions files are no longer supported. Move ${files.length === 1 ? "this file" : "these files"} to .auto/agents and use the root-level Agent facade format: ${files.join(", ")}`
23224
+ `Legacy ${sourcePathJoin(displayResourceRoot2, "sessions")} files are no longer supported. Move ${legacyFiles.length === 1 ? "this file" : "these files"} to ${sourcePathJoin(displayResourceRoot2, "agents")} and use the root-level Agent facade format: ${legacyFiles.map((file2) => file2.path).join(", ")}`
22474
23225
  );
22475
23226
  }
22476
- function assertNoStandaloneResourceFiles(root) {
23227
+ function assertNoStandaloneSourceFiles(files, resourceRoot, displayResourceRoot2) {
22477
23228
  for (const { directory, kind, guidance } of [
22478
23229
  {
22479
23230
  directory: "environments",
@@ -22486,151 +23237,174 @@ function assertNoStandaloneResourceFiles(root) {
22486
23237
  guidance: "Define identities inline on the owning .auto/agents YAML file."
22487
23238
  }
22488
23239
  ]) {
22489
- const path2 = join5(root, directory);
22490
- let entries;
22491
- try {
22492
- entries = readdirSync3(path2, { withFileTypes: true });
22493
- } catch {
22494
- continue;
22495
- }
22496
- const files = resourceApplyFiles(path2, entries);
22497
- if (files.length === 0) {
23240
+ const standaloneFiles = files.filter(
23241
+ (file2) => isResourceFileUnderDirectory(
23242
+ file2.path,
23243
+ sourcePathJoin(resourceRoot, directory)
23244
+ )
23245
+ );
23246
+ if (standaloneFiles.length === 0) {
22498
23247
  continue;
22499
23248
  }
22500
23249
  throw new Error(
22501
- `Standalone .auto/${directory} ${kind} resources are no longer supported. ${guidance} Move ${files.length === 1 ? "this file" : "these files"}: ${files.join(", ")}`
23250
+ `Standalone ${sourcePathJoin(displayResourceRoot2, directory)} ${kind} resources are no longer supported. ${guidance} Move ${standaloneFiles.length === 1 ? "this file" : "these files"}: ${standaloneFiles.map((file2) => file2.path).join(", ")}`
22502
23251
  );
22503
23252
  }
22504
23253
  }
22505
- function assertValidFragmentFiles(root) {
22506
- const fragmentsRoot = join5(root, "fragments");
22507
- let entries;
22508
- try {
22509
- entries = readdirSync3(fragmentsRoot, { withFileTypes: true });
22510
- } catch {
22511
- return;
22512
- }
22513
- for (const path2 of resourceApplyFiles(fragmentsRoot, entries)) {
23254
+ function assertValidFragmentSourceFiles(files, resourceRoot, fileIndex) {
23255
+ const fragments = files.filter(
23256
+ (file2) => isResourceFileUnderDirectory(
23257
+ file2.path,
23258
+ sourcePathJoin(resourceRoot, "fragments")
23259
+ )
23260
+ );
23261
+ for (const file2 of fragments) {
22514
23262
  try {
22515
- validateAgentFragmentFile(path2);
23263
+ const documents = readDocumentsFromSource(file2);
23264
+ if (documents.length !== 1) {
23265
+ throw new Error(
23266
+ `Agent authoring file ${file2.path} must contain exactly one document`
23267
+ );
23268
+ }
23269
+ validateAgentFragmentDocument(documents[0], file2.path, {
23270
+ fileIndex,
23271
+ stack: []
23272
+ });
22516
23273
  } catch (error51) {
22517
23274
  throw new Error(
22518
- `Invalid fragment file ${path2}: ${error51 instanceof Error ? error51.message : String(error51)}`
23275
+ `Invalid fragment file ${file2.path}: ${error51 instanceof Error ? error51.message : String(error51)}`
22519
23276
  );
22520
23277
  }
22521
23278
  }
22522
23279
  }
22523
- function mcpOAuthAgentToolConnectionsFromAgentTools(input) {
22524
- return Object.entries(input.tools).flatMap(([alias, tool]) => {
22525
- if (tool.kind !== "mcp_remote" || tool.disabled || tool.auth.kind !== "mcp_oauth") {
23280
+ var init_project_apply_files = __esm({
23281
+ "../../packages/schemas/src/project-apply-files/index.ts"() {
23282
+ "use strict";
23283
+ init_agents();
23284
+ init_environments();
23285
+ init_identities();
23286
+ init_project_resources();
23287
+ init_agent_authoring();
23288
+ init_apply_result();
23289
+ init_assets2();
23290
+ init_source();
23291
+ }
23292
+ });
23293
+
23294
+ // ../../packages/schemas/src/project-apply-files.ts
23295
+ var init_project_apply_files2 = __esm({
23296
+ "../../packages/schemas/src/project-apply-files.ts"() {
23297
+ "use strict";
23298
+ init_project_apply_files();
23299
+ }
23300
+ });
23301
+
23302
+ // src/commands/apply/files.ts
23303
+ import {
23304
+ readFileSync as readFileSync4,
23305
+ readdirSync as readdirSync3,
23306
+ realpathSync,
23307
+ statSync as statSync2
23308
+ } from "fs";
23309
+ import {
23310
+ basename as basename3,
23311
+ dirname as dirname5,
23312
+ extname as extname3,
23313
+ isAbsolute as isAbsolute2,
23314
+ join as join5,
23315
+ relative,
23316
+ resolve as resolve2
23317
+ } from "path";
23318
+ function readProjectApplyRequest(options) {
23319
+ if (options.file && options.directory) {
23320
+ throw new Error("Cannot use --file with --directory.");
23321
+ }
23322
+ if (options.file) {
23323
+ const file2 = resolve2(options.file);
23324
+ const projectRoot2 = applyFileProjectRoot(file2);
23325
+ const sourceRoot = applyFileSourceRoot(file2, projectRoot2);
23326
+ return readProjectApplyFileSource({
23327
+ file: sourceFile(file2, projectRoot2),
23328
+ files: sourceFiles(sourceRoot, projectRoot2),
23329
+ readAsset: filesystemAssetReader(projectRoot2)
23330
+ });
23331
+ }
23332
+ const directory = resolve2(options.directory ?? join5(process.cwd(), ".auto"));
23333
+ const projectRoot = applyProjectRoot(directory);
23334
+ return readProjectApplyDirectorySource({
23335
+ files: sourceFiles(directory, projectRoot),
23336
+ resourceRoot: sourcePathRelative(projectRoot, directory),
23337
+ displayResourceRoot: displayResourceRoot(directory),
23338
+ emptyMessage: `No resource files found in ${directory}`,
23339
+ readAsset: filesystemAssetReader(projectRoot)
23340
+ });
23341
+ }
23342
+ function sourceFiles(root, projectRoot) {
23343
+ let entries;
23344
+ try {
23345
+ entries = readdirSync3(root, { withFileTypes: true });
23346
+ } catch {
23347
+ return [];
23348
+ }
23349
+ return entries.flatMap((entry) => {
23350
+ const path2 = join5(root, entry.name);
23351
+ if (entry.isDirectory()) {
23352
+ return sourceFiles(path2, projectRoot);
23353
+ }
23354
+ if (!entry.isFile()) {
22526
23355
  return [];
22527
23356
  }
22528
- return [
22529
- {
22530
- agent: input.agent,
22531
- tool: alias,
22532
- connection: tool.auth.connection
22533
- }
22534
- ];
23357
+ return [sourceFile(path2, projectRoot)];
22535
23358
  });
22536
23359
  }
22537
- function readApplyDocumentFile(path2) {
22538
- const source = readFileSync4(path2, "utf8");
22539
- let documents;
22540
- try {
22541
- const parsedDocuments = parseYamlDocuments2(source);
22542
- const parseError = parsedDocuments.flatMap((document) => document.errors).at(0);
22543
- if (parseError) {
22544
- throw parseError;
22545
- }
22546
- documents = parsedDocuments.filter((document) => document.contents !== null).map((document) => document.toJSON());
22547
- } catch (error51) {
22548
- throw new Error(
22549
- `Invalid apply file: ${error51 instanceof Error ? error51.message : String(error51)}`
22550
- );
22551
- }
22552
- if (documents.length === 0) {
22553
- throw new Error(`Invalid apply file: ${path2} is empty`);
22554
- }
22555
- if (documents.length === 1) {
22556
- const system = ProjectApplySystemConfigSchema.safeParse(documents[0]);
22557
- if (system.success) {
22558
- const resources = system.data.spec.resources;
22559
- assertNoExplicitStandaloneResources(resources, path2);
22560
- return {
22561
- ...system.data.spec,
22562
- resourceRecords: resources.map((resource) => ({
22563
- resource,
22564
- generatedFromAgent: false
22565
- }))
22566
- };
22567
- }
22568
- }
22569
- const resourceRecords = documents.flatMap(
22570
- (document) => readApplyDocument(document, path2)
22571
- );
23360
+ function sourceFile(path2, projectRoot) {
22572
23361
  return {
22573
- delete: [],
22574
- dryRun: false,
22575
- prune: false,
22576
- resources: resourceRecords.map((record2) => record2.resource),
22577
- resourceRecords,
22578
- assets: {}
23362
+ path: sourcePathRelative(projectRoot, path2),
23363
+ contentBase64: readFileSync4(path2).toString("base64")
22579
23364
  };
22580
23365
  }
22581
- function readApplyDocument(document, path2) {
22582
- assertAgentAuthoringDocument(document, path2);
22583
- const result = compileAgentDocumentValue(document, path2);
22584
- return result.resources.map((resource) => ({
22585
- resource,
22586
- generatedFromAgent: resource !== result.resource
22587
- }));
23366
+ function filesystemAssetReader(projectRoot) {
23367
+ return ({ asset, resourceName }) => {
23368
+ const path2 = validateAgentAvatarAsset({
23369
+ asset,
23370
+ resourceName,
23371
+ projectRoot
23372
+ });
23373
+ return {
23374
+ path: path2,
23375
+ bytes: readFileSync4(path2)
23376
+ };
23377
+ };
22588
23378
  }
22589
- function assertNoExplicitStandaloneResources(resources, path2) {
22590
- for (const resource of resources) {
22591
- if (resource.kind !== RESOURCE_KIND_ENVIRONMENT && resource.kind !== RESOURCE_KIND_IDENTITY) {
22592
- continue;
22593
- }
22594
- throw standaloneResourceError(resource.kind, path2);
22595
- }
23379
+ function applyProjectRoot(directory) {
23380
+ const resolved = resolve2(directory);
23381
+ return basename3(resolved) === ".auto" ? dirname5(resolved) : resolved;
22596
23382
  }
22597
- function readApplyAssets(resources, projectRoot) {
22598
- const assets = {};
22599
- for (const resource of resources) {
22600
- const target = avatarAssetTarget(resource);
22601
- if (!target || assets[target.asset]) {
22602
- continue;
23383
+ function applyFileProjectRoot(file2) {
23384
+ let dir = dirname5(resolve2(file2));
23385
+ while (true) {
23386
+ if (basename3(dir) === ".auto") {
23387
+ return dirname5(dir);
22603
23388
  }
22604
- const resolvedPath = validateAgentAvatarAsset({
22605
- asset: target.asset,
22606
- resourceName: target.resourceName,
22607
- projectRoot
22608
- });
22609
- const bytes = readFileSync4(resolvedPath);
22610
- const dimensionsProblem = avatarAssetDimensionsProblem(bytes);
22611
- if (dimensionsProblem) {
22612
- throw new Error(
22613
- `Invalid identity avatar asset for "${target.resourceName}": ${dimensionsProblem}`
22614
- );
23389
+ const parent = dirname5(dir);
23390
+ if (parent === dir) {
23391
+ return process.cwd();
22615
23392
  }
22616
- assets[target.asset] = {
22617
- sha256: createHash3("sha256").update(bytes).digest("hex"),
22618
- contentType: extname2(resolvedPath).toLowerCase() === ".png" ? "image/png" : "image/jpeg",
22619
- dataBase64: bytes.toString("base64")
22620
- };
23393
+ dir = parent;
22621
23394
  }
22622
- return assets;
22623
23395
  }
22624
- function avatarAssetTarget(resource) {
22625
- if (resource.kind === RESOURCE_KIND_IDENTITY) {
22626
- const asset = resource.spec.avatar?.asset;
22627
- return asset ? { asset, resourceName: resource.metadata.name } : void 0;
22628
- }
22629
- if (resource.kind === RESOURCE_KIND_AGENT && typeof resource.spec.identity === "object" && resource.spec.identity !== null && !Array.isArray(resource.spec.identity)) {
22630
- const asset = resource.spec.identity.avatar?.asset;
22631
- return asset ? { asset, resourceName: resource.metadata.name } : void 0;
22632
- }
22633
- return void 0;
23396
+ function applyFileSourceRoot(file2, projectRoot) {
23397
+ const autoRoot = resolve2(projectRoot, ".auto");
23398
+ return file2 === autoRoot || isInside(file2, autoRoot) ? autoRoot : dirname5(file2);
23399
+ }
23400
+ function displayResourceRoot(directory) {
23401
+ return basename3(directory) === ".auto" ? ".auto" : directory;
23402
+ }
23403
+ function sourcePathRelative(from, to) {
23404
+ return relative(from, to).replaceAll("\\", "/");
23405
+ }
23406
+ function isInside(path2, parent) {
23407
+ return path2.startsWith(`${parent}/`);
22634
23408
  }
22635
23409
  function validateAgentAvatarAsset(input) {
22636
23410
  if (isAbsolute2(input.asset)) {
@@ -22679,103 +23453,21 @@ function validateAgentAvatarAsset(input) {
22679
23453
  `Invalid identity avatar asset for "${input.resourceName}": asset must be ${MAX_AVATAR_ASSET_BYTES} bytes or smaller`
22680
23454
  );
22681
23455
  }
22682
- const extension = extname2(resolvedAssetPath).toLowerCase();
22683
- if (!ALLOWED_AVATAR_EXTENSIONS.has(extension)) {
23456
+ const extension = extname3(resolvedAssetPath).toLowerCase();
23457
+ if (!ALLOWED_AVATAR_EXTENSIONS2.has(extension)) {
22684
23458
  throw new Error(
22685
23459
  `Invalid identity avatar asset for "${input.resourceName}": asset must be a PNG or JPEG image`
22686
23460
  );
22687
23461
  }
22688
23462
  return resolvedAssetPath;
22689
23463
  }
22690
- function applyProjectRoot(directory) {
22691
- const resolved = resolve2(directory);
22692
- return basename3(resolved) === ".auto" ? dirname5(resolved) : resolved;
22693
- }
22694
- function applyFileProjectRoot(file2) {
22695
- let dir = dirname5(resolve2(file2));
22696
- while (true) {
22697
- if (basename3(dir) === ".auto") {
22698
- return dirname5(dir);
22699
- }
22700
- const parent = dirname5(dir);
22701
- if (parent === dir) {
22702
- return process.cwd();
22703
- }
22704
- dir = parent;
22705
- }
22706
- }
22707
- function isInside(path2, parent) {
22708
- return path2.startsWith(`${parent}/`);
22709
- }
22710
- function assertAgentAuthoringDocument(document, path2) {
22711
- if (!isRecord2(document) || !("kind" in document)) {
22712
- return;
22713
- }
22714
- if (document.kind === "session") {
22715
- throw new Error(
22716
- 'Legacy resource kind "session" is no longer supported. Use .auto/agents with the root-level Agent facade format.'
22717
- );
22718
- }
22719
- if (document.kind === RESOURCE_KIND_ENVIRONMENT || document.kind === RESOURCE_KIND_IDENTITY) {
22720
- throw standaloneResourceError(document.kind, path2);
22721
- }
22722
- if (document.kind !== RESOURCE_KIND_AGENT) {
22723
- throw new Error(
22724
- `Unsupported apply resource kind "${String(document.kind)}"; supported kind is "${RESOURCE_KIND_AGENT}"`
22725
- );
22726
- }
22727
- const parsed = AgentApplyRequestSchema.safeParse({
22728
- metadata: document.metadata,
22729
- spec: document.spec
22730
- });
22731
- if (parsed.success) {
22732
- throw new Error(
22733
- `Legacy agent resource envelopes are no longer supported in ${path2}. Use the root-level Agent facade format under .auto/agents.`
22734
- );
22735
- }
22736
- }
22737
- function standaloneResourceError(kind, path2) {
22738
- if (kind === RESOURCE_KIND_ENVIRONMENT) {
22739
- return new Error(
22740
- `Standalone environment resources are no longer supported in ${path2}. Define environments inline in .auto/agents YAML, using fragment imports under .auto/fragments/environments for reused runtimes.`
22741
- );
22742
- }
22743
- return new Error(
22744
- `Standalone identity resources are no longer supported in ${path2}. Define identities inline on the owning .auto/agents YAML file.`
22745
- );
22746
- }
22747
- function primaryApplyDirectory(kind) {
22748
- return APPLY_DIRECTORIES[kind];
22749
- }
22750
- function isRecord2(value) {
22751
- return typeof value === "object" && value !== null && !Array.isArray(value);
22752
- }
22753
- function resourceApplyFiles(directory, entries) {
22754
- const files = [];
22755
- for (const entry of entries) {
22756
- const path2 = join5(directory, entry.name);
22757
- if (entry.isDirectory()) {
22758
- files.push(
22759
- ...resourceApplyFiles(path2, readdirSync3(path2, { withFileTypes: true }))
22760
- );
22761
- continue;
22762
- }
22763
- if (entry.isFile() && /\.(json|ya?ml)$/i.test(entry.name)) {
22764
- files.push(path2);
22765
- }
22766
- }
22767
- return files.sort((left, right) => left.localeCompare(right));
22768
- }
22769
- var APPLY_DIRECTORIES, ALLOWED_AVATAR_EXTENSIONS;
23464
+ var ALLOWED_AVATAR_EXTENSIONS2;
22770
23465
  var init_files = __esm({
22771
23466
  "src/commands/apply/files.ts"() {
22772
23467
  "use strict";
22773
23468
  init_src();
22774
- init_authoring();
22775
- APPLY_DIRECTORIES = {
22776
- agent: "agents"
22777
- };
22778
- ALLOWED_AVATAR_EXTENSIONS = /* @__PURE__ */ new Set([".jpg", ".jpeg", ".png"]);
23469
+ init_project_apply_files2();
23470
+ ALLOWED_AVATAR_EXTENSIONS2 = /* @__PURE__ */ new Set([".jpg", ".jpeg", ".png"]);
22779
23471
  }
22780
23472
  });
22781
23473