agent-first-data 0.8.1 → 0.9.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
@@ -131,16 +131,16 @@ const notFound = buildJson(
131
131
 
132
132
  ### Output Formatters (returns string)
133
133
 
134
- Format values for CLI output and logs. `outputJson` uses full `_secret` redaction by default. `outputJsonWith` supports explicit scoped policies. Use the `*WithOptions` functions to pass legacy secret names such as `api_key`. YAML and Plain always redact secrets and apply human-readable formatting.
134
+ Format values for CLI output and logs. `outputJson` uses full `_secret` redaction by default. `outputJsonWith` supports explicit scoped policies. Use `OutputOptions` to pass legacy secret names such as `api_key` or request schema-preserving YAML/plain rendering with `OutputStyle.Raw`.
135
135
 
136
136
  ```typescript
137
137
  outputJson(value: JsonValue): string // Single-line JSON, original keys, for programs/logs
138
138
  outputJsonWith(value: JsonValue, redactionPolicy: RedactionPolicy): string
139
- outputJsonWithOptions(value: JsonValue, redactionOptions: RedactionOptions): string
139
+ outputJsonWithOptions(value: JsonValue, outputOptions: OutputOptions): string
140
140
  outputYaml(value: JsonValue): string // Multi-line YAML, keys stripped, values formatted
141
- outputYamlWithOptions(value: JsonValue, redactionOptions: RedactionOptions): string
141
+ outputYamlWithOptions(value: JsonValue, outputOptions: OutputOptions): string
142
142
  outputPlain(value: JsonValue): string // Single-line logfmt, keys stripped, values formatted
143
- outputPlainWithOptions(value: JsonValue, redactionOptions: RedactionOptions): string
143
+ outputPlainWithOptions(value: JsonValue, outputOptions: OutputOptions): string
144
144
  ```
145
145
 
146
146
  ```typescript
@@ -154,9 +154,19 @@ type RedactionOptions = {
154
154
  policy?: RedactionPolicy;
155
155
  secretNames?: readonly string[]; // legacy names like "api_key" or "authorization"
156
156
  }
157
+
158
+ enum OutputStyle {
159
+ Readable = "Readable",
160
+ Raw = "Raw",
161
+ }
162
+
163
+ type OutputOptions = {
164
+ redaction?: RedactionOptions;
165
+ style?: OutputStyle;
166
+ }
157
167
  ```
158
168
 
159
- Secret names match exact field names at any nesting level; there is no trim, case folding, hyphen/underscore normalization, glob, regex, or substring matching. They do not change YAML/Plain suffix stripping.
169
+ Secret names match exact field names at any nesting level; there is no trim, case folding, hyphen/underscore normalization, glob, regex, or substring matching. `OutputOptions` combines `RedactionOptions` with `OutputStyle.Readable` (default suffix stripping and value formatting) or `OutputStyle.Raw` (no suffix stripping or value formatting).
160
170
 
161
171
  **Example:**
162
172
  ```typescript
@@ -222,6 +232,7 @@ type OutputFormat = "json" | "yaml" | "plain"
222
232
  cliParseOutput(s: string): OutputFormat // Parse --output flag; throws on unknown
223
233
  cliParseLogFilters(entries: string[]): string[] // Normalize --log: trim, lowercase, dedup, remove empty
224
234
  cliOutput(value: JsonValue, format: OutputFormat): string // Dispatch to outputJson/Yaml/Plain
235
+ cliOutputWithOptions(value: JsonValue, format: OutputFormat, outputOptions: OutputOptions): string
225
236
  buildCliError(message: string, hint?: string): JsonValue // {code:"error", error_code:"invalid_request", hint?, retryable:false, trace:{duration_ms:0}}
226
237
  ```
227
238
 
package/dist/cli.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * AFDATA CLI helpers — output format parsing, log filter normalization, error building.
3
3
  */
4
- import { JsonValue } from "./format.js";
4
+ import { JsonValue, type OutputOptions } from "./format.js";
5
5
  /** Output format for CLI and pipe/MCP modes. */
6
6
  export type OutputFormat = "json" | "yaml" | "plain";
7
7
  /**
@@ -29,6 +29,11 @@ export declare function cliParseLogFilters(entries: string[]): string[];
29
29
  * cliOutput({ code: "ok" }, "plain") // → "code=ok"
30
30
  */
31
31
  export declare function cliOutput(value: JsonValue, format: OutputFormat): string;
32
+ /**
33
+ * Dispatch output formatting with explicit redaction and style.
34
+ * JSON ignores OutputStyle and preserves original keys and values after redaction.
35
+ */
36
+ export declare function cliOutputWithOptions(value: JsonValue, format: OutputFormat, outputOptions: OutputOptions): string;
32
37
  /**
33
38
  * Build a standard CLI parse error value.
34
39
  * Use when flag parsing fails or a flag value is invalid.
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * AFDATA CLI helpers — output format parsing, log filter normalization, error building.
3
3
  */
4
- import { outputJson, outputYaml, outputPlain } from "./format.js";
4
+ import { outputJson, outputJsonWithOptions, outputYaml, outputYamlWithOptions, outputPlain, outputPlainWithOptions, } from "./format.js";
5
5
  /**
6
6
  * Parse the --output flag value into an OutputFormat.
7
7
  * Throws on unknown values; catch and pass message to buildCliError.
@@ -47,6 +47,17 @@ export function cliOutput(value, format) {
47
47
  return outputPlain(value);
48
48
  return outputJson(value);
49
49
  }
50
+ /**
51
+ * Dispatch output formatting with explicit redaction and style.
52
+ * JSON ignores OutputStyle and preserves original keys and values after redaction.
53
+ */
54
+ export function cliOutputWithOptions(value, format, outputOptions) {
55
+ if (format === "yaml")
56
+ return outputYamlWithOptions(value, outputOptions);
57
+ if (format === "plain")
58
+ return outputPlainWithOptions(value, outputOptions);
59
+ return outputJsonWithOptions(value, outputOptions);
60
+ }
50
61
  /**
51
62
  * Build a standard CLI parse error value.
52
63
  * Use when flag parsing fails or a flag value is invalid.
package/dist/format.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * AFDATA output formatting and protocol templates.
3
3
  *
4
- * 16 public APIs and 2 types: protocol builders, redacted value helpers,
5
- * output formatters, redaction, parseSize, RedactionPolicy, and RedactionOptions.
4
+ * 16 public APIs and 4 types: protocol builders, redacted value helpers,
5
+ * output formatters, redaction, parseSize, RedactionPolicy, RedactionOptions,
6
+ * OutputStyle, and OutputOptions.
6
7
  */
7
8
  export type JsonValue = string | number | boolean | null | JsonValue[] | {
8
9
  [key: string]: JsonValue;
@@ -27,20 +28,30 @@ export type RedactionOptions = {
27
28
  */
28
29
  secretNames?: readonly string[];
29
30
  };
31
+ export declare enum OutputStyle {
32
+ Readable = "Readable",
33
+ Raw = "Raw"
34
+ }
35
+ export type OutputOptions = {
36
+ /** Redaction options applied before rendering. */
37
+ redaction?: RedactionOptions;
38
+ /** Rendering style for YAML/plain output. Omitted means readable. */
39
+ style?: OutputStyle;
40
+ };
30
41
  /** Format as single-line JSON. Secrets redacted, original keys, raw values. */
31
42
  export declare function outputJson(value: JsonValue): string;
32
43
  /** Format as single-line JSON with explicit redaction policy. */
33
44
  export declare function outputJsonWith(value: JsonValue, redactionPolicy: RedactionPolicy): string;
34
- /** Format as single-line JSON with explicit redaction options. */
35
- export declare function outputJsonWithOptions(value: JsonValue, redactionOptions: RedactionOptions): string;
45
+ /** Format as single-line JSON with explicit output options. */
46
+ export declare function outputJsonWithOptions(value: JsonValue, outputOptions: OutputOptions): string;
36
47
  /** Format as multi-line YAML. Keys stripped, values formatted, secrets redacted. */
37
48
  export declare function outputYaml(value: JsonValue): string;
38
- /** Format as multi-line YAML with explicit redaction options. */
39
- export declare function outputYamlWithOptions(value: JsonValue, redactionOptions: RedactionOptions): string;
49
+ /** Format as multi-line YAML with explicit output options. */
50
+ export declare function outputYamlWithOptions(value: JsonValue, outputOptions: OutputOptions): string;
40
51
  /** Format as single-line logfmt. Keys stripped, values formatted, secrets redacted. */
41
52
  export declare function outputPlain(value: JsonValue): string;
42
- /** Format as single-line logfmt with explicit redaction options. */
43
- export declare function outputPlainWithOptions(value: JsonValue, redactionOptions: RedactionOptions): string;
53
+ /** Format as single-line logfmt with explicit output options. */
54
+ export declare function outputPlainWithOptions(value: JsonValue, outputOptions: OutputOptions): string;
44
55
  /** Redact _secret fields in-place. */
45
56
  export declare function internalRedactSecrets(value: JsonValue): void;
46
57
  /** Redact secret fields in-place using explicit redaction options. */
package/dist/format.js CHANGED
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * AFDATA output formatting and protocol templates.
3
3
  *
4
- * 16 public APIs and 2 types: protocol builders, redacted value helpers,
5
- * output formatters, redaction, parseSize, RedactionPolicy, and RedactionOptions.
4
+ * 16 public APIs and 4 types: protocol builders, redacted value helpers,
5
+ * output formatters, redaction, parseSize, RedactionPolicy, RedactionOptions,
6
+ * OutputStyle, and OutputOptions.
6
7
  */
7
8
  // ═══════════════════════════════════════════
8
9
  // Public API: Protocol Builders
@@ -40,6 +41,11 @@ export var RedactionPolicy;
40
41
  RedactionPolicy["RedactionNone"] = "RedactionNone";
41
42
  RedactionPolicy["RedactionStrict"] = "RedactionStrict";
42
43
  })(RedactionPolicy || (RedactionPolicy = {}));
44
+ export var OutputStyle;
45
+ (function (OutputStyle) {
46
+ OutputStyle["Readable"] = "Readable";
47
+ OutputStyle["Raw"] = "Raw";
48
+ })(OutputStyle || (OutputStyle = {}));
43
49
  /** Format as single-line JSON. Secrets redacted, original keys, raw values. */
44
50
  export function outputJson(value) {
45
51
  return JSON.stringify(redactedValue(value));
@@ -48,39 +54,40 @@ export function outputJson(value) {
48
54
  export function outputJsonWith(value, redactionPolicy) {
49
55
  return JSON.stringify(redactedValueWith(value, redactionPolicy));
50
56
  }
51
- /** Format as single-line JSON with explicit redaction options. */
52
- export function outputJsonWithOptions(value, redactionOptions) {
53
- return JSON.stringify(redactedValueWithOptions(value, redactionOptions));
57
+ /** Format as single-line JSON with explicit output options. */
58
+ export function outputJsonWithOptions(value, outputOptions) {
59
+ return JSON.stringify(redactedValueWithOptions(value, outputOptions.redaction ?? {}));
54
60
  }
55
61
  /** Format as multi-line YAML. Keys stripped, values formatted, secrets redacted. */
56
62
  export function outputYaml(value) {
57
- value = redactedValue(value);
58
- const lines = ["---"];
59
- renderYamlProcessed(value, 0, lines);
60
- return lines.join("\n");
63
+ return outputYamlWithOptions(value, {});
61
64
  }
62
- /** Format as multi-line YAML with explicit redaction options. */
63
- export function outputYamlWithOptions(value, redactionOptions) {
64
- value = redactedValueWithOptions(value, redactionOptions);
65
+ /** Format as multi-line YAML with explicit output options. */
66
+ export function outputYamlWithOptions(value, outputOptions) {
67
+ value = redactedValueWithOptions(value, outputOptions.redaction ?? {});
65
68
  const lines = ["---"];
66
- renderYamlProcessed(value, 0, lines);
69
+ if (outputOptions.style === OutputStyle.Raw) {
70
+ renderYamlRaw(value, 0, lines);
71
+ }
72
+ else {
73
+ renderYamlProcessed(value, 0, lines);
74
+ }
67
75
  return lines.join("\n");
68
76
  }
69
77
  /** Format as single-line logfmt. Keys stripped, values formatted, secrets redacted. */
70
78
  export function outputPlain(value) {
71
- value = redactedValue(value);
72
- const pairs = [];
73
- collectPlainPairs(value, "", pairs);
74
- pairs.sort(([a], [b]) => jcsCompare(a, b));
75
- return pairs
76
- .map(([k, v]) => `${k}=${quoteLogfmtValue(v)}`)
77
- .join(" ");
79
+ return outputPlainWithOptions(value, {});
78
80
  }
79
- /** Format as single-line logfmt with explicit redaction options. */
80
- export function outputPlainWithOptions(value, redactionOptions) {
81
- value = redactedValueWithOptions(value, redactionOptions);
81
+ /** Format as single-line logfmt with explicit output options. */
82
+ export function outputPlainWithOptions(value, outputOptions) {
83
+ value = redactedValueWithOptions(value, outputOptions.redaction ?? {});
82
84
  const pairs = [];
83
- collectPlainPairs(value, "", pairs);
85
+ if (outputOptions.style === OutputStyle.Raw) {
86
+ collectPlainPairsRaw(value, "", pairs);
87
+ }
88
+ else {
89
+ collectPlainPairs(value, "", pairs);
90
+ }
84
91
  pairs.sort(([a], [b]) => jcsCompare(a, b));
85
92
  return pairs
86
93
  .map(([k, v]) => `${k}=${quoteLogfmtValue(v)}`)
@@ -530,6 +537,69 @@ function renderYamlProcessed(value, indent, lines) {
530
537
  }
531
538
  }
532
539
  }
540
+ function renderYamlRaw(value, indent, lines) {
541
+ const prefix = " ".repeat(indent);
542
+ if (isObject(value)) {
543
+ for (const key of sortedObjectKeys(value)) {
544
+ renderYamlFieldRaw(prefix, key, value[key], indent, lines);
545
+ }
546
+ }
547
+ else if (Array.isArray(value)) {
548
+ renderYamlArrayRaw(value, indent, lines);
549
+ }
550
+ else {
551
+ lines.push(`${prefix}${yamlScalar(value)}`);
552
+ }
553
+ }
554
+ function renderYamlFieldRaw(prefix, key, value, indent, lines) {
555
+ if (isObject(value)) {
556
+ if (Object.keys(value).length > 0) {
557
+ lines.push(`${prefix}${key}:`);
558
+ renderYamlRaw(value, indent + 1, lines);
559
+ }
560
+ else {
561
+ lines.push(`${prefix}${key}: {}`);
562
+ }
563
+ }
564
+ else if (Array.isArray(value)) {
565
+ if (value.length > 0) {
566
+ lines.push(`${prefix}${key}:`);
567
+ renderYamlArrayRaw(value, indent + 1, lines);
568
+ }
569
+ else {
570
+ lines.push(`${prefix}${key}: []`);
571
+ }
572
+ }
573
+ else {
574
+ lines.push(`${prefix}${key}: ${yamlScalar(value)}`);
575
+ }
576
+ }
577
+ function renderYamlArrayRaw(arr, indent, lines) {
578
+ const prefix = " ".repeat(indent);
579
+ for (const item of arr) {
580
+ if (isObject(item)) {
581
+ if (Object.keys(item).length > 0) {
582
+ lines.push(`${prefix}-`);
583
+ renderYamlRaw(item, indent + 1, lines);
584
+ }
585
+ else {
586
+ lines.push(`${prefix}- {}`);
587
+ }
588
+ }
589
+ else if (Array.isArray(item)) {
590
+ if (item.length > 0) {
591
+ lines.push(`${prefix}-`);
592
+ renderYamlArrayRaw(item, indent + 1, lines);
593
+ }
594
+ else {
595
+ lines.push(`${prefix}- []`);
596
+ }
597
+ }
598
+ else {
599
+ lines.push(`${prefix}- ${yamlScalar(item)}`);
600
+ }
601
+ }
602
+ }
533
603
  function escapeYamlStr(s) {
534
604
  return s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
535
605
  }
@@ -569,6 +639,26 @@ function collectPlainPairs(value, prefix, pairs) {
569
639
  }
570
640
  }
571
641
  }
642
+ function collectPlainPairsRaw(value, prefix, pairs) {
643
+ if (!isObject(value))
644
+ return;
645
+ for (const key of sortedObjectKeys(value)) {
646
+ const v = value[key];
647
+ const fullKey = prefix ? `${prefix}.${key}` : key;
648
+ if (isObject(v)) {
649
+ collectPlainPairsRaw(v, fullKey, pairs);
650
+ }
651
+ else if (Array.isArray(v)) {
652
+ pairs.push([fullKey, v.map((i) => plainScalarRaw(i)).join(",")]);
653
+ }
654
+ else if (v === null) {
655
+ pairs.push([fullKey, ""]);
656
+ }
657
+ else {
658
+ pairs.push([fullKey, plainScalar(v)]);
659
+ }
660
+ }
661
+ }
572
662
  function plainScalar(value) {
573
663
  if (typeof value === "string")
574
664
  return value;
@@ -580,6 +670,12 @@ function plainScalar(value) {
580
670
  return value.toString();
581
671
  return String(value);
582
672
  }
673
+ function plainScalarRaw(value) {
674
+ if (isObject(value) || Array.isArray(value)) {
675
+ return JSON.stringify(sortJsonValue(value));
676
+ }
677
+ return plainScalar(value);
678
+ }
583
679
  function quoteLogfmtValue(value) {
584
680
  if (value === "")
585
681
  return "";
@@ -645,6 +741,21 @@ function sanitizeForJson(value, stack = new WeakSet()) {
645
741
  function isObject(value) {
646
742
  return typeof value === "object" && value !== null && !Array.isArray(value);
647
743
  }
744
+ function sortedObjectKeys(obj) {
745
+ return Object.keys(obj).sort(jcsCompare);
746
+ }
747
+ function sortJsonValue(value) {
748
+ if (Array.isArray(value))
749
+ return value.map(sortJsonValue);
750
+ if (isObject(value)) {
751
+ const out = {};
752
+ for (const key of sortedObjectKeys(value)) {
753
+ out[key] = sortJsonValue(value[key]);
754
+ }
755
+ return out;
756
+ }
757
+ return value;
758
+ }
648
759
  function jcsCompare(a, b) {
649
760
  const ua = Array.from(a).flatMap((c) => {
650
761
  const cp = c.codePointAt(0);
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Agent-First Data (AFDATA) — suffix-driven output formatting and protocol templates.
3
3
  */
4
- export { buildJsonOk, buildJsonError, buildJson, RedactionPolicy, type RedactionOptions, outputJson, outputJsonWith, outputJsonWithOptions, outputYaml, outputYamlWithOptions, outputPlain, outputPlainWithOptions, internalRedactSecrets, internalRedactSecretsWithOptions, redactedValue, redactedValueWith, redactedValueWithOptions, parseSize, } from "./format.js";
4
+ export { buildJsonOk, buildJsonError, buildJson, RedactionPolicy, type RedactionOptions, OutputStyle, type OutputOptions, outputJson, outputJsonWith, outputJsonWithOptions, outputYaml, outputYamlWithOptions, outputPlain, outputPlainWithOptions, internalRedactSecrets, internalRedactSecretsWithOptions, redactedValue, redactedValueWith, redactedValueWithOptions, parseSize, } from "./format.js";
5
5
  export { log, span, initJson, initPlain, initYaml } from "./afdata_logging.js";
6
- export { type OutputFormat, cliParseOutput, cliParseLogFilters, cliOutput, buildCliError } from "./cli.js";
6
+ export { type OutputFormat, cliParseOutput, cliParseLogFilters, cliOutput, cliOutputWithOptions, buildCliError, } from "./cli.js";
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Agent-First Data (AFDATA) — suffix-driven output formatting and protocol templates.
3
3
  */
4
- export { buildJsonOk, buildJsonError, buildJson, RedactionPolicy, outputJson, outputJsonWith, outputJsonWithOptions, outputYaml, outputYamlWithOptions, outputPlain, outputPlainWithOptions, internalRedactSecrets, internalRedactSecretsWithOptions, redactedValue, redactedValueWith, redactedValueWithOptions, parseSize, } from "./format.js";
4
+ export { buildJsonOk, buildJsonError, buildJson, RedactionPolicy, OutputStyle, outputJson, outputJsonWith, outputJsonWithOptions, outputYaml, outputYamlWithOptions, outputPlain, outputPlainWithOptions, internalRedactSecrets, internalRedactSecretsWithOptions, redactedValue, redactedValueWith, redactedValueWithOptions, parseSize, } from "./format.js";
5
5
  export { log, span, initJson, initPlain, initYaml } from "./afdata_logging.js";
6
- export { cliParseOutput, cliParseLogFilters, cliOutput, buildCliError } from "./cli.js";
6
+ export { cliParseOutput, cliParseLogFilters, cliOutput, cliOutputWithOptions, buildCliError, } from "./cli.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-first-data",
3
- "version": "0.8.1",
3
+ "version": "0.9.0",
4
4
  "description": "A naming convention that lets AI agents understand your data without being told what it means.",
5
5
  "license": "MIT",
6
6
  "repository": {