@foldspace_npm/harness 0.1.3 → 0.1.4

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/README.md CHANGED
@@ -95,7 +95,7 @@ Non-interactive / CI form:
95
95
  ```bash
96
96
  npx --yes @foldspace_npm/harness init my-agent \
97
97
  --product-id FR8JUQZAQRZB \
98
- --agent-api-name my-agent \
98
+ --agent-key my-agent \
99
99
  --domain app.example.com \
100
100
  --name "My Agent"
101
101
  ```
@@ -105,12 +105,14 @@ When running directly from a harness checkout during development:
105
105
  ```bash
106
106
  node bin/cli.mjs init ../my-agent \
107
107
  --product-id FR8JUQZAQRZB \
108
- --agent-api-name my-agent \
108
+ --agent-key my-agent \
109
109
  --domain app.example.com
110
110
  ```
111
111
 
112
- `--name` is optional and defaults to the target directory name. The product ID
113
- must be the bare ID, not an `EU-…` SDK key. The domain may be a hostname or an
112
+ The Agent Key is the value shown in Agent Studio, such as `my-agent`.
113
+ `--agent-api-name` remains a deprecated alias for `--agent-key`. `--name` is
114
+ optional and defaults to the target directory name. The product ID must be the
115
+ bare ID, not the `EU-…-1-1` SDK loader key. The domain may be a hostname or an
114
116
  HTTP(S) URL without a port or path.
115
117
 
116
118
  For safety, `init` requires a target path that does not exist. It does not
package/bin/cli.mjs CHANGED
@@ -62,9 +62,13 @@ function printHelp(topic, json) {
62
62
  }
63
63
 
64
64
  function normalizeCommandArgs(command, args) {
65
- const options = new Map(
66
- command.options.map((option) => [option.name, option]),
67
- );
65
+ const options = new Map();
66
+ for (const option of command.options) {
67
+ options.set(option.name, { option, canonicalName: option.name });
68
+ for (const alias of option.deprecatedAliases || []) {
69
+ options.set(alias, { option, canonicalName: option.name });
70
+ }
71
+ }
68
72
  const seen = new Set();
69
73
  const normalized = [];
70
74
  let positionals = 0;
@@ -81,14 +85,17 @@ function normalizeCommandArgs(command, args) {
81
85
 
82
86
  const separator = token.indexOf("=");
83
87
  const name = separator > -1 ? token.slice(0, separator) : token;
84
- const option = options.get(name);
85
- if (!option) throw new Error(`unknown option '${name}'`);
86
- if (seen.has(name)) throw new Error(`option '${name}' was provided twice`);
87
- seen.add(name);
88
+ const match = options.get(name);
89
+ if (!match) throw new Error(`unknown option '${name}'`);
90
+ const { option, canonicalName } = match;
91
+ if (seen.has(canonicalName)) {
92
+ throw new Error(`option '${canonicalName}' was provided twice`);
93
+ }
94
+ seen.add(canonicalName);
88
95
 
89
96
  if (option.kind === "flag") {
90
97
  if (separator > -1) throw new Error(`option '${name}' takes no value`);
91
- normalized.push(name);
98
+ normalized.push(canonicalName);
92
99
  continue;
93
100
  }
94
101
 
@@ -97,7 +104,7 @@ function normalizeCommandArgs(command, args) {
97
104
  if (!optionValue || optionValue.startsWith("--")) {
98
105
  throw new Error(`option '${name}' requires a value`);
99
106
  }
100
- normalized.push(name, optionValue);
107
+ normalized.push(canonicalName, optionValue);
101
108
  }
102
109
  return normalized;
103
110
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@foldspace_npm/harness",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Build and verify portable Foldspace action artifacts against a live app.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli-help.mjs CHANGED
@@ -74,6 +74,10 @@ export function renderCommandHelp(registry, name) {
74
74
  `${option.name}${option.value ? ` <${option.value}>` : ""}`,
75
75
  `${option.description}${
76
76
  option.default ? ` (default: ${option.default})` : ""
77
+ }${
78
+ option.deprecatedAliases?.length
79
+ ? ` (deprecated alias: ${option.deprecatedAliases.join(", ")})`
80
+ : ""
77
81
  }`,
78
82
  ]);
79
83
  sections.push("", "Options:", rows(optionRows));
@@ -21,7 +21,7 @@ export const CLI_COMMANDS = Object.freeze([
21
21
  group: "start",
22
22
  summary: "Create a configured Foldspace actions project",
23
23
  usage:
24
- "foldspace init [<directory>] [--product-id <id>] [--agent-api-name <name>] [--domain <host>] [--name <display-name>]",
24
+ "foldspace init [<directory>] [--product-id <id>] [--agent-key <key>] [--domain <host>] [--name <display-name>]",
25
25
  risk: "local-write",
26
26
  environment: "node",
27
27
  environmentVariables: [],
@@ -37,8 +37,9 @@ export const CLI_COMMANDS = Object.freeze([
37
37
  value("--product-id", "id", "Bare Foldspace product ID", {
38
38
  required: "non-interactive",
39
39
  }),
40
- value("--agent-api-name", "name", "Agent API name", {
40
+ value("--agent-key", "key", "Agent Key shown in Agent Studio", {
41
41
  required: "non-interactive",
42
+ deprecatedAliases: ["--agent-api-name"],
42
43
  }),
43
44
  value("--domain", "host", "Target hostname or HTTP(S) URL", {
44
45
  required: "non-interactive",
@@ -50,7 +51,7 @@ export const CLI_COMMANDS = Object.freeze([
50
51
  prerequisites: [
51
52
  "Node 20 or newer",
52
53
  "A target directory that does not already exist",
53
- "Non-interactive use requires directory, product ID, agent name, and domain",
54
+ "Non-interactive use requires directory, product ID, Agent Key, and domain",
54
55
  ],
55
56
  effects: ["Creates a new local project; never initializes Git"],
56
57
  next: [
package/src/init.mjs CHANGED
@@ -8,7 +8,13 @@ import { commandByName } from "./cli-registry.mjs";
8
8
 
9
9
  const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
10
10
  const defaultTemplateRoot = path.join(packageRoot, "templates", "agent-starter");
11
- const allowedFlags = new Set(["name", "product-id", "agent-api-name", "domain"]);
11
+ const allowedFlags = new Set([
12
+ "name",
13
+ "product-id",
14
+ "agent-key",
15
+ "agent-api-name",
16
+ "domain",
17
+ ]);
12
18
  const tokenPattern = /\{\{([A-Z0-9_]+)\}\}/g;
13
19
  const defaultDirectory = "my-agent";
14
20
 
@@ -75,12 +81,17 @@ export function parseInitArgs(argv) {
75
81
  if (positional.length > 1) {
76
82
  throw new Error(`Usage: ${initUsage}`);
77
83
  }
84
+ if (flags["agent-key"] && flags["agent-api-name"]) {
85
+ throw new Error(
86
+ "Use --agent-key only; --agent-api-name is its deprecated alias.",
87
+ );
88
+ }
78
89
 
79
90
  return {
80
91
  directory: positional[0] || null,
81
92
  displayName: flags.name || null,
82
93
  productId: flags["product-id"] || null,
83
- agentApiName: flags["agent-api-name"] || null,
94
+ agentApiName: flags["agent-key"] || flags["agent-api-name"] || null,
84
95
  domain: flags.domain || null,
85
96
  };
86
97
  }
@@ -89,7 +100,7 @@ function missingInitFields(parsed) {
89
100
  const missing = [];
90
101
  if (!parsed.directory) missing.push("directory");
91
102
  if (!parsed.productId) missing.push("product-id");
92
- if (!parsed.agentApiName) missing.push("agent-api-name");
103
+ if (!parsed.agentApiName) missing.push("agent-key");
93
104
  if (!parsed.domain) missing.push("domain");
94
105
  return missing;
95
106
  }
@@ -208,8 +219,8 @@ async function promptForMissingFields(parsed, options = {}) {
208
219
 
209
220
  if (!next.agentApiName) {
210
221
  next.agentApiName = await askUntilValid(
211
- "Agent API name",
212
- (value) => validateIdentifier(value, "Agent API name"),
222
+ "Agent Key",
223
+ (value) => validateIdentifier(value, "Agent Key"),
213
224
  options,
214
225
  );
215
226
  }
@@ -243,7 +254,7 @@ function finalizeInitConfig(parsed) {
243
254
 
244
255
  for (const [key, label] of [
245
256
  ["productId", "product-id"],
246
- ["agentApiName", "agent-api-name"],
257
+ ["agentApiName", "agent-key"],
247
258
  ["domain", "domain"],
248
259
  ]) {
249
260
  if (!parsed[key]) {
@@ -282,7 +293,7 @@ function createTemplateValues(config, harnessVersion) {
282
293
  }
283
294
 
284
295
  const productId = validateProductId(config.productId);
285
- const agentApiName = validateIdentifier(config.agentApiName, "Agent API name");
296
+ const agentApiName = validateIdentifier(config.agentApiName, "Agent Key");
286
297
  const target = normalizeTarget(config.domain);
287
298
  const hosts =
288
299
  target.domain === "localhost" || /^\d+(?:\.\d+){3}$/.test(target.domain)