neozip-cli 0.90.0 → 0.95.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.
Files changed (74) hide show
  1. package/AGENTS.md +93 -0
  2. package/CHANGELOG.md +58 -1
  3. package/DOCUMENTATION.md +22 -30
  4. package/README.md +104 -42
  5. package/dist/src/account/account-state.js +95 -0
  6. package/dist/src/account/format-account-status.js +62 -0
  7. package/dist/src/account/identity-provision.js +79 -0
  8. package/dist/src/account/identity-wrap.js +106 -0
  9. package/dist/src/account/profile-crypto.js +85 -0
  10. package/dist/src/account/profile-store.js +129 -0
  11. package/dist/src/account/require-account.js +32 -0
  12. package/dist/src/account/types.js +3 -0
  13. package/dist/src/account/wallet-evm.js +46 -0
  14. package/dist/src/account/wallet-setup.js +33 -0
  15. package/dist/src/archive/crypto-self.js +117 -0
  16. package/dist/src/archive/identity-key.js +217 -0
  17. package/dist/src/archive/recipient-lookup.js +61 -0
  18. package/dist/src/cli/output.js +100 -0
  19. package/dist/src/cli/params.js +122 -0
  20. package/dist/src/cli/schema.js +186 -0
  21. package/dist/src/cli/validate.js +119 -0
  22. package/dist/src/commands/mintTimestampProof.js +26 -14
  23. package/dist/src/config/ConfigSetup.js +82 -423
  24. package/dist/src/connect/command.js +364 -0
  25. package/dist/src/connection/bootstrap.js +50 -0
  26. package/dist/src/connection/cli-guidance.js +101 -0
  27. package/dist/src/connection/cli-prefs.js +180 -0
  28. package/dist/src/connection/cli-settings.js +140 -0
  29. package/dist/src/connection/cli-types.js +14 -0
  30. package/dist/src/connection/coordinator.js +83 -0
  31. package/dist/src/connection/credentials.js +33 -0
  32. package/dist/src/connection/crypto.js +96 -0
  33. package/dist/src/connection/dump.js +117 -0
  34. package/dist/src/connection/funding.js +187 -0
  35. package/dist/src/connection/incomplete-setup.js +89 -0
  36. package/dist/src/connection/interactive.js +871 -0
  37. package/dist/src/connection/legacy-profile-reader.js +87 -0
  38. package/dist/src/connection/magic-link.js +142 -0
  39. package/dist/src/connection/migrate.js +115 -0
  40. package/dist/src/connection/onboarding.js +616 -0
  41. package/dist/src/connection/origin.js +69 -0
  42. package/dist/src/connection/phase.js +101 -0
  43. package/dist/src/connection/phone.js +26 -0
  44. package/dist/src/connection/promote-active.js +56 -0
  45. package/dist/src/connection/reset.js +56 -0
  46. package/dist/src/connection/status-report.js +52 -0
  47. package/dist/src/connection/store.js +406 -0
  48. package/dist/src/connection/token-auth.js +44 -0
  49. package/dist/src/connection/types.js +3 -0
  50. package/dist/src/connection/wallet-json-migration.js +155 -0
  51. package/dist/src/connection/wallet-login.js +65 -0
  52. package/dist/src/connection/wallet-setup.js +83 -0
  53. package/dist/src/constants/wallet-identity.js +14 -0
  54. package/dist/src/exit-codes.js +54 -10
  55. package/dist/src/neolist.js +93 -9
  56. package/dist/src/neounzip.js +217 -59
  57. package/dist/src/neozip/blockchain.js +18 -18
  58. package/dist/src/neozip/createZip.js +114 -91
  59. package/dist/src/neozip/upgradeZip.js +14 -11
  60. package/dist/src/neozip.js +252 -75
  61. package/dist/src/skills/command.js +256 -0
  62. package/dist/src/skills/locate.js +99 -0
  63. package/dist/src/util/mask.js +34 -0
  64. package/dist/src/util/token-service-fetch.js +26 -0
  65. package/env.example +18 -85
  66. package/package.json +89 -82
  67. package/skills/neozip-connect/SKILL.md +95 -0
  68. package/skills/neozip-create/SKILL.md +57 -0
  69. package/skills/neozip-extract/SKILL.md +58 -0
  70. package/skills/neozip-legacy/SKILL.md +48 -0
  71. package/skills/neozip-list/SKILL.md +56 -0
  72. package/skills/neozip-shared/SKILL.md +60 -0
  73. package/dist/src/commands/verifyEmail.js +0 -146
  74. package/dist/src/config/ConfigStore.js +0 -406
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.IdentityKeyVersionError = exports.IdentityKeyTamperError = void 0;
37
+ exports.unwrapX25519PrivateKey = unwrapX25519PrivateKey;
38
+ exports.hasConfiguredIdentityKey = hasConfiguredIdentityKey;
39
+ exports.resolveIdentityPrivateKeyHex = resolveIdentityPrivateKeyHex;
40
+ const crypto = __importStar(require("node:crypto"));
41
+ const ethers_1 = require("ethers");
42
+ const wallet_identity_1 = require("../constants/wallet-identity");
43
+ const crypto_self_1 = require("./crypto-self");
44
+ const recipient_lookup_1 = require("./recipient-lookup");
45
+ class IdentityKeyTamperError extends Error {
46
+ constructor(message) {
47
+ super(message);
48
+ this.name = "IdentityKeyTamperError";
49
+ }
50
+ }
51
+ exports.IdentityKeyTamperError = IdentityKeyTamperError;
52
+ class IdentityKeyVersionError extends Error {
53
+ constructor(message) {
54
+ super(message);
55
+ this.name = "IdentityKeyVersionError";
56
+ }
57
+ }
58
+ exports.IdentityKeyVersionError = IdentityKeyVersionError;
59
+ function buildCanonicalAad(params) {
60
+ const lowerAddr = params.evmAddress.toLowerCase();
61
+ const addrBytes = Buffer.from(lowerAddr, "ascii");
62
+ if (params.x25519SpkiDer.length !== 44) {
63
+ throw new Error(`Unexpected SPKI DER length ${params.x25519SpkiDer.length}, expected 44 bytes`);
64
+ }
65
+ return Buffer.concat([
66
+ addrBytes,
67
+ Buffer.from([wallet_identity_1.WRAP_FORMAT_VERSION]),
68
+ params.x25519SpkiDer,
69
+ ]);
70
+ }
71
+ function deriveKek(rawEoaPrivBytes, saltB64) {
72
+ if (rawEoaPrivBytes.length !== 32) {
73
+ throw new Error("EOA private key must be 32 bytes");
74
+ }
75
+ const salt = Buffer.from(saltB64, "base64");
76
+ if (salt.length !== wallet_identity_1.WRAP_KDF_SALT_LEN) {
77
+ throw new Error(`Wrap KDF salt must be ${wallet_identity_1.WRAP_KDF_SALT_LEN} bytes`);
78
+ }
79
+ const okm = crypto.hkdfSync("sha256", rawEoaPrivBytes, salt, wallet_identity_1.WRAP_KDF_INFO, 32);
80
+ return Buffer.from(okm);
81
+ }
82
+ function pkcs8FromRaw(rawPriv) {
83
+ const prefix = Buffer.from("302e020100300506032b656e04200420", "hex");
84
+ return Buffer.concat([prefix, rawPriv]);
85
+ }
86
+ function unwrapX25519PrivateKey(params) {
87
+ const { bundle } = params;
88
+ if (bundle.wrapFormatVersion !== wallet_identity_1.WRAP_FORMAT_VERSION) {
89
+ throw new IdentityKeyVersionError(`Unsupported wrap format version ${bundle.wrapFormatVersion}`);
90
+ }
91
+ if (bundle.wrapAead !== wallet_identity_1.WRAP_AEAD || bundle.wrapKdfInfo !== wallet_identity_1.WRAP_KDF_INFO) {
92
+ throw new IdentityKeyVersionError("Unsupported wrap format");
93
+ }
94
+ const expectedSpki = Buffer.from(params.expectedSpkiDerB64, "base64");
95
+ if (expectedSpki.length !== 44 ||
96
+ !expectedSpki.subarray(0, wallet_identity_1.X25519_SPKI_PREFIX.length).equals(wallet_identity_1.X25519_SPKI_PREFIX)) {
97
+ throw new IdentityKeyTamperError("Invalid server X25519 SPKI");
98
+ }
99
+ const recomputedAad = buildCanonicalAad({
100
+ evmAddress: params.expectedEvmAddress,
101
+ x25519SpkiDer: expectedSpki,
102
+ });
103
+ const advertisedAad = Buffer.from(bundle.wrapAadB64, "base64");
104
+ if (advertisedAad.length !== recomputedAad.length ||
105
+ !crypto.timingSafeEqual(advertisedAad, recomputedAad)) {
106
+ throw new IdentityKeyTamperError("Wrap AAD does not match local recomputation");
107
+ }
108
+ const kek = deriveKek(params.rawEoaPrivBytes, bundle.wrapKdfSaltB64);
109
+ const iv = Buffer.from(bundle.wrapIvB64, "base64");
110
+ if (iv.length !== wallet_identity_1.WRAP_IV_LEN) {
111
+ kek.fill(0);
112
+ throw new IdentityKeyVersionError(`Invalid wrap IV length ${iv.length}`);
113
+ }
114
+ const wrapped = Buffer.from(bundle.wrappedPrivateKeyB64, "base64");
115
+ const ct = wrapped.subarray(0, wrapped.length - 16);
116
+ const tag = wrapped.subarray(wrapped.length - 16);
117
+ try {
118
+ const decipher = crypto.createDecipheriv("aes-256-gcm", kek, iv);
119
+ decipher.setAAD(recomputedAad);
120
+ decipher.setAuthTag(tag);
121
+ const pt = Buffer.concat([decipher.update(ct), decipher.final()]);
122
+ if (pt.length !== 32) {
123
+ pt.fill(0);
124
+ throw new IdentityKeyTamperError("Unwrapped key length is not 32 bytes");
125
+ }
126
+ return pt;
127
+ }
128
+ finally {
129
+ kek.fill(0);
130
+ }
131
+ }
132
+ async function fetchJson(url, init) {
133
+ const response = await fetch(url, init);
134
+ const ct = response.headers.get("content-type") || "";
135
+ if (!ct.includes("json")) {
136
+ return { ok: response.ok, status: response.status, data: null };
137
+ }
138
+ try {
139
+ return {
140
+ ok: response.ok,
141
+ status: response.status,
142
+ data: (await response.json()),
143
+ };
144
+ }
145
+ catch {
146
+ return { ok: response.ok, status: response.status, data: null };
147
+ }
148
+ }
149
+ async function loadIdentityKeyFromWallet(config) {
150
+ const accessToken = config.tokenServiceAccessToken?.trim();
151
+ const walletKey = config.walletKey?.trim();
152
+ if (!accessToken || !walletKey) {
153
+ throw new Error("Wallet identity key requires NEOZIP_TOKEN_SERVICE_ACCESS_TOKEN and NEOZIP_WALLET_PASSKEY in MCP env.");
154
+ }
155
+ const self = await (0, crypto_self_1.fetchCryptoSelf)(config);
156
+ if (!self.ok) {
157
+ throw new Error(self.hint
158
+ ? `${self.error} (${self.hint})`
159
+ : self.error);
160
+ }
161
+ const walletId = self.data.walletId;
162
+ const expectedSpkiB64 = self.data.x25519PublicKey;
163
+ const baseUrl = (0, recipient_lookup_1.resolveTokenServiceBaseUrl)(config);
164
+ const auth = { Authorization: `Bearer ${accessToken}` };
165
+ const keyRes = await fetchJson(`${baseUrl}/identity/wallets/${walletId}/identity-key`, {
166
+ headers: auth,
167
+ });
168
+ if (!keyRes.ok || !keyRes.data?.success || !keyRes.data.identityKey) {
169
+ throw new Error(keyRes.data?.error ||
170
+ `Failed to fetch identity key (HTTP ${keyRes.status})`);
171
+ }
172
+ const bundle = keyRes.data.identityKey;
173
+ const wallet = new ethers_1.Wallet(walletKey);
174
+ const rawEoa = Buffer.from(wallet.privateKey.startsWith("0x")
175
+ ? wallet.privateKey.slice(2)
176
+ : wallet.privateKey, "hex");
177
+ const expectedAddr = bundle.evmAddress || wallet.address;
178
+ let x25519Private = null;
179
+ try {
180
+ x25519Private = unwrapX25519PrivateKey({
181
+ rawEoaPrivBytes: rawEoa,
182
+ bundle,
183
+ expectedEvmAddress: expectedAddr,
184
+ expectedSpkiDerB64: expectedSpkiB64,
185
+ });
186
+ const hex = x25519Private.toString("hex");
187
+ return hex;
188
+ }
189
+ finally {
190
+ rawEoa.fill(0);
191
+ if (x25519Private)
192
+ x25519Private.fill(0);
193
+ }
194
+ }
195
+ function hasConfiguredIdentityKey(config) {
196
+ return Boolean(config.identityPrivateKeyHex?.trim() ||
197
+ (config.tokenServiceAccessToken?.trim() && config.walletKey?.trim()));
198
+ }
199
+ /**
200
+ * Resolve X25519 private key hex for recipient-encrypted archives.
201
+ * Never pass through MCP tool arguments — env/config only.
202
+ */
203
+ async function resolveIdentityPrivateKeyHex(config) {
204
+ const envHex = config.identityPrivateKeyHex?.trim();
205
+ if (envHex) {
206
+ const clean = envHex.startsWith("0x") ? envHex.slice(2) : envHex;
207
+ if (!/^[0-9a-fA-F]{64}$/.test(clean)) {
208
+ throw new Error("NEOZIP_IDENTITY_PRIVATE_KEY_HEX must be 64 hex characters (32-byte X25519 key)");
209
+ }
210
+ return clean.toLowerCase();
211
+ }
212
+ if (config.tokenServiceAccessToken && config.walletKey) {
213
+ return loadIdentityKeyFromWallet(config);
214
+ }
215
+ return null;
216
+ }
217
+ //# sourceMappingURL=identity-key.js.map
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.spkiBase64ToRawHex = spkiBase64ToRawHex;
4
+ exports.resolveTokenServiceBaseUrl = resolveTokenServiceBaseUrl;
5
+ exports.lookupRecipientByEmail = lookupRecipientByEmail;
6
+ exports.resolveRecipientsFromEmails = resolveRecipientsFromEmails;
7
+ const token_service_1 = require("neozip-blockchain/token-service");
8
+ const wallet_identity_1 = require("../constants/wallet-identity");
9
+ function spkiBase64ToRawHex(spkiBase64) {
10
+ const spkiDer = Buffer.from(spkiBase64, "base64");
11
+ if (spkiDer.length !== 44) {
12
+ throw new Error(`Unexpected SPKI DER length ${spkiDer.length}, expected 44 bytes for X25519`);
13
+ }
14
+ return spkiDer.subarray(12).toString("hex");
15
+ }
16
+ function resolveTokenServiceBaseUrl(config, serverUrl) {
17
+ return (0, token_service_1.getTokenServiceUrl)({
18
+ serverUrl: serverUrl || config.tokenServiceUrl || undefined,
19
+ }).replace(/\/+$/, "");
20
+ }
21
+ async function lookupRecipientByEmail(email, config, options) {
22
+ const trimmed = email.trim().toLowerCase();
23
+ if (!trimmed.includes("@")) {
24
+ throw new Error(`Invalid recipient email: ${email}`);
25
+ }
26
+ const baseUrl = resolveTokenServiceBaseUrl(config, options?.serverUrl);
27
+ const url = `${baseUrl}/crypto/public?email=${encodeURIComponent(trimmed)}`;
28
+ const response = await fetch(url, { method: "GET" });
29
+ const data = (await response.json());
30
+ if (!response.ok || !data.success || !data.crypto?.x25519PublicKey) {
31
+ throw new Error(data.error ||
32
+ `No public key found for ${trimmed} (HTTP ${response.status})`);
33
+ }
34
+ const publicKeyHex = spkiBase64ToRawHex(data.crypto.x25519PublicKey);
35
+ return {
36
+ identity: {
37
+ identity: trimmed,
38
+ identityType: wallet_identity_1.TOKEN_SERVICE_RECIPIENT_IDENTITY_TYPE,
39
+ address: data.crypto.evmAddress || "",
40
+ publicKeyHex,
41
+ keyFormat: "x25519",
42
+ },
43
+ evmAddress: data.crypto.evmAddress || "",
44
+ recipientSuites: data.crypto.recipientSuites,
45
+ cryptoProvisionedAt: data.crypto.cryptoProvisionedAt,
46
+ };
47
+ }
48
+ async function resolveRecipientsFromEmails(emails, config, options) {
49
+ const seen = new Set();
50
+ const recipients = [];
51
+ for (const email of emails) {
52
+ const normalized = email.trim().toLowerCase();
53
+ if (seen.has(normalized))
54
+ continue;
55
+ seen.add(normalized);
56
+ const { identity } = await lookupRecipientByEmail(normalized, config, options);
57
+ recipients.push(identity);
58
+ }
59
+ return recipients;
60
+ }
61
+ //# sourceMappingURL=recipient-lookup.js.map
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ /**
3
+ * Shared output layer for agent-friendly machine-readable output.
4
+ *
5
+ * Design rules (see dev_doc / AGENTS.md):
6
+ * - Human text is the default. JSON is opt-in via `--format json` (or, on
7
+ * neolist, the legacy `-j`/`--json` flag).
8
+ * - Structured results and structured errors are written to STDOUT as a single
9
+ * JSON object so a caller can parse stdout directly.
10
+ * - Human hints, progress, and decorative logs go to STDERR (or are suppressed)
11
+ * so they never corrupt JSON on stdout.
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.setOutputFormat = setOutputFormat;
15
+ exports.getOutputFormat = getOutputFormat;
16
+ exports.isJsonOutput = isJsonOutput;
17
+ exports.detectOutputFormat = detectOutputFormat;
18
+ exports.stripFormatFlag = stripFormatFlag;
19
+ exports.emitResult = emitResult;
20
+ exports.emitError = emitError;
21
+ let currentFormat = 'text';
22
+ /** Set the process-wide output format (call once, early, from each binary). */
23
+ function setOutputFormat(format) {
24
+ currentFormat = format;
25
+ }
26
+ /** Get the current process-wide output format. */
27
+ function getOutputFormat() {
28
+ return currentFormat;
29
+ }
30
+ /** Convenience predicate: are we emitting machine-readable JSON? */
31
+ function isJsonOutput() {
32
+ return currentFormat === 'json';
33
+ }
34
+ /**
35
+ * Detect the desired output format from raw argv.
36
+ *
37
+ * Recognizes `--format json|text` and `--format=json|text`. The bare `--json`
38
+ * flag is intentionally NOT treated as an output switch here because on neozip /
39
+ * neounzip `--json` carries an input payload value. neolist handles its own
40
+ * legacy `--json`/`-j` output toggle and maps it to setOutputFormat('json').
41
+ */
42
+ function detectOutputFormat(argv) {
43
+ for (let i = 0; i < argv.length; i++) {
44
+ const arg = argv[i];
45
+ if (arg === '--format') {
46
+ const value = argv[i + 1];
47
+ if (value === 'json')
48
+ return 'json';
49
+ if (value === 'text')
50
+ return 'text';
51
+ }
52
+ else if (arg.startsWith('--format=')) {
53
+ const value = arg.slice('--format='.length);
54
+ if (value === 'json')
55
+ return 'json';
56
+ if (value === 'text')
57
+ return 'text';
58
+ }
59
+ }
60
+ return 'text';
61
+ }
62
+ /**
63
+ * Remove `--format <value>` / `--format=<value>` tokens from argv so the
64
+ * existing per-binary parsers don't have to know about them.
65
+ */
66
+ function stripFormatFlag(argv) {
67
+ const result = [];
68
+ for (let i = 0; i < argv.length; i++) {
69
+ const arg = argv[i];
70
+ if (arg === '--format') {
71
+ // Skip the flag and its value.
72
+ i++;
73
+ continue;
74
+ }
75
+ if (arg.startsWith('--format=')) {
76
+ continue;
77
+ }
78
+ result.push(arg);
79
+ }
80
+ return result;
81
+ }
82
+ /**
83
+ * Emit a successful structured result as pretty JSON on stdout.
84
+ *
85
+ * Writes directly to process.stdout so it bypasses any `quiet` handling used to
86
+ * silence decorative human logs in JSON mode.
87
+ */
88
+ function emitResult(result) {
89
+ const payload = { ok: true, ...result };
90
+ process.stdout.write(JSON.stringify(payload, null, 2) + '\n');
91
+ }
92
+ /**
93
+ * Emit a structured error as pretty JSON on stdout. Used by the exit-code
94
+ * helpers when running in JSON mode.
95
+ */
96
+ function emitError(error) {
97
+ const payload = { ok: false, error };
98
+ process.stdout.write(JSON.stringify(payload, null, 2) + '\n');
99
+ }
100
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ /**
3
+ * Agent input parsing: `--params` and `--json`.
4
+ *
5
+ * - `--params '<JSON>'` control/options object (the "how": level, encrypt,
6
+ * blockchain, network, output dir, overwrite policy, ...). Maps onto the
7
+ * binary's options object.
8
+ * - `--json '<JSON>'` payload object (the "what": archive + inputs/targets,
9
+ * e.g. {archive, files, include, exclude, entries, exdir}). Maps onto
10
+ * positional arguments.
11
+ *
12
+ * Either flag accepts `-` as its value to read the JSON document from stdin.
13
+ *
14
+ * Precedence: values from `--params`/`--json` seed the option/positional state
15
+ * BEFORE the normal flag loop runs, so explicit CLI flags always win.
16
+ */
17
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ var desc = Object.getOwnPropertyDescriptor(m, k);
20
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
21
+ desc = { enumerable: true, get: function() { return m[k]; } };
22
+ }
23
+ Object.defineProperty(o, k2, desc);
24
+ }) : (function(o, m, k, k2) {
25
+ if (k2 === undefined) k2 = k;
26
+ o[k2] = m[k];
27
+ }));
28
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
29
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
30
+ }) : function(o, v) {
31
+ o["default"] = v;
32
+ });
33
+ var __importStar = (this && this.__importStar) || (function () {
34
+ var ownKeys = function(o) {
35
+ ownKeys = Object.getOwnPropertyNames || function (o) {
36
+ var ar = [];
37
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
38
+ return ar;
39
+ };
40
+ return ownKeys(o);
41
+ };
42
+ return function (mod) {
43
+ if (mod && mod.__esModule) return mod;
44
+ var result = {};
45
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
46
+ __setModuleDefault(result, mod);
47
+ return result;
48
+ };
49
+ })();
50
+ Object.defineProperty(exports, "__esModule", { value: true });
51
+ exports.parseJsonObjectArg = parseJsonObjectArg;
52
+ exports.extractAgentInput = extractAgentInput;
53
+ const fs = __importStar(require("fs"));
54
+ const validate_1 = require("./validate");
55
+ /**
56
+ * Parse a JSON object from a flag value. A value of `-` reads from stdin.
57
+ * Throws ValidationError on invalid input or non-object JSON.
58
+ */
59
+ function parseJsonObjectArg(raw, flag) {
60
+ return readJsonValue(raw, flag);
61
+ }
62
+ function readJsonValue(raw, flag) {
63
+ let text = raw;
64
+ if (raw === '-') {
65
+ try {
66
+ text = fs.readFileSync(0, 'utf8');
67
+ }
68
+ catch (err) {
69
+ throw new validate_1.ValidationError(`Failed to read ${flag} from stdin: ${err instanceof Error ? err.message : String(err)}`);
70
+ }
71
+ }
72
+ let parsed;
73
+ try {
74
+ parsed = JSON.parse(text);
75
+ }
76
+ catch (err) {
77
+ throw new validate_1.ValidationError(`Invalid ${flag} JSON: ${err instanceof Error ? err.message : String(err)}`);
78
+ }
79
+ if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
80
+ throw new validate_1.ValidationError(`${flag} must be a JSON object`);
81
+ }
82
+ return parsed;
83
+ }
84
+ /**
85
+ * Extract `--params` / `--json` from argv. Returns the parsed objects plus argv
86
+ * with those tokens removed so the existing per-binary parser can run unchanged.
87
+ *
88
+ * Supports `--flag value`, `--flag=value`. A `-` value reads from stdin.
89
+ */
90
+ function extractAgentInput(argv) {
91
+ const out = { argv: [] };
92
+ for (let i = 0; i < argv.length; i++) {
93
+ const arg = argv[i];
94
+ if (arg === '--params' || arg === '--json') {
95
+ const value = argv[i + 1];
96
+ if (value === undefined) {
97
+ throw new validate_1.ValidationError(`${arg} requires a JSON value (or '-' for stdin)`);
98
+ }
99
+ i++;
100
+ const obj = readJsonValue(value, arg);
101
+ if (arg === '--params')
102
+ out.params = obj;
103
+ else
104
+ out.payload = obj;
105
+ continue;
106
+ }
107
+ if (arg.startsWith('--params=') || arg.startsWith('--json=')) {
108
+ const eq = arg.indexOf('=');
109
+ const flag = arg.slice(0, eq);
110
+ const value = arg.slice(eq + 1);
111
+ const obj = readJsonValue(value, flag);
112
+ if (flag === '--params')
113
+ out.params = obj;
114
+ else
115
+ out.payload = obj;
116
+ continue;
117
+ }
118
+ out.argv.push(arg);
119
+ }
120
+ return out;
121
+ }
122
+ //# sourceMappingURL=params.js.map