@autohq/cli 0.1.138 → 0.1.139

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.
@@ -26268,7 +26268,7 @@ Object.assign(lookup, {
26268
26268
  // package.json
26269
26269
  var package_default = {
26270
26270
  name: "@autohq/cli",
26271
- version: "0.1.138",
26271
+ version: "0.1.139",
26272
26272
  license: "SEE LICENSE IN README.md",
26273
26273
  publishConfig: {
26274
26274
  access: "public"
package/dist/index.js CHANGED
@@ -21204,7 +21204,7 @@ var init_package = __esm({
21204
21204
  "package.json"() {
21205
21205
  package_default = {
21206
21206
  name: "@autohq/cli",
21207
- version: "0.1.138",
21207
+ version: "0.1.139",
21208
21208
  license: "SEE LICENSE IN README.md",
21209
21209
  publishConfig: {
21210
21210
  access: "public"
@@ -21386,9 +21386,10 @@ function compileAgentFile(path2) {
21386
21386
  const context = { graph: /* @__PURE__ */ new Map(), removals: [] };
21387
21387
  const document = readSingleDocument(path2);
21388
21388
  const compiled = finalizeAgentApplyShape(
21389
- compileAgentDocument(document, path2, [], context)
21389
+ compileAgentDocument(document, path2, [], context),
21390
+ path2
21390
21391
  );
21391
- const parsed = ProjectApplyResourceSchema.safeParse(compiled);
21392
+ const parsed = ProjectApplyResourceSchema.safeParse(compiled.resource);
21392
21393
  if (!parsed.success) {
21393
21394
  throw new Error(`Invalid compiled agent ${path2}: ${parsed.error.message}`);
21394
21395
  }
@@ -21399,6 +21400,7 @@ function compileAgentFile(path2) {
21399
21400
  }
21400
21401
  return {
21401
21402
  resource: parsed.data,
21403
+ resources: [...compiled.resources, parsed.data],
21402
21404
  graph: [...context.graph.values()],
21403
21405
  removals: context.removals
21404
21406
  };
@@ -21406,9 +21408,10 @@ function compileAgentFile(path2) {
21406
21408
  function compileAgentDocumentValue(document, path2) {
21407
21409
  const context = { graph: /* @__PURE__ */ new Map(), removals: [] };
21408
21410
  const compiled = finalizeAgentApplyShape(
21409
- compileAgentDocument(document, path2, [], context)
21411
+ compileAgentDocument(document, path2, [], context),
21412
+ path2
21410
21413
  );
21411
- const parsed = ProjectApplyResourceSchema.safeParse(compiled);
21414
+ const parsed = ProjectApplyResourceSchema.safeParse(compiled.resource);
21412
21415
  if (!parsed.success) {
21413
21416
  throw new Error(`Invalid compiled agent ${path2}: ${parsed.error.message}`);
21414
21417
  }
@@ -21419,6 +21422,7 @@ function compileAgentDocumentValue(document, path2) {
21419
21422
  }
21420
21423
  return {
21421
21424
  resource: parsed.data,
21425
+ resources: [...compiled.resources, parsed.data],
21422
21426
  graph: [...context.graph.values()],
21423
21427
  removals: context.removals
21424
21428
  };
@@ -21641,14 +21645,13 @@ function authoringDocumentApplyShape(document, path2) {
21641
21645
  continue;
21642
21646
  }
21643
21647
  if (AGENT_METADATA_FIELDS.has(key)) {
21644
- const metadataKey = key === "name" ? "name" : key;
21645
21648
  assertNoDuplicateFacadeField({
21646
21649
  path: path2,
21647
21650
  field: key,
21648
- target: `metadata.${metadataKey}`,
21649
- targetValue: metadata[metadataKey]
21651
+ target: `metadata.${key}`,
21652
+ targetValue: metadata[key]
21650
21653
  });
21651
- metadata[metadataKey] = value;
21654
+ metadata[key] = value;
21652
21655
  continue;
21653
21656
  }
21654
21657
  if (AGENT_SPEC_FIELDS.has(key)) {
@@ -21667,12 +21670,18 @@ function authoringDocumentApplyShape(document, path2) {
21667
21670
  spec: resolveFileBackedFields(spec, path2)
21668
21671
  };
21669
21672
  }
21670
- function finalizeAgentApplyShape(document) {
21673
+ function finalizeAgentApplyShape(document, path2) {
21671
21674
  if (!isRecord(document) || !isRecord(document.spec)) {
21672
- return document;
21675
+ return { resource: document, resources: [] };
21673
21676
  }
21674
21677
  const next = structuredClone(document);
21675
21678
  const spec = next.spec;
21679
+ const resources = [];
21680
+ if (isRecord(spec.environment)) {
21681
+ const environment = inlineEnvironmentResource(spec.environment, path2);
21682
+ spec.environment = environment.metadata.name;
21683
+ resources.push(environment);
21684
+ }
21676
21685
  if (Array.isArray(spec.triggers)) {
21677
21686
  spec.triggers = spec.triggers.map((trigger) => {
21678
21687
  if (!isRecord(trigger) || !("name" in trigger)) {
@@ -21683,7 +21692,32 @@ function finalizeAgentApplyShape(document) {
21683
21692
  return compiledTrigger;
21684
21693
  });
21685
21694
  }
21686
- return next;
21695
+ return { resource: next, resources };
21696
+ }
21697
+ function inlineEnvironmentResource(document, path2) {
21698
+ const metadata = {};
21699
+ const spec = {};
21700
+ for (const [key, value] of Object.entries(document)) {
21701
+ if (value === void 0) {
21702
+ continue;
21703
+ }
21704
+ if (AGENT_METADATA_FIELDS.has(key)) {
21705
+ metadata[key] = value;
21706
+ continue;
21707
+ }
21708
+ spec[key] = value;
21709
+ }
21710
+ const parsed = EnvironmentApplyRequestSchema.safeParse({ metadata, spec });
21711
+ if (!parsed.success) {
21712
+ throw new Error(
21713
+ `Invalid inline environment in ${path2}: ${parsed.error.message}`
21714
+ );
21715
+ }
21716
+ return {
21717
+ kind: RESOURCE_KIND_ENVIRONMENT,
21718
+ metadata: parsed.data.metadata,
21719
+ spec: parsed.data.spec
21720
+ };
21687
21721
  }
21688
21722
  function assertNoDuplicateFacadeField(input) {
21689
21723
  if (input.targetValue !== void 0) {
@@ -21919,11 +21953,18 @@ function readProjectApplyRequest(options) {
21919
21953
  }
21920
21954
  if (options.file) {
21921
21955
  const request = readApplyDocumentFile(options.file);
21956
+ const resources2 = dedupeGeneratedResources(request.resourceRecords);
21922
21957
  const assets2 = readApplyAssets(
21923
- request.resources,
21958
+ resources2,
21924
21959
  applyFileProjectRoot(options.file)
21925
21960
  );
21926
- return { ...request, assets: assets2 };
21961
+ return {
21962
+ delete: request.delete,
21963
+ dryRun: request.dryRun,
21964
+ prune: request.prune,
21965
+ resources: resources2,
21966
+ assets: assets2
21967
+ };
21927
21968
  }
21928
21969
  const directory = options.directory ?? join4(process.cwd(), ".auto");
21929
21970
  assertNoLegacySessionFiles(directory);
@@ -21931,20 +21972,78 @@ function readProjectApplyRequest(options) {
21931
21972
  if (files.length === 0) {
21932
21973
  throw new Error(`No resource files found in ${directory}`);
21933
21974
  }
21934
- const resources = [];
21975
+ const resourceRecords = [];
21935
21976
  for (const { kind, path: path2 } of files) {
21936
21977
  const request = readApplyDocumentFile(path2);
21937
- for (const resource of request.resources) {
21938
- if (resource.kind !== kind) {
21978
+ for (const { resource, generatedFromAgent } of request.resourceRecords) {
21979
+ if (!isAllowedDirectoryResourceKind(kind, resource, generatedFromAgent)) {
21939
21980
  throw new Error(
21940
21981
  `Resource kind "${resource.kind}" in ${path2} does not match .auto/${primaryApplyDirectory(kind)}`
21941
21982
  );
21942
21983
  }
21943
- resources.push(resource);
21984
+ resourceRecords.push({ resource, generatedFromAgent });
21944
21985
  }
21945
21986
  }
21987
+ const resources = dedupeGeneratedResources(resourceRecords);
21946
21988
  const assets = readApplyAssets(resources, applyProjectRoot(directory));
21947
- return { delete: [], dryRun: false, prune: true, resources, assets };
21989
+ return {
21990
+ delete: [],
21991
+ dryRun: false,
21992
+ prune: true,
21993
+ resources,
21994
+ assets
21995
+ };
21996
+ }
21997
+ function isAllowedDirectoryResourceKind(directoryKind, resource, generatedFromAgent) {
21998
+ if (resource.kind === directoryKind) {
21999
+ return true;
22000
+ }
22001
+ return directoryKind === RESOURCE_KIND_SESSION && resource.kind === RESOURCE_KIND_ENVIRONMENT && generatedFromAgent;
22002
+ }
22003
+ function dedupeGeneratedResources(records) {
22004
+ const recordsByKey = /* @__PURE__ */ new Map();
22005
+ const deduped = [];
22006
+ for (const record2 of records) {
22007
+ const { resource } = record2;
22008
+ const key = `${resource.kind}/${resource.metadata.name}`;
22009
+ const existing = recordsByKey.get(key);
22010
+ if (!existing) {
22011
+ recordsByKey.set(key, record2);
22012
+ deduped.push(record2);
22013
+ continue;
22014
+ }
22015
+ if (!record2.generatedFromAgent && !existing.generatedFromAgent) {
22016
+ deduped.push(record2);
22017
+ continue;
22018
+ }
22019
+ if (stableResource(resource) !== stableResource(existing.resource)) {
22020
+ throw new Error(
22021
+ `Conflicting generated resource "${key}" from agent authoring. Inline environment definitions must be identical when they share a name.`
22022
+ );
22023
+ }
22024
+ }
22025
+ return deduped.map((record2) => record2.resource);
22026
+ }
22027
+ function stableResource(resource) {
22028
+ return JSON.stringify({
22029
+ kind: resource.kind,
22030
+ metadata: metadataComparable(resource.metadata),
22031
+ spec: sortJson(resource.spec)
22032
+ });
22033
+ }
22034
+ function metadataComparable(metadata) {
22035
+ return sortJson(metadata);
22036
+ }
22037
+ function sortJson(value) {
22038
+ if (Array.isArray(value)) {
22039
+ return value.map(sortJson);
22040
+ }
22041
+ if (isRecord2(value)) {
22042
+ return Object.fromEntries(
22043
+ Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, nested]) => [key, sortJson(nested)])
22044
+ );
22045
+ }
22046
+ return value;
21948
22047
  }
21949
22048
  function appliedResourceKind(request, response, index) {
21950
22049
  const plannedResources = response.plan.filter(
@@ -22046,21 +22145,36 @@ function readApplyDocumentFile(path2) {
22046
22145
  if (documents.length === 1) {
22047
22146
  const system = ProjectApplySystemConfigSchema.safeParse(documents[0]);
22048
22147
  if (system.success) {
22049
- return system.data.spec;
22148
+ const resources = system.data.spec.resources;
22149
+ return {
22150
+ ...system.data.spec,
22151
+ resourceRecords: resources.map((resource) => ({
22152
+ resource,
22153
+ generatedFromAgent: false
22154
+ }))
22155
+ };
22050
22156
  }
22051
22157
  }
22158
+ const resourceRecords = documents.flatMap(
22159
+ (document) => readApplyDocument(document, path2)
22160
+ );
22052
22161
  return {
22053
22162
  delete: [],
22054
22163
  dryRun: false,
22055
22164
  prune: false,
22056
- resources: documents.map((document) => readApplyDocument(document, path2)),
22165
+ resources: resourceRecords.map((record2) => record2.resource),
22166
+ resourceRecords,
22057
22167
  assets: {}
22058
22168
  };
22059
22169
  }
22060
22170
  function readApplyDocument(document, path2) {
22061
22171
  const candidate = applyCandidate(document);
22062
22172
  if (candidate.kind === RESOURCE_KIND_SESSION) {
22063
- return compileAgentDocumentValue(document, path2).resource;
22173
+ const result = compileAgentDocumentValue(document, path2);
22174
+ return result.resources.map((resource) => ({
22175
+ resource,
22176
+ generatedFromAgent: resource !== result.resource
22177
+ }));
22064
22178
  }
22065
22179
  const parsed = APPLY_SCHEMAS[candidate.kind].safeParse(candidate.value);
22066
22180
  if (!parsed.success) {
@@ -22068,11 +22182,16 @@ function readApplyDocument(document, path2) {
22068
22182
  `Invalid ${candidate.kind} resource: ${parsed.error.message}`
22069
22183
  );
22070
22184
  }
22071
- return {
22072
- kind: candidate.kind,
22073
- metadata: parsed.data.metadata,
22074
- spec: parsed.data.spec
22075
- };
22185
+ return [
22186
+ {
22187
+ resource: {
22188
+ kind: candidate.kind,
22189
+ metadata: parsed.data.metadata,
22190
+ spec: parsed.data.spec
22191
+ },
22192
+ generatedFromAgent: false
22193
+ }
22194
+ ];
22076
22195
  }
22077
22196
  function readApplyAssets(resources, projectRoot) {
22078
22197
  const assets = {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autohq/cli",
3
- "version": "0.1.138",
3
+ "version": "0.1.139",
4
4
  "license": "SEE LICENSE IN README.md",
5
5
  "publishConfig": {
6
6
  "access": "public"