@finchtech/cli 0.5.1 → 0.5.2
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 +10 -6
- package/dist/finch.js +199 -166
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Install the public npm package with `npm install -g @finchtech/cli`, then run `f
|
|
|
4
4
|
|
|
5
5
|
The Finch Agent CLI stores wallet keys and AgentCLI Session bearers only in an owner-only `FINCHTECH_HOME`, which defaults to `~/.finchtech`; secrets are never accepted as command arguments or emitted to stdout.
|
|
6
6
|
|
|
7
|
-
For an existing private key, run `finch wallet use --file <PATH>` on a fresh installation, then `finch login --help` to choose an authentication chain. The file must contain a single 32-byte hex private key (64 hexadecimal digits, optionally prefixed with `0x`) and have owner-only permissions. First import is offline and makes that wallet current. `finch wallet create` generates a new identity instead. An existing Account switch with a stored Session revokes that Account before changing the current wallet. With no stored Session, switching is offline and does not claim remote revocation. A pending login must be recovered before switching; other partial or corrupt Session state requires explicit repair. Incomplete wallet files require recovery from backup; residual local authorization requires restoring the original wallet or explicitly clearing local authorization with `finch logout --local`.
|
|
7
|
+
For an existing private key, run `finch wallet use --file <PATH>` on a fresh installation, then `finch login --help` to choose an authentication chain. The file must contain a single 32-byte hex private key (64 hexadecimal digits, optionally prefixed with `0x`) and have owner-only permissions. First import is offline and makes that wallet current. `finch wallet create` generates a new identity instead. `finch wallet list` shows offline the current wallet and every registered address; `finch wallet use <ADDRESS>` accepts only one of those addresses. An existing Account switch with a stored Session revokes that Account before changing the current wallet. With no stored Session, switching is offline and does not claim remote revocation. A pending login must be recovered before switching; other partial or corrupt Session state requires explicit repair. Incomplete wallet files require recovery from backup; residual local authorization requires restoring the original wallet or explicitly clearing local authorization with `finch logout --local`.
|
|
8
8
|
|
|
9
9
|
`finch logout` revokes Account-bound CLI/MCP remote authority before removing local Session and grant state. `finch logout --local` clears only local `session/` and `grants/`, makes no network request and reports `remoteRevoked: false`. Both preserve profiles, registered wallets and transaction/publication journals. Ordinary logout and wallet switching proceed independently of unfinished journals; resume a journal later with its original wallet and matching Account/environment.
|
|
10
10
|
|
|
@@ -20,11 +20,11 @@ Publication intent HTTP failures identify the Session-owned `/api/v1/agent-cli/s
|
|
|
20
20
|
|
|
21
21
|
The CLI measures the exact final multipart request, including metadata and framing. At or below 4,000,000 bytes it posts that request to the inline upload route. Above it the object goes through the staged transport instead: the CLI asks for a signed URL, writes the bytes straight to storage, and has the server read them back, verify them and pin them, so the platform's 4,500,000-byte request-body limit does not apply. These MB thresholds are decimal. The per-object ceilings are enforced against the final object either way: 30 MiB (31,457,280 bytes) for a package, 5 MiB for a cover, and 3 MiB (3,145,728 bytes) for a manifest. The package ceiling is one shared constant, applied by upload admission, by the retrieval route, by this client before it uploads, and by this client when it downloads, so a package that publishes is a package that reads back. Repacking a compressed source ZIP may increase its size. Passing admission does not certify production upload success or authorize replaying a previously failed publication.
|
|
22
22
|
|
|
23
|
-
The command groups are `wallet`, `login/status/logout`, `site`, `mcp doctor`, `mcp connect`, `mcp authorize`, `credentials`, `intent`, `purchase`, `task`, and `skill`. Run `finch --help` for the exact command list as one JSON value.
|
|
23
|
+
The command groups are `wallet`, `login/status/logout`, `site`, `mcp doctor`, `mcp connect`, `mcp authorize`, `credentials`, `intent`, `purchase`, `task`, and `skill`. Run `finch --help` for the exact command list as one JSON value. Every command prints exactly one JSON value, so there is no `--json` option. Invalid input returns `AGENT_MARKET_REQUEST_INVALID` with exit code 2 and a message that names the rejected option, missing argument or unknown subcommand together with the command's usage. Argument values are never echoed.
|
|
24
24
|
|
|
25
25
|
`finch site open` creates a sixty-second one-use handoff from the active AgentCLI Session and opens the exact configured Finch origin in the local default Browser. `finch site login <REQUEST_URL>` binds a website-created five-minute request once, then opens the same confirmation page. Both commands require the wallet, CLI, and graphical Browser on the user's machine. A launch failure returns `BROWSER_OPEN_FAILED` without printing the secret completion URL. The Browser receives only a normal seven-day Finch Web Session; wallet signing, broadcast, and market confirmation remain local CLI actions.
|
|
26
26
|
|
|
27
|
-
`finch mcp doctor` is read-only. It returns a `checks` object for endpoint, wallet, local Session, remote Session authority, and MCP discovery. Each check reports `ok`, `missing`, `invalid`, `unavailable`, or `skipped`, with guidance for unhealthy checks. Missing login or wallet state does not prevent independent discovery checks; an invalid endpoint prevents network checks. The command emits one JSON report with exit code 0 when ready, or 2 when any required check is unhealthy. It verifies the endpoint, wallet/key binding, Account, Session identity, environment, audience and expiry, plus the MCP challenge and required OAuth capabilities. Each remote read has a 15-second timeout. Wallet inspection does not migrate legacy files. Client guide availability, client names, guide versions and repository paths do not affect readiness; `compatibilityManifestUrl` is only an informational link. The Agent Harness owns Remote MCP configuration, OAuth credentials, and refresh; the CLI never configures the Harness and never reads Harness OAuth material.
|
|
27
|
+
`finch mcp doctor` is read-only. It returns a `checks` object for endpoint, wallet, local Session, remote Session authority, and MCP discovery. Each check reports `ok`, `missing`, `invalid`, `unavailable`, or `skipped`, with guidance for unhealthy checks. A failed network check adds `httpStatus` when a response arrived, or the Node.js `networkErrorCode` (for example `ENOTFOUND`, `TIMEOUT`, or a TLS code such as `UNABLE_TO_GET_ISSUER_CERT_LOCALLY`) when none did; TLS certificate failures also name the HTTPS-intercepting proxy case. Missing login or wallet state does not prevent independent discovery checks; an invalid endpoint prevents network checks. The command emits one JSON report with exit code 0 when ready, or 2 when any required check is unhealthy. It verifies the endpoint, wallet/key binding, Account, Session identity, environment, audience and expiry, plus the MCP challenge and required OAuth capabilities. Each remote read has a 15-second timeout. Wallet inspection does not migrate legacy files. Client guide availability, client names, guide versions and repository paths do not affect readiness; `compatibilityManifestUrl` is only an informational link. The Agent Harness owns Remote MCP configuration, OAuth credentials, and refresh; the CLI never configures the Harness and never reads Harness OAuth material.
|
|
28
28
|
|
|
29
29
|
The CLI approves the Harness's native OAuth request with the active local AgentCLI Session through one of three entry points, tried in this order:
|
|
30
30
|
|
|
@@ -36,7 +36,7 @@ Each entry point applies the same origin, redirect, state, scope, and RFC 9207 i
|
|
|
36
36
|
|
|
37
37
|
Doctor's `ready: true` is scoped by `readinessScope: "cli_session_and_mcp_discovery"`. Its `harnessOAuth.status` is always `not_checked`: CLI login and valid discovery metadata do not establish that the connected Harness has usable OAuth credentials, a saved issuer, or working refresh. The result includes identity-verification and native reauthorization guidance. If the Harness reports an OAuth failure, start its native MCP authorization flow again, approve the fresh request through the entry points above, then verify MCP identity again.
|
|
38
38
|
|
|
39
|
-
Run `finch login --help` to list supported production authentication chain IDs (1, 10, 56, 8453, 42161, 43114). For example, `finch login --chain-id 56` selects BNB Smart Chain for authentication only.
|
|
39
|
+
Run `finch login --help` to list supported production authentication chain IDs (1, 10, 56, 8453, 42161, 43114, 1776). For example, `finch login --chain-id 56` selects BNB Smart Chain for authentication only.
|
|
40
40
|
|
|
41
41
|
Ordinary installs require no profile file or environment selection. Network commands default to the PROD endpoint at `https://www.finchtech.ai`. `finch login --chain-id <CHAIN_ID>` explicitly selects only the authentication chain, which the selected server must support. Market transaction chains come from Remote MCP/API plans and are independent of the login chain. `intent approve` signs only the shared publication-v2 or Local-purchase-v1 EIP-712 authorization; it cannot sign arbitrary transaction calldata.
|
|
42
42
|
|
|
@@ -70,7 +70,7 @@ Recover an interrupted action with `finch task recover <taskId> <publish|award|r
|
|
|
70
70
|
|
|
71
71
|
Skill preparations return `walletIntent.intentId`. With the updated CLI, run `skill purchase-submit`, `convert-submit`, `price-submit`, or `supply-submit` with `--intent <intentId>`. The commands fetch server-bound transaction bytes and use only the CLI Session for execution and confirmation. `--from-file` reads only the handoff reference; changing price, chain or calldata in the file cannot change the signed call. Prepare unexecuted old plan files again through MCP. CLI 0.5.0 supports this handoff; npm publication is a separate release step.
|
|
72
72
|
|
|
73
|
-
`skill publish-submit --path <file-or-directory> --intent <intentId>` and `skill version-submit` retain local filtering, ZIP construction, packaging, encryption, upload and key custody. The server fixes the prepared business metadata and records each transaction stage once. `skill asset-upload --path <cover> --intent <intentId>` uploads a prepared public cover. `skill presentation-submit
|
|
73
|
+
`skill publish-submit --path <file-or-directory> --intent <intentId>` and `skill version-submit` retain local filtering, ZIP construction, packaging, encryption, upload and key custody. The server fixes the prepared business metadata and records each transaction stage once. `skill asset-upload --path <cover> --intent <intentId>` uploads a prepared public cover. `skill presentation-submit` is retired and refuses before wallet or network access. Use Remote MCP `skill_market_presentation_update` to save listing text, cover, demo video and detail tabs as database overrides without a transaction. Repeating an intent with a recorded transaction resumes confirmation. An unfinished publication requires its original protected material journal; restoring it preserves uploaded bytes and keys.
|
|
74
74
|
|
|
75
75
|
Recover wallet results with `skill recover intent <fingerprint>` and publication material with `skill recover publication <fingerprint>`. Recovery preserves broadcast hashes and the publication pending-send protections. Old buyer journals are admitted only as receipt-only recovery after the server reconstructs and verifies their confirmed canonical transaction. Existing publication journals retain their conservative typed recovery path. A confirmed receipt or projected stage can replay without another signature/broadcast; preserve journals during projection lag.
|
|
76
76
|
|
|
@@ -83,7 +83,7 @@ Version 0.3.1 fixes Skill search continuation: pass the returned `nextCursor` un
|
|
|
83
83
|
Older clients receive an upgrade message from the Skill search API.
|
|
84
84
|
|
|
85
85
|
Version 0.3.0 upgrades Skill publication and encrypted delivery together. Upgrade with
|
|
86
|
-
`npm install -g @finchtech/cli@0.5.
|
|
86
|
+
`npm install -g @finchtech/cli@0.5.2` and verify `finch --version` before publishing new Skills
|
|
87
87
|
or downloading encrypted Skills from the upgraded gateway. Older CLI versions cannot use
|
|
88
88
|
the new encrypted delivery, including for historical Skills; 0.3.0 retains historical package support.
|
|
89
89
|
|
|
@@ -180,3 +180,7 @@ Keep existing journals when upgrading. Agent recovery uses the owned operation/i
|
|
|
180
180
|
## Recovery-preserving Account transitions (CLI 0.5.1)
|
|
181
181
|
|
|
182
182
|
CLI 0.5.1 allows ordinary logout and wallet switching with unfinished transaction/publication journals, preserving Account-wide CLI/MCP revocation and the original recovery evidence. It removes the redundant local recovery index. Invalid or expired Sessions receive direct same-authority login guidance. The bundle also includes the shared Avalanche PROD authentication allowlist already deployed on Finch.
|
|
183
|
+
|
|
184
|
+
## Actionable usage errors, wallet list and network diagnostics (CLI 0.5.2)
|
|
185
|
+
|
|
186
|
+
CLI 0.5.2 names the rejected option, missing argument or unknown subcommand together with the command's usage instead of a generic schema message; every command already prints JSON, so there is no `--json` option. `finch wallet list` shows the current wallet and registered addresses offline. Failed `finch mcp doctor` network checks report `httpStatus` or `networkErrorCode`, so a TLS-intercepting proxy, DNS failure or timeout is distinguishable from a server outage. Its PROD authentication-chain help also lists Injective (`1776`). Upgrade the installed executable to receive these changes; updating the Skill or website alone does not apply them.
|
package/dist/finch.js
CHANGED
|
@@ -6619,7 +6619,7 @@ var init_package = __esm({
|
|
|
6619
6619
|
"package.json"() {
|
|
6620
6620
|
package_default = {
|
|
6621
6621
|
name: "@finchtech/cli",
|
|
6622
|
-
version: "0.5.
|
|
6622
|
+
version: "0.5.2",
|
|
6623
6623
|
description: "Finch Agent CLI for wallet custody, Session-owned execution, and MCP OAuth approval.",
|
|
6624
6624
|
type: "module",
|
|
6625
6625
|
bin: {
|
|
@@ -21941,6 +21941,45 @@ var init_agent_service = __esm({
|
|
|
21941
21941
|
paymentTokenSymbol: "USDC",
|
|
21942
21942
|
paymentTokenDecimals: 6
|
|
21943
21943
|
}
|
|
21944
|
+
},
|
|
21945
|
+
"1776": {
|
|
21946
|
+
enabled: true,
|
|
21947
|
+
network: {
|
|
21948
|
+
chainId: 1776,
|
|
21949
|
+
name: "Injective",
|
|
21950
|
+
explorerUrl: "https://blockscout.injective.network",
|
|
21951
|
+
defaultRpcUrls: [
|
|
21952
|
+
"https://sentry.evm-rpc.injective.network"
|
|
21953
|
+
]
|
|
21954
|
+
},
|
|
21955
|
+
sourceRepository: "FinchipAI/Finch-Agent-Service-Protocol",
|
|
21956
|
+
sourceCommit: "97f6f0810932b282de482238ec0f9460cdc177b3",
|
|
21957
|
+
contracts: {
|
|
21958
|
+
protocol: "0xd0f6f5be7581ad76f0b6cf10e468c017c9aad902",
|
|
21959
|
+
protocolImplementation: "0xeb426199277c10cd12ade7858bff24eb67d3342e",
|
|
21960
|
+
protocolProxyAdmin: "0xa6cb95ee7262b198c7727344cae7e95afd2922ee",
|
|
21961
|
+
vault: "0xf5bdf5f74c5597151bd3fd978cdd741d9f7f7103",
|
|
21962
|
+
vaultImplementation: "0xe8e53bca9ada0dfc77d977db5d929973db79d2df",
|
|
21963
|
+
vaultProxyAdmin: "0x45869f4af762ff7adee9a8a1a3264c5518320b98",
|
|
21964
|
+
paymentToken: "0xa00c59ff5a080d2b954d0c75e46e22a0c371235a"
|
|
21965
|
+
},
|
|
21966
|
+
authority: {
|
|
21967
|
+
admin: "0x4fcb985a020dc1dd8a5dfc4adf4606eac4f68075",
|
|
21968
|
+
treasury: "0xd5ca4d96a17723fd008b2c3f1a413cb0736a2848",
|
|
21969
|
+
settlementAttestor: "0x1dc1ccc1ebdcdd6c57a8c22776883b45c6824cf6",
|
|
21970
|
+
refundAttestor: "0x1dc1ccc1ebdcdd6c57a8c22776883b45c6824cf6",
|
|
21971
|
+
freezeKeeper: "0x1dc1ccc1ebdcdd6c57a8c22776883b45c6824cf6"
|
|
21972
|
+
},
|
|
21973
|
+
deployment: {
|
|
21974
|
+
firstBlock: "185194836",
|
|
21975
|
+
completedBlock: "185194908",
|
|
21976
|
+
confirmations: 2,
|
|
21977
|
+
deploymentHash: "0x3b6a22dfb42ecc1d4800a60971ccf932bd39a005cec796a9bcef9a31702e0b33"
|
|
21978
|
+
},
|
|
21979
|
+
policy: {
|
|
21980
|
+
paymentTokenSymbol: "USDC",
|
|
21981
|
+
paymentTokenDecimals: 6
|
|
21982
|
+
}
|
|
21944
21983
|
}
|
|
21945
21984
|
}
|
|
21946
21985
|
}
|
|
@@ -22328,6 +22367,44 @@ var init_task_protocol = __esm({
|
|
|
22328
22367
|
paymentTokenSymbol: "USDC",
|
|
22329
22368
|
paymentTokenDecimals: 6
|
|
22330
22369
|
}
|
|
22370
|
+
},
|
|
22371
|
+
"1776": {
|
|
22372
|
+
enabled: true,
|
|
22373
|
+
network: {
|
|
22374
|
+
chainId: 1776,
|
|
22375
|
+
name: "Injective",
|
|
22376
|
+
explorerUrl: "https://blockscout.injective.network",
|
|
22377
|
+
defaultRpcUrls: [
|
|
22378
|
+
"https://sentry.evm-rpc.injective.network"
|
|
22379
|
+
]
|
|
22380
|
+
},
|
|
22381
|
+
sourceRepository: "FinchipAI/Finch-Task-Protocol",
|
|
22382
|
+
sourceCommit: "b3331c2488e9b5cc7159beb58be0ba3f60430d7e",
|
|
22383
|
+
abiSourceCommit: "c4491b8fe85a09840c5873bc6ac142c580febd32",
|
|
22384
|
+
contracts: {
|
|
22385
|
+
protocol: "0x20ab3a991f987a6f7ccb4e8f21a9c6e1097d7a19",
|
|
22386
|
+
protocolImplementation: "0xe520cd670add2f8813e3c76bd69a033c5cfa5b92",
|
|
22387
|
+
protocolProxyAdmin: "0x2ae16beefb2a74efceb32379a54052871c86aeb8",
|
|
22388
|
+
vault: "0xcb19ea4fa56c3fc0c03892ec4b76e546572ba2b8",
|
|
22389
|
+
vaultImplementation: "0x43fe3e0afb3ed8c2851b6326522e031599a44a30",
|
|
22390
|
+
vaultProxyAdmin: "0xa19b2318184e1f826ccf4d6d7eaeb5356efe3dce",
|
|
22391
|
+
paymentToken: "0xa00c59ff5a080d2b954d0c75e46e22a0c371235a"
|
|
22392
|
+
},
|
|
22393
|
+
authority: {
|
|
22394
|
+
admin: "0x4fcb985a020dc1dd8a5dfc4adf4606eac4f68075",
|
|
22395
|
+
treasury: "0xd5ca4d96a17723fd008b2c3f1a413cb0736a2848",
|
|
22396
|
+
awardAttestor: "0x1dc1ccc1ebdcdd6c57a8c22776883b45c6824cf6",
|
|
22397
|
+
freezeKeeper: "0x1dc1ccc1ebdcdd6c57a8c22776883b45c6824cf6"
|
|
22398
|
+
},
|
|
22399
|
+
deployment: {
|
|
22400
|
+
firstBlock: "185193254",
|
|
22401
|
+
completedBlock: "185193311",
|
|
22402
|
+
confirmations: 2
|
|
22403
|
+
},
|
|
22404
|
+
policy: {
|
|
22405
|
+
paymentTokenSymbol: "USDC",
|
|
22406
|
+
paymentTokenDecimals: 6
|
|
22407
|
+
}
|
|
22331
22408
|
}
|
|
22332
22409
|
}
|
|
22333
22410
|
}
|
|
@@ -22991,7 +23068,7 @@ var init_internal_apps = __esm({
|
|
|
22991
23068
|
sessionTtlSeconds: 28800,
|
|
22992
23069
|
queryAgentEnabled: true,
|
|
22993
23070
|
aiBaseUrl: "https://api.tokenrouter.com/v1",
|
|
22994
|
-
aiModel: "xiaomi/mimo-v2.6-
|
|
23071
|
+
aiModel: "xiaomi/mimo-v2.6-pro"
|
|
22995
23072
|
},
|
|
22996
23073
|
ops: {
|
|
22997
23074
|
sessionTtlSeconds: 28800,
|
|
@@ -23003,7 +23080,7 @@ var init_internal_apps = __esm({
|
|
|
23003
23080
|
sessionTtlSeconds: 28800,
|
|
23004
23081
|
queryAgentEnabled: true,
|
|
23005
23082
|
aiBaseUrl: "https://api.tokenrouter.com/v1",
|
|
23006
|
-
aiModel: "xiaomi/mimo-v2.6-
|
|
23083
|
+
aiModel: "xiaomi/mimo-v2.6-pro"
|
|
23007
23084
|
},
|
|
23008
23085
|
ops: {
|
|
23009
23086
|
sessionTtlSeconds: 28800,
|
|
@@ -23013,9 +23090,9 @@ var init_internal_apps = __esm({
|
|
|
23013
23090
|
production: {
|
|
23014
23091
|
data: {
|
|
23015
23092
|
sessionTtlSeconds: 28800,
|
|
23016
|
-
queryAgentEnabled:
|
|
23093
|
+
queryAgentEnabled: true,
|
|
23017
23094
|
aiBaseUrl: "https://api.tokenrouter.com/v1",
|
|
23018
|
-
aiModel: "xiaomi/mimo-v2.6-
|
|
23095
|
+
aiModel: "xiaomi/mimo-v2.6-pro"
|
|
23019
23096
|
},
|
|
23020
23097
|
ops: {
|
|
23021
23098
|
sessionTtlSeconds: 28800,
|
|
@@ -23492,13 +23569,15 @@ var init_src = __esm({
|
|
|
23492
23569
|
});
|
|
23493
23570
|
|
|
23494
23571
|
// ../../packages/skill-market-contracts/src/public.ts
|
|
23495
|
-
var SKILL_V3_ENVELOPE_SCHEME, SKILL_V3_LIT_ENVELOPE_SCHEME;
|
|
23572
|
+
var SKILL_V3_ENVELOPE_SCHEME, SKILL_V3_LIT_ENVELOPE_SCHEME, SKILL_PUBLICATION_ROYALTY_BPS, SKILL_PUBLICATION_USAGE_LIMIT;
|
|
23496
23573
|
var init_public = __esm({
|
|
23497
23574
|
"../../packages/skill-market-contracts/src/public.ts"() {
|
|
23498
23575
|
"use strict";
|
|
23499
23576
|
init_src();
|
|
23500
23577
|
SKILL_V3_ENVELOPE_SCHEME = "FINCHIP_V2";
|
|
23501
23578
|
SKILL_V3_LIT_ENVELOPE_SCHEME = "LIT_V1";
|
|
23579
|
+
SKILL_PUBLICATION_ROYALTY_BPS = 250;
|
|
23580
|
+
SKILL_PUBLICATION_USAGE_LIMIT = 0;
|
|
23502
23581
|
}
|
|
23503
23582
|
});
|
|
23504
23583
|
|
|
@@ -24150,6 +24229,7 @@ function localFailureMessage(error51) {
|
|
|
24150
24229
|
}
|
|
24151
24230
|
return "Protected local state is corrupt. Recreate the affected profile, login, or recovery state.";
|
|
24152
24231
|
}
|
|
24232
|
+
if (error51 instanceof CliUsageError) return error51.message;
|
|
24153
24233
|
if (error51.message === "FINCHTECH_HOME is required.") {
|
|
24154
24234
|
return "FINCHTECH_HOME is required. Set it to the protected Finch Agent CLI state directory.";
|
|
24155
24235
|
}
|
|
@@ -24163,7 +24243,7 @@ function localFailureMessage(error51) {
|
|
|
24163
24243
|
if (publicInputMessages.includes(error51.message)) return error51.message;
|
|
24164
24244
|
return "Command input does not match the expected schema. Check finch help for this command.";
|
|
24165
24245
|
}
|
|
24166
|
-
var CliAuthorityError, CliProductionUnavailableError, BrowserOpenError, MCP_AUTHORIZATION_FLOW_GUIDANCE, McpAuthorizationFlowError, CLI_SESSION_RENEWAL_GUIDANCE, CliSkillSourceError, CliSkillPresentationStaleError, CliSkillRecoveryUncertainError, CliSkillPublicationError;
|
|
24246
|
+
var CliAuthorityError, CliProductionUnavailableError, BrowserOpenError, MCP_AUTHORIZATION_FLOW_GUIDANCE, McpAuthorizationFlowError, CliUsageError, CLI_SESSION_RENEWAL_GUIDANCE, CliSkillSourceError, CliSkillPresentationStaleError, CliSkillRecoveryUncertainError, CliSkillPublicationError;
|
|
24167
24247
|
var init_cli_error = __esm({
|
|
24168
24248
|
"src/cli-error.ts"() {
|
|
24169
24249
|
"use strict";
|
|
@@ -24213,6 +24293,12 @@ var init_cli_error = __esm({
|
|
|
24213
24293
|
code = "MCP_AUTHORIZATION_FLOW_FAILED";
|
|
24214
24294
|
guidance;
|
|
24215
24295
|
};
|
|
24296
|
+
CliUsageError = class extends TypeError {
|
|
24297
|
+
constructor(message) {
|
|
24298
|
+
super(message);
|
|
24299
|
+
this.name = "CliUsageError";
|
|
24300
|
+
}
|
|
24301
|
+
};
|
|
24216
24302
|
CLI_SESSION_RENEWAL_GUIDANCE = "The CLI Session is invalid or expired. Run finch login --chain-id <CHAIN_ID> using the same wallet, endpoint and authentication chain. Use finch login --help to list supported authentication chains. Existing recovery journals are preserved.";
|
|
24217
24303
|
CliSkillSourceError = class extends TypeError {
|
|
24218
24304
|
constructor(diagnosticCode, details, message) {
|
|
@@ -28808,9 +28894,6 @@ function packageForVersion(manifest6, version6) {
|
|
|
28808
28894
|
function withVersion(manifest6, entry2) {
|
|
28809
28895
|
return buildManifest([...manifest6?.versions ?? [], entry2], manifest6?.presentation, manifest6?.documents);
|
|
28810
28896
|
}
|
|
28811
|
-
function withPresentation(manifest6, presentation) {
|
|
28812
|
-
return buildManifest(manifest6.versions, presentation, manifest6.documents);
|
|
28813
|
-
}
|
|
28814
28897
|
var MAX_SKILL_MANIFEST_BYTES, SKILL_MANIFEST_SCHEME, SKILL_DETAIL_KINDS, DETAIL_MEDIA_TYPES, DETAIL_HASH, DETAIL_ASSET_PATH, DETAIL_IPFS_URI, DETAIL_STORAGE_URI, DETAIL_BUCKET_BY_KIND, DETAIL_MEDIA_HOST;
|
|
28815
28898
|
var init_manifest = __esm({
|
|
28816
28899
|
"../../packages/skill-content/src/manifest.ts"() {
|
|
@@ -32439,7 +32522,7 @@ var init_identity = __esm({
|
|
|
32439
32522
|
"../../packages/agent-market-contracts/src/v1/identity.ts"() {
|
|
32440
32523
|
"use strict";
|
|
32441
32524
|
init_common3();
|
|
32442
|
-
PRODUCTION_AUTH_CHAIN_IDS = Object.freeze([1, 10, 56, 8453, 42161, 43114]);
|
|
32525
|
+
PRODUCTION_AUTH_CHAIN_IDS = Object.freeze([1, 10, 56, 8453, 42161, 43114, 1776]);
|
|
32443
32526
|
TEST_AUTH_CHAIN_IDS = Object.freeze([84532]);
|
|
32444
32527
|
IDENTITY_SCOPE_ORDER_CONTRACT = Object.freeze({
|
|
32445
32528
|
order: "ascii_lexicographic",
|
|
@@ -57569,7 +57652,7 @@ function publishPlan(value, context) {
|
|
|
57569
57652
|
const chainId = assertAuthority(plan, "publish", context.walletAddress);
|
|
57570
57653
|
assertLocalAction(plan.localAction, "skill publish-submit");
|
|
57571
57654
|
const request2 = object2(plan.request, "Skill publish request");
|
|
57572
|
-
exact2(request2, ["chainId", "slug", "name", "category", "licenseTypeName", "imageURI", "sourceKind", "contentMode", "unitPrice", "maxSupply",
|
|
57655
|
+
exact2(request2, ["chainId", "slug", "name", "category", "licenseTypeName", "imageURI", "sourceKind", "contentMode", "unitPrice", "maxSupply", ...Object.hasOwn(request2, "summary") ? ["summary"] : []], "Skill publish request");
|
|
57573
57656
|
if (request2.chainId !== chainId) throw new TypeError("Skill publish request chain is invalid.");
|
|
57574
57657
|
string4(request2.slug, "Skill slug");
|
|
57575
57658
|
string4(request2.name, "Skill name");
|
|
@@ -57583,8 +57666,6 @@ function publishPlan(value, context) {
|
|
|
57583
57666
|
contentMode(request2.contentMode);
|
|
57584
57667
|
string4(request2.unitPrice, "Skill unitPrice", DECIMAL);
|
|
57585
57668
|
string4(request2.maxSupply, "Skill maxSupply", DECIMAL);
|
|
57586
|
-
string4(request2.usageLimit, "Skill usageLimit", DECIMAL);
|
|
57587
|
-
if (!Number.isInteger(request2.royaltyBPS) || Number(request2.royaltyBPS) < 0 || Number(request2.royaltyBPS) > 1e3) throw new TypeError("Skill royaltyBPS is invalid.");
|
|
57588
57669
|
return {
|
|
57589
57670
|
chainId,
|
|
57590
57671
|
request: request2,
|
|
@@ -57631,32 +57712,6 @@ function managePlan(value, walletAddress2, kind) {
|
|
|
57631
57712
|
signingAuthority: plan.signingAuthority
|
|
57632
57713
|
}, walletAddress2) };
|
|
57633
57714
|
}
|
|
57634
|
-
function presentationPlan(value, walletAddress2) {
|
|
57635
|
-
const plan = object2(value, "Skill presentation plan");
|
|
57636
|
-
exact2(plan, [
|
|
57637
|
-
"kind",
|
|
57638
|
-
"sourceCommit",
|
|
57639
|
-
"chainId",
|
|
57640
|
-
"walletAddress",
|
|
57641
|
-
"signingAuthority",
|
|
57642
|
-
"skillId",
|
|
57643
|
-
"currentVersion",
|
|
57644
|
-
"currentManifestURI",
|
|
57645
|
-
"presentation",
|
|
57646
|
-
"localAction"
|
|
57647
|
-
], "Skill presentation plan");
|
|
57648
|
-
const chainId = assertAuthority(plan, "presentation", walletAddress2);
|
|
57649
|
-
const skillId = string4(plan.skillId, "Skill id", /^[1-9][0-9]*$/u);
|
|
57650
|
-
assertLocalAction(plan.localAction, "skill presentation-submit", skillId);
|
|
57651
|
-
return {
|
|
57652
|
-
chainId,
|
|
57653
|
-
skillId,
|
|
57654
|
-
currentVersion: integer2(plan.currentVersion, "Current version"),
|
|
57655
|
-
currentManifestURI: string4(plan.currentManifestURI, "Current manifest URI", IPFS),
|
|
57656
|
-
presentation: buildPresentation(plan.presentation),
|
|
57657
|
-
signingAuthority: signingAuthority(plan.signingAuthority, walletAddress2)
|
|
57658
|
-
};
|
|
57659
|
-
}
|
|
57660
57715
|
function assetPlan(value, walletAddress2) {
|
|
57661
57716
|
const plan = object2(value, "Skill asset plan");
|
|
57662
57717
|
exact2(plan, [
|
|
@@ -58045,10 +58100,10 @@ var init_skill_local_flow = __esm({
|
|
|
58045
58100
|
async save(fingerprint, journal) {
|
|
58046
58101
|
await required2(this.recovery, "Skill publication recovery").saveSkillPublicationRecovery(fingerprint, journal);
|
|
58047
58102
|
}
|
|
58048
|
-
async project(chainId, transactionHash3, bearer, intentId, stage) {
|
|
58103
|
+
async project(chainId, transactionHash3, bearer, intentId, stage, requireReady = true) {
|
|
58049
58104
|
if (intentId === void 0 && this.api.confirmSkillProjection === void 0) return;
|
|
58050
58105
|
const status = await required2(this.api.confirmSkillProjection, "Skill projection confirmation").call(this.api, chainId, transactionHash3, bearer, intentId, stage);
|
|
58051
|
-
if (intentId !== void 0 && status !== "projected") throw new TypeError("Skill projection is pending. Resume the saved Skill recovery.");
|
|
58106
|
+
if (requireReady && intentId !== void 0 && status !== "projected") throw new TypeError("The Skill transaction is confirmed; presentation projection is pending. Resume the saved Skill recovery to retry projection without sending another transaction.");
|
|
58052
58107
|
}
|
|
58053
58108
|
async stage(progress, context, fingerprint, journal, stage, action, request2, prepare) {
|
|
58054
58109
|
progress.journal = journal;
|
|
@@ -58062,7 +58117,7 @@ var init_skill_local_flow = __esm({
|
|
|
58062
58117
|
await this.save(fingerprint, journal);
|
|
58063
58118
|
progress.uncertain = false;
|
|
58064
58119
|
progress.phase = "projection";
|
|
58065
|
-
await this.project(journal.chainId, journal.receipts[stage].transactionHash, context.bearer, context.intentId, stage);
|
|
58120
|
+
await this.project(journal.chainId, journal.receipts[stage].transactionHash, context.bearer, context.intentId, stage, journal.kind !== "version" || stage !== "primary");
|
|
58066
58121
|
return;
|
|
58067
58122
|
}
|
|
58068
58123
|
if ((stage !== "uri" || context.intentId !== void 0) && (journal.pendingStage != null || journal.version !== 6)) {
|
|
@@ -58104,7 +58159,7 @@ var init_skill_local_flow = __esm({
|
|
|
58104
58159
|
await this.save(fingerprint, journal);
|
|
58105
58160
|
progress.uncertain = false;
|
|
58106
58161
|
progress.phase = "projection";
|
|
58107
|
-
await this.project(journal.chainId, journal.receipts[stage].transactionHash, context.bearer, context.intentId, stage);
|
|
58162
|
+
await this.project(journal.chainId, journal.receipts[stage].transactionHash, context.bearer, context.intentId, stage, journal.kind !== "version" || stage !== "primary");
|
|
58108
58163
|
}
|
|
58109
58164
|
async recoverWithProgress(fingerprint, context, progress) {
|
|
58110
58165
|
progress.phase = "recovery";
|
|
@@ -58570,68 +58625,11 @@ var init_skill_local_flow = __esm({
|
|
|
58570
58625
|
await this.project(plan.chainId, submission.transactionHash, context.bearer, context.intentId);
|
|
58571
58626
|
return { ...submission, chainId: plan.chainId, skillId: plan.request.skillId, kind };
|
|
58572
58627
|
}
|
|
58573
|
-
/**
|
|
58574
|
-
|
|
58575
|
-
|
|
58576
|
-
|
|
58577
|
-
|
|
58578
|
-
* through the caller before receipt waiting; legacy callers retain the convergent URI retry.
|
|
58579
|
-
*/
|
|
58580
|
-
async publishPresentation(planValue, context) {
|
|
58581
|
-
return this.publication((progress) => this.publishPresentationWithProgress(planValue, context, progress));
|
|
58582
|
-
}
|
|
58583
|
-
async publishPresentationWithProgress(planValue, context, progress) {
|
|
58584
|
-
const plan = presentationPlan(planValue, context.walletAddress);
|
|
58585
|
-
progress.resubmitSafe = true;
|
|
58586
|
-
const liveVersion = await required2(this.api.readSkillCurrentVersion, "Skill version API").call(this.api, plan.chainId, plan.skillId, context.bearer, context.intentId);
|
|
58587
|
-
if (liveVersion !== plan.currentVersion) {
|
|
58588
|
-
throw new CliSkillPresentationStaleError("version_moved", plan.currentVersion, liveVersion);
|
|
58589
|
-
}
|
|
58590
|
-
const currentBytes = await required2(this.api.fetchSkillStoredContent, "Skill content relay").call(this.api, plan.currentManifestURI, context.bearer);
|
|
58591
|
-
const currentManifest = parseManifest2(currentBytes);
|
|
58592
|
-
if (currentManifest === null) {
|
|
58593
|
-
throw new CliSkillPresentationStaleError("manifest_unreadable", plan.currentVersion, liveVersion);
|
|
58594
|
-
}
|
|
58595
|
-
progress.phase = "upload";
|
|
58596
|
-
const manifestURI = await this.upload({
|
|
58597
|
-
bytes: serializeManifest(withPresentation(currentManifest, plan.presentation)),
|
|
58598
|
-
filename: `skill-${plan.skillId}.versions.json`,
|
|
58599
|
-
bearer: context.bearer,
|
|
58600
|
-
objectKind: "manifest"
|
|
58601
|
-
});
|
|
58602
|
-
const request2 = { action: "setSkillURI", chainId: plan.chainId, skillId: plan.skillId, packageURI: manifestURI };
|
|
58603
|
-
progress.phase = "intent";
|
|
58604
|
-
const prepared = await required2(this.api.requestSkillIntent, "Skill intent API").call(this.api, request2, context.bearer, context.intentId);
|
|
58605
|
-
const resumed = await context.resumePrepared?.(request2, object2(prepared, "Skill presentation intent"));
|
|
58606
|
-
if (resumed) {
|
|
58607
|
-
await this.project(plan.chainId, resumed.transactionHash, context.bearer, context.intentId);
|
|
58608
|
-
return { ...resumed, chainId: plan.chainId, skillId: plan.skillId, currentVersion: plan.currentVersion, manifestURI };
|
|
58609
|
-
}
|
|
58610
|
-
progress.phase = "transaction";
|
|
58611
|
-
progress.uncertain = true;
|
|
58612
|
-
const submission = await this.send(
|
|
58613
|
-
context,
|
|
58614
|
-
"setSkillURI",
|
|
58615
|
-
request2,
|
|
58616
|
-
prepared,
|
|
58617
|
-
plan.signingAuthority,
|
|
58618
|
-
async ({ transactionHash: transactionHash3 }) => {
|
|
58619
|
-
progress.broadcast = { setSkillURI: transactionHash3 };
|
|
58620
|
-
const fingerprint = await context.onBroadcast?.({ request: request2, intent: object2(prepared, "Skill presentation intent"), transactionHash: transactionHash3 });
|
|
58621
|
-
if (fingerprint) {
|
|
58622
|
-
progress.walletFingerprint = fingerprint;
|
|
58623
|
-
progress.journalSaved = true;
|
|
58624
|
-
progress.resubmitSafe = false;
|
|
58625
|
-
}
|
|
58626
|
-
progress.uncertain = false;
|
|
58627
|
-
}
|
|
58628
|
-
);
|
|
58629
|
-
await context.onReceipt?.(submission.blockNumber);
|
|
58630
|
-
progress.broadcast = { setSkillURI: submission.transactionHash };
|
|
58631
|
-
progress.uncertain = false;
|
|
58632
|
-
progress.phase = "projection";
|
|
58633
|
-
await this.project(plan.chainId, submission.transactionHash, context.bearer, context.intentId);
|
|
58634
|
-
return { ...submission, chainId: plan.chainId, skillId: plan.skillId, currentVersion: plan.currentVersion, manifestURI };
|
|
58628
|
+
/** Retained only to give installed callers an explicit upgrade instruction before any I/O. */
|
|
58629
|
+
async publishPresentation(_planValue, _context) {
|
|
58630
|
+
void _planValue;
|
|
58631
|
+
void _context;
|
|
58632
|
+
throw new TypeError("SKILL_PRESENTATION_FLOW_REMOVED: Use skill_market_presentation_update through Remote MCP.");
|
|
58635
58633
|
}
|
|
58636
58634
|
async uploadCover(path2, planValue, context) {
|
|
58637
58635
|
const plan = assetPlan(planValue, context.walletAddress);
|
|
@@ -58936,6 +58934,26 @@ var init_loopback_callback = __esm({
|
|
|
58936
58934
|
import { createHash as createHash3, randomUUID } from "node:crypto";
|
|
58937
58935
|
import { isDeepStrictEqual } from "node:util";
|
|
58938
58936
|
import { open as open2 } from "node:fs/promises";
|
|
58937
|
+
function transportErrorCode(error51) {
|
|
58938
|
+
let current = error51.cause;
|
|
58939
|
+
for (let depth = 0; depth < 4 && current instanceof Error; depth += 1) {
|
|
58940
|
+
if (current.name === "TimeoutError") return "TIMEOUT";
|
|
58941
|
+
const code = current.code;
|
|
58942
|
+
if (typeof code === "string" && /^[A-Z][A-Z0-9_]{1,63}$/u.test(code)) return code;
|
|
58943
|
+
current = current.cause;
|
|
58944
|
+
}
|
|
58945
|
+
return null;
|
|
58946
|
+
}
|
|
58947
|
+
function httpFailureCheck(cause, status, guidance) {
|
|
58948
|
+
if (cause.status !== null) return { status, message: guidance, httpStatus: cause.status };
|
|
58949
|
+
const networkErrorCode = transportErrorCode(cause);
|
|
58950
|
+
if (networkErrorCode === null) return { status, message: `No HTTP response was received. ${guidance}` };
|
|
58951
|
+
return {
|
|
58952
|
+
status,
|
|
58953
|
+
message: TLS_ERROR_CODE.test(networkErrorCode) ? `TLS certificate verification failed. If a proxy, VPN or security software intercepts HTTPS on this machine, make Node.js trust its certificate authority, for example with NODE_EXTRA_CA_CERTS. ${guidance}` : `No HTTP response was received. ${guidance}`,
|
|
58954
|
+
networkErrorCode
|
|
58955
|
+
};
|
|
58956
|
+
}
|
|
58939
58957
|
function required3(value, name) {
|
|
58940
58958
|
if (value === void 0) throw new TypeError(`CLI dependency ${name} is unavailable.`);
|
|
58941
58959
|
return value;
|
|
@@ -59203,7 +59221,7 @@ function parseTaskRecoveryJournal(value, expected) {
|
|
|
59203
59221
|
idempotencyKey: journal.idempotencyKey
|
|
59204
59222
|
});
|
|
59205
59223
|
}
|
|
59206
|
-
var MAXIMUM_STDIN_AUTHORIZATION_BYTES, FinchCliApplication;
|
|
59224
|
+
var MAXIMUM_STDIN_AUTHORIZATION_BYTES, TLS_ERROR_CODE, FinchCliApplication;
|
|
59207
59225
|
var init_application = __esm({
|
|
59208
59226
|
"src/application.ts"() {
|
|
59209
59227
|
"use strict";
|
|
@@ -59220,6 +59238,7 @@ var init_application = __esm({
|
|
|
59220
59238
|
init_cli_error();
|
|
59221
59239
|
init_loopback_callback();
|
|
59222
59240
|
MAXIMUM_STDIN_AUTHORIZATION_BYTES = 4098;
|
|
59241
|
+
TLS_ERROR_CODE = /CERT|SSL|TLS|SELF_SIGNED/u;
|
|
59223
59242
|
FinchCliApplication = class {
|
|
59224
59243
|
api;
|
|
59225
59244
|
state;
|
|
@@ -59519,6 +59538,12 @@ var init_application = __esm({
|
|
|
59519
59538
|
await required3(this.state.saveWallet, "state.saveWallet").call(this.state, { walletAddress: walletAddress2, privateKey: privateKey3 });
|
|
59520
59539
|
return Object.freeze({ walletAddress: walletAddress2 });
|
|
59521
59540
|
}
|
|
59541
|
+
async listWallets() {
|
|
59542
|
+
const walletAddresses = await required3(this.state.listWalletAddresses, "state.listWalletAddresses").call(this.state);
|
|
59543
|
+
if (walletAddresses.length === 0) return Object.freeze({ currentWalletAddress: null, walletAddresses });
|
|
59544
|
+
const current = await required3(this.state.readWalletAddress, "state.readWalletAddress").call(this.state);
|
|
59545
|
+
return Object.freeze({ currentWalletAddress: current.walletAddress, walletAddresses });
|
|
59546
|
+
}
|
|
59522
59547
|
async showWallet() {
|
|
59523
59548
|
const wallet = await required3(this.state.readWalletAddress, "state.readWalletAddress").call(this.state);
|
|
59524
59549
|
return Object.freeze({ walletAddress: wallet.walletAddress });
|
|
@@ -59600,7 +59625,7 @@ var init_application = __esm({
|
|
|
59600
59625
|
}];
|
|
59601
59626
|
} else if (cause instanceof CliHttpError) {
|
|
59602
59627
|
const unavailable = cause.status === 429 || cause.status !== null && cause.status >= 500;
|
|
59603
|
-
return [null,
|
|
59628
|
+
return [null, httpFailureCheck(cause, !unavailable && (cause.status === 401 || cause.status === 403 || cause.code === "CLI_RESPONSE_INVALID") ? "invalid" : "unavailable", guidance)];
|
|
59604
59629
|
} else if (cause instanceof TypeError || cause instanceof CliAuthorityError) {
|
|
59605
59630
|
return [null, { status: "invalid", message: guidance }];
|
|
59606
59631
|
} else {
|
|
@@ -59737,7 +59762,9 @@ var init_application = __esm({
|
|
|
59737
59762
|
if (!/^0x[0-9a-f]{40}$/u.test(target.walletAddress)) throw new TypeError("Wallet address is invalid.");
|
|
59738
59763
|
if (input.file === void 0) {
|
|
59739
59764
|
const wallets = await required3(this.state.listWalletAddresses, "state.listWalletAddresses").call(this.state);
|
|
59740
|
-
if (!wallets.includes(target.walletAddress))
|
|
59765
|
+
if (!wallets.includes(target.walletAddress)) {
|
|
59766
|
+
throw new CliUsageError("Wallet is not registered in FINCHTECH_HOME. Run finch wallet list to see registered wallets, or finch wallet use --file <PATH> to import a private key.");
|
|
59767
|
+
}
|
|
59741
59768
|
}
|
|
59742
59769
|
if (target.walletAddress === current.walletAddress.toLowerCase()) return Object.freeze(target);
|
|
59743
59770
|
if (this.state.readOptionalSession !== void 0 && await this.state.readOptionalSession.call(this.state) === null) {
|
|
@@ -60057,45 +60084,9 @@ var init_application = __esm({
|
|
|
60057
60084
|
const managed = await this.submitSkillIntent(kind === "price" ? "set_unit_price" : "set_max_supply", planFile);
|
|
60058
60085
|
return { ...managed, nextAction: { operationId: "skill_market.skills.get", request: { chainId: managed.chainId, skillId: managed.skillId } } };
|
|
60059
60086
|
}
|
|
60060
|
-
async submitSkillPresentation(
|
|
60061
|
-
|
|
60062
|
-
|
|
60063
|
-
const plan = owned.preparation;
|
|
60064
|
-
assertSigningAuthority(plan, authority.session);
|
|
60065
|
-
if (owned.stages.primary?.transactionHash) return this.confirmSkillWalletResult(owned.intentId, owned.stages.primary.transactionHash, authority.session);
|
|
60066
|
-
let journal;
|
|
60067
|
-
const walletPlan = (request2, intent2) => ({ kind: "presentation", sourceCommit: plan.sourceCommit, walletAddress: plan.walletAddress, signingAuthority: plan.signingAuthority, request: request2, ...intent2, walletIntent: { intentId: owned.intentId, kind: owned.kind } });
|
|
60068
|
-
const context = Object.freeze({
|
|
60069
|
-
privateKey: authority.wallet.privateKey,
|
|
60070
|
-
walletAddress: authority.wallet.walletAddress,
|
|
60071
|
-
bearer: authority.session.rawBearer,
|
|
60072
|
-
intentId: owned.intentId,
|
|
60073
|
-
origin: authority.session.origin,
|
|
60074
|
-
resumePrepared: async (request2, intent2) => {
|
|
60075
|
-
const fingerprint = skillBuyerIntentFingerprint(walletPlan(request2, intent2));
|
|
60076
|
-
const stored = await this.state.readSkillBuyerIntentRecovery?.(fingerprint);
|
|
60077
|
-
if (stored == null) return null;
|
|
60078
|
-
const recovered = await this.recoverSkill("intent", fingerprint);
|
|
60079
|
-
if (recovered.status !== "projected") throw new TypeError("Skill projection is pending. Resume the recorded wallet result.");
|
|
60080
|
-
return { transactionHash: String(recovered.transactionHash), blockNumber: String(recovered.blockNumber) };
|
|
60081
|
-
},
|
|
60082
|
-
onBroadcast: async (broadcast) => {
|
|
60083
|
-
journal = createSkillBuyerIntentJournal({ intent: walletPlan(broadcast.request, broadcast.intent), intentId: owned.intentId, origin: authority.session.origin, accountId: authority.session.accountId, walletAddress: authority.wallet.walletAddress, environment: authority.session.environment, transactionHash: broadcast.transactionHash, idempotencyKey: skillIntentConfirmationIdempotencyKey(Number(plan.chainId), broadcast.transactionHash) });
|
|
60084
|
-
await required3(this.state.saveSkillBuyerIntentRecovery, "state.saveSkillBuyerIntentRecovery").call(this.state, journal.fingerprint, journal);
|
|
60085
|
-
return journal.fingerprint;
|
|
60086
|
-
},
|
|
60087
|
-
onReceipt: async (blockNumber2) => {
|
|
60088
|
-
if (!journal) throw new TypeError("Skill presentation broadcast was not checkpointed.");
|
|
60089
|
-
journal = withSkillBuyerIntentReceipt(journal, blockNumber2);
|
|
60090
|
-
await required3(this.state.saveSkillBuyerIntentRecovery, "state.saveSkillBuyerIntentRecovery").call(this.state, journal.fingerprint, journal);
|
|
60091
|
-
}
|
|
60092
|
-
});
|
|
60093
|
-
const published = await required3(this.skillLocalFlow, "skill local flow").publishPresentation(plan, context);
|
|
60094
|
-
if (journal) await required3(this.state.clearSkillBuyerIntentRecovery, "state.clearSkillBuyerIntentRecovery").call(this.state, journal.fingerprint);
|
|
60095
|
-
return { ...published, nextAction: { operationId: "skill_market.manage.get", request: {
|
|
60096
|
-
chainId: published.chainId,
|
|
60097
|
-
skillId: published.skillId
|
|
60098
|
-
} } };
|
|
60087
|
+
async submitSkillPresentation(_planFile) {
|
|
60088
|
+
void _planFile;
|
|
60089
|
+
throw new TypeError("SKILL_PRESENTATION_FLOW_REMOVED: Use skill_market_presentation_update through Remote MCP to save presentation, documents and video directly without a wallet transaction.");
|
|
60099
60090
|
}
|
|
60100
60091
|
async uploadSkillAsset(path2, planFile) {
|
|
60101
60092
|
const authority = await this.walletAuthority();
|
|
@@ -60499,6 +60490,23 @@ function helpTopic(allArguments) {
|
|
|
60499
60490
|
}
|
|
60500
60491
|
return null;
|
|
60501
60492
|
}
|
|
60493
|
+
function usageError(allArguments, grammar) {
|
|
60494
|
+
const arguments_ = finchOwnArguments(allArguments);
|
|
60495
|
+
const command = FINCH_COMMANDS.filter((candidate) => candidate.split(" ").every((word, index2) => arguments_[index2] === word)).sort((left, right) => right.length - left.length)[0];
|
|
60496
|
+
if (command === void 0) {
|
|
60497
|
+
const group = FINCH_COMMANDS.filter((candidate) => candidate.startsWith(`${arguments_[0]} `));
|
|
60498
|
+
if (group.length > 0) {
|
|
60499
|
+
return new CliUsageError(`Unknown finch ${arguments_[0]} command. Supported: ${group.map((candidate) => `finch ${candidate}`).join(", ")}.`);
|
|
60500
|
+
}
|
|
60501
|
+
return new CliUsageError(`${grammar.detail ?? "Unknown finch command."} Run finch help to list supported commands.`);
|
|
60502
|
+
}
|
|
60503
|
+
const usage = FINCH_COMMAND_USAGE[command];
|
|
60504
|
+
if (grammar.detail !== null) return new CliUsageError(`${grammar.detail} Usage: ${usage}`);
|
|
60505
|
+
const accepted = new Set(usage.match(/--[a-z][a-z0-9-]*/gu) ?? []);
|
|
60506
|
+
if (accepted.has("--intent")) accepted.add("--from-file");
|
|
60507
|
+
const unsupported = [...new Set(arguments_.filter((argument) => OPTION_NAME.test(argument) && argument !== "--help" && !accepted.has(argument)))];
|
|
60508
|
+
return new CliUsageError(unsupported.length > 0 ? `finch ${command} does not accept ${unsupported.join(", ")}. Usage: ${usage}` : `Unexpected arguments for finch ${command}. Usage: ${usage}`);
|
|
60509
|
+
}
|
|
60502
60510
|
function method(value, name) {
|
|
60503
60511
|
if (value === void 0) throw new TypeError(`Command ${name} is unavailable.`);
|
|
60504
60512
|
return value;
|
|
@@ -60506,31 +60514,31 @@ function method(value, name) {
|
|
|
60506
60514
|
function exactOption(arguments_, name) {
|
|
60507
60515
|
const index2 = arguments_.indexOf(name);
|
|
60508
60516
|
if (index2 < 0 || index2 !== arguments_.lastIndexOf(name) || index2 + 1 >= arguments_.length) {
|
|
60509
|
-
throw new
|
|
60517
|
+
throw new CommandGrammarError(`${name} is required exactly once.`);
|
|
60510
60518
|
}
|
|
60511
60519
|
const value = arguments_[index2 + 1];
|
|
60512
|
-
if (value === void 0 || value.startsWith("--")) throw new
|
|
60520
|
+
if (value === void 0 || value.startsWith("--")) throw new CommandGrammarError(`${name} requires a value.`);
|
|
60513
60521
|
return value;
|
|
60514
60522
|
}
|
|
60515
60523
|
function assertExactOptions(arguments_, start, names) {
|
|
60516
60524
|
const options = arguments_.slice(start);
|
|
60517
60525
|
if (options.length !== names.length * 2) {
|
|
60518
|
-
throw new
|
|
60526
|
+
throw new CommandGrammarError();
|
|
60519
60527
|
}
|
|
60520
60528
|
const actualNames = options.filter((_value, index2) => index2 % 2 === 0);
|
|
60521
60529
|
if (actualNames.some((name) => !names.includes(name)) || new Set(actualNames).size !== names.length) {
|
|
60522
|
-
throw new
|
|
60530
|
+
throw new CommandGrammarError();
|
|
60523
60531
|
}
|
|
60524
60532
|
}
|
|
60525
60533
|
function optionalOptions(arguments_, start, names) {
|
|
60526
60534
|
const options = arguments_.slice(start);
|
|
60527
|
-
if (options.length % 2 !== 0) throw new
|
|
60535
|
+
if (options.length % 2 !== 0) throw new CommandGrammarError();
|
|
60528
60536
|
const result2 = {};
|
|
60529
60537
|
for (let index2 = 0; index2 < options.length; index2 += 2) {
|
|
60530
60538
|
const name = options[index2];
|
|
60531
60539
|
const value = options[index2 + 1];
|
|
60532
60540
|
if (name === void 0 || value === void 0 || !names.includes(name) || Object.hasOwn(result2, name) || value.startsWith("--")) {
|
|
60533
|
-
throw new
|
|
60541
|
+
throw new CommandGrammarError();
|
|
60534
60542
|
}
|
|
60535
60543
|
result2[name] = value;
|
|
60536
60544
|
}
|
|
@@ -60542,10 +60550,18 @@ function result(command, data) {
|
|
|
60542
60550
|
function walletIntentInput(arguments_) {
|
|
60543
60551
|
const file2 = arguments_.includes("--from-file") ? exactOption(arguments_, "--from-file") : void 0;
|
|
60544
60552
|
const intent2 = arguments_.includes("--intent") ? exactOption(arguments_, "--intent") : void 0;
|
|
60545
|
-
if (file2 === void 0 === (intent2 === void 0)) throw new
|
|
60553
|
+
if (file2 === void 0 === (intent2 === void 0)) throw new CommandGrammarError("Provide exactly one of --intent or --from-file.");
|
|
60546
60554
|
return intent2 ?? file2;
|
|
60547
60555
|
}
|
|
60548
60556
|
async function routeCommand(arguments_, application) {
|
|
60557
|
+
try {
|
|
60558
|
+
return await dispatchCommand(arguments_, application);
|
|
60559
|
+
} catch (cause) {
|
|
60560
|
+
if (cause instanceof CommandGrammarError) throw usageError(arguments_, cause);
|
|
60561
|
+
throw cause;
|
|
60562
|
+
}
|
|
60563
|
+
}
|
|
60564
|
+
async function dispatchCommand(arguments_, application) {
|
|
60549
60565
|
if (arguments_.length === 0 || arguments_.length === 1 && ["--help", "help"].includes(arguments_[0])) {
|
|
60550
60566
|
return Object.freeze({ command: "help", commands: FINCH_COMMANDS });
|
|
60551
60567
|
}
|
|
@@ -60573,12 +60589,15 @@ async function routeCommand(arguments_, application) {
|
|
|
60573
60589
|
}
|
|
60574
60590
|
const commands = FINCH_COMMANDS.filter((command) => command.startsWith(`${topic} `));
|
|
60575
60591
|
if (commands.length > 0) return Object.freeze({ command: "help", topic, commands });
|
|
60576
|
-
throw new
|
|
60592
|
+
throw new CommandGrammarError("Unknown finch help topic.");
|
|
60577
60593
|
}
|
|
60578
60594
|
const [first, second, third] = arguments_;
|
|
60579
60595
|
if (first === "wallet" && second === "create" && arguments_.length === 2) {
|
|
60580
60596
|
return result("wallet.create", await method(application.createWallet, "wallet create").call(application));
|
|
60581
60597
|
}
|
|
60598
|
+
if (first === "wallet" && second === "list" && arguments_.length === 2) {
|
|
60599
|
+
return result("wallet.list", await method(application.listWallets, "wallet list").call(application));
|
|
60600
|
+
}
|
|
60582
60601
|
if (first === "wallet" && second === "show" && arguments_.length === 2) {
|
|
60583
60602
|
return result("wallet.show", await method(application.showWallet, "wallet show").call(application));
|
|
60584
60603
|
}
|
|
@@ -60589,13 +60608,13 @@ async function routeCommand(arguments_, application) {
|
|
|
60589
60608
|
if (arguments_.length === 4 && third === "--file" && arguments_[3] !== void 0 && !arguments_[3].startsWith("--")) {
|
|
60590
60609
|
return result("wallet.use", await method(application.useWallet, "wallet use").call(application, Object.freeze({ file: arguments_[3] })));
|
|
60591
60610
|
}
|
|
60592
|
-
throw new
|
|
60611
|
+
throw new CommandGrammarError();
|
|
60593
60612
|
}
|
|
60594
60613
|
if (first === "login") {
|
|
60595
60614
|
const rawChainId = exactOption(arguments_, "--chain-id");
|
|
60596
60615
|
assertExactOptions(arguments_, 1, ["--chain-id"]);
|
|
60597
60616
|
if (!/^[1-9][0-9]*$/u.test(rawChainId) || !Number.isSafeInteger(Number(rawChainId))) {
|
|
60598
|
-
throw new
|
|
60617
|
+
throw new CommandGrammarError("--chain-id must be a positive safe integer.");
|
|
60599
60618
|
}
|
|
60600
60619
|
return result("login", await method(application.login, "login").call(application, Number(rawChainId)));
|
|
60601
60620
|
}
|
|
@@ -60632,7 +60651,7 @@ async function routeCommand(arguments_, application) {
|
|
|
60632
60651
|
const framed = arguments_.includes("--from-file");
|
|
60633
60652
|
const bearer = arguments_.includes("--bearer-token-file");
|
|
60634
60653
|
if (framed === bearer) {
|
|
60635
|
-
throw new
|
|
60654
|
+
throw new CommandGrammarError("Choose exactly one of --from-file or --bearer-token-file.");
|
|
60636
60655
|
}
|
|
60637
60656
|
const input = framed ? Object.freeze({ kind: "framed", path: exactOption(arguments_, "--from-file") }) : Object.freeze({
|
|
60638
60657
|
kind: "bearer_token",
|
|
@@ -60697,7 +60716,7 @@ async function routeCommand(arguments_, application) {
|
|
|
60697
60716
|
if (first === "task" && second === "recover" && third !== void 0 && arguments_.length === 4) {
|
|
60698
60717
|
const kind = arguments_[3];
|
|
60699
60718
|
if (!["publish", "award", "reclaim"].includes(String(kind))) {
|
|
60700
|
-
throw new
|
|
60719
|
+
throw new CommandGrammarError("Task recovery kind must be publish, award, or reclaim.");
|
|
60701
60720
|
}
|
|
60702
60721
|
return result("task.recover", await method(application.recoverTask, "task recover").call(application, third, kind));
|
|
60703
60722
|
}
|
|
@@ -60708,7 +60727,7 @@ async function routeCommand(arguments_, application) {
|
|
|
60708
60727
|
}
|
|
60709
60728
|
if (first === "skill" && second === "recover" && arguments_.length === 4) {
|
|
60710
60729
|
if (!["publication", "intent"].includes(String(third)) || arguments_[3] === void 0) {
|
|
60711
|
-
throw new
|
|
60730
|
+
throw new CommandGrammarError("Skill recovery kind must be publication or intent.");
|
|
60712
60731
|
}
|
|
60713
60732
|
return result("skill.recover", await method(application.recoverSkill, "skill recover").call(application, third, arguments_[3]));
|
|
60714
60733
|
}
|
|
@@ -60739,16 +60758,18 @@ async function routeCommand(arguments_, application) {
|
|
|
60739
60758
|
optionalOptions(arguments_, 2, ["--from-file", "--intent", "--out-file"]);
|
|
60740
60759
|
return result("skill.download", await method(application.downloadSkill, "skill download").call(application, walletIntentInput(arguments_), exactOption(arguments_, "--out-file")));
|
|
60741
60760
|
}
|
|
60742
|
-
throw new
|
|
60761
|
+
throw new CommandGrammarError();
|
|
60743
60762
|
}
|
|
60744
|
-
var FINCH_COMMANDS, FINCH_CLI_IDENTITY, FINCH_CLI_PACKAGE, FINCH_CLI_VERSION, FINCH_COMMAND_USAGE;
|
|
60763
|
+
var FINCH_COMMANDS, FINCH_CLI_IDENTITY, FINCH_CLI_PACKAGE, FINCH_CLI_VERSION, FINCH_COMMAND_USAGE, CommandGrammarError, OPTION_NAME;
|
|
60745
60764
|
var init_command_router = __esm({
|
|
60746
60765
|
"src/command-router.ts"() {
|
|
60747
60766
|
"use strict";
|
|
60748
60767
|
init_package();
|
|
60749
60768
|
init_v1();
|
|
60769
|
+
init_cli_error();
|
|
60750
60770
|
FINCH_COMMANDS = Object.freeze([
|
|
60751
60771
|
"wallet create",
|
|
60772
|
+
"wallet list",
|
|
60752
60773
|
"wallet show",
|
|
60753
60774
|
"wallet use",
|
|
60754
60775
|
"login",
|
|
@@ -60790,6 +60811,7 @@ var init_command_router = __esm({
|
|
|
60790
60811
|
FINCH_CLI_VERSION = package_default.version;
|
|
60791
60812
|
FINCH_COMMAND_USAGE = Object.freeze({
|
|
60792
60813
|
"wallet create": "finch wallet create",
|
|
60814
|
+
"wallet list": "finch wallet list",
|
|
60793
60815
|
"wallet show": "finch wallet show",
|
|
60794
60816
|
"wallet use": "finch wallet use <ADDRESS> | finch wallet use --file <PATH>",
|
|
60795
60817
|
login: "finch login --chain-id <CHAIN_ID>",
|
|
@@ -60826,6 +60848,15 @@ var init_command_router = __esm({
|
|
|
60826
60848
|
"skill recover publication": "finch skill recover publication <FINGERPRINT>",
|
|
60827
60849
|
"skill recover intent": "finch skill recover intent <FINGERPRINT>"
|
|
60828
60850
|
});
|
|
60851
|
+
CommandGrammarError = class extends Error {
|
|
60852
|
+
constructor(detail = null) {
|
|
60853
|
+
super(detail ?? "Command arguments do not match the finch command tree.");
|
|
60854
|
+
this.detail = detail;
|
|
60855
|
+
this.name = "CommandGrammarError";
|
|
60856
|
+
}
|
|
60857
|
+
detail;
|
|
60858
|
+
};
|
|
60859
|
+
OPTION_NAME = /^--[a-z][a-z0-9-]{0,39}$/u;
|
|
60829
60860
|
}
|
|
60830
60861
|
});
|
|
60831
60862
|
|
|
@@ -63487,7 +63518,7 @@ function expectedCall(kind, request2, deployment) {
|
|
|
63487
63518
|
function expectedPreparedCall(action, request2, deployment) {
|
|
63488
63519
|
const skillId = () => unsigned2(request2.skillId, "Skill id", true);
|
|
63489
63520
|
if (action === "createSkill") {
|
|
63490
|
-
if (typeof request2.plaintext !== "boolean"
|
|
63521
|
+
if (typeof request2.plaintext !== "boolean") throw new TypeError("Skill create request is invalid.");
|
|
63491
63522
|
return {
|
|
63492
63523
|
to: getAddress(deployment.skillFactoryAddress),
|
|
63493
63524
|
value: BigInt(0),
|
|
@@ -63503,8 +63534,10 @@ function expectedPreparedCall(action, request2, deployment) {
|
|
|
63503
63534
|
plaintext: request2.plaintext,
|
|
63504
63535
|
unitPrice: unsigned2(request2.unitPrice, "Skill unit price"),
|
|
63505
63536
|
maxSupply: unsigned2(request2.maxSupply, "Skill max supply"),
|
|
63506
|
-
|
|
63507
|
-
|
|
63537
|
+
// Immutable and Finch-enforced nowhere, so every entrance writes the same fixed
|
|
63538
|
+
// values (Finch-Site issue #1240) instead of trusting caller-supplied ones.
|
|
63539
|
+
royaltyBPS: BigInt(SKILL_PUBLICATION_ROYALTY_BPS),
|
|
63540
|
+
usageLimit: BigInt(SKILL_PUBLICATION_USAGE_LIMIT)
|
|
63508
63541
|
}] })
|
|
63509
63542
|
};
|
|
63510
63543
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@finchtech/cli",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "Finch Agent CLI for wallet custody, Session-owned execution, and MCP OAuth approval.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -37,10 +37,10 @@
|
|
|
37
37
|
"viem": "2.55.15",
|
|
38
38
|
"vitest": "4.1.10",
|
|
39
39
|
"@finch/agent-market-contracts": "0.1.0",
|
|
40
|
-
"@finch/deployment-manifest": "0.1.0",
|
|
41
|
-
"@finch/skill-market-contracts": "0.1.0",
|
|
42
40
|
"@finch/skill-content": "0.1.0",
|
|
43
|
-
"@finch/
|
|
41
|
+
"@finch/deployment-manifest": "0.1.0",
|
|
42
|
+
"@finch/task-market-contracts": "0.1.0",
|
|
43
|
+
"@finch/skill-market-contracts": "0.1.0"
|
|
44
44
|
},
|
|
45
45
|
"scripts": {
|
|
46
46
|
"build": "esbuild src/bootstrap.ts --bundle --platform=node --format=esm --target=node20 --outfile=dist/finch.js --banner:js=\"import { createRequire as createBundleRequire } from 'node:module'; const require = createBundleRequire(import.meta.url);\"",
|