tokenfold 0.4.1 → 0.5.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 +25 -15
- package/dist/index.d.ts +96 -95
- package/dist/index.js +70 -86
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,38 +1,48 @@
|
|
|
1
|
-
# tokenfold for Node.js
|
|
1
|
+
# tokenfold for Node.js
|
|
2
2
|
|
|
3
|
-
Zero-runtime-dependency TypeScript bindings for the
|
|
3
|
+
Zero-runtime-dependency TypeScript bindings for the Tokenfold Rust CLI.
|
|
4
4
|
|
|
5
5
|
```sh
|
|
6
6
|
npm install tokenfold
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
```ts
|
|
10
|
-
import { compress } from "tokenfold";
|
|
10
|
+
import { compress, decode, inspect } from "tokenfold";
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const receipt = await inspect(input, { format: "json", preset: "balanced" });
|
|
13
|
+
const { payload, report, text } = await compress(input, {
|
|
13
14
|
format: "json",
|
|
14
|
-
|
|
15
|
+
preset: "balanced",
|
|
15
16
|
});
|
|
16
17
|
```
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
Payloads are `Uint8Array`; the `text` convenience getter decodes UTF-8 strictly.
|
|
20
|
+
`inspect` returns only the side-effect-free receipt.
|
|
21
|
+
|
|
22
|
+
Recoverable pruning is explicit and generic-JSON-only:
|
|
21
23
|
|
|
22
24
|
```ts
|
|
23
25
|
import { compress, retrieve } from "tokenfold";
|
|
24
26
|
|
|
25
|
-
const
|
|
27
|
+
const result = await compress(feed, {
|
|
26
28
|
format: "json",
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
targetTokens: 2_000,
|
|
30
|
+
pruning: {
|
|
31
|
+
keepRatio: 0.35,
|
|
32
|
+
preservePaths: ["meta"],
|
|
33
|
+
retrievalStore: ".tokenfold/retrieve",
|
|
34
|
+
},
|
|
30
35
|
});
|
|
31
|
-
const
|
|
36
|
+
const marker = JSON.parse(result.text).items.find((item) => item.$tf_ref);
|
|
37
|
+
const original = await retrieve(marker, { retrievalStore: ".tokenfold/retrieve" });
|
|
32
38
|
```
|
|
33
39
|
|
|
34
|
-
|
|
35
|
-
|
|
40
|
+
Explicit TOON output is verified before emission and restored with `decode`:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
const encoded = await compress(input, { format: "json", encoding: "toon" });
|
|
44
|
+
const jsonBytes = await decode(encoded.payload, { from: "toon" });
|
|
45
|
+
```
|
|
36
46
|
|
|
37
47
|
Requires Node.js 22 or newer. The matching native CLI is installed through an
|
|
38
48
|
optional platform package; set `TOKENFOLD_BINARY_PATH` to use a custom binary.
|
package/dist/index.d.ts
CHANGED
|
@@ -3,35 +3,23 @@ import { TokenFoldProcessError } from "./errors.js";
|
|
|
3
3
|
import { run, type Input, type ProcessResult, type RunOptions } from "./process.js";
|
|
4
4
|
export { binaryPath, run, TokenFoldProcessError };
|
|
5
5
|
export type { Input, ProcessResult, RunOptions };
|
|
6
|
-
export type
|
|
7
|
-
export type
|
|
8
|
-
|
|
9
|
-
export type
|
|
6
|
+
export type Preset = "conservative" | "balanced" | "aggressive";
|
|
7
|
+
export type OutputEncoding = "json" | "toon";
|
|
8
|
+
export type InputFormat = "auto" | "openai" | "anthropic" | "json" | "text" | "command" | "diff";
|
|
9
|
+
export type DecodeFormat = "auto" | "json" | "toon" | "text";
|
|
10
|
+
export interface PruningPolicy {
|
|
11
|
+
keepRatio?: number;
|
|
12
|
+
preservePaths?: readonly string[];
|
|
13
|
+
retrievalStore?: string;
|
|
14
|
+
retrievalNamespace?: string;
|
|
15
|
+
}
|
|
10
16
|
export interface CompressionOptions {
|
|
11
|
-
format?:
|
|
12
|
-
|
|
17
|
+
format?: InputFormat;
|
|
18
|
+
preset?: Preset;
|
|
13
19
|
targetTokens?: number;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
storeOriginals?: boolean;
|
|
18
|
-
retrieveNamespace?: string;
|
|
19
|
-
/**
|
|
20
|
-
* Opt-in LOSSY JSON array-item pruning (`--lossy`): drops whole array items to hit a token
|
|
21
|
-
* budget instead of only restructuring them. Generic JSON only — on any other format the run
|
|
22
|
-
* is a no-op and `json_prune` comes back as `status: "skipped"` with
|
|
23
|
-
* `skipped_reason: "not_applicable_to_format"`, persisting nothing. Dropped items are replaced
|
|
24
|
-
* by `$tf_ref` markers and stay recoverable via {@link retrieve}; pruning needs a durable
|
|
25
|
-
* filesystem retrieval store, so pass `configPath` when you want one other than the default.
|
|
26
|
-
*/
|
|
27
|
-
lossy?: LossyPath;
|
|
28
|
-
/**
|
|
29
|
-
* `--lossy-ratio`: a best-effort selection hint (0.0..=1.0), not an enforced budget — the
|
|
30
|
-
* achieved ratio differs by design. Use `targetTokens` for a real ceiling.
|
|
31
|
-
*/
|
|
32
|
-
lossyRatio?: number;
|
|
33
|
-
/** `--lossy-preserve`: dot-separated paths (e.g. `data.results`) whose arrays are never pruned. */
|
|
34
|
-
lossyPreserve?: readonly string[];
|
|
20
|
+
requireTarget?: boolean;
|
|
21
|
+
encoding?: OutputEncoding;
|
|
22
|
+
pruning?: PruningPolicy;
|
|
35
23
|
configPath?: string;
|
|
36
24
|
signal?: AbortSignal;
|
|
37
25
|
}
|
|
@@ -40,19 +28,6 @@ export interface EstimatorInfo {
|
|
|
40
28
|
model: string | null;
|
|
41
29
|
is_exact: boolean;
|
|
42
30
|
}
|
|
43
|
-
export interface BudgetReport {
|
|
44
|
-
target_tokens: number | null;
|
|
45
|
-
protected_floor: number;
|
|
46
|
-
achieved_tokens: number;
|
|
47
|
-
}
|
|
48
|
-
export interface QualityReport {
|
|
49
|
-
eval_profile_id: string;
|
|
50
|
-
task_scope: string;
|
|
51
|
-
validated_ratio_band: string | null;
|
|
52
|
-
quality_retention: number;
|
|
53
|
-
contrastive_failure_rate: number;
|
|
54
|
-
gate_passed: boolean;
|
|
55
|
-
}
|
|
56
31
|
export interface Warning {
|
|
57
32
|
code: string;
|
|
58
33
|
severity: "info" | "warn" | "critical";
|
|
@@ -71,12 +46,39 @@ export interface TransformReport {
|
|
|
71
46
|
skipped_reason: string | null;
|
|
72
47
|
warnings: readonly Warning[];
|
|
73
48
|
}
|
|
74
|
-
export interface
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
49
|
+
export interface BudgetReport {
|
|
50
|
+
status: "not_requested" | "met" | "best_effort" | "unreachable";
|
|
51
|
+
target_tokens: number | null;
|
|
52
|
+
protected_floor: number;
|
|
53
|
+
achieved_tokens: number;
|
|
54
|
+
}
|
|
55
|
+
export interface EncodingReport {
|
|
56
|
+
codec: string;
|
|
57
|
+
version: string;
|
|
58
|
+
roundtrip_verified: boolean;
|
|
59
|
+
tokens_before: number;
|
|
60
|
+
tokens_after: number;
|
|
61
|
+
token_delta: number;
|
|
78
62
|
warnings: readonly Warning[];
|
|
79
63
|
}
|
|
64
|
+
export interface PruningReport {
|
|
65
|
+
requested: boolean;
|
|
66
|
+
applied: boolean;
|
|
67
|
+
preview: boolean;
|
|
68
|
+
candidate_items: number;
|
|
69
|
+
retained_items: number;
|
|
70
|
+
pruned_items: number;
|
|
71
|
+
evidence_refs: number;
|
|
72
|
+
preserve_paths: readonly string[];
|
|
73
|
+
}
|
|
74
|
+
export interface QualityReport {
|
|
75
|
+
eval_profile_id: string;
|
|
76
|
+
task_scope: string;
|
|
77
|
+
validated_ratio_band: string | null;
|
|
78
|
+
quality_retention: number | null;
|
|
79
|
+
contrastive_failure_rate: number | null;
|
|
80
|
+
gate_passed: boolean;
|
|
81
|
+
}
|
|
80
82
|
export interface RetrievalReport {
|
|
81
83
|
store_namespace: string;
|
|
82
84
|
hash_algorithm: string;
|
|
@@ -85,82 +87,81 @@ export interface RetrievalReport {
|
|
|
85
87
|
persisted_original_bytes: number;
|
|
86
88
|
skipped_original_bytes: number;
|
|
87
89
|
}
|
|
88
|
-
export interface
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
child_exit_code: number | null;
|
|
101
|
-
duration_ms: number;
|
|
102
|
-
raw_output_bytes: number;
|
|
103
|
-
stdout_bytes: number;
|
|
104
|
-
stderr_bytes: number;
|
|
105
|
-
stderr_mode: string;
|
|
106
|
-
stderr_truncated: boolean;
|
|
107
|
-
compressed_output_bytes: number;
|
|
108
|
-
filter_pack_id: string | null;
|
|
109
|
-
filter_version: string | null;
|
|
110
|
-
never_worse_applied: boolean;
|
|
90
|
+
export interface PipelineStageReport {
|
|
91
|
+
id: string;
|
|
92
|
+
version: string | null;
|
|
93
|
+
input_bytes: number | null;
|
|
94
|
+
output_bytes: number | null;
|
|
95
|
+
saved_bytes: number | null;
|
|
96
|
+
input_tokens: number | null;
|
|
97
|
+
output_tokens: number | null;
|
|
98
|
+
saved_tokens: number | null;
|
|
99
|
+
estimator: EstimatorInfo | null;
|
|
100
|
+
status: string;
|
|
101
|
+
duration_ms: number | null;
|
|
111
102
|
bypass_reason: string | null;
|
|
103
|
+
provenance: string;
|
|
104
|
+
recoverability: string;
|
|
105
|
+
evidence_ref: string | null;
|
|
112
106
|
}
|
|
113
|
-
export interface
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
107
|
+
export interface PipelineReport {
|
|
108
|
+
raw_input_bytes: number | null;
|
|
109
|
+
raw_input_tokens: number | null;
|
|
110
|
+
final_output_bytes: number;
|
|
111
|
+
final_output_tokens: number;
|
|
112
|
+
total_saved_tokens: number | null;
|
|
113
|
+
raw_capture: string;
|
|
114
|
+
upstream_recoverability: string;
|
|
115
|
+
stages: readonly PipelineStageReport[];
|
|
118
116
|
}
|
|
119
|
-
export interface
|
|
117
|
+
export interface CompressionReceipt {
|
|
120
118
|
schema_version: string;
|
|
119
|
+
status: "compressed" | "passthrough";
|
|
121
120
|
original_tokens: number;
|
|
122
121
|
compressed_tokens: number;
|
|
123
122
|
saved_tokens: number;
|
|
124
123
|
savings_ratio: number;
|
|
125
124
|
savings_pct: number;
|
|
126
125
|
estimator: EstimatorInfo;
|
|
127
|
-
|
|
128
|
-
mode: string;
|
|
126
|
+
preset: Preset;
|
|
129
127
|
format: string;
|
|
128
|
+
output_encoding: string;
|
|
130
129
|
task_scope: string;
|
|
131
130
|
request_id: string | null;
|
|
131
|
+
pipeline: PipelineReport | null;
|
|
132
132
|
quality: QualityReport | null;
|
|
133
133
|
budget: BudgetReport | null;
|
|
134
|
-
|
|
134
|
+
encoding: EncodingReport | null;
|
|
135
|
+
pruning: PruningReport | null;
|
|
135
136
|
retrieval: RetrievalReport | null;
|
|
136
|
-
output_savings: OutputSavingsReport | null;
|
|
137
|
-
bypass: BypassReport | null;
|
|
138
|
-
command: CommandReport | null;
|
|
139
|
-
ledger: LedgerReport | null;
|
|
140
137
|
transforms: readonly TransformReport[];
|
|
141
138
|
warnings: readonly Warning[];
|
|
139
|
+
cache: unknown;
|
|
140
|
+
output_savings: unknown;
|
|
141
|
+
bypass: unknown;
|
|
142
|
+
command: unknown;
|
|
143
|
+
ledger: unknown;
|
|
142
144
|
}
|
|
145
|
+
export type CompressionReport = CompressionReceipt;
|
|
143
146
|
export interface CompressionResult {
|
|
144
147
|
payload: Uint8Array;
|
|
145
|
-
|
|
148
|
+
readonly text: string;
|
|
149
|
+
report: CompressionReceipt;
|
|
150
|
+
}
|
|
151
|
+
export declare class BudgetUnmetError extends Error {
|
|
152
|
+
readonly receipt: CompressionReceipt;
|
|
153
|
+
constructor(receipt: CompressionReceipt);
|
|
146
154
|
}
|
|
147
155
|
export declare function compress(input: Input, options?: CompressionOptions): Promise<CompressionResult>;
|
|
148
|
-
export declare function inspect(input: Input, options?: CompressionOptions): Promise<
|
|
156
|
+
export declare function inspect(input: Input, options?: CompressionOptions): Promise<CompressionReceipt>;
|
|
157
|
+
export declare function decode(input: Input, options?: {
|
|
158
|
+
from?: DecodeFormat;
|
|
159
|
+
signal?: AbortSignal;
|
|
160
|
+
}): Promise<Uint8Array>;
|
|
149
161
|
export interface RetrieveOptions {
|
|
150
|
-
|
|
162
|
+
retrievalStore?: string;
|
|
151
163
|
namespace?: string;
|
|
152
164
|
configPath?: string;
|
|
153
165
|
signal?: AbortSignal;
|
|
154
166
|
}
|
|
155
|
-
|
|
156
|
-
* Restores the original bytes of something a lossy run dropped, or a `storeOriginals` run saved,
|
|
157
|
-
* mirroring `tokenfold retrieve`. `reference` is either a raw hex SHA-256 hash — a compressed
|
|
158
|
-
* payload's `$tf_ref.hash` — or a `[tokenfold:retrieve hash=... namespace=...]` text marker,
|
|
159
|
-
* whose embedded namespace is used when `options.namespace` is omitted. A CompressionReport
|
|
160
|
-
* path is NOT a valid reference: the current report schema carries no per-entry hash, and the
|
|
161
|
-
* CLI rejects it rather than guessing.
|
|
162
|
-
*
|
|
163
|
-
* Throws `TokenFoldProcessError` (`code: "tokenfold_exit"`) when the hash is unknown, its TTL
|
|
164
|
-
* has elapsed, or the reference is malformed — the CLI reports all of those as a non-zero exit.
|
|
165
|
-
*/
|
|
166
|
-
export declare function retrieve(reference: string, options?: RetrieveOptions): Promise<Uint8Array>;
|
|
167
|
+
export declare function retrieve(reference: string | Record<string, unknown>, options?: RetrieveOptions): Promise<Uint8Array>;
|
package/dist/index.js
CHANGED
|
@@ -2,114 +2,98 @@ import { binaryPath } from "./binary.js";
|
|
|
2
2
|
import { TokenFoldProcessError } from "./errors.js";
|
|
3
3
|
import { run } from "./process.js";
|
|
4
4
|
export { binaryPath, run, TokenFoldProcessError };
|
|
5
|
+
export class BudgetUnmetError extends Error {
|
|
6
|
+
receipt;
|
|
7
|
+
constructor(receipt) { super(`token budget unmet: achieved ${receipt.compressed_tokens} tokens`); this.name = "BudgetUnmetError"; this.receipt = receipt; }
|
|
8
|
+
}
|
|
5
9
|
function argumentsFor(command, options) {
|
|
6
|
-
|
|
7
|
-
// `compress --dry-run`, which routes to the same code path and, exactly like `inspect --json`,
|
|
8
|
-
// writes the report to stdout and no payload. So a lossy inspect() becomes that instead.
|
|
9
|
-
const wantsLossy = options.lossy !== undefined ||
|
|
10
|
-
options.lossyRatio !== undefined ||
|
|
11
|
-
(options.lossyPreserve?.length ?? 0) > 0;
|
|
12
|
-
const previewLossy = command === "inspect" && wantsLossy;
|
|
13
|
-
const args = previewLossy ? ["compress", "--json", "--dry-run"] : [command, "--json"];
|
|
14
|
-
const compressing = command === "compress" || previewLossy;
|
|
10
|
+
const args = [command, "--receipt-format", "json"];
|
|
15
11
|
if (options.format)
|
|
16
12
|
args.push("--format", options.format);
|
|
17
|
-
if (options.
|
|
18
|
-
args.push("--
|
|
13
|
+
if (options.preset)
|
|
14
|
+
args.push("--preset", options.preset);
|
|
19
15
|
if (options.targetTokens !== undefined)
|
|
20
16
|
args.push("--target-tokens", String(options.targetTokens));
|
|
21
|
-
if (options.
|
|
22
|
-
args.push("--
|
|
23
|
-
if (options.
|
|
24
|
-
args.push("--
|
|
25
|
-
if (options.
|
|
26
|
-
args.push("--
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
// knob is worse than the CLI's own "the following required arguments were not provided".
|
|
36
|
-
if (options.lossy)
|
|
37
|
-
args.push("--lossy", options.lossy);
|
|
38
|
-
if (options.lossyRatio !== undefined)
|
|
39
|
-
args.push("--lossy-ratio", String(options.lossyRatio));
|
|
40
|
-
for (const path of options.lossyPreserve ?? [])
|
|
41
|
-
args.push("--lossy-preserve", path);
|
|
17
|
+
if (options.requireTarget)
|
|
18
|
+
args.push("--require-target");
|
|
19
|
+
if (options.encoding)
|
|
20
|
+
args.push("--encoding", options.encoding);
|
|
21
|
+
if (options.pruning) {
|
|
22
|
+
args.push("--prune");
|
|
23
|
+
if (options.pruning.keepRatio !== undefined)
|
|
24
|
+
args.push("--keep-ratio", String(options.pruning.keepRatio));
|
|
25
|
+
for (const path of options.pruning.preservePaths ?? [])
|
|
26
|
+
args.push("--preserve", path);
|
|
27
|
+
if (options.pruning.retrievalStore)
|
|
28
|
+
args.push("--retrieval-store", options.pruning.retrievalStore);
|
|
29
|
+
if (options.pruning.retrievalNamespace)
|
|
30
|
+
args.push("--retrieval-namespace", options.pruning.retrievalNamespace);
|
|
42
31
|
}
|
|
43
32
|
if (options.configPath)
|
|
44
33
|
args.push("--config", options.configPath);
|
|
45
34
|
return args;
|
|
46
35
|
}
|
|
47
|
-
function
|
|
36
|
+
function parseReceipt(bytes, result) {
|
|
37
|
+
const text = Buffer.from(bytes).toString("utf8");
|
|
38
|
+
const json = text.split("\ntokenfold:", 1)[0] ?? "";
|
|
48
39
|
try {
|
|
49
|
-
return JSON.parse(
|
|
40
|
+
return JSON.parse(json);
|
|
50
41
|
}
|
|
51
42
|
catch (cause) {
|
|
52
|
-
throw new TokenFoldProcessError("tokenfold returned an invalid JSON
|
|
53
|
-
code: "invalid_report",
|
|
54
|
-
exitCode: result.exitCode,
|
|
55
|
-
signal: result.signal,
|
|
56
|
-
stderr: result.stderr,
|
|
57
|
-
cause,
|
|
58
|
-
});
|
|
43
|
+
throw new TokenFoldProcessError("tokenfold returned an invalid JSON receipt", { code: "invalid_report", exitCode: result.exitCode, signal: result.signal, stderr: result.stderr, cause });
|
|
59
44
|
}
|
|
60
45
|
}
|
|
61
|
-
function
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
stderr: result.stderr,
|
|
69
|
-
});
|
|
46
|
+
function optionsFor(input, signal) {
|
|
47
|
+
const options = { env: { TOKENFOLD_ANALYTICS_ENABLED: "false" } };
|
|
48
|
+
if (input !== undefined)
|
|
49
|
+
options.stdin = input;
|
|
50
|
+
if (signal)
|
|
51
|
+
options.signal = signal;
|
|
52
|
+
return options;
|
|
70
53
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
stdin: input,
|
|
74
|
-
env: { TOKENFOLD_ANALYTICS_ENABLED: "false" },
|
|
75
|
-
};
|
|
76
|
-
if (options.signal)
|
|
77
|
-
runOptions.signal = options.signal;
|
|
78
|
-
const result = await run(argumentsFor(command, options), runOptions);
|
|
79
|
-
throwIfFailed(result);
|
|
80
|
-
const reportBytes = command === "compress" ? result.stderr : result.stdout;
|
|
81
|
-
return {
|
|
82
|
-
payload: command === "compress" ? result.stdout : Uint8Array.from(Buffer.from(input)),
|
|
83
|
-
report: parseReport(reportBytes, result),
|
|
84
|
-
};
|
|
54
|
+
function withText(payload, report) {
|
|
55
|
+
return { payload, report, get text() { return new TextDecoder("utf-8", { fatal: true }).decode(payload); } };
|
|
85
56
|
}
|
|
86
|
-
export function compress(input, options = {}) {
|
|
87
|
-
|
|
57
|
+
export async function compress(input, options = {}) {
|
|
58
|
+
const result = await run(argumentsFor("compress", options), optionsFor(input, options.signal));
|
|
59
|
+
if (result.exitCode !== 0 && result.exitCode !== 7)
|
|
60
|
+
throwProcess(result);
|
|
61
|
+
const receipt = parseReceipt(result.stderr, result);
|
|
62
|
+
if (result.exitCode === 7)
|
|
63
|
+
throw new BudgetUnmetError(receipt);
|
|
64
|
+
return withText(result.stdout, receipt);
|
|
88
65
|
}
|
|
89
|
-
export function inspect(input, options = {}) {
|
|
90
|
-
|
|
66
|
+
export async function inspect(input, options = {}) {
|
|
67
|
+
const result = await run(argumentsFor("inspect", options), optionsFor(input, options.signal));
|
|
68
|
+
if (result.exitCode !== 0 && result.exitCode !== 7)
|
|
69
|
+
throwProcess(result);
|
|
70
|
+
const receipt = parseReceipt(result.stdout, result);
|
|
71
|
+
if (result.exitCode === 7)
|
|
72
|
+
throw new BudgetUnmetError(receipt);
|
|
73
|
+
return receipt;
|
|
74
|
+
}
|
|
75
|
+
export async function decode(input, options = {}) {
|
|
76
|
+
const args = ["decode"];
|
|
77
|
+
if (options.from)
|
|
78
|
+
args.push("--from", options.from);
|
|
79
|
+
const result = await run(args, optionsFor(input, options.signal));
|
|
80
|
+
if (result.exitCode !== 0)
|
|
81
|
+
throwProcess(result);
|
|
82
|
+
return result.stdout;
|
|
91
83
|
}
|
|
92
|
-
/**
|
|
93
|
-
* Restores the original bytes of something a lossy run dropped, or a `storeOriginals` run saved,
|
|
94
|
-
* mirroring `tokenfold retrieve`. `reference` is either a raw hex SHA-256 hash — a compressed
|
|
95
|
-
* payload's `$tf_ref.hash` — or a `[tokenfold:retrieve hash=... namespace=...]` text marker,
|
|
96
|
-
* whose embedded namespace is used when `options.namespace` is omitted. A CompressionReport
|
|
97
|
-
* path is NOT a valid reference: the current report schema carries no per-entry hash, and the
|
|
98
|
-
* CLI rejects it rather than guessing.
|
|
99
|
-
*
|
|
100
|
-
* Throws `TokenFoldProcessError` (`code: "tokenfold_exit"`) when the hash is unknown, its TTL
|
|
101
|
-
* has elapsed, or the reference is malformed — the CLI reports all of those as a non-zero exit.
|
|
102
|
-
*/
|
|
103
84
|
export async function retrieve(reference, options = {}) {
|
|
104
|
-
const args = ["retrieve", reference];
|
|
85
|
+
const args = ["retrieve", typeof reference === "string" ? reference : JSON.stringify(reference)];
|
|
86
|
+
if (options.retrievalStore)
|
|
87
|
+
args.push("--retrieval-store", options.retrievalStore);
|
|
105
88
|
if (options.namespace)
|
|
106
|
-
args.push("--
|
|
89
|
+
args.push("--retrieval-namespace", options.namespace);
|
|
107
90
|
if (options.configPath)
|
|
108
91
|
args.push("--config", options.configPath);
|
|
109
|
-
const
|
|
110
|
-
if (
|
|
111
|
-
|
|
112
|
-
const result = await run(args, runOptions);
|
|
113
|
-
throwIfFailed(result);
|
|
92
|
+
const result = await run(args, optionsFor(undefined, options.signal));
|
|
93
|
+
if (result.exitCode !== 0)
|
|
94
|
+
throwProcess(result);
|
|
114
95
|
return result.stdout;
|
|
115
96
|
}
|
|
97
|
+
function throwProcess(result) {
|
|
98
|
+
throw new TokenFoldProcessError(`tokenfold exited with status ${result.exitCode ?? result.signal}`, { code: "tokenfold_exit", exitCode: result.exitCode, signal: result.signal, stderr: result.stderr });
|
|
99
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tokenfold",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Token-aware compression for LLM payloads, backed by the tokenfold Rust CLI.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -49,11 +49,11 @@
|
|
|
49
49
|
"prepack": "npm run build"
|
|
50
50
|
},
|
|
51
51
|
"optionalDependencies": {
|
|
52
|
-
"@tokenfold/cli-darwin-x64": "0.
|
|
53
|
-
"@tokenfold/cli-darwin-arm64": "0.
|
|
54
|
-
"@tokenfold/cli-linux-x64": "0.
|
|
55
|
-
"@tokenfold/cli-linux-arm64": "0.
|
|
56
|
-
"@tokenfold/cli-win32-x64": "0.
|
|
52
|
+
"@tokenfold/cli-darwin-x64": "0.5.0",
|
|
53
|
+
"@tokenfold/cli-darwin-arm64": "0.5.0",
|
|
54
|
+
"@tokenfold/cli-linux-x64": "0.5.0",
|
|
55
|
+
"@tokenfold/cli-linux-arm64": "0.5.0",
|
|
56
|
+
"@tokenfold/cli-win32-x64": "0.5.0"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@types/node": "^24.0.0",
|