agent-first-data 0.19.1 → 0.21.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.
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ import { installStreamRedirectFromRawArgs } from "agent-first-data/stream-redire
|
|
|
33
33
|
- YAML keeps original keys and values (structure-preserving, like JSON), sorting keys by UTF-16 code unit order and quoting/escaping unsafe keys and string scalars. Plain strips formatting suffixes, formats values, sorts the same way, and renders nested objects/arrays as canonical JSON.
|
|
34
34
|
- Logging records use `kind:"log"` with a nested `log` payload and a separate `level` field, so error-level logs are not terminal protocol errors.
|
|
35
35
|
- `buildCliError(message, hint?)` returns a strict-ready CLI error with `error.retryable:false` and `trace:{}`.
|
|
36
|
-
- Use `cliHandleVersionOrContinue()` before argument parsing so
|
|
36
|
+
- Use `cliHandleVersionOrContinue()` before argument parsing so `--version`/`-V` always answers with a structured protocol-v1 `kind:"result"` version event — JSON by default, or `--output yaml|plain`/`--json` for another format; there is no conventional bare-text form. Pass your own value-taking global flag names so their value is not mistaken for the subcommand boundary.
|
|
37
37
|
- Use `installStreamRedirectFromRawArgs()` (from `agent-first-data/stream-redirect`) before version/help handling if a CLI exposes `--stdout-file` or `--stderr-file`; stderr is redirected as native diagnostics, not JSON. Node fd-level redirection is process-lifetime because the standard library does not expose `dup2` restoration.
|
|
38
38
|
|
|
39
39
|
## Reference
|
|
@@ -61,7 +61,8 @@ assert!(rendered.contains("\"api_key_secret\":\"***\""));
|
|
|
61
61
|
For a finite CLI execution implemented in Rust, create one `CliEmitter`, select
|
|
62
62
|
`OutputFormat` through `cli_parse_output`, enable strict protocol, and emit one
|
|
63
63
|
terminal result or error. Handle version before clap with
|
|
64
|
-
`cli_handle_version_or_continue(raw_args, name, version)
|
|
64
|
+
`cli_handle_version_or_continue(raw_args, cmd, name, display_name, version, build)`,
|
|
65
|
+
which always answers `--version`/`-V` with a structured version event.
|
|
65
66
|
For non-CLI HTTP/MCP/SSE serialization, call `redacted_value()` or
|
|
66
67
|
`redact_url_secrets()` explicitly at the boundary.
|
|
67
68
|
|
|
@@ -284,7 +284,7 @@ Required cross-language behavior to rely on:
|
|
|
284
284
|
- Use `redact_url_secrets()` for URLs embedded in log messages or prose before interpolating them into output.
|
|
285
285
|
- Use `cli_parse_output()`, `cli_parse_log_filters()`, `render()`, `build_cli_error()`, and the version helper for CLI tools instead of custom parsing/error envelopes.
|
|
286
286
|
- `build_cli_error(message, hint?)` returns a strict-ready CLI error with `error.retryable:false` and `trace:{}`.
|
|
287
|
-
- Rust CLIs should call `cli_handle_version_or_continue(raw_args, name, version)` before clap parsing so `--version
|
|
287
|
+
- Rust CLIs (feature `cli`/`cli-help`) should call `cli_handle_version_or_continue(raw_args, cmd, name, display_name, version, build)` before clap parsing so `--version`/`-V` always emits a structured `kind:"result"` event with `result.code == "version"`, `result.name`, and `result.version` (plus optional `result.display_name`/`result.build`) instead of clap's plain text — JSON by default, `--output yaml|plain` or `--json` for another format; there is no conventional bare-text form. Pass the caller's own `clap::Command` (e.g. `Cli::command()`) so any value-taking global flag it defines (e.g. `--stdout-file`) is recognized and its value is never mistaken for the subcommand boundary.
|
|
288
288
|
- Use the protocol reader `decode_protocol_event(text)` to parse and strict-validate a single JSON text line, receiving a typed decoded event.
|
|
289
289
|
|
|
290
290
|
## AFDATA Logging
|
package/dist/cli.d.ts
CHANGED
|
@@ -165,29 +165,42 @@ export declare class CliEmitter {
|
|
|
165
165
|
*/
|
|
166
166
|
finishResult(payload: JsonValue): number;
|
|
167
167
|
}
|
|
168
|
-
/** Build a standard CLI version value. */
|
|
169
|
-
export declare function buildCliVersion(version: string): Event;
|
|
170
168
|
/**
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
169
|
+
* Build a standard CLI version event: a `kind:"result"` event whose payload is
|
|
170
|
+
* `{ code: "version", name, version }`, plus `display_name`/`build` when given.
|
|
171
|
+
* `name` is the short/bin identity (e.g. `"afdata"`); `displayName` is an
|
|
172
|
+
* optional human-facing product name (e.g. `"Agent-First Data"`); `build` is an
|
|
173
|
+
* opaque caller-supplied identifier (a git commit SHA, for example) — its
|
|
174
|
+
* meaning is entirely up to the caller. Both are `undefined` when unavailable,
|
|
175
|
+
* and simply absent from the payload. Note the JSON field is `display_name`
|
|
176
|
+
* (snake_case) even though the parameter is `displayName`.
|
|
174
177
|
*/
|
|
175
|
-
export declare function
|
|
178
|
+
export declare function buildCliVersion(name: string, displayName: string | undefined, version: string, build: string | undefined): Event;
|
|
179
|
+
/**
|
|
180
|
+
* Render a CLI version response as a protocol-v1 event in `format`. There is no
|
|
181
|
+
* conventional-text path — `format` is required.
|
|
182
|
+
*/
|
|
183
|
+
export declare function cliRenderVersion(name: string, displayName: string | undefined, version: string, build: string | undefined, format: OutputFormat): string;
|
|
176
184
|
/**
|
|
177
185
|
* Render version output if --version/-V is present; otherwise return undefined.
|
|
178
186
|
* Throws for malformed version requests, for example `--version --output xml`.
|
|
179
187
|
*
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
* `--
|
|
183
|
-
*
|
|
188
|
+
* The one blessed behavior: `--version` always answers with a protocol-v1
|
|
189
|
+
* `kind:"result"` version event — JSON by default, or `--output yaml|plain` (or
|
|
190
|
+
* `--json`) for another format. There is no conventional bare-text path.
|
|
191
|
+
*
|
|
192
|
+
* `valueFlags` is the caller's own value-taking global long flags (with or
|
|
193
|
+
* without leading dashes; the leading dashes are stripped internally). It is the
|
|
194
|
+
* TS analog of Rust's `&clap::Command`: the pre-parser consults it so a global
|
|
195
|
+
* flag's space-separated value (e.g. `--log request,startup`) is never mistaken
|
|
196
|
+
* for the subcommand boundary, which would hide a later `--version`/`--output`.
|
|
184
197
|
*
|
|
185
198
|
* Only a top-level version request is recognized: scanning stops at the first
|
|
186
199
|
* positional argument (the subcommand) or `--`, so `tool sub --version <value>`
|
|
187
200
|
* leaves `--version` for the subcommand's parser rather than printing the
|
|
188
201
|
* tool version.
|
|
189
202
|
*/
|
|
190
|
-
export declare function cliHandleVersionOrContinue(rawArgs: string[], name: string, version: string): string | undefined;
|
|
203
|
+
export declare function cliHandleVersionOrContinue(rawArgs: string[], valueFlags: string[], name: string, displayName: string | undefined, version: string, build: string | undefined): string | undefined;
|
|
191
204
|
/**
|
|
192
205
|
* Build a standard CLI parse error value. This function cannot fail.
|
|
193
206
|
* Use when flag parsing fails or a flag value is invalid.
|
package/dist/cli.js
CHANGED
|
@@ -274,34 +274,70 @@ export class CliEmitter {
|
|
|
274
274
|
return this.finish(jsonResult(payload).build(), 0);
|
|
275
275
|
}
|
|
276
276
|
}
|
|
277
|
-
/**
|
|
278
|
-
|
|
279
|
-
|
|
277
|
+
/**
|
|
278
|
+
* Build a standard CLI version event: a `kind:"result"` event whose payload is
|
|
279
|
+
* `{ code: "version", name, version }`, plus `display_name`/`build` when given.
|
|
280
|
+
* `name` is the short/bin identity (e.g. `"afdata"`); `displayName` is an
|
|
281
|
+
* optional human-facing product name (e.g. `"Agent-First Data"`); `build` is an
|
|
282
|
+
* opaque caller-supplied identifier (a git commit SHA, for example) — its
|
|
283
|
+
* meaning is entirely up to the caller. Both are `undefined` when unavailable,
|
|
284
|
+
* and simply absent from the payload. Note the JSON field is `display_name`
|
|
285
|
+
* (snake_case) even though the parameter is `displayName`.
|
|
286
|
+
*/
|
|
287
|
+
export function buildCliVersion(name, displayName, version, build) {
|
|
288
|
+
return jsonResult({
|
|
289
|
+
code: "version",
|
|
290
|
+
name,
|
|
291
|
+
version,
|
|
292
|
+
...(displayName !== undefined ? { display_name: displayName } : {}),
|
|
293
|
+
...(build !== undefined ? { build } : {}),
|
|
294
|
+
}).build();
|
|
280
295
|
}
|
|
281
296
|
/**
|
|
282
|
-
* Render CLI version
|
|
283
|
-
*
|
|
284
|
-
* conventional "<name> <version>" text.
|
|
297
|
+
* Render a CLI version response as a protocol-v1 event in `format`. There is no
|
|
298
|
+
* conventional-text path — `format` is required.
|
|
285
299
|
*/
|
|
286
|
-
export function cliRenderVersion(name, version, format
|
|
287
|
-
const rendered =
|
|
300
|
+
export function cliRenderVersion(name, displayName, version, build, format) {
|
|
301
|
+
const rendered = render(buildCliVersion(name, displayName, version, build), format);
|
|
288
302
|
return `${rendered.replace(/\n+$/u, "")}\n`;
|
|
289
303
|
}
|
|
304
|
+
/**
|
|
305
|
+
* Split a flag argument into its long name (leading dashes stripped, any
|
|
306
|
+
* `=value` suffix dropped) and inline value. Returns `undefined` name for a
|
|
307
|
+
* non-flag or the bare `-`. `--output=` yields an empty-string inline value.
|
|
308
|
+
*/
|
|
309
|
+
function splitFlag(arg) {
|
|
310
|
+
if (!arg.startsWith("-") || arg === "-")
|
|
311
|
+
return { name: undefined, inlineValue: undefined };
|
|
312
|
+
const eq = arg.indexOf("=");
|
|
313
|
+
const flag = eq === -1 ? arg : arg.slice(0, eq);
|
|
314
|
+
const inlineValue = eq === -1 ? undefined : arg.slice(eq + 1);
|
|
315
|
+
const name = flag.replace(/^-+/u, "");
|
|
316
|
+
if (name === "")
|
|
317
|
+
return { name: undefined, inlineValue: undefined };
|
|
318
|
+
return { name, inlineValue };
|
|
319
|
+
}
|
|
290
320
|
/**
|
|
291
321
|
* Render version output if --version/-V is present; otherwise return undefined.
|
|
292
322
|
* Throws for malformed version requests, for example `--version --output xml`.
|
|
293
323
|
*
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
* `--
|
|
297
|
-
*
|
|
324
|
+
* The one blessed behavior: `--version` always answers with a protocol-v1
|
|
325
|
+
* `kind:"result"` version event — JSON by default, or `--output yaml|plain` (or
|
|
326
|
+
* `--json`) for another format. There is no conventional bare-text path.
|
|
327
|
+
*
|
|
328
|
+
* `valueFlags` is the caller's own value-taking global long flags (with or
|
|
329
|
+
* without leading dashes; the leading dashes are stripped internally). It is the
|
|
330
|
+
* TS analog of Rust's `&clap::Command`: the pre-parser consults it so a global
|
|
331
|
+
* flag's space-separated value (e.g. `--log request,startup`) is never mistaken
|
|
332
|
+
* for the subcommand boundary, which would hide a later `--version`/`--output`.
|
|
298
333
|
*
|
|
299
334
|
* Only a top-level version request is recognized: scanning stops at the first
|
|
300
335
|
* positional argument (the subcommand) or `--`, so `tool sub --version <value>`
|
|
301
336
|
* leaves `--version` for the subcommand's parser rather than printing the
|
|
302
337
|
* tool version.
|
|
303
338
|
*/
|
|
304
|
-
export function cliHandleVersionOrContinue(rawArgs, name, version) {
|
|
339
|
+
export function cliHandleVersionOrContinue(rawArgs, valueFlags, name, displayName, version, build) {
|
|
340
|
+
const valueFlagSet = new Set(valueFlags.map((flag) => flag.replace(/^-+/u, "")));
|
|
305
341
|
let versionRequested = false;
|
|
306
342
|
let outputFormat;
|
|
307
343
|
let outputError;
|
|
@@ -314,6 +350,7 @@ export function cliHandleVersionOrContinue(rawArgs, name, version) {
|
|
|
314
350
|
// git/cargo/clap: this pre-parser only owns a top-level version request.
|
|
315
351
|
if (!arg.startsWith("-"))
|
|
316
352
|
break;
|
|
353
|
+
const { name: flagName, inlineValue } = splitFlag(arg);
|
|
317
354
|
if (arg === "--version" || arg === "-V") {
|
|
318
355
|
versionRequested = true;
|
|
319
356
|
i += 1;
|
|
@@ -329,15 +366,21 @@ export function cliHandleVersionOrContinue(rawArgs, name, version) {
|
|
|
329
366
|
i += 1;
|
|
330
367
|
continue;
|
|
331
368
|
}
|
|
332
|
-
|
|
369
|
+
// `--output-to` takes a value but does not affect version text output.
|
|
370
|
+
// Consume its space-separated value so it is not mistaken for the
|
|
371
|
+
// subcommand boundary (which would hide a later `--version`/`--output`).
|
|
372
|
+
if (flagName === "output-to") {
|
|
373
|
+
const hasSpaceValue = inlineValue === undefined && rawArgs[i + 1] !== undefined && !rawArgs[i + 1].startsWith("-");
|
|
374
|
+
i += hasSpaceValue ? 2 : 1;
|
|
375
|
+
continue;
|
|
376
|
+
}
|
|
377
|
+
if (flagName === "output") {
|
|
333
378
|
let value;
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
value = arg.slice("--output=".length);
|
|
379
|
+
if (inlineValue !== undefined) {
|
|
380
|
+
value = inlineValue;
|
|
337
381
|
}
|
|
338
382
|
else if (rawArgs[i + 1] !== undefined && !rawArgs[i + 1].startsWith("-")) {
|
|
339
383
|
value = rawArgs[i + 1];
|
|
340
|
-
step = 2;
|
|
341
384
|
}
|
|
342
385
|
if (value === undefined) {
|
|
343
386
|
outputError = new Error("missing value for --output: expected json, yaml, or plain");
|
|
@@ -356,16 +399,20 @@ export function cliHandleVersionOrContinue(rawArgs, name, version) {
|
|
|
356
399
|
outputError = e;
|
|
357
400
|
}
|
|
358
401
|
}
|
|
359
|
-
i +=
|
|
402
|
+
i += inlineValue !== undefined || value === undefined ? 1 : 2;
|
|
360
403
|
continue;
|
|
361
404
|
}
|
|
362
|
-
|
|
405
|
+
// Any other flag: consult the caller's own value-taking global flags so a
|
|
406
|
+
// flag's space-separated value is never mistaken for the subcommand
|
|
407
|
+
// boundary above.
|
|
408
|
+
const hasSpaceValue = inlineValue === undefined && rawArgs[i + 1] !== undefined && !rawArgs[i + 1].startsWith("-");
|
|
409
|
+
i += hasSpaceValue && flagName !== undefined && valueFlagSet.has(flagName) ? 2 : 1;
|
|
363
410
|
}
|
|
364
411
|
if (!versionRequested)
|
|
365
412
|
return undefined;
|
|
366
413
|
if (outputError !== undefined)
|
|
367
414
|
throw outputError;
|
|
368
|
-
return cliRenderVersion(name, version, outputFormat ??
|
|
415
|
+
return cliRenderVersion(name, displayName, version, build, outputFormat ?? "json");
|
|
369
416
|
}
|
|
370
417
|
/**
|
|
371
418
|
* Build a standard CLI parse error value. This function cannot fail.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-first-data",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "A naming convention that lets AI agents understand your data without being told what it means, plus a CLI and library for reading and safely editing structured JSON, TOML, YAML, dotenv, and INI documents.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|