agent-first-data 0.2.4 → 0.4.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
@@ -1,6 +1,6 @@
1
1
  # agent-first-data
2
2
 
3
- **Agent-First Data (AFD)** — Suffix-driven output formatting and protocol templates for AI agents.
3
+ **Agent-First Data (AFDATA)** — Suffix-driven output formatting and protocol templates for AI agents.
4
4
 
5
5
  The field name is the schema. Agents read `latency_ms` and know milliseconds, `api_key_secret` and know to redact, no external schema needed.
6
6
 
@@ -18,23 +18,37 @@ A backup tool invoked from the CLI — flags, env vars, and config all use the s
18
18
  API_KEY_SECRET=sk-1234 cloudback --timeout-s 30 --max-file-size-bytes 10737418240 /data/backup.tar.gz
19
19
  ```
20
20
 
21
- The tool reads env vars, flags, and config — all with AFD suffixes — and emits a startup message:
21
+ For CLI diagnostics, enable log categories explicitly:
22
+
23
+ ```bash
24
+ --log startup,request,progress,retry,redirect
25
+ --verbose # shorthand for all categories
26
+ ```
27
+
28
+ Without these flags, startup diagnostics should stay off by default.
29
+
30
+ The tool reads env vars, flags, and config — all with AFDATA suffixes — and can emit a startup diagnostic event:
22
31
 
23
32
  ```typescript
24
- import { buildJsonStartup, outputJson, outputYaml, outputPlain } from "agent-first-data";
33
+ import { buildJson, outputJson, outputYaml, outputPlain } from "agent-first-data";
25
34
 
26
- const startup = buildJsonStartup(
27
- { timeout_s: 30, max_file_size_bytes: 10737418240 },
28
- { input_path: "/data/backup.tar.gz" },
29
- { API_KEY_SECRET: process.env.API_KEY_SECRET ?? null },
35
+ const startup = buildJson(
36
+ "log",
37
+ {
38
+ event: "startup",
39
+ config: { timeout_s: 30, max_file_size_bytes: 10737418240 },
40
+ args: { input_path: "/data/backup.tar.gz" },
41
+ env: { API_KEY_SECRET: process.env.API_KEY_SECRET ?? null },
42
+ },
30
43
  );
31
44
  ```
32
45
 
33
46
  Three output formats, same data:
34
47
 
35
48
  ```
36
- JSON: {"code":"startup","args":{"input_path":"/data/backup.tar.gz"},"config":{"max_file_size_bytes":10737418240,"timeout_s":30},"env":{"API_KEY_SECRET":"***"}}
37
- YAML: code: "startup"
49
+ JSON: {"code":"log","event":"startup","args":{"input_path":"/data/backup.tar.gz"},"config":{"max_file_size_bytes":10737418240,"timeout_s":30},"env":{"API_KEY_SECRET":"***"}}
50
+ YAML: code: "log"
51
+ event: "startup"
38
52
  args:
39
53
  input_path: "/data/backup.tar.gz"
40
54
  config:
@@ -42,25 +56,22 @@ YAML: code: "startup"
42
56
  timeout: "30s"
43
57
  env:
44
58
  API_KEY: "***"
45
- Plain: args.input_path=/data/backup.tar.gz code=startup config.max_file_size=10.0GB config.timeout=30s env.API_KEY=***
59
+ Plain: args.input_path=/data/backup.tar.gz code=log event=startup config.max_file_size=10.0GB config.timeout=30s env.API_KEY=***
46
60
  ```
47
61
 
48
62
  `--timeout-s` → `timeout_s` → `timeout: 30s`. `API_KEY_SECRET` → `API_KEY: "***"`. The suffix is the schema.
49
63
 
50
64
  ## API Reference
51
65
 
52
- Total: **9 public APIs** + **AFD logging** (4 protocol builders + 3 output functions + 1 internal + 1 utility)
66
+ Total: **12 public APIs and 1 type** + **AFDATA logging** (3 protocol builders + 3 output functions + 1 internal + 1 utility + 4 CLI helpers + `OutputFormat`)
53
67
 
54
68
  ### Protocol Builders (returns JsonValue)
55
69
 
56
- Build AFD protocol structures. Return JSON-serializable objects for API responses.
70
+ Build AFDATA protocol structures. Return JSON-serializable objects for API responses.
57
71
 
58
72
  ```typescript
59
73
  type JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue };
60
74
 
61
- // Startup (configuration)
62
- buildJsonStartup(config: JsonValue, args: JsonValue, env: JsonValue): JsonValue
63
-
64
75
  // Success (result)
65
76
  buildJsonOk(result: JsonValue, trace?: JsonValue): JsonValue
66
77
 
@@ -75,13 +86,17 @@ buildJson(code: string, fields: JsonValue, trace?: JsonValue): JsonValue
75
86
 
76
87
  **Example:**
77
88
  ```typescript
78
- import { buildJsonStartup, buildJsonOk, buildJsonError, buildJson } from "agent-first-data";
89
+ import { buildJsonOk, buildJsonError, buildJson } from "agent-first-data";
79
90
 
80
91
  // Startup
81
- const startup = buildJsonStartup(
82
- { api_key_secret: "sk-123", timeout_s: 30 },
83
- { config_path: "config.yml" },
84
- { RUST_LOG: "info" },
92
+ const startup = buildJson(
93
+ "log",
94
+ {
95
+ event: "startup",
96
+ config: { api_key_secret: "sk-123", timeout_s: 30 },
97
+ args: { config_path: "config.yml" },
98
+ env: { RUST_LOG: "info" },
99
+ },
85
100
  );
86
101
 
87
102
  // Success (always include trace)
@@ -162,6 +177,42 @@ parseSize("1.5K"); // 1536
162
177
  parseSize("512"); // 512
163
178
  ```
164
179
 
180
+ ### CLI Helpers (for tools built on AFDATA)
181
+
182
+ Shared helpers that prevent flag-parsing drift between CLI tools. Use these instead of reimplementing `--output` and `--log` handling in each tool.
183
+
184
+ ```typescript
185
+ type OutputFormat = "json" | "yaml" | "plain"
186
+
187
+ cliParseOutput(s: string): OutputFormat // Parse --output flag; throws on unknown
188
+ cliParseLogFilters(entries: string[]): string[] // Normalize --log: trim, lowercase, dedup, remove empty
189
+ cliOutput(value: JsonValue, format: OutputFormat): string // Dispatch to outputJson/Yaml/Plain
190
+ buildCliError(message: string): JsonValue // {code:"error", error_code:"invalid_request", retryable:false, trace:{duration_ms:0}}
191
+ ```
192
+
193
+ **Canonical pattern** — parse all flags before doing work, emit JSONL errors to stdout:
194
+
195
+ ```typescript
196
+ import {
197
+ type OutputFormat, cliParseOutput, cliParseLogFilters,
198
+ cliOutput, buildCliError, outputJson,
199
+ } from "agent-first-data";
200
+
201
+ let fmt: OutputFormat;
202
+ try {
203
+ fmt = cliParseOutput(outputArg);
204
+ } catch (e) {
205
+ console.log(outputJson(buildCliError((e as Error).message)));
206
+ process.exit(2);
207
+ }
208
+
209
+ const log = cliParseLogFilters(logArg ? logArg.split(",") : []);
210
+ // ... do work ...
211
+ console.log(cliOutput(result, fmt));
212
+ ```
213
+
214
+ See `examples/agent_cli.ts` for the complete working example (`npx tsx --test examples/agent_cli.ts`).
215
+
165
216
  ## Usage Examples
166
217
 
167
218
  ### Example 1: REST API
@@ -185,17 +236,22 @@ app.get("/users/:id", (req, res) => {
185
236
  ### Example 2: CLI Tool (Complete Lifecycle)
186
237
 
187
238
  ```typescript
188
- import { buildJsonStartup, buildJsonOk, buildJson, outputYaml, outputPlain } from "agent-first-data";
239
+ import { buildJsonOk, buildJson, outputYaml, outputPlain } from "agent-first-data";
189
240
 
190
241
  // 1. Startup
191
- const startup = buildJsonStartup(
192
- { api_key_secret: "sk-sensitive-key", timeout_s: 30 },
193
- { input_path: "data.json" },
194
- { RUST_LOG: "info" },
242
+ const startup = buildJson(
243
+ "log",
244
+ {
245
+ event: "startup",
246
+ config: { api_key_secret: "sk-sensitive-key", timeout_s: 30 },
247
+ args: { input_path: "data.json" },
248
+ env: { RUST_LOG: "info" },
249
+ },
195
250
  );
196
251
  console.log(outputYaml(startup));
197
252
  // ---
198
- // code: "startup"
253
+ // code: "log"
254
+ // event: "startup"
199
255
  // args:
200
256
  // input_path: "data.json"
201
257
  // config:
@@ -245,6 +301,7 @@ const result = buildJsonOk(
245
301
  );
246
302
 
247
303
  // Print JSONL to stdout (secrets redacted, one JSON object per line)
304
+ // Channel policy: machine-readable protocol/log events must not use stderr.
248
305
  console.log(outputJson(result));
249
306
  // {"code":"ok","result":{"status":"success"},"trace":{"api_key_secret":"***","duration_ms":250}}
250
307
  ```
@@ -286,9 +343,9 @@ console.log(outputPlain(data));
286
343
  // api_key=*** cache_ttl=3600s count=42 created_at=2025-02-07T00:00:00.000Z file_size=5.0MB payment=50000000msats price=$99.99 request_timeout=5.0s success_rate=95.5% user_name=alice
287
344
  ```
288
345
 
289
- ## AFD Logging
346
+ ## AFDATA Logging
290
347
 
291
- AFD-compliant structured logging. Every log line is formatted using the library's own `outputJson`/`outputPlain`/`outputYaml` functions. Span fields are carried via `AsyncLocalStorage` (async-safe), automatically flattened into each log line. Zero dependencies beyond Node.js built-ins.
348
+ AFDATA-compliant structured logging. Every log line is formatted using the library's own `outputJson`/`outputPlain`/`outputYaml` functions. Span fields are carried via `AsyncLocalStorage` (async-safe), automatically flattened into each log line. Zero dependencies beyond Node.js built-ins.
292
349
 
293
350
  ### API
294
351
 
@@ -367,8 +424,8 @@ await span({ request_id: "abc-123" }, async () => {
367
424
  The `code` field defaults to the log level. Override with an explicit field:
368
425
 
369
426
  ```typescript
370
- log.info("Server ready", { code: "startup" });
371
- // {"timestamp_epoch_ms":...,"message":"Server ready","code":"startup"}
427
+ log.info("Server ready", { code: "log", event: "startup" });
428
+ // {"timestamp_epoch_ms":...,"message":"Server ready","code":"log","event":"startup"}
372
429
  ```
373
430
 
374
431
  ### Output Fields
@@ -385,7 +442,7 @@ Every log line contains:
385
442
 
386
443
  ### Log Output Formats
387
444
 
388
- All three formats use the library's own output functions, so AFD suffix processing applies to log fields too:
445
+ All three formats use the library's own output functions, so AFDATA suffix processing applies to log fields too:
389
446
 
390
447
  | Format | Function | Keys | Values | Use case |
391
448
  |:-------|:---------|:-----|:-------|:---------|
@@ -419,8 +476,8 @@ All formats automatically redact `_secret` fields.
419
476
 
420
477
  This package is part of the [agent-first-data](https://github.com/cmnspore/agent-first-data) repository, which also contains:
421
478
 
422
- - **`spec/`** — Full AFD specification with suffix definitions, protocol format rules, and cross-language test fixtures
423
- - **`skills/`** — Claude Code skill for AI agents working with AFD conventions
479
+ - **`spec/`** — Full AFDATA specification with suffix definitions, protocol format rules, and cross-language test fixtures
480
+ - **`skills/`** — AI coding agent skill for working with AFDATA conventions
424
481
 
425
482
  To run tests, clone the full repository (tests use shared cross-language fixtures from `spec/fixtures/`):
426
483
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * AFD-compliant structured logging.
2
+ * AFDATA-compliant structured logging.
3
3
  *
4
4
  * Outputs log events using agent-first-data formatting functions:
5
5
  * - JSON: single-line JSONL via outputJson (secrets redacted, original keys)
@@ -9,7 +9,7 @@
9
9
  * Span fields are carried via AsyncLocalStorage (async-safe).
10
10
  *
11
11
  * Usage:
12
- * import { log, span, initJson, initPlain, initYaml } from "agent-first-data/afd_logging";
12
+ * import { log, span, initJson, initPlain, initYaml } from "agent-first-data/afdata_logging";
13
13
  * initJson(); // or initPlain() or initYaml()
14
14
  * log.info("Server started");
15
15
  * await span({ request_id: "abc" }, async () => {
@@ -23,7 +23,7 @@ export declare function initPlain(): void;
23
23
  /** Set log output to multi-line YAML (keys stripped, values formatted). */
24
24
  export declare function initYaml(): void;
25
25
  /**
26
- * AFD logger. Each method outputs a single log line to stdout.
26
+ * AFDATA logger. Each method outputs a single log line to stdout.
27
27
  * Format is controlled by initJson/initPlain/initYaml (default: JSON).
28
28
  */
29
29
  export declare const log: {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * AFD-compliant structured logging.
2
+ * AFDATA-compliant structured logging.
3
3
  *
4
4
  * Outputs log events using agent-first-data formatting functions:
5
5
  * - JSON: single-line JSONL via outputJson (secrets redacted, original keys)
@@ -9,7 +9,7 @@
9
9
  * Span fields are carried via AsyncLocalStorage (async-safe).
10
10
  *
11
11
  * Usage:
12
- * import { log, span, initJson, initPlain, initYaml } from "agent-first-data/afd_logging";
12
+ * import { log, span, initJson, initPlain, initYaml } from "agent-first-data/afdata_logging";
13
13
  * initJson(); // or initPlain() or initYaml()
14
14
  * log.info("Server started");
15
15
  * await span({ request_id: "abc" }, async () => {
@@ -68,7 +68,7 @@ function emit(level, message, fields) {
68
68
  process.stdout.write(line + "\n");
69
69
  }
70
70
  /**
71
- * AFD logger. Each method outputs a single log line to stdout.
71
+ * AFDATA logger. Each method outputs a single log line to stdout.
72
72
  * Format is controlled by initJson/initPlain/initYaml (default: JSON).
73
73
  */
74
74
  export const log = {
package/dist/cli.d.ts ADDED
@@ -0,0 +1,42 @@
1
+ /**
2
+ * AFDATA CLI helpers — output format parsing, log filter normalization, error building.
3
+ */
4
+ import { JsonValue } from "./format.js";
5
+ /** Output format for CLI and pipe/MCP modes. */
6
+ export type OutputFormat = "json" | "yaml" | "plain";
7
+ /**
8
+ * Parse the --output flag value into an OutputFormat.
9
+ * Throws on unknown values; catch and pass message to buildCliError.
10
+ *
11
+ * @example
12
+ * cliParseOutput("json") // → "json"
13
+ * cliParseOutput("xml") // throws Error
14
+ */
15
+ export declare function cliParseOutput(s: string): OutputFormat;
16
+ /**
17
+ * Normalize --output flag entries: trim, lowercase, deduplicate, remove empty.
18
+ * Accepts pre-split entries (e.g. after splitting on comma).
19
+ *
20
+ * @example
21
+ * cliParseLogFilters(["Query", " error ", "query"]) // → ["query", "error"]
22
+ */
23
+ export declare function cliParseLogFilters(entries: string[]): string[];
24
+ /**
25
+ * Dispatch output formatting by OutputFormat.
26
+ * Equivalent to calling outputJson, outputYaml, or outputPlain directly.
27
+ *
28
+ * @example
29
+ * cliOutput({ code: "ok" }, "plain") // → "code=ok"
30
+ */
31
+ export declare function cliOutput(value: JsonValue, format: OutputFormat): string;
32
+ /**
33
+ * Build a standard CLI parse error value.
34
+ * Use when flag parsing fails or a flag value is invalid.
35
+ * Print with outputJson and exit with code 2.
36
+ *
37
+ * @example
38
+ * const err = buildCliError("--output: invalid value 'xml'");
39
+ * console.log(outputJson(err));
40
+ * process.exit(2);
41
+ */
42
+ export declare function buildCliError(message: string): JsonValue;
package/dist/cli.js ADDED
@@ -0,0 +1,68 @@
1
+ /**
2
+ * AFDATA CLI helpers — output format parsing, log filter normalization, error building.
3
+ */
4
+ import { outputJson, outputYaml, outputPlain } from "./format.js";
5
+ /**
6
+ * Parse the --output flag value into an OutputFormat.
7
+ * Throws on unknown values; catch and pass message to buildCliError.
8
+ *
9
+ * @example
10
+ * cliParseOutput("json") // → "json"
11
+ * cliParseOutput("xml") // throws Error
12
+ */
13
+ export function cliParseOutput(s) {
14
+ if (s === "json" || s === "yaml" || s === "plain") {
15
+ return s;
16
+ }
17
+ throw new Error(`invalid --output format '${s}': expected json, yaml, or plain`);
18
+ }
19
+ /**
20
+ * Normalize --output flag entries: trim, lowercase, deduplicate, remove empty.
21
+ * Accepts pre-split entries (e.g. after splitting on comma).
22
+ *
23
+ * @example
24
+ * cliParseLogFilters(["Query", " error ", "query"]) // → ["query", "error"]
25
+ */
26
+ export function cliParseLogFilters(entries) {
27
+ const out = [];
28
+ for (const entry of entries) {
29
+ const s = entry.trim().toLowerCase();
30
+ if (s && !out.includes(s)) {
31
+ out.push(s);
32
+ }
33
+ }
34
+ return out;
35
+ }
36
+ /**
37
+ * Dispatch output formatting by OutputFormat.
38
+ * Equivalent to calling outputJson, outputYaml, or outputPlain directly.
39
+ *
40
+ * @example
41
+ * cliOutput({ code: "ok" }, "plain") // → "code=ok"
42
+ */
43
+ export function cliOutput(value, format) {
44
+ if (format === "yaml")
45
+ return outputYaml(value);
46
+ if (format === "plain")
47
+ return outputPlain(value);
48
+ return outputJson(value);
49
+ }
50
+ /**
51
+ * Build a standard CLI parse error value.
52
+ * Use when flag parsing fails or a flag value is invalid.
53
+ * Print with outputJson and exit with code 2.
54
+ *
55
+ * @example
56
+ * const err = buildCliError("--output: invalid value 'xml'");
57
+ * console.log(outputJson(err));
58
+ * process.exit(2);
59
+ */
60
+ export function buildCliError(message) {
61
+ return {
62
+ code: "error",
63
+ error_code: "invalid_request",
64
+ error: message,
65
+ retryable: false,
66
+ trace: { duration_ms: 0 },
67
+ };
68
+ }
package/dist/format.d.ts CHANGED
@@ -1,13 +1,11 @@
1
1
  /**
2
- * AFD output formatting and protocol templates.
2
+ * AFDATA output formatting and protocol templates.
3
3
  *
4
- * 9 public APIs: 4 protocol builders + 3 output formatters + 1 redaction + 1 utility.
4
+ * 8 public APIs: 3 protocol builders + 3 output formatters + 1 redaction + 1 utility.
5
5
  */
6
6
  export type JsonValue = string | number | boolean | null | JsonValue[] | {
7
7
  [key: string]: JsonValue;
8
8
  };
9
- /** Build {code: "startup", config, args, env}. */
10
- export declare function buildJsonStartup(config: JsonValue, args: JsonValue, env: JsonValue): JsonValue;
11
9
  /** Build {code: "ok", result, trace?}. */
12
10
  export declare function buildJsonOk(result: JsonValue, trace?: JsonValue): JsonValue;
13
11
  /** Build {code: "error", error: message, trace?}. */
package/dist/format.js CHANGED
@@ -1,15 +1,11 @@
1
1
  /**
2
- * AFD output formatting and protocol templates.
2
+ * AFDATA output formatting and protocol templates.
3
3
  *
4
- * 9 public APIs: 4 protocol builders + 3 output formatters + 1 redaction + 1 utility.
4
+ * 8 public APIs: 3 protocol builders + 3 output formatters + 1 redaction + 1 utility.
5
5
  */
6
6
  // ═══════════════════════════════════════════
7
7
  // Public API: Protocol Builders
8
8
  // ═══════════════════════════════════════════
9
- /** Build {code: "startup", config, args, env}. */
10
- export function buildJsonStartup(config, args, env) {
11
- return { code: "startup", config, args, env };
12
- }
13
9
  /** Build {code: "ok", result, trace?}. */
14
10
  export function buildJsonOk(result, trace) {
15
11
  const m = { code: "ok", result };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  /**
2
- * Agent-First Data (AFD) — suffix-driven output formatting and protocol templates.
2
+ * Agent-First Data (AFDATA) — suffix-driven output formatting and protocol templates.
3
3
  */
4
- export { buildJsonStartup, buildJsonOk, buildJsonError, buildJson, outputJson, outputYaml, outputPlain, internalRedactSecrets, parseSize } from "./format.js";
5
- export { log, span, initJson, initPlain, initYaml } from "./afd_logging.js";
4
+ export { buildJsonOk, buildJsonError, buildJson, outputJson, outputYaml, outputPlain, internalRedactSecrets, parseSize } from "./format.js";
5
+ export { log, span, initJson, initPlain, initYaml } from "./afdata_logging.js";
6
+ export { type OutputFormat, cliParseOutput, cliParseLogFilters, cliOutput, buildCliError } from "./cli.js";
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  /**
2
- * Agent-First Data (AFD) — suffix-driven output formatting and protocol templates.
2
+ * Agent-First Data (AFDATA) — suffix-driven output formatting and protocol templates.
3
3
  */
4
- export { buildJsonStartup, buildJsonOk, buildJsonError, buildJson, outputJson, outputYaml, outputPlain, internalRedactSecrets, parseSize } from "./format.js";
5
- export { log, span, initJson, initPlain, initYaml } from "./afd_logging.js";
4
+ export { buildJsonOk, buildJsonError, buildJson, outputJson, outputYaml, outputPlain, internalRedactSecrets, parseSize } from "./format.js";
5
+ export { log, span, initJson, initPlain, initYaml } from "./afdata_logging.js";
6
+ export { cliParseOutput, cliParseLogFilters, cliOutput, buildCliError } from "./cli.js";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agent-first-data",
3
- "version": "0.2.4",
4
- "description": "Agent-First Data (AFD) — suffix-driven output formatting and protocol templates for AI agents",
3
+ "version": "0.4.0",
4
+ "description": "Agent-First Data (AFDATA) — suffix-driven output formatting and protocol templates for AI agents",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -15,9 +15,9 @@
15
15
  "import": "./dist/index.js",
16
16
  "types": "./dist/index.d.ts"
17
17
  },
18
- "./afd_logging": {
19
- "import": "./dist/afd_logging.js",
20
- "types": "./dist/afd_logging.d.ts"
18
+ "./afdata_logging": {
19
+ "import": "./dist/afdata_logging.js",
20
+ "types": "./dist/afdata_logging.d.ts"
21
21
  }
22
22
  },
23
23
  "files": [