@vultisig/cli 0.15.2 → 0.15.4
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/CHANGELOG.md +14 -0
- package/README.md +34 -6
- package/dist/index.js +203 -68
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @vultisig/cli
|
|
2
2
|
|
|
3
|
+
## 0.15.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#276](https://github.com/vultisig/vultisig-sdk/pull/276) [`59382c1`](https://github.com/vultisig/vultisig-sdk/commit/59382c1859512fbd362962ede5e92b100d3a5921) Thanks [@rcoderdev](https://github.com/rcoderdev)! - feat(cli): structured machine-readable errors for agent ask, pipe, and executor
|
|
8
|
+
- `agent ask --json` failures include stable `code` with existing `error` string
|
|
9
|
+
- NDJSON pipe `error` events and failed `tool_result` lines include `code`
|
|
10
|
+
- executor `ActionResult` failures carry `AgentErrorCode`; SSE errors accept optional backend `code`
|
|
11
|
+
- document error codes in CLI README
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [[`59382c1`](https://github.com/vultisig/vultisig-sdk/commit/59382c1859512fbd362962ede5e92b100d3a5921)]:
|
|
14
|
+
- @vultisig/sdk@0.15.4
|
|
15
|
+
- @vultisig/rujira@10.0.0
|
|
16
|
+
|
|
3
17
|
## 0.15.2
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -658,7 +658,7 @@ explorer:https://etherscan.io/tx/0x9f8e7d6c...
|
|
|
658
658
|
"session_id": "abc123-def456",
|
|
659
659
|
"response": "Your ETH balance is 1.5 ETH ($3,750.00 USD).",
|
|
660
660
|
"tool_calls": [
|
|
661
|
-
{ "action": "
|
|
661
|
+
{ "action": "get_balances", "success": true, "data": { "balances": [{ "chain": "Ethereum", "symbol": "ETH", "amount": "1.5", "decimals": 18, "raw_amount": "1500000000000000000" }] } }
|
|
662
662
|
],
|
|
663
663
|
"transactions": [
|
|
664
664
|
{ "hash": "0x9f8e7d6c...", "chain": "ethereum", "explorerUrl": "https://etherscan.io/tx/0x9f8e7d6c..." }
|
|
@@ -666,6 +666,36 @@ explorer:https://etherscan.io/tx/0x9f8e7d6c...
|
|
|
666
666
|
}
|
|
667
667
|
```
|
|
668
668
|
|
|
669
|
+
On failure, stdout is a single JSON object with both a human `error` string and a stable `code` (the `error` field is unchanged for older parsers):
|
|
670
|
+
|
|
671
|
+
```json
|
|
672
|
+
{ "error": "Agent backend unreachable at https://example.invalid", "code": "BACKEND_UNREACHABLE" }
|
|
673
|
+
```
|
|
674
|
+
|
|
675
|
+
Each entry in `tool_calls` may include `code` when `success` is false (same values as below).
|
|
676
|
+
|
|
677
|
+
##### Error codes (`agent ask --json`, `--via-agent`, executor)
|
|
678
|
+
|
|
679
|
+
Orchestrators should branch on `code`. The message in `error` / `message` stays human-readable and may change between releases.
|
|
680
|
+
|
|
681
|
+
| Code | Typical meaning |
|
|
682
|
+
|------|-----------------|
|
|
683
|
+
| `BACKEND_UNREACHABLE` | Agent health check failed or backend not responding |
|
|
684
|
+
| `AUTH_FAILED` | Auth/token failure, HTTP 401/403, or wrong vault password |
|
|
685
|
+
| `VAULT_LOCKED` | Encrypted vault needs unlock (password) |
|
|
686
|
+
| `PASSWORD_REQUIRED` | Password was not supplied when required (e.g. pipe mode or signing) |
|
|
687
|
+
| `CONFIRMATION_REQUIRED` | User confirmation needed (pipe mode; message prefix `CONFIRMATION_REQUIRED:`) |
|
|
688
|
+
| `ACTION_NOT_IMPLEMENTED` | Local executor does not implement this action type |
|
|
689
|
+
| `INVALID_INPUT` | Bad parameters, unknown chain, malformed NDJSON input, etc. |
|
|
690
|
+
| `NETWORK_ERROR` | RPC/fetch connectivity (includes many SDK `VaultError` network cases) |
|
|
691
|
+
| `TIMEOUT` | Deadline exceeded, or abort where the message indicates a timeout |
|
|
692
|
+
| `TRANSACTION_FAILED` | Build/broadcast/gas errors mapped from the SDK |
|
|
693
|
+
| `SIGNING_FAILED` | MPC/signing failed |
|
|
694
|
+
| `SESSION_NOT_INITIALIZED` | Internal session state error |
|
|
695
|
+
| `UNKNOWN_ERROR` | Unclassified failure (default for opaque SSE `error` events). Plain `AbortError` without “timeout” in the message maps here. |
|
|
696
|
+
|
|
697
|
+
SSE `error` events may optionally include a `code` field from the backend; if it matches one of the values above, it is passed through unchanged. Otherwise the CLI infers a code from the message.
|
|
698
|
+
|
|
669
699
|
**Agent ask options:**
|
|
670
700
|
- `--session <id>` - Continue an existing conversation
|
|
671
701
|
- `--backend-url <url>` - Agent backend URL (default: https://abe.vultisig.com)
|
|
@@ -712,15 +742,13 @@ The pipe interface uses NDJSON (one JSON object per line) on stdin/stdout. Desig
|
|
|
712
742
|
| `ready` | `vault, addresses` | Session initialized, addresses for all chains |
|
|
713
743
|
| `session` | `id` | Conversation ID for resuming later |
|
|
714
744
|
| `history` | `messages[]` | Previous messages when resuming a session |
|
|
715
|
-
| `auth` | `status, error?` | Authentication result (`authenticated` or `failed`) |
|
|
716
|
-
| `conversation` | `id` | Conversation created or resumed |
|
|
717
745
|
| `text_delta` | `delta` | Streaming text chunk from the agent |
|
|
718
746
|
| `tool_call` | `id, action, params?, status` | Action started (`running`) |
|
|
719
|
-
| `tool_result` | `id, action, success, data?, error?` | Action completed |
|
|
747
|
+
| `tool_result` | `id, action, success, data?, error?, code?` | Action completed (`code` when `success` is false) |
|
|
720
748
|
| `tx_status` | `tx_hash, chain, status, explorer_url?` | Transaction broadcast/confirmed/failed |
|
|
721
749
|
| `assistant` | `content` | Full assistant response |
|
|
722
750
|
| `suggestions` | `suggestions[]` | Suggested follow-up actions |
|
|
723
|
-
| `error` | `message` | Error (
|
|
751
|
+
| `error` | `message, code` | Error or control signal (`PASSWORD_REQUIRED`, `CONFIRMATION_REQUIRED: …`; always includes stable `code`) |
|
|
724
752
|
| `done` | `{}` | Response cycle complete |
|
|
725
753
|
|
|
726
754
|
**Example session:**
|
|
@@ -740,7 +768,7 @@ echo '{"type":"message","content":"What is my ETH balance?"}' | vultisig agent -
|
|
|
740
768
|
{"type":"done"}
|
|
741
769
|
```
|
|
742
770
|
|
|
743
|
-
When the agent needs a password mid-session (e.g. for signing), it emits `{"type":"error","message":"PASSWORD_REQUIRED"}`. Respond with `{"type":"password","password":"..."}` on stdin.
|
|
771
|
+
When the agent needs a password mid-session (e.g. for signing), it emits `{"type":"error","message":"PASSWORD_REQUIRED","code":"PASSWORD_REQUIRED"}`. Respond with `{"type":"password","password":"..."}` on stdin.
|
|
744
772
|
|
|
745
773
|
#### Session Management
|
|
746
774
|
|
package/dist/index.js
CHANGED
|
@@ -4226,6 +4226,122 @@ function displayDiscountTier(tierInfo) {
|
|
|
4226
4226
|
import chalk9 from "chalk";
|
|
4227
4227
|
import Table from "cli-table3";
|
|
4228
4228
|
|
|
4229
|
+
// src/agent/agentErrors.ts
|
|
4230
|
+
import { VaultError, VaultErrorCode, VaultImportError, VaultImportErrorCode } from "@vultisig/sdk";
|
|
4231
|
+
var AgentErrorCode = /* @__PURE__ */ ((AgentErrorCode3) => {
|
|
4232
|
+
AgentErrorCode3["BACKEND_UNREACHABLE"] = "BACKEND_UNREACHABLE";
|
|
4233
|
+
AgentErrorCode3["AUTH_FAILED"] = "AUTH_FAILED";
|
|
4234
|
+
AgentErrorCode3["VAULT_LOCKED"] = "VAULT_LOCKED";
|
|
4235
|
+
AgentErrorCode3["PASSWORD_REQUIRED"] = "PASSWORD_REQUIRED";
|
|
4236
|
+
AgentErrorCode3["CONFIRMATION_REQUIRED"] = "CONFIRMATION_REQUIRED";
|
|
4237
|
+
AgentErrorCode3["ACTION_NOT_IMPLEMENTED"] = "ACTION_NOT_IMPLEMENTED";
|
|
4238
|
+
AgentErrorCode3["INVALID_INPUT"] = "INVALID_INPUT";
|
|
4239
|
+
AgentErrorCode3["NETWORK_ERROR"] = "NETWORK_ERROR";
|
|
4240
|
+
AgentErrorCode3["TIMEOUT"] = "TIMEOUT";
|
|
4241
|
+
AgentErrorCode3["TRANSACTION_FAILED"] = "TRANSACTION_FAILED";
|
|
4242
|
+
AgentErrorCode3["SIGNING_FAILED"] = "SIGNING_FAILED";
|
|
4243
|
+
AgentErrorCode3["SESSION_NOT_INITIALIZED"] = "SESSION_NOT_INITIALIZED";
|
|
4244
|
+
AgentErrorCode3["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
|
|
4245
|
+
return AgentErrorCode3;
|
|
4246
|
+
})(AgentErrorCode || {});
|
|
4247
|
+
var AGENT_ERROR_CODE_VALUES = new Set(Object.values(AgentErrorCode));
|
|
4248
|
+
function isAgentErrorCode(value) {
|
|
4249
|
+
return AGENT_ERROR_CODE_VALUES.has(value);
|
|
4250
|
+
}
|
|
4251
|
+
function mapVaultError(err) {
|
|
4252
|
+
if (err.code === VaultErrorCode.InvalidConfig && /failed to unlock vault/i.test(err.message)) {
|
|
4253
|
+
return "AUTH_FAILED" /* AUTH_FAILED */;
|
|
4254
|
+
}
|
|
4255
|
+
switch (err.code) {
|
|
4256
|
+
case VaultErrorCode.Timeout:
|
|
4257
|
+
return "TIMEOUT" /* TIMEOUT */;
|
|
4258
|
+
case VaultErrorCode.NetworkError:
|
|
4259
|
+
case VaultErrorCode.BalanceFetchFailed:
|
|
4260
|
+
return "NETWORK_ERROR" /* NETWORK_ERROR */;
|
|
4261
|
+
case VaultErrorCode.SigningFailed:
|
|
4262
|
+
return "SIGNING_FAILED" /* SIGNING_FAILED */;
|
|
4263
|
+
case VaultErrorCode.BroadcastFailed:
|
|
4264
|
+
case VaultErrorCode.GasEstimationFailed:
|
|
4265
|
+
return "TRANSACTION_FAILED" /* TRANSACTION_FAILED */;
|
|
4266
|
+
case VaultErrorCode.NotImplemented:
|
|
4267
|
+
return "ACTION_NOT_IMPLEMENTED" /* ACTION_NOT_IMPLEMENTED */;
|
|
4268
|
+
case VaultErrorCode.InvalidAmount:
|
|
4269
|
+
case VaultErrorCode.UnsupportedChain:
|
|
4270
|
+
case VaultErrorCode.UnsupportedToken:
|
|
4271
|
+
case VaultErrorCode.ChainNotSupported:
|
|
4272
|
+
case VaultErrorCode.InvalidVault:
|
|
4273
|
+
case VaultErrorCode.InvalidPublicKey:
|
|
4274
|
+
case VaultErrorCode.InvalidChainCode:
|
|
4275
|
+
case VaultErrorCode.AddressDerivationFailed:
|
|
4276
|
+
return "INVALID_INPUT" /* INVALID_INPUT */;
|
|
4277
|
+
case VaultErrorCode.InvalidConfig:
|
|
4278
|
+
return "INVALID_INPUT" /* INVALID_INPUT */;
|
|
4279
|
+
default:
|
|
4280
|
+
return "UNKNOWN_ERROR" /* UNKNOWN_ERROR */;
|
|
4281
|
+
}
|
|
4282
|
+
}
|
|
4283
|
+
function mapVaultImportError(err) {
|
|
4284
|
+
switch (err.code) {
|
|
4285
|
+
case VaultImportErrorCode.PASSWORD_REQUIRED:
|
|
4286
|
+
return "PASSWORD_REQUIRED" /* PASSWORD_REQUIRED */;
|
|
4287
|
+
case VaultImportErrorCode.INVALID_PASSWORD:
|
|
4288
|
+
return "AUTH_FAILED" /* AUTH_FAILED */;
|
|
4289
|
+
default:
|
|
4290
|
+
return "INVALID_INPUT" /* INVALID_INPUT */;
|
|
4291
|
+
}
|
|
4292
|
+
}
|
|
4293
|
+
function networkishMessage(msg) {
|
|
4294
|
+
return /ECONNREFUSED|ENOTFOUND|ETIMEDOUT|network|fetch failed|socket/i.test(msg) || /getaddrinfo|certificate|TLS|SSL/i.test(msg);
|
|
4295
|
+
}
|
|
4296
|
+
function inferAgentErrorCodeFromMessage(message) {
|
|
4297
|
+
const m = message.trim();
|
|
4298
|
+
if (!m) return "UNKNOWN_ERROR" /* UNKNOWN_ERROR */;
|
|
4299
|
+
if (/agent backend unreachable/i.test(m)) return "BACKEND_UNREACHABLE" /* BACKEND_UNREACHABLE */;
|
|
4300
|
+
if (/authentication failed|^auth failed/i.test(m)) return "AUTH_FAILED" /* AUTH_FAILED */;
|
|
4301
|
+
if (m === "PASSWORD_REQUIRED") return "PASSWORD_REQUIRED" /* PASSWORD_REQUIRED */;
|
|
4302
|
+
if (/^CONFIRMATION_REQUIRED:/i.test(m)) return "CONFIRMATION_REQUIRED" /* CONFIRMATION_REQUIRED */;
|
|
4303
|
+
if (/password required|password not provided|use --password/i.test(m)) return "PASSWORD_REQUIRED" /* PASSWORD_REQUIRED */;
|
|
4304
|
+
if (/session not initialized/i.test(m)) return "SESSION_NOT_INITIALIZED" /* SESSION_NOT_INITIALIZED */;
|
|
4305
|
+
if (/not implemented locally|is not yet implemented|is not implemented locally|action type .*not implemented/i.test(m)) {
|
|
4306
|
+
return "ACTION_NOT_IMPLEMENTED" /* ACTION_NOT_IMPLEMENTED */;
|
|
4307
|
+
}
|
|
4308
|
+
if (/\(401\)|\(403\)|\b401\b|\b403\b|unauthorized|forbidden/i.test(m)) return "AUTH_FAILED" /* AUTH_FAILED */;
|
|
4309
|
+
if (/failed to unlock vault/i.test(m)) return "AUTH_FAILED" /* AUTH_FAILED */;
|
|
4310
|
+
if (/vault.*locked|must unlock|unlock.*vault/i.test(m)) return "VAULT_LOCKED" /* VAULT_LOCKED */;
|
|
4311
|
+
if (/timed out|timeout/i.test(m)) return "TIMEOUT" /* TIMEOUT */;
|
|
4312
|
+
if (networkishMessage(m)) return "NETWORK_ERROR" /* NETWORK_ERROR */;
|
|
4313
|
+
if (/unknown chain|unknown from_chain|unknown to_chain/i.test(m) || /\bis required\b|\bmissing\b|\brequires\b/i.test(m) || /no pending transaction|invalid or empty tx|could not stage calldata|server transaction missing/i.test(m) || /build_custom_tx requires|incomplete for a contract call|invalid der:/i.test(m)) {
|
|
4314
|
+
return "INVALID_INPUT" /* INVALID_INPUT */;
|
|
4315
|
+
}
|
|
4316
|
+
return "UNKNOWN_ERROR" /* UNKNOWN_ERROR */;
|
|
4317
|
+
}
|
|
4318
|
+
function nodeErrCode(err) {
|
|
4319
|
+
if (err && typeof err === "object" && "code" in err && typeof err.code === "string") {
|
|
4320
|
+
return err.code;
|
|
4321
|
+
}
|
|
4322
|
+
return void 0;
|
|
4323
|
+
}
|
|
4324
|
+
function normalizeAgentError(err) {
|
|
4325
|
+
if (err instanceof VaultError) {
|
|
4326
|
+
return { code: mapVaultError(err), message: err.message };
|
|
4327
|
+
}
|
|
4328
|
+
if (err instanceof VaultImportError) {
|
|
4329
|
+
return { code: mapVaultImportError(err), message: err.message };
|
|
4330
|
+
}
|
|
4331
|
+
const name = err instanceof Error ? err.name : "";
|
|
4332
|
+
if (name === "AbortError") {
|
|
4333
|
+
const message2 = err instanceof Error ? err.message : "Aborted";
|
|
4334
|
+
const code = /timed out|timeout/i.test(message2) ? "TIMEOUT" /* TIMEOUT */ : "UNKNOWN_ERROR" /* UNKNOWN_ERROR */;
|
|
4335
|
+
return { code, message: message2 };
|
|
4336
|
+
}
|
|
4337
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
4338
|
+
const nc = nodeErrCode(err);
|
|
4339
|
+
if (nc === "ECONNREFUSED" || nc === "ENOTFOUND" || nc === "ETIMEDOUT") {
|
|
4340
|
+
return { code: "NETWORK_ERROR" /* NETWORK_ERROR */, message };
|
|
4341
|
+
}
|
|
4342
|
+
return { code: inferAgentErrorCodeFromMessage(message), message };
|
|
4343
|
+
}
|
|
4344
|
+
|
|
4229
4345
|
// src/agent/ask.ts
|
|
4230
4346
|
var AskInterface = class {
|
|
4231
4347
|
session;
|
|
@@ -4252,10 +4368,10 @@ var AskInterface = class {
|
|
|
4252
4368
|
`);
|
|
4253
4369
|
}
|
|
4254
4370
|
},
|
|
4255
|
-
onToolResult: (_id, action, success2, data, error2) => {
|
|
4256
|
-
this.toolCalls.push({ action, success: success2, data, error: error2 });
|
|
4371
|
+
onToolResult: (_id, action, success2, data, error2, code) => {
|
|
4372
|
+
this.toolCalls.push({ action, success: success2, data, error: error2, code });
|
|
4257
4373
|
if (this.verbose) {
|
|
4258
|
-
const status = success2 ? "ok" : `error: ${error2}`;
|
|
4374
|
+
const status = success2 ? "ok" : `error: ${error2}${code ? ` [${code}]` : ""}`;
|
|
4259
4375
|
process.stderr.write(`[tool] ${action}: ${status}
|
|
4260
4376
|
`);
|
|
4261
4377
|
}
|
|
@@ -4274,8 +4390,8 @@ var AskInterface = class {
|
|
|
4274
4390
|
`);
|
|
4275
4391
|
}
|
|
4276
4392
|
},
|
|
4277
|
-
onError: (message) => {
|
|
4278
|
-
process.stderr.write(`[error] ${message}
|
|
4393
|
+
onError: (message, code) => {
|
|
4394
|
+
process.stderr.write(`[error] ${message} [${code}]
|
|
4279
4395
|
`);
|
|
4280
4396
|
},
|
|
4281
4397
|
onDone: () => {
|
|
@@ -4406,6 +4522,17 @@ function padTo32Bytes(buf) {
|
|
|
4406
4522
|
}
|
|
4407
4523
|
|
|
4408
4524
|
// src/agent/client.ts
|
|
4525
|
+
function sseErrorToMessage(value) {
|
|
4526
|
+
if (value == null) return "";
|
|
4527
|
+
if (typeof value === "string") return value;
|
|
4528
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return String(value);
|
|
4529
|
+
if (value instanceof Error) return value.message;
|
|
4530
|
+
try {
|
|
4531
|
+
return JSON.stringify(value);
|
|
4532
|
+
} catch {
|
|
4533
|
+
return String(value);
|
|
4534
|
+
}
|
|
4535
|
+
}
|
|
4409
4536
|
var AgentClient = class {
|
|
4410
4537
|
baseUrl;
|
|
4411
4538
|
authToken = null;
|
|
@@ -4460,7 +4587,9 @@ var AgentClient = class {
|
|
|
4460
4587
|
return this.post(`/agent/conversations/${conversationId}`, req);
|
|
4461
4588
|
}
|
|
4462
4589
|
async deleteConversation(conversationId, publicKey) {
|
|
4463
|
-
await this.delete(`/agent/conversations/${conversationId}`, {
|
|
4590
|
+
await this.delete(`/agent/conversations/${conversationId}`, {
|
|
4591
|
+
public_key: publicKey
|
|
4592
|
+
});
|
|
4464
4593
|
}
|
|
4465
4594
|
// ============================================================================
|
|
4466
4595
|
// Messages - JSON mode
|
|
@@ -4581,9 +4710,12 @@ var AgentClient = class {
|
|
|
4581
4710
|
result.message = parsed.message || parsed;
|
|
4582
4711
|
callbacks.onMessage?.(result.message);
|
|
4583
4712
|
break;
|
|
4584
|
-
case "error":
|
|
4585
|
-
|
|
4713
|
+
case "error": {
|
|
4714
|
+
const msg = sseErrorToMessage(parsed.error);
|
|
4715
|
+
const codeFromBackend = typeof parsed.code === "string" && isAgentErrorCode(parsed.code) ? parsed.code : inferAgentErrorCodeFromMessage(msg);
|
|
4716
|
+
callbacks.onError?.(msg, codeFromBackend);
|
|
4586
4717
|
break;
|
|
4718
|
+
}
|
|
4587
4719
|
case "done":
|
|
4588
4720
|
break;
|
|
4589
4721
|
}
|
|
@@ -5092,11 +5224,13 @@ var AgentExecutor = class {
|
|
|
5092
5224
|
data
|
|
5093
5225
|
};
|
|
5094
5226
|
} catch (err) {
|
|
5227
|
+
const { code, message } = normalizeAgentError(err);
|
|
5095
5228
|
return {
|
|
5096
5229
|
action: action.type,
|
|
5097
5230
|
action_id: action.id,
|
|
5098
5231
|
success: false,
|
|
5099
|
-
error:
|
|
5232
|
+
error: message,
|
|
5233
|
+
code
|
|
5100
5234
|
};
|
|
5101
5235
|
}
|
|
5102
5236
|
}
|
|
@@ -6449,7 +6583,12 @@ var PipeInterface = class {
|
|
|
6449
6583
|
const cmd = JSON.parse(nextLine);
|
|
6450
6584
|
await this.handleCommand(cmd);
|
|
6451
6585
|
} catch (err) {
|
|
6452
|
-
|
|
6586
|
+
const { message, code } = normalizeAgentError(err);
|
|
6587
|
+
this.emit({
|
|
6588
|
+
type: "error",
|
|
6589
|
+
message: `Invalid input: ${message}`,
|
|
6590
|
+
code: code === "UNKNOWN_ERROR" /* UNKNOWN_ERROR */ ? "INVALID_INPUT" /* INVALID_INPUT */ : code
|
|
6591
|
+
});
|
|
6453
6592
|
}
|
|
6454
6593
|
}
|
|
6455
6594
|
processing = false;
|
|
@@ -6490,8 +6629,16 @@ var PipeInterface = class {
|
|
|
6490
6629
|
onToolCall: (id, action, params) => {
|
|
6491
6630
|
this.emit({ type: "tool_call", id, action, params, status: "running" });
|
|
6492
6631
|
},
|
|
6493
|
-
onToolResult: (id, action, success2, data, error2) => {
|
|
6494
|
-
this.emit({
|
|
6632
|
+
onToolResult: (id, action, success2, data, error2, code) => {
|
|
6633
|
+
this.emit({
|
|
6634
|
+
type: "tool_result",
|
|
6635
|
+
id,
|
|
6636
|
+
action,
|
|
6637
|
+
success: success2,
|
|
6638
|
+
data,
|
|
6639
|
+
error: error2,
|
|
6640
|
+
...!success2 && code ? { code } : {}
|
|
6641
|
+
});
|
|
6495
6642
|
},
|
|
6496
6643
|
onAssistantMessage: (content) => {
|
|
6497
6644
|
this.emit({ type: "assistant", content });
|
|
@@ -6508,8 +6655,8 @@ var PipeInterface = class {
|
|
|
6508
6655
|
explorer_url: explorerUrl
|
|
6509
6656
|
});
|
|
6510
6657
|
},
|
|
6511
|
-
onError: (message) => {
|
|
6512
|
-
this.emit({ type: "error", message });
|
|
6658
|
+
onError: (message, code) => {
|
|
6659
|
+
this.emit({ type: "error", message, code });
|
|
6513
6660
|
},
|
|
6514
6661
|
onDone: () => {
|
|
6515
6662
|
this.emit({ type: "done" });
|
|
@@ -6517,13 +6664,17 @@ var PipeInterface = class {
|
|
|
6517
6664
|
requestPassword: async () => {
|
|
6518
6665
|
return new Promise((resolve) => {
|
|
6519
6666
|
this.pendingPasswordResolve = resolve;
|
|
6520
|
-
this.emit({ type: "error", message: "PASSWORD_REQUIRED" });
|
|
6667
|
+
this.emit({ type: "error", message: "PASSWORD_REQUIRED", code: "PASSWORD_REQUIRED" /* PASSWORD_REQUIRED */ });
|
|
6521
6668
|
});
|
|
6522
6669
|
},
|
|
6523
6670
|
requestConfirmation: async (message) => {
|
|
6524
6671
|
return new Promise((resolve) => {
|
|
6525
6672
|
this.pendingConfirmResolve = resolve;
|
|
6526
|
-
this.emit({
|
|
6673
|
+
this.emit({
|
|
6674
|
+
type: "error",
|
|
6675
|
+
message: `CONFIRMATION_REQUIRED: ${message}`,
|
|
6676
|
+
code: "CONFIRMATION_REQUIRED" /* CONFIRMATION_REQUIRED */
|
|
6677
|
+
});
|
|
6527
6678
|
});
|
|
6528
6679
|
}
|
|
6529
6680
|
};
|
|
@@ -6535,7 +6686,8 @@ var PipeInterface = class {
|
|
|
6535
6686
|
try {
|
|
6536
6687
|
await this.session.sendMessage(cmd.content, callbacks);
|
|
6537
6688
|
} catch (err) {
|
|
6538
|
-
|
|
6689
|
+
const { message, code } = normalizeAgentError(err);
|
|
6690
|
+
this.emit({ type: "error", message, code });
|
|
6539
6691
|
this.emit({ type: "done" });
|
|
6540
6692
|
}
|
|
6541
6693
|
break;
|
|
@@ -6555,7 +6707,11 @@ var PipeInterface = class {
|
|
|
6555
6707
|
break;
|
|
6556
6708
|
}
|
|
6557
6709
|
default:
|
|
6558
|
-
this.emit({
|
|
6710
|
+
this.emit({
|
|
6711
|
+
type: "error",
|
|
6712
|
+
message: `Unknown command type: ${cmd.type}`,
|
|
6713
|
+
code: "INVALID_INPUT" /* INVALID_INPUT */
|
|
6714
|
+
});
|
|
6559
6715
|
}
|
|
6560
6716
|
}
|
|
6561
6717
|
emit(event) {
|
|
@@ -6738,7 +6894,8 @@ var AgentSession = class {
|
|
|
6738
6894
|
action_id: result.action_id,
|
|
6739
6895
|
success: result.success,
|
|
6740
6896
|
data: result.data || {},
|
|
6741
|
-
error: result.error || ""
|
|
6897
|
+
error: result.error || "",
|
|
6898
|
+
...!result.success && result.code ? { code: result.code } : {}
|
|
6742
6899
|
};
|
|
6743
6900
|
}
|
|
6744
6901
|
let serverTxStoredFromStream = 0;
|
|
@@ -6771,22 +6928,16 @@ var AgentSession = class {
|
|
|
6771
6928
|
},
|
|
6772
6929
|
onMessage: (_msg) => {
|
|
6773
6930
|
},
|
|
6774
|
-
onError: (error2) => {
|
|
6775
|
-
ui.onError(error2);
|
|
6931
|
+
onError: (error2, code) => {
|
|
6932
|
+
ui.onError(error2, code);
|
|
6776
6933
|
}
|
|
6777
6934
|
},
|
|
6778
6935
|
this.abortController?.signal
|
|
6779
6936
|
);
|
|
6780
6937
|
const responseText = streamResult.message?.content || streamResult.fullText || "";
|
|
6781
|
-
const
|
|
6782
|
-
if (
|
|
6783
|
-
|
|
6784
|
-
if (cleanText) {
|
|
6785
|
-
ui.onAssistantMessage(cleanText);
|
|
6786
|
-
}
|
|
6787
|
-
streamResult.actions.push(...inlineActions);
|
|
6788
|
-
} else if (responseText) {
|
|
6789
|
-
ui.onAssistantMessage(responseText);
|
|
6938
|
+
const displayText = stripLeakedToolCallTags(responseText);
|
|
6939
|
+
if (displayText) {
|
|
6940
|
+
ui.onAssistantMessage(displayText);
|
|
6790
6941
|
}
|
|
6791
6942
|
const actions = streamResult.actions.filter((a) => a.type !== "sign_tx");
|
|
6792
6943
|
if (actions.length > 0) {
|
|
@@ -6860,7 +7011,8 @@ var AgentSession = class {
|
|
|
6860
7011
|
action: action.type,
|
|
6861
7012
|
action_id: action.id,
|
|
6862
7013
|
success: false,
|
|
6863
|
-
error: "Password not provided"
|
|
7014
|
+
error: "Password not provided",
|
|
7015
|
+
code: "PASSWORD_REQUIRED" /* PASSWORD_REQUIRED */
|
|
6864
7016
|
});
|
|
6865
7017
|
continue;
|
|
6866
7018
|
}
|
|
@@ -6869,7 +7021,7 @@ var AgentSession = class {
|
|
|
6869
7021
|
ui.onToolCall(action.id, action.type, action.params);
|
|
6870
7022
|
const result = await this.executor.executeAction(action);
|
|
6871
7023
|
results.push(result);
|
|
6872
|
-
ui.onToolResult(action.id, action.type, result.success, result.data, result.error);
|
|
7024
|
+
ui.onToolResult(action.id, action.type, result.success, result.data, result.error, result.code);
|
|
6873
7025
|
if (action.type === "sign_tx" && result.success && result.data) {
|
|
6874
7026
|
const txHash = result.data.tx_hash;
|
|
6875
7027
|
const chain = result.data.chain;
|
|
@@ -6899,34 +7051,12 @@ var AgentSession = class {
|
|
|
6899
7051
|
this.historyMessages = [];
|
|
6900
7052
|
}
|
|
6901
7053
|
};
|
|
6902
|
-
function
|
|
6903
|
-
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
while ((match = invokeRegex.exec(text)) !== null) {
|
|
6907
|
-
const actionType = match[1];
|
|
6908
|
-
const body = match[2];
|
|
6909
|
-
const params = {};
|
|
6910
|
-
const paramRegex = /<parameter\s+name="([^"]+)">([\s\S]*?)<\/parameter>/g;
|
|
6911
|
-
let paramMatch;
|
|
6912
|
-
while ((paramMatch = paramRegex.exec(body)) !== null) {
|
|
6913
|
-
const key = paramMatch[1];
|
|
6914
|
-
const value = paramMatch[2];
|
|
6915
|
-
try {
|
|
6916
|
-
params[key] = JSON.parse(value);
|
|
6917
|
-
} catch {
|
|
6918
|
-
params[key] = value;
|
|
6919
|
-
}
|
|
6920
|
-
}
|
|
6921
|
-
actions.push({
|
|
6922
|
-
id: `inline_${actionType}_${Date.now()}`,
|
|
6923
|
-
type: actionType,
|
|
6924
|
-
title: actionType,
|
|
6925
|
-
params,
|
|
6926
|
-
auto_execute: true
|
|
6927
|
-
});
|
|
7054
|
+
function stripLeakedToolCallTags(text) {
|
|
7055
|
+
if (!text) return "";
|
|
7056
|
+
if (!/<invoke\s+name="[^"]*">/.test(text) && !text.includes("minimax:tool_call")) {
|
|
7057
|
+
return text;
|
|
6928
7058
|
}
|
|
6929
|
-
return
|
|
7059
|
+
return text.replace(/<invoke\s+name="[^"]*">[\s\S]*?<\/invoke>/g, "").replace(/<\/?minimax:tool_call>/g, "").replace(/\n{3,}/g, "\n\n").trim();
|
|
6930
7060
|
}
|
|
6931
7061
|
function getTokenCachePath() {
|
|
6932
7062
|
const dir = process.env.VULTISIG_CONFIG_DIR ?? join2(homedir2(), ".vultisig");
|
|
@@ -7102,7 +7232,7 @@ var ChatTUI = class {
|
|
|
7102
7232
|
console.log(` ${chalk8.yellow("\u26A1")} ${chalk8.yellow(action)} ${chalk8.gray("...")}`);
|
|
7103
7233
|
}
|
|
7104
7234
|
},
|
|
7105
|
-
onToolResult: (_id, action, success2, data, error2) => {
|
|
7235
|
+
onToolResult: (_id, action, success2, data, error2, code) => {
|
|
7106
7236
|
if (success2) {
|
|
7107
7237
|
if (this.verbose) {
|
|
7108
7238
|
const summary = data ? summarizeData(data) : "";
|
|
@@ -7111,7 +7241,8 @@ var ChatTUI = class {
|
|
|
7111
7241
|
console.log(` ${chalk8.green("\u2713")} ${chalk8.green(action)}`);
|
|
7112
7242
|
}
|
|
7113
7243
|
} else {
|
|
7114
|
-
|
|
7244
|
+
const suffix = code && this.verbose ? chalk8.gray(` (${code})`) : "";
|
|
7245
|
+
console.log(` ${chalk8.red("\u2717")} ${chalk8.red(action)}: ${chalk8.red(error2 || "failed")}${suffix}`);
|
|
7115
7246
|
}
|
|
7116
7247
|
},
|
|
7117
7248
|
onAssistantMessage: (content) => {
|
|
@@ -7139,12 +7270,13 @@ var ChatTUI = class {
|
|
|
7139
7270
|
console.log(` ${chalk8.blue.underline(explorerUrl)}`);
|
|
7140
7271
|
}
|
|
7141
7272
|
},
|
|
7142
|
-
onError: (message) => {
|
|
7273
|
+
onError: (message, code) => {
|
|
7143
7274
|
if (this.isStreaming) {
|
|
7144
7275
|
process.stdout.write("\n");
|
|
7145
7276
|
this.isStreaming = false;
|
|
7146
7277
|
}
|
|
7147
|
-
|
|
7278
|
+
const suffix = this.verbose ? chalk8.gray(` (${code})`) : "";
|
|
7279
|
+
console.log(` ${chalk8.red("Error")}: ${message}${suffix}`);
|
|
7148
7280
|
},
|
|
7149
7281
|
onDone: () => {
|
|
7150
7282
|
if (this.isStreaming) {
|
|
@@ -7353,7 +7485,8 @@ async function executeAgent(ctx2, options) {
|
|
|
7353
7485
|
const addresses = session.getVaultAddresses();
|
|
7354
7486
|
await pipe.start(vault.name, addresses);
|
|
7355
7487
|
} catch (err) {
|
|
7356
|
-
|
|
7488
|
+
const { code, message } = normalizeAgentError(err);
|
|
7489
|
+
process.stdout.write(JSON.stringify({ type: "error", message, code }) + "\n");
|
|
7357
7490
|
process.exit(1);
|
|
7358
7491
|
}
|
|
7359
7492
|
} else {
|
|
@@ -7363,7 +7496,8 @@ async function executeAgent(ctx2, options) {
|
|
|
7363
7496
|
await session.initialize(callbacks);
|
|
7364
7497
|
await tui.start();
|
|
7365
7498
|
} catch (err) {
|
|
7366
|
-
|
|
7499
|
+
const { message } = normalizeAgentError(err);
|
|
7500
|
+
console.error(`Agent error: ${message}`);
|
|
7367
7501
|
process.exit(1);
|
|
7368
7502
|
}
|
|
7369
7503
|
}
|
|
@@ -7418,10 +7552,11 @@ tx:${tx.chain}:${tx.hash}
|
|
|
7418
7552
|
}
|
|
7419
7553
|
}
|
|
7420
7554
|
} catch (err) {
|
|
7555
|
+
const { code, message: message2 } = normalizeAgentError(err);
|
|
7421
7556
|
if (options.json) {
|
|
7422
|
-
process.stdout.write(JSON.stringify({ error:
|
|
7557
|
+
process.stdout.write(JSON.stringify({ error: message2, code }) + "\n");
|
|
7423
7558
|
} else {
|
|
7424
|
-
process.stderr.write(`Error: ${
|
|
7559
|
+
process.stderr.write(`Error: ${message2} [${code}]
|
|
7425
7560
|
`);
|
|
7426
7561
|
}
|
|
7427
7562
|
process.exit(1);
|
|
@@ -8953,7 +9088,7 @@ var cachedVersion = null;
|
|
|
8953
9088
|
function getVersion() {
|
|
8954
9089
|
if (cachedVersion) return cachedVersion;
|
|
8955
9090
|
if (true) {
|
|
8956
|
-
cachedVersion = "0.15.
|
|
9091
|
+
cachedVersion = "0.15.4";
|
|
8957
9092
|
return cachedVersion;
|
|
8958
9093
|
}
|
|
8959
9094
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vultisig/cli",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.4",
|
|
4
4
|
"description": "Command-line wallet for Vultisig - multi-chain MPC wallet management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"@cosmjs/stargate": "^0.38.1",
|
|
56
56
|
"@noble/hashes": "^2.0.1",
|
|
57
57
|
"@vultisig/rujira": "^10.0.0",
|
|
58
|
-
"@vultisig/sdk": "^0.15.
|
|
58
|
+
"@vultisig/sdk": "^0.15.4",
|
|
59
59
|
"chalk": "^5.6.2",
|
|
60
60
|
"cli-table3": "^0.6.5",
|
|
61
61
|
"commander": "^14.0.3",
|