@herdctl/core 5.5.0 → 5.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/dist/config/__tests__/merge.test.js +1 -1
  2. package/dist/config/__tests__/merge.test.js.map +1 -1
  3. package/dist/config/index.d.ts +1 -1
  4. package/dist/config/index.d.ts.map +1 -1
  5. package/dist/config/index.js +3 -1
  6. package/dist/config/index.js.map +1 -1
  7. package/dist/config/schema.d.ts +10 -2
  8. package/dist/config/schema.d.ts.map +1 -1
  9. package/dist/config/schema.js +6 -2
  10. package/dist/config/schema.js.map +1 -1
  11. package/dist/distribution/__tests__/agent-discovery.test.d.ts +7 -0
  12. package/dist/distribution/__tests__/agent-discovery.test.d.ts.map +1 -0
  13. package/dist/distribution/__tests__/agent-discovery.test.js +443 -0
  14. package/dist/distribution/__tests__/agent-discovery.test.js.map +1 -0
  15. package/dist/distribution/__tests__/agent-info.test.d.ts +7 -0
  16. package/dist/distribution/__tests__/agent-info.test.d.ts.map +1 -0
  17. package/dist/distribution/__tests__/agent-info.test.js +568 -0
  18. package/dist/distribution/__tests__/agent-info.test.js.map +1 -0
  19. package/dist/distribution/__tests__/agent-remover.test.d.ts +7 -0
  20. package/dist/distribution/__tests__/agent-remover.test.d.ts.map +1 -0
  21. package/dist/distribution/__tests__/agent-remover.test.js +498 -0
  22. package/dist/distribution/__tests__/agent-remover.test.js.map +1 -0
  23. package/dist/distribution/__tests__/agent-repo-metadata.test.d.ts +5 -0
  24. package/dist/distribution/__tests__/agent-repo-metadata.test.d.ts.map +1 -0
  25. package/dist/distribution/__tests__/agent-repo-metadata.test.js +500 -0
  26. package/dist/distribution/__tests__/agent-repo-metadata.test.js.map +1 -0
  27. package/dist/distribution/__tests__/env-scanner.test.d.ts +5 -0
  28. package/dist/distribution/__tests__/env-scanner.test.d.ts.map +1 -0
  29. package/dist/distribution/__tests__/env-scanner.test.js +576 -0
  30. package/dist/distribution/__tests__/env-scanner.test.js.map +1 -0
  31. package/dist/distribution/__tests__/file-installer.test.d.ts +7 -0
  32. package/dist/distribution/__tests__/file-installer.test.d.ts.map +1 -0
  33. package/dist/distribution/__tests__/file-installer.test.js +714 -0
  34. package/dist/distribution/__tests__/file-installer.test.js.map +1 -0
  35. package/dist/distribution/__tests__/fleet-config-updater.test.d.ts +7 -0
  36. package/dist/distribution/__tests__/fleet-config-updater.test.d.ts.map +1 -0
  37. package/dist/distribution/__tests__/fleet-config-updater.test.js +531 -0
  38. package/dist/distribution/__tests__/fleet-config-updater.test.js.map +1 -0
  39. package/dist/distribution/__tests__/installation-metadata.test.d.ts +2 -0
  40. package/dist/distribution/__tests__/installation-metadata.test.d.ts.map +1 -0
  41. package/dist/distribution/__tests__/installation-metadata.test.js +292 -0
  42. package/dist/distribution/__tests__/installation-metadata.test.js.map +1 -0
  43. package/dist/distribution/__tests__/integration.test.d.ts +10 -0
  44. package/dist/distribution/__tests__/integration.test.d.ts.map +1 -0
  45. package/dist/distribution/__tests__/integration.test.js +522 -0
  46. package/dist/distribution/__tests__/integration.test.js.map +1 -0
  47. package/dist/distribution/__tests__/repository-fetcher.test.d.ts +5 -0
  48. package/dist/distribution/__tests__/repository-fetcher.test.d.ts.map +1 -0
  49. package/dist/distribution/__tests__/repository-fetcher.test.js +386 -0
  50. package/dist/distribution/__tests__/repository-fetcher.test.js.map +1 -0
  51. package/dist/distribution/__tests__/repository-validator.test.d.ts +7 -0
  52. package/dist/distribution/__tests__/repository-validator.test.d.ts.map +1 -0
  53. package/dist/distribution/__tests__/repository-validator.test.js +447 -0
  54. package/dist/distribution/__tests__/repository-validator.test.js.map +1 -0
  55. package/dist/distribution/__tests__/source-specifier.test.d.ts +5 -0
  56. package/dist/distribution/__tests__/source-specifier.test.d.ts.map +1 -0
  57. package/dist/distribution/__tests__/source-specifier.test.js +533 -0
  58. package/dist/distribution/__tests__/source-specifier.test.js.map +1 -0
  59. package/dist/distribution/agent-discovery.d.ts +81 -0
  60. package/dist/distribution/agent-discovery.d.ts.map +1 -0
  61. package/dist/distribution/agent-discovery.js +264 -0
  62. package/dist/distribution/agent-discovery.js.map +1 -0
  63. package/dist/distribution/agent-info.d.ts +86 -0
  64. package/dist/distribution/agent-info.d.ts.map +1 -0
  65. package/dist/distribution/agent-info.js +225 -0
  66. package/dist/distribution/agent-info.js.map +1 -0
  67. package/dist/distribution/agent-remover.d.ts +83 -0
  68. package/dist/distribution/agent-remover.d.ts.map +1 -0
  69. package/dist/distribution/agent-remover.js +222 -0
  70. package/dist/distribution/agent-remover.js.map +1 -0
  71. package/dist/distribution/agent-repo-metadata.d.ts +181 -0
  72. package/dist/distribution/agent-repo-metadata.d.ts.map +1 -0
  73. package/dist/distribution/agent-repo-metadata.js +143 -0
  74. package/dist/distribution/agent-repo-metadata.js.map +1 -0
  75. package/dist/distribution/env-scanner.d.ts +78 -0
  76. package/dist/distribution/env-scanner.d.ts.map +1 -0
  77. package/dist/distribution/env-scanner.js +144 -0
  78. package/dist/distribution/env-scanner.js.map +1 -0
  79. package/dist/distribution/file-installer.d.ts +80 -0
  80. package/dist/distribution/file-installer.d.ts.map +1 -0
  81. package/dist/distribution/file-installer.js +268 -0
  82. package/dist/distribution/file-installer.js.map +1 -0
  83. package/dist/distribution/fleet-config-updater.d.ts +96 -0
  84. package/dist/distribution/fleet-config-updater.d.ts.map +1 -0
  85. package/dist/distribution/fleet-config-updater.js +266 -0
  86. package/dist/distribution/fleet-config-updater.js.map +1 -0
  87. package/dist/distribution/index.d.ts +23 -0
  88. package/dist/distribution/index.d.ts.map +1 -0
  89. package/dist/distribution/index.js +42 -0
  90. package/dist/distribution/index.js.map +1 -0
  91. package/dist/distribution/installation-metadata.d.ts +191 -0
  92. package/dist/distribution/installation-metadata.d.ts.map +1 -0
  93. package/dist/distribution/installation-metadata.js +100 -0
  94. package/dist/distribution/installation-metadata.js.map +1 -0
  95. package/dist/distribution/repository-fetcher.d.ts +104 -0
  96. package/dist/distribution/repository-fetcher.d.ts.map +1 -0
  97. package/dist/distribution/repository-fetcher.js +246 -0
  98. package/dist/distribution/repository-fetcher.js.map +1 -0
  99. package/dist/distribution/repository-validator.d.ts +86 -0
  100. package/dist/distribution/repository-validator.d.ts.map +1 -0
  101. package/dist/distribution/repository-validator.js +296 -0
  102. package/dist/distribution/repository-validator.js.map +1 -0
  103. package/dist/distribution/source-specifier.d.ts +106 -0
  104. package/dist/distribution/source-specifier.d.ts.map +1 -0
  105. package/dist/distribution/source-specifier.js +247 -0
  106. package/dist/distribution/source-specifier.js.map +1 -0
  107. package/dist/fleet-manager/errors.d.ts +15 -0
  108. package/dist/fleet-manager/errors.d.ts.map +1 -1
  109. package/dist/fleet-manager/errors.js +16 -0
  110. package/dist/fleet-manager/errors.js.map +1 -1
  111. package/dist/fleet-manager/fleet-manager.d.ts.map +1 -1
  112. package/dist/fleet-manager/fleet-manager.js +31 -9
  113. package/dist/fleet-manager/fleet-manager.js.map +1 -1
  114. package/dist/index.d.ts +1 -0
  115. package/dist/index.d.ts.map +1 -1
  116. package/dist/index.js +2 -0
  117. package/dist/index.js.map +1 -1
  118. package/dist/runner/message-processor.d.ts.map +1 -1
  119. package/dist/runner/message-processor.js +7 -2
  120. package/dist/runner/message-processor.js.map +1 -1
  121. package/dist/runner/runtime/container-manager.js +1 -1
  122. package/dist/runner/runtime/container-manager.js.map +1 -1
  123. package/dist/scheduler/errors.d.ts +15 -0
  124. package/dist/scheduler/errors.d.ts.map +1 -1
  125. package/dist/scheduler/schedule-runner.d.ts.map +1 -1
  126. package/dist/scheduler/schedule-runner.js +6 -5
  127. package/dist/scheduler/schedule-runner.js.map +1 -1
  128. package/dist/state/__tests__/jsonl-parser.test.d.ts +5 -0
  129. package/dist/state/__tests__/jsonl-parser.test.d.ts.map +1 -0
  130. package/dist/state/__tests__/jsonl-parser.test.js +307 -0
  131. package/dist/state/__tests__/jsonl-parser.test.js.map +1 -0
  132. package/dist/state/__tests__/session-attribution.test.d.ts +2 -0
  133. package/dist/state/__tests__/session-attribution.test.d.ts.map +1 -0
  134. package/dist/state/__tests__/session-attribution.test.js +567 -0
  135. package/dist/state/__tests__/session-attribution.test.js.map +1 -0
  136. package/dist/state/__tests__/session-discovery.test.d.ts +2 -0
  137. package/dist/state/__tests__/session-discovery.test.d.ts.map +1 -0
  138. package/dist/state/__tests__/session-discovery.test.js +941 -0
  139. package/dist/state/__tests__/session-discovery.test.js.map +1 -0
  140. package/dist/state/__tests__/session-metadata.test.d.ts +2 -0
  141. package/dist/state/__tests__/session-metadata.test.d.ts.map +1 -0
  142. package/dist/state/__tests__/session-metadata.test.js +422 -0
  143. package/dist/state/__tests__/session-metadata.test.js.map +1 -0
  144. package/dist/state/__tests__/tool-parsing.test.d.ts +5 -0
  145. package/dist/state/__tests__/tool-parsing.test.d.ts.map +1 -0
  146. package/dist/state/__tests__/tool-parsing.test.js +315 -0
  147. package/dist/state/__tests__/tool-parsing.test.js.map +1 -0
  148. package/dist/state/index.d.ts +5 -0
  149. package/dist/state/index.d.ts.map +1 -1
  150. package/dist/state/index.js +10 -0
  151. package/dist/state/index.js.map +1 -1
  152. package/dist/state/jsonl-parser.d.ts +115 -0
  153. package/dist/state/jsonl-parser.d.ts.map +1 -0
  154. package/dist/state/jsonl-parser.js +437 -0
  155. package/dist/state/jsonl-parser.js.map +1 -0
  156. package/dist/state/session-attribution.d.ts +35 -0
  157. package/dist/state/session-attribution.d.ts.map +1 -0
  158. package/dist/state/session-attribution.js +179 -0
  159. package/dist/state/session-attribution.js.map +1 -0
  160. package/dist/state/session-discovery.d.ts +188 -0
  161. package/dist/state/session-discovery.d.ts.map +1 -0
  162. package/dist/state/session-discovery.js +513 -0
  163. package/dist/state/session-discovery.js.map +1 -0
  164. package/dist/state/session-metadata.d.ts +186 -0
  165. package/dist/state/session-metadata.d.ts.map +1 -0
  166. package/dist/state/session-metadata.js +297 -0
  167. package/dist/state/session-metadata.js.map +1 -0
  168. package/dist/state/tool-parsing.d.ts +88 -0
  169. package/dist/state/tool-parsing.d.ts.map +1 -0
  170. package/dist/state/tool-parsing.js +199 -0
  171. package/dist/state/tool-parsing.js.map +1 -0
  172. package/package.json +1 -1
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Environment Variable Scanner
3
+ *
4
+ * Scans agent.yaml content (as raw text) and extracts all ${VAR} and ${VAR:-default}
5
+ * references. Used to inform users which environment variables they need to set
6
+ * after installing an agent.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * const yamlContent = `
11
+ * name: my-agent
12
+ * env:
13
+ * webhook: \${DISCORD_WEBHOOK_URL}
14
+ * token: \${API_TOKEN:-default-token}
15
+ * `;
16
+ *
17
+ * const result = scanEnvVariables(yamlContent);
18
+ * // result = {
19
+ * // variables: [
20
+ * // { name: "API_TOKEN", defaultValue: "default-token" },
21
+ * // { name: "DISCORD_WEBHOOK_URL" }
22
+ * // ],
23
+ * // required: [{ name: "DISCORD_WEBHOOK_URL" }],
24
+ * // optional: [{ name: "API_TOKEN", defaultValue: "default-token" }]
25
+ * // }
26
+ * ```
27
+ */
28
+ /**
29
+ * Represents an environment variable reference found in the YAML content.
30
+ */
31
+ export interface EnvVariable {
32
+ /** The variable name (e.g., "DISCORD_WEBHOOK_URL") */
33
+ name: string;
34
+ /** The default value if specified with :- syntax, or undefined */
35
+ defaultValue?: string;
36
+ }
37
+ /**
38
+ * Result of scanning YAML content for environment variable references.
39
+ */
40
+ export interface EnvScanResult {
41
+ /** All unique environment variables found, sorted alphabetically */
42
+ variables: EnvVariable[];
43
+ /** Variables that have no default value (user MUST set these) */
44
+ required: EnvVariable[];
45
+ /** Variables that have a default value (optional to set) */
46
+ optional: EnvVariable[];
47
+ }
48
+ /**
49
+ * Scans YAML content for environment variable references.
50
+ *
51
+ * This function scans raw text (not parsed YAML) to extract all ${VAR} and
52
+ * ${VAR:-default} patterns. It:
53
+ * - Deduplicates variables (same name only listed once)
54
+ * - Prefers entries with defaults when a variable appears both with and without
55
+ * - Sorts alphabetically by variable name
56
+ * - Partitions into required (no default) and optional (has default) lists
57
+ * - Excludes HERDCTL_* prefixed variables (internal to herdctl)
58
+ *
59
+ * @param yamlContent - The raw YAML file content to scan
60
+ * @returns EnvScanResult with variables, required, and optional arrays
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * const result = scanEnvVariables(`
65
+ * webhook: \${WEBHOOK_URL}
66
+ * api_key: \${API_KEY:-sk-default}
67
+ * # Comment with \${COMMENT_VAR}
68
+ * `);
69
+ *
70
+ * // result.variables = [
71
+ * // { name: "API_KEY", defaultValue: "sk-default" },
72
+ * // { name: "COMMENT_VAR" },
73
+ * // { name: "WEBHOOK_URL" }
74
+ * // ]
75
+ * ```
76
+ */
77
+ export declare function scanEnvVariables(yamlContent: string): EnvScanResult;
78
+ //# sourceMappingURL=env-scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-scanner.d.ts","sourceRoot":"","sources":["../../src/distribution/env-scanner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAMH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,oEAAoE;IACpE,SAAS,EAAE,WAAW,EAAE,CAAC;IACzB,iEAAiE;IACjE,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,4DAA4D;IAC5D,QAAQ,EAAE,WAAW,EAAE,CAAC;CACzB;AAoCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,CAiEnE"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Environment Variable Scanner
3
+ *
4
+ * Scans agent.yaml content (as raw text) and extracts all ${VAR} and ${VAR:-default}
5
+ * references. Used to inform users which environment variables they need to set
6
+ * after installing an agent.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * const yamlContent = `
11
+ * name: my-agent
12
+ * env:
13
+ * webhook: \${DISCORD_WEBHOOK_URL}
14
+ * token: \${API_TOKEN:-default-token}
15
+ * `;
16
+ *
17
+ * const result = scanEnvVariables(yamlContent);
18
+ * // result = {
19
+ * // variables: [
20
+ * // { name: "API_TOKEN", defaultValue: "default-token" },
21
+ * // { name: "DISCORD_WEBHOOK_URL" }
22
+ * // ],
23
+ * // required: [{ name: "DISCORD_WEBHOOK_URL" }],
24
+ * // optional: [{ name: "API_TOKEN", defaultValue: "default-token" }]
25
+ * // }
26
+ * ```
27
+ */
28
+ // =============================================================================
29
+ // Constants
30
+ // =============================================================================
31
+ /**
32
+ * Regular expression to match ${VAR} and ${VAR:-default} patterns.
33
+ * This is the same pattern used in packages/core/src/config/interpolate.ts.
34
+ *
35
+ * Captures:
36
+ * - Group 1: Variable name (letters, numbers, underscores, starting with letter or underscore)
37
+ * - Group 2: Default value (everything after :- if present)
38
+ */
39
+ const ENV_VAR_PATTERN = /\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-([^}]*))?\}/g;
40
+ /**
41
+ * Variables to exclude from scan results.
42
+ * These are herdctl-internal variables, not agent-specific configuration.
43
+ */
44
+ const EXCLUDED_PREFIXES = ["HERDCTL_"];
45
+ // =============================================================================
46
+ // Implementation
47
+ // =============================================================================
48
+ /**
49
+ * Checks if a variable name should be excluded from results.
50
+ *
51
+ * @param name - The variable name to check
52
+ * @returns true if the variable should be excluded
53
+ */
54
+ function shouldExclude(name) {
55
+ return EXCLUDED_PREFIXES.some((prefix) => name.startsWith(prefix));
56
+ }
57
+ /**
58
+ * Scans YAML content for environment variable references.
59
+ *
60
+ * This function scans raw text (not parsed YAML) to extract all ${VAR} and
61
+ * ${VAR:-default} patterns. It:
62
+ * - Deduplicates variables (same name only listed once)
63
+ * - Prefers entries with defaults when a variable appears both with and without
64
+ * - Sorts alphabetically by variable name
65
+ * - Partitions into required (no default) and optional (has default) lists
66
+ * - Excludes HERDCTL_* prefixed variables (internal to herdctl)
67
+ *
68
+ * @param yamlContent - The raw YAML file content to scan
69
+ * @returns EnvScanResult with variables, required, and optional arrays
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * const result = scanEnvVariables(`
74
+ * webhook: \${WEBHOOK_URL}
75
+ * api_key: \${API_KEY:-sk-default}
76
+ * # Comment with \${COMMENT_VAR}
77
+ * `);
78
+ *
79
+ * // result.variables = [
80
+ * // { name: "API_KEY", defaultValue: "sk-default" },
81
+ * // { name: "COMMENT_VAR" },
82
+ * // { name: "WEBHOOK_URL" }
83
+ * // ]
84
+ * ```
85
+ */
86
+ export function scanEnvVariables(yamlContent) {
87
+ // Handle empty or non-string input
88
+ if (!yamlContent || typeof yamlContent !== "string") {
89
+ return {
90
+ variables: [],
91
+ required: [],
92
+ optional: [],
93
+ };
94
+ }
95
+ // Map to track unique variables, preferring entries with defaults
96
+ const variableMap = new Map();
97
+ // Reset regex state (global regexes are stateful)
98
+ ENV_VAR_PATTERN.lastIndex = 0;
99
+ // Find all matches
100
+ let match = null;
101
+ while ((match = ENV_VAR_PATTERN.exec(yamlContent)) !== null) {
102
+ const name = match[1];
103
+ const defaultValue = match[2];
104
+ // Skip excluded variables
105
+ if (shouldExclude(name)) {
106
+ continue;
107
+ }
108
+ const existing = variableMap.get(name);
109
+ // If variable already exists, prefer the entry with a default value
110
+ if (existing) {
111
+ if (defaultValue !== undefined && existing.defaultValue === undefined) {
112
+ variableMap.set(name, { name, defaultValue });
113
+ }
114
+ // Otherwise keep existing (either already has default, or neither has default)
115
+ }
116
+ else {
117
+ // First occurrence of this variable
118
+ const variable = { name };
119
+ if (defaultValue !== undefined) {
120
+ variable.defaultValue = defaultValue;
121
+ }
122
+ variableMap.set(name, variable);
123
+ }
124
+ }
125
+ // Convert to array and sort alphabetically by name
126
+ const variables = Array.from(variableMap.values()).sort((a, b) => a.name.localeCompare(b.name));
127
+ // Partition into required and optional
128
+ const required = [];
129
+ const optional = [];
130
+ for (const variable of variables) {
131
+ if (variable.defaultValue !== undefined) {
132
+ optional.push(variable);
133
+ }
134
+ else {
135
+ required.push(variable);
136
+ }
137
+ }
138
+ return {
139
+ variables,
140
+ required,
141
+ optional,
142
+ };
143
+ }
144
+ //# sourceMappingURL=env-scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-scanner.js","sourceRoot":"","sources":["../../src/distribution/env-scanner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AA4BH,gFAAgF;AAChF,YAAY;AACZ,gFAAgF;AAEhF;;;;;;;GAOG;AACH,MAAM,eAAe,GAAG,+CAA+C,CAAC;AAExE;;;GAGG;AACH,MAAM,iBAAiB,GAAG,CAAC,UAAU,CAAC,CAAC;AAEvC,gFAAgF;AAChF,iBAAiB;AACjB,gFAAgF;AAEhF;;;;;GAKG;AACH,SAAS,aAAa,CAAC,IAAY;IACjC,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AACrE,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,UAAU,gBAAgB,CAAC,WAAmB;IAClD,mCAAmC;IACnC,IAAI,CAAC,WAAW,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;QACpD,OAAO;YACL,SAAS,EAAE,EAAE;YACb,QAAQ,EAAE,EAAE;YACZ,QAAQ,EAAE,EAAE;SACb,CAAC;IACJ,CAAC;IAED,kEAAkE;IAClE,MAAM,WAAW,GAAG,IAAI,GAAG,EAAuB,CAAC;IAEnD,kDAAkD;IAClD,eAAe,CAAC,SAAS,GAAG,CAAC,CAAC;IAE9B,mBAAmB;IACnB,IAAI,KAAK,GAA2B,IAAI,CAAC;IACzC,OAAO,CAAC,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC5D,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAE9B,0BAA0B;QAC1B,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,SAAS;QACX,CAAC;QAED,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAEvC,oEAAoE;QACpE,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,YAAY,KAAK,SAAS,IAAI,QAAQ,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;gBACtE,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;YAChD,CAAC;YACD,+EAA+E;QACjF,CAAC;aAAM,CAAC;YACN,oCAAoC;YACpC,MAAM,QAAQ,GAAgB,EAAE,IAAI,EAAE,CAAC;YACvC,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;gBAC/B,QAAQ,CAAC,YAAY,GAAG,YAAY,CAAC;YACvC,CAAC;YACD,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED,mDAAmD;IACnD,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAEhG,uCAAuC;IACvC,MAAM,QAAQ,GAAkB,EAAE,CAAC;IACnC,MAAM,QAAQ,GAAkB,EAAE,CAAC;IAEnC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,IAAI,QAAQ,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YACxC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,OAAO;QACL,SAAS;QACT,QAAQ;QACR,QAAQ;KACT,CAAC;AACJ,CAAC"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * File Installation for Agent Distribution
3
+ *
4
+ * Copies agent files from a fetched/temp directory to `./agents/<name>/` in the
5
+ * user's project. Creates the workspace directory and writes installation metadata.
6
+ */
7
+ import { FleetManagerError, type FleetManagerErrorCode } from "../fleet-manager/errors.js";
8
+ import type { InstallationSource } from "./installation-metadata.js";
9
+ /**
10
+ * Options for installing agent files
11
+ */
12
+ export interface InstallOptions {
13
+ /** The directory containing the fetched agent repo files */
14
+ sourceDir: string;
15
+ /** The target base directory (where agents/ lives, usually project root) */
16
+ targetBaseDir: string;
17
+ /** The source specifier info for metadata tracking */
18
+ source: InstallationSource;
19
+ /** Optional: override the target path instead of using ./agents/<name>/ */
20
+ targetPath?: string;
21
+ /** If true, remove existing target directory before installing */
22
+ force?: boolean;
23
+ }
24
+ /**
25
+ * Result of a successful agent file installation
26
+ */
27
+ export interface InstallResult {
28
+ /** The agent name (from agent.yaml) */
29
+ agentName: string;
30
+ /** The full path to the installed agent directory */
31
+ installPath: string;
32
+ /** List of files that were copied (relative paths) */
33
+ copiedFiles: string[];
34
+ }
35
+ /**
36
+ * Error codes for agent installation failures
37
+ */
38
+ export declare const AGENT_ALREADY_EXISTS: FleetManagerErrorCode;
39
+ export declare const INVALID_AGENT_NAME: FleetManagerErrorCode;
40
+ export declare const MISSING_AGENT_YAML: FleetManagerErrorCode;
41
+ export declare const INVALID_AGENT_YAML: FleetManagerErrorCode;
42
+ /**
43
+ * Error thrown when agent file installation fails
44
+ */
45
+ export declare class AgentInstallError extends FleetManagerError {
46
+ constructor(message: string, code: FleetManagerErrorCode);
47
+ }
48
+ /**
49
+ * Install agent files from a source directory to the target location
50
+ *
51
+ * This function:
52
+ * 1. Reads the agent name from `agent.yaml` in the source directory
53
+ * 2. Validates the agent name against AGENT_NAME_PATTERN
54
+ * 3. Checks that the target directory doesn't already exist
55
+ * 4. Copies all files from source to target, excluding `.git/` and `node_modules/`
56
+ * 5. Creates an empty `workspace/` directory for agent runtime use
57
+ * 6. Writes `metadata.json` with installation tracking information
58
+ *
59
+ * @param options - Installation options
60
+ * @returns Installation result with agent name, install path, and copied files
61
+ * @throws {AgentInstallError} When installation fails
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * const result = await installAgentFiles({
66
+ * sourceDir: "/tmp/herdctl-github-xxxxx",
67
+ * targetBaseDir: "/path/to/project",
68
+ * source: {
69
+ * type: "github",
70
+ * url: "https://github.com/user/agent-repo",
71
+ * ref: "v1.0.0"
72
+ * }
73
+ * });
74
+ *
75
+ * console.log(`Installed ${result.agentName} to ${result.installPath}`);
76
+ * console.log(`Copied ${result.copiedFiles.length} files`);
77
+ * ```
78
+ */
79
+ export declare function installAgentFiles(options: InstallOptions): Promise<InstallResult>;
80
+ //# sourceMappingURL=file-installer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-installer.d.ts","sourceRoot":"","sources":["../../src/distribution/file-installer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAAE,iBAAiB,EAAE,KAAK,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAG3F,OAAO,KAAK,EAAwB,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAQ3F;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,aAAa,EAAE,MAAM,CAAC;IACtB,sDAAsD;IACtD,MAAM,EAAE,kBAAkB,CAAC;IAC3B,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,sDAAsD;IACtD,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAMD;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,qBAA8C,CAAC;AAClF,eAAO,MAAM,kBAAkB,EAAE,qBAA4C,CAAC;AAC9E,eAAO,MAAM,kBAAkB,EAAE,qBAA4C,CAAC;AAC9E,eAAO,MAAM,kBAAkB,EAAE,qBAA4C,CAAC;AAE9E;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,iBAAiB;gBAC1C,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,qBAAqB;CAIzD;AA8LD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CA+EvF"}
@@ -0,0 +1,268 @@
1
+ /**
2
+ * File Installation for Agent Distribution
3
+ *
4
+ * Copies agent files from a fetched/temp directory to `./agents/<name>/` in the
5
+ * user's project. Creates the workspace directory and writes installation metadata.
6
+ */
7
+ import { access, cp, mkdir, readdir, readFile, writeFile } from "node:fs/promises";
8
+ import { join } from "node:path";
9
+ import { parse as parseYaml, YAMLParseError } from "yaml";
10
+ import { FleetManagerError } from "../fleet-manager/errors.js";
11
+ import { createLogger } from "../utils/logger.js";
12
+ import { AGENT_NAME_PATTERN } from "./agent-repo-metadata.js";
13
+ const logger = createLogger("distribution:installer");
14
+ // =============================================================================
15
+ // Error Classes
16
+ // =============================================================================
17
+ /**
18
+ * Error codes for agent installation failures
19
+ */
20
+ export const AGENT_ALREADY_EXISTS = "AGENT_ALREADY_EXISTS";
21
+ export const INVALID_AGENT_NAME = "INVALID_AGENT_NAME";
22
+ export const MISSING_AGENT_YAML = "MISSING_AGENT_YAML";
23
+ export const INVALID_AGENT_YAML = "INVALID_AGENT_YAML";
24
+ /**
25
+ * Error thrown when agent file installation fails
26
+ */
27
+ export class AgentInstallError extends FleetManagerError {
28
+ constructor(message, code) {
29
+ super(message, { code });
30
+ this.name = "AgentInstallError";
31
+ }
32
+ }
33
+ // =============================================================================
34
+ // Constants
35
+ // =============================================================================
36
+ /**
37
+ * Directories to exclude when copying agent files
38
+ */
39
+ const EXCLUDED_DIRS = new Set([".git", "node_modules"]);
40
+ /**
41
+ * Metadata file name for installation tracking
42
+ */
43
+ const METADATA_FILE = "metadata.json";
44
+ /**
45
+ * Workspace directory name (created for agent runtime use)
46
+ */
47
+ const WORKSPACE_DIR = "workspace";
48
+ // =============================================================================
49
+ // Helper Functions
50
+ // =============================================================================
51
+ /**
52
+ * Check if a path exists
53
+ */
54
+ async function pathExists(filePath) {
55
+ try {
56
+ await access(filePath);
57
+ return true;
58
+ }
59
+ catch {
60
+ return false;
61
+ }
62
+ }
63
+ /**
64
+ * Read and parse agent.yaml to extract the agent name
65
+ */
66
+ async function readAgentName(sourceDir) {
67
+ const agentYamlPath = join(sourceDir, "agent.yaml");
68
+ // Check if agent.yaml exists
69
+ if (!(await pathExists(agentYamlPath))) {
70
+ throw new AgentInstallError(`agent.yaml not found in source directory: ${sourceDir}`, MISSING_AGENT_YAML);
71
+ }
72
+ // Read and parse the file
73
+ let content;
74
+ try {
75
+ content = await readFile(agentYamlPath, "utf-8");
76
+ }
77
+ catch (err) {
78
+ const error = err;
79
+ throw new AgentInstallError(`Failed to read agent.yaml: ${error.message}`, MISSING_AGENT_YAML);
80
+ }
81
+ // Parse YAML
82
+ let parsed;
83
+ try {
84
+ parsed = parseYaml(content);
85
+ }
86
+ catch (err) {
87
+ if (err instanceof YAMLParseError) {
88
+ const position = err.linePos?.[0];
89
+ const locationInfo = position ? ` at line ${position.line}, column ${position.col}` : "";
90
+ throw new AgentInstallError(`Invalid YAML syntax in agent.yaml${locationInfo}: ${err.message}`, INVALID_AGENT_YAML);
91
+ }
92
+ throw new AgentInstallError(`Failed to parse agent.yaml: ${err.message}`, INVALID_AGENT_YAML);
93
+ }
94
+ // Extract and validate name
95
+ if (!parsed || typeof parsed !== "object") {
96
+ throw new AgentInstallError("agent.yaml must contain a valid YAML object with a 'name' field", INVALID_AGENT_YAML);
97
+ }
98
+ const data = parsed;
99
+ const name = data.name;
100
+ if (typeof name !== "string" || name.trim() === "") {
101
+ throw new AgentInstallError("agent.yaml must have a 'name' field with a non-empty string value", INVALID_AGENT_YAML);
102
+ }
103
+ return name;
104
+ }
105
+ /**
106
+ * Validate an agent name against the AGENT_NAME_PATTERN
107
+ */
108
+ function validateAgentName(name) {
109
+ if (!AGENT_NAME_PATTERN.test(name)) {
110
+ throw new AgentInstallError(`Invalid agent name "${name}". Agent names must start with a letter or number ` +
111
+ `and contain only letters, numbers, underscores, and hyphens.`, INVALID_AGENT_NAME);
112
+ }
113
+ }
114
+ /**
115
+ * Recursively copy directory contents, excluding specified directories.
116
+ * Returns the list of copied files (relative paths).
117
+ */
118
+ async function copyDirectoryRecursive(sourceDir, targetDir, excludedDirs, relativePath = "") {
119
+ const copiedFiles = [];
120
+ // Create target directory if it doesn't exist
121
+ await mkdir(targetDir, { recursive: true });
122
+ // Read source directory contents
123
+ const entries = await readdir(sourceDir, { withFileTypes: true });
124
+ for (const entry of entries) {
125
+ const sourcePath = join(sourceDir, entry.name);
126
+ const targetPath = join(targetDir, entry.name);
127
+ const entryRelativePath = relativePath ? join(relativePath, entry.name) : entry.name;
128
+ if (entry.isDirectory()) {
129
+ // Skip excluded directories
130
+ if (excludedDirs.has(entry.name)) {
131
+ logger.debug("Skipping excluded directory", { path: entryRelativePath });
132
+ continue;
133
+ }
134
+ // Recursively copy subdirectory
135
+ const subFiles = await copyDirectoryRecursive(sourcePath, targetPath, excludedDirs, entryRelativePath);
136
+ copiedFiles.push(...subFiles);
137
+ }
138
+ else if (entry.isFile()) {
139
+ // Copy file
140
+ await cp(sourcePath, targetPath);
141
+ copiedFiles.push(entryRelativePath);
142
+ }
143
+ // Skip symlinks and other special files
144
+ }
145
+ return copiedFiles;
146
+ }
147
+ /**
148
+ * Write installation metadata to metadata.json
149
+ */
150
+ async function writeMetadata(installPath, source) {
151
+ const metadata = {
152
+ source,
153
+ installed_at: new Date().toISOString(),
154
+ installed_by: `herdctl@${getHerdctlVersion()}`,
155
+ };
156
+ const metadataPath = join(installPath, METADATA_FILE);
157
+ await writeFile(metadataPath, JSON.stringify(metadata, null, 2), "utf-8");
158
+ logger.debug("Wrote metadata.json", { path: metadataPath });
159
+ }
160
+ /**
161
+ * Get herdctl version from package.json (simplified - returns unknown if not found)
162
+ */
163
+ function getHerdctlVersion() {
164
+ // In a real implementation, this would read from package.json
165
+ // For now, we return a placeholder that will be replaced with actual version
166
+ return "unknown";
167
+ }
168
+ // =============================================================================
169
+ // Main Installer
170
+ // =============================================================================
171
+ /**
172
+ * Install agent files from a source directory to the target location
173
+ *
174
+ * This function:
175
+ * 1. Reads the agent name from `agent.yaml` in the source directory
176
+ * 2. Validates the agent name against AGENT_NAME_PATTERN
177
+ * 3. Checks that the target directory doesn't already exist
178
+ * 4. Copies all files from source to target, excluding `.git/` and `node_modules/`
179
+ * 5. Creates an empty `workspace/` directory for agent runtime use
180
+ * 6. Writes `metadata.json` with installation tracking information
181
+ *
182
+ * @param options - Installation options
183
+ * @returns Installation result with agent name, install path, and copied files
184
+ * @throws {AgentInstallError} When installation fails
185
+ *
186
+ * @example
187
+ * ```typescript
188
+ * const result = await installAgentFiles({
189
+ * sourceDir: "/tmp/herdctl-github-xxxxx",
190
+ * targetBaseDir: "/path/to/project",
191
+ * source: {
192
+ * type: "github",
193
+ * url: "https://github.com/user/agent-repo",
194
+ * ref: "v1.0.0"
195
+ * }
196
+ * });
197
+ *
198
+ * console.log(`Installed ${result.agentName} to ${result.installPath}`);
199
+ * console.log(`Copied ${result.copiedFiles.length} files`);
200
+ * ```
201
+ */
202
+ export async function installAgentFiles(options) {
203
+ const { sourceDir, targetBaseDir, source, targetPath, force } = options;
204
+ logger.debug("Starting agent file installation", {
205
+ sourceDir,
206
+ targetBaseDir,
207
+ sourceType: source.type,
208
+ targetPath,
209
+ force,
210
+ });
211
+ // ==========================================================================
212
+ // 1. Read agent name from agent.yaml
213
+ // ==========================================================================
214
+ const agentName = await readAgentName(sourceDir);
215
+ logger.debug("Read agent name from agent.yaml", { agentName });
216
+ // ==========================================================================
217
+ // 2. Validate agent name
218
+ // ==========================================================================
219
+ validateAgentName(agentName);
220
+ logger.debug("Agent name validated", { agentName });
221
+ // ==========================================================================
222
+ // 3. Determine target path and check it doesn't exist (unless force)
223
+ // ==========================================================================
224
+ const installPath = targetPath ?? join(targetBaseDir, "agents", agentName);
225
+ if (await pathExists(installPath)) {
226
+ if (force) {
227
+ // Remove existing directory when force is true
228
+ logger.debug("Force mode: removing existing directory", { installPath });
229
+ const { rm } = await import("node:fs/promises");
230
+ await rm(installPath, { recursive: true, force: true });
231
+ }
232
+ else {
233
+ throw new AgentInstallError(`Agent "${agentName}" already exists at ${installPath}. ` +
234
+ `Remove the existing agent first or use a different name.`, AGENT_ALREADY_EXISTS);
235
+ }
236
+ }
237
+ logger.debug("Target path determined", { installPath });
238
+ // ==========================================================================
239
+ // 4. Copy files (excluding .git and node_modules)
240
+ // ==========================================================================
241
+ logger.info("Copying agent files", {
242
+ source: sourceDir,
243
+ destination: installPath,
244
+ });
245
+ const copiedFiles = await copyDirectoryRecursive(sourceDir, installPath, EXCLUDED_DIRS);
246
+ logger.debug("Files copied", { count: copiedFiles.length });
247
+ // ==========================================================================
248
+ // 5. Create workspace directory
249
+ // ==========================================================================
250
+ const workspacePath = join(installPath, WORKSPACE_DIR);
251
+ await mkdir(workspacePath, { recursive: true });
252
+ logger.debug("Created workspace directory", { path: workspacePath });
253
+ // ==========================================================================
254
+ // 6. Write metadata.json
255
+ // ==========================================================================
256
+ await writeMetadata(installPath, source);
257
+ logger.info("Agent installation complete", {
258
+ agentName,
259
+ installPath,
260
+ copiedFiles: copiedFiles.length,
261
+ });
262
+ return {
263
+ agentName,
264
+ installPath,
265
+ copiedFiles,
266
+ };
267
+ }
268
+ //# sourceMappingURL=file-installer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-installer.js","sourceRoot":"","sources":["../../src/distribution/file-installer.ts"],"names":[],"mappings":"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"}