vana-cli 0.15.0 → 0.23.3
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 +73 -15
- package/dist/cli/app/ask.d.ts +38 -0
- package/dist/cli/app/ask.d.ts.map +1 -0
- package/dist/cli/app/ask.js +110 -0
- package/dist/cli/app/ask.js.map +1 -0
- package/dist/cli/app/derivatives.d.ts +41 -0
- package/dist/cli/app/derivatives.d.ts.map +1 -0
- package/dist/cli/app/derivatives.js +227 -0
- package/dist/cli/app/derivatives.js.map +1 -0
- package/dist/cli/app/escrow.d.ts +44 -0
- package/dist/cli/app/escrow.d.ts.map +1 -0
- package/dist/cli/app/escrow.js +275 -0
- package/dist/cli/app/escrow.js.map +1 -0
- package/dist/cli/app/index.d.ts +11 -0
- package/dist/cli/app/index.d.ts.map +1 -0
- package/dist/cli/app/index.js +151 -0
- package/dist/cli/app/index.js.map +1 -0
- package/dist/cli/app/onchain.d.ts +14 -0
- package/dist/cli/app/onchain.d.ts.map +1 -0
- package/dist/cli/app/onchain.js +84 -0
- package/dist/cli/app/onchain.js.map +1 -0
- package/dist/cli/app/outcome.d.ts +45 -0
- package/dist/cli/app/outcome.d.ts.map +1 -0
- package/dist/cli/app/outcome.js +55 -0
- package/dist/cli/app/outcome.js.map +1 -0
- package/dist/cli/app/read.d.ts +43 -0
- package/dist/cli/app/read.d.ts.map +1 -0
- package/dist/cli/app/read.js +429 -0
- package/dist/cli/app/read.js.map +1 -0
- package/dist/cli/app/register.d.ts +34 -0
- package/dist/cli/app/register.d.ts.map +1 -0
- package/dist/cli/app/register.js +113 -0
- package/dist/cli/app/register.js.map +1 -0
- package/dist/cli/app/request.d.ts +50 -0
- package/dist/cli/app/request.d.ts.map +1 -0
- package/dist/cli/app/request.js +252 -0
- package/dist/cli/app/request.js.map +1 -0
- package/dist/cli/app/requests.d.ts +21 -0
- package/dist/cli/app/requests.d.ts.map +1 -0
- package/dist/cli/app/requests.js +163 -0
- package/dist/cli/app/requests.js.map +1 -0
- package/dist/cli/app/whoami.d.ts +13 -0
- package/dist/cli/app/whoami.d.ts.map +1 -0
- package/dist/cli/app/whoami.js +71 -0
- package/dist/cli/app/whoami.js.map +1 -0
- package/dist/cli/auth.d.ts +18 -0
- package/dist/cli/auth.d.ts.map +1 -1
- package/dist/cli/auth.js +109 -7
- package/dist/cli/auth.js.map +1 -1
- package/dist/cli/index.d.ts +2 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +307 -49
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp-server.d.ts.map +1 -1
- package/dist/cli/mcp-server.js +32 -3
- package/dist/cli/mcp-server.js.map +1 -1
- package/dist/core/app-key.d.ts +50 -0
- package/dist/core/app-key.d.ts.map +1 -0
- package/dist/core/app-key.js +171 -0
- package/dist/core/app-key.js.map +1 -0
- package/dist/core/assets.d.ts +33 -0
- package/dist/core/assets.d.ts.map +1 -0
- package/dist/core/assets.js +87 -0
- package/dist/core/assets.js.map +1 -0
- package/dist/core/cli-types.d.ts +30 -0
- package/dist/core/cli-types.d.ts.map +1 -1
- package/dist/core/cli-types.js +16 -0
- package/dist/core/cli-types.js.map +1 -1
- package/dist/core/exit-codes.d.ts +48 -0
- package/dist/core/exit-codes.d.ts.map +1 -0
- package/dist/core/exit-codes.js +96 -0
- package/dist/core/exit-codes.js.map +1 -0
- package/dist/core/network.d.ts +52 -0
- package/dist/core/network.d.ts.map +1 -0
- package/dist/core/network.js +83 -0
- package/dist/core/network.js.map +1 -0
- package/dist/core/paths.d.ts +4 -2
- package/dist/core/paths.d.ts.map +1 -1
- package/dist/core/paths.js +8 -6
- package/dist/core/paths.js.map +1 -1
- package/dist/core/receipts.d.ts +37 -0
- package/dist/core/receipts.d.ts.map +1 -0
- package/dist/core/receipts.js +72 -0
- package/dist/core/receipts.js.map +1 -0
- package/dist/core/requests-store.d.ts +54 -0
- package/dist/core/requests-store.d.ts.map +1 -0
- package/dist/core/requests-store.js +83 -0
- package/dist/core/requests-store.js.map +1 -0
- package/dist/personal-server/registered.d.ts +25 -0
- package/dist/personal-server/registered.d.ts.map +1 -0
- package/dist/personal-server/registered.js +49 -0
- package/dist/personal-server/registered.js.map +1 -0
- package/dist/server/request-signer.d.ts.map +1 -1
- package/dist/server/request-signer.js +7 -24
- package/dist/server/request-signer.js.map +1 -1
- package/dist/server/session-relay.d.ts +6 -5
- package/dist/server/session-relay.d.ts.map +1 -1
- package/dist/server/session-relay.js +48 -51
- package/dist/server/session-relay.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,37 +1,95 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Vana CLI
|
|
2
2
|
|
|
3
|
-
`vana
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
`vana` is the command line for Vana: it collects a person's own data into
|
|
4
|
+
their Personal Server, and it drives the builder side of the protocol so an
|
|
5
|
+
app or an agent can ask for that data, read it, and pay for it from a
|
|
6
|
+
terminal.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
This repository also ships the JavaScript SDK the CLI is built on, which is
|
|
9
|
+
documented further down.
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
## Install
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
Run it without installing anything:
|
|
12
14
|
|
|
13
15
|
```bash
|
|
14
|
-
|
|
15
|
-
brew install vana
|
|
16
|
-
vana status
|
|
16
|
+
npx vana-cli status
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
Or
|
|
19
|
+
Or install the standalone binary, which is signed and notarized on macOS:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
22
|
curl -fsSL https://raw.githubusercontent.com/vana-com/vana-cli/main/install/install.sh | sh
|
|
23
|
+
vana status
|
|
23
24
|
```
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
Windows uses `install/install.ps1`. Homebrew (`brew tap vana-com/tap && brew
|
|
27
|
+
install vana`) is still published but lags the installer.
|
|
28
|
+
|
|
29
|
+
The npm route runs under your own Node, which some endpoint security
|
|
30
|
+
products prefer over an unknown executable; the installer gives you a
|
|
31
|
+
single self-contained binary with no Node required. Both are the same CLI.
|
|
26
32
|
|
|
27
|
-
|
|
33
|
+
## Two halves
|
|
28
34
|
|
|
29
|
-
|
|
35
|
+
**Owner side** collects your own data and keeps it in your Personal Server:
|
|
30
36
|
|
|
31
37
|
```bash
|
|
32
|
-
vana
|
|
38
|
+
vana login # Vana account, or --server <url> for a self-hosted PS
|
|
39
|
+
vana connect github # managed browser, collects, syncs to your server
|
|
40
|
+
vana data show github # what was collected
|
|
41
|
+
vana server status # your server, local and registered URLs
|
|
33
42
|
```
|
|
34
43
|
|
|
44
|
+
**Builder side** is what an app or an agent uses to work with someone
|
|
45
|
+
else's data, with their consent:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
vana app register # once per machine
|
|
49
|
+
vana app request --scopes github.repositories # prints an approval URL, waits
|
|
50
|
+
vana app read github.repositories --grant <id> # signed read
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`request` returns the grant id once the person approves. `read` stops at
|
|
54
|
+
exit 4 with the exact price before spending anything; add `--pay` to settle
|
|
55
|
+
it from escrow and `--max-fee` to cap it. The rest of the group:
|
|
56
|
+
|
|
57
|
+
| Command | What it does |
|
|
58
|
+
| ---------------------------------------------------- | ------------------------------------------------------------------------------- |
|
|
59
|
+
| `vana app ask "<q>" --sources a,b --derived <scope>` | ask a question computed on the person's own server, without reading the sources |
|
|
60
|
+
| `vana app status <derived-scope>` | is the answer coming, and when |
|
|
61
|
+
| `vana app lineage <scope>` | what an answer was computed from, redacted where it must be |
|
|
62
|
+
| `vana app whoami` | app address, key source, network, registration state |
|
|
63
|
+
| `vana app requests list\|show <id>` | what was asked, what was approved |
|
|
64
|
+
| `vana app escrow balance\|fund` | what the app can spend, and funding it |
|
|
65
|
+
| `vana app onchain <scope> --owner <addr>` | data point version, hashes, deletion state |
|
|
66
|
+
|
|
67
|
+
Everything defaults to **moksha**, the testnet; `--network mainnet` spends
|
|
68
|
+
real money and is never implied.
|
|
69
|
+
|
|
70
|
+
## For agents
|
|
71
|
+
|
|
72
|
+
Every command takes `--json` and `--no-input`, and exits with a code an
|
|
73
|
+
agent can branch on: `0` done, `1` failed, `2` bad usage, `3` no grant,
|
|
74
|
+
`4` payment required, `5` no server answered, `6` not ready yet, `7` a
|
|
75
|
+
person has to act. The full contract is in
|
|
76
|
+
[docs/CLI-EXIT-CODE-MATRIX.md](./docs/CLI-EXIT-CODE-MATRIX.md).
|
|
77
|
+
|
|
78
|
+
Install the skills that teach an agent each half:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
vana skills install builder # ask for access, read, pay
|
|
82
|
+
vana skills install connect-data # collect your own data
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
There is also an MCP server over stdio for clients that prefer tools:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
claude mcp add vana -- vana mcp
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## The SDK
|
|
92
|
+
|
|
35
93
|
## What problem this solves
|
|
36
94
|
|
|
37
95
|
Your users already have rich personal data — ChatGPT conversations, Instagram activity, Gmail, purchase history — but it's locked inside the platforms that collected it. As a builder, you can't easily use that data to personalize onboarding, tailor recommendations, or skip lengthy signup forms.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `vana app ask "<question>" --sources a,b --derived <scope>`
|
|
3
|
+
*
|
|
4
|
+
* The consent path by default: the question travels inside an access
|
|
5
|
+
* request, so the person approves the question itself and the app ends up
|
|
6
|
+
* holding a grant on the answer rather than on the sources it was computed
|
|
7
|
+
* from. `--registered` switches to the builder-registered path, which needs
|
|
8
|
+
* a read grant on every source scope and says so.
|
|
9
|
+
*
|
|
10
|
+
* This composes commands that already exist rather than reimplementing
|
|
11
|
+
* them: it creates the request, waits for the answer to settle, and reads
|
|
12
|
+
* the derived scope through the same escrow path, gates and receipts as any
|
|
13
|
+
* other read. Costs are reported separately (see derivatives.ts).
|
|
14
|
+
*/
|
|
15
|
+
import { type AppCommandOptions } from "./outcome.js";
|
|
16
|
+
import { runAppRead } from "./read.js";
|
|
17
|
+
import { runAppRequest } from "./request.js";
|
|
18
|
+
import { runAppStatus } from "./derivatives.js";
|
|
19
|
+
export interface AskCommandOptions extends AppCommandOptions {
|
|
20
|
+
sources?: string;
|
|
21
|
+
derived?: string;
|
|
22
|
+
/** Settle the derived-scope read from escrow. */
|
|
23
|
+
pay?: boolean;
|
|
24
|
+
maxFee?: string;
|
|
25
|
+
timeout?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Register the question as a builder instead of carrying it through
|
|
28
|
+
* consent. Needs a read grant on every source scope.
|
|
29
|
+
*/
|
|
30
|
+
registered?: boolean;
|
|
31
|
+
}
|
|
32
|
+
export interface AskDeps {
|
|
33
|
+
request?: typeof runAppRequest;
|
|
34
|
+
status?: typeof runAppStatus;
|
|
35
|
+
read?: typeof runAppRead;
|
|
36
|
+
}
|
|
37
|
+
export declare function runAppAsk(question: string, options: AskCommandOptions, deps?: AskDeps): Promise<number>;
|
|
38
|
+
//# sourceMappingURL=ask.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ask.d.ts","sourceRoot":"","sources":["../../../src/cli/app/ask.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAOH,OAAO,EAAkB,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,UAAU,EAA2B,MAAM,WAAW,CAAC;AAChE,OAAO,EAAE,aAAa,EAA8B,MAAM,cAAc,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAgBhD,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;IAC1D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,OAAO;IACtB,OAAO,CAAC,EAAE,OAAO,aAAa,CAAC;IAC/B,MAAM,CAAC,EAAE,OAAO,YAAY,CAAC;IAC7B,IAAI,CAAC,EAAE,OAAO,UAAU,CAAC;CAC1B;AAED,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,iBAAiB,EAC1B,IAAI,GAAE,OAAY,GACjB,OAAO,CAAC,MAAM,CAAC,CA0FjB"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `vana app ask "<question>" --sources a,b --derived <scope>`
|
|
3
|
+
*
|
|
4
|
+
* The consent path by default: the question travels inside an access
|
|
5
|
+
* request, so the person approves the question itself and the app ends up
|
|
6
|
+
* holding a grant on the answer rather than on the sources it was computed
|
|
7
|
+
* from. `--registered` switches to the builder-registered path, which needs
|
|
8
|
+
* a read grant on every source scope and says so.
|
|
9
|
+
*
|
|
10
|
+
* This composes commands that already exist rather than reimplementing
|
|
11
|
+
* them: it creates the request, waits for the answer to settle, and reads
|
|
12
|
+
* the derived scope through the same escrow path, gates and receipts as any
|
|
13
|
+
* other read. Costs are reported separately (see derivatives.ts).
|
|
14
|
+
*/
|
|
15
|
+
import { UnknownNetworkError, resolveNetwork, } from "../../core/network.js";
|
|
16
|
+
import { emitAppOutcome } from "./outcome.js";
|
|
17
|
+
import { runAppRead } from "./read.js";
|
|
18
|
+
import { runAppRequest } from "./request.js";
|
|
19
|
+
import { runAppStatus } from "./derivatives.js";
|
|
20
|
+
import { createRequestsStore } from "../../core/requests-store.js";
|
|
21
|
+
/** Newest approved grant covering a scope, from the local request index. */
|
|
22
|
+
function findGrantForScope(scope, network) {
|
|
23
|
+
return (createRequestsStore()
|
|
24
|
+
.list({ network })
|
|
25
|
+
.find((entry) => Boolean(entry.grantId) &&
|
|
26
|
+
(entry.approvedScopes ?? entry.scopes).includes(scope))?.grantId ?? null);
|
|
27
|
+
}
|
|
28
|
+
export async function runAppAsk(question, options, deps = {}) {
|
|
29
|
+
let network;
|
|
30
|
+
try {
|
|
31
|
+
network = resolveNetwork(options.network);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
if (error instanceof UnknownNetworkError) {
|
|
35
|
+
return emitAppOutcome(options, {
|
|
36
|
+
status: "failed",
|
|
37
|
+
code: "bad_usage",
|
|
38
|
+
message: error.message,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
const sources = (options.sources ?? "")
|
|
44
|
+
.split(",")
|
|
45
|
+
.map((entry) => entry.trim())
|
|
46
|
+
.filter(Boolean);
|
|
47
|
+
if (!question.trim() || sources.length === 0 || !options.derived) {
|
|
48
|
+
return emitAppOutcome(options, {
|
|
49
|
+
status: "failed",
|
|
50
|
+
code: "bad_usage",
|
|
51
|
+
message: "ask needs a question, --sources and --derived.",
|
|
52
|
+
remedy: `vana app ask "..." --sources spotify.history --derived myapp.summary`,
|
|
53
|
+
network: network.name,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
if (options.registered) {
|
|
57
|
+
// Honest refusal rather than a half-path: registering a question as the
|
|
58
|
+
// builder requires a read grant on every source scope, which is exactly
|
|
59
|
+
// the access the consent path is designed to avoid. Until someone needs
|
|
60
|
+
// it, say so instead of pretending.
|
|
61
|
+
return emitAppOutcome(options, {
|
|
62
|
+
status: "failed",
|
|
63
|
+
code: "bad_usage",
|
|
64
|
+
message: "--registered is not wired yet. It needs a read grant on every source scope, which the consent path deliberately avoids.",
|
|
65
|
+
remedy: `drop --registered to ask through consent`,
|
|
66
|
+
network: network.name,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
// 1. Ask the person. The derived scope must also be granted as a plain
|
|
70
|
+
// read so the answer can be read back; request validates that.
|
|
71
|
+
const requestOptions = {
|
|
72
|
+
...options,
|
|
73
|
+
scopes: [...sources, options.derived].join(","),
|
|
74
|
+
question,
|
|
75
|
+
derived: options.derived,
|
|
76
|
+
sources: options.sources,
|
|
77
|
+
};
|
|
78
|
+
const requestExit = await (deps.request ?? runAppRequest)(requestOptions);
|
|
79
|
+
if (requestExit !== 0) {
|
|
80
|
+
// request already emitted a precise outcome (7 when a person must act,
|
|
81
|
+
// 3 on denial, 6 on timeout); nothing to add.
|
|
82
|
+
return requestExit;
|
|
83
|
+
}
|
|
84
|
+
// 2. Wait for the answer to settle on the owner's server.
|
|
85
|
+
const statusExit = await (deps.status ?? runAppStatus)(options.derived, options);
|
|
86
|
+
if (statusExit !== 0) {
|
|
87
|
+
return statusExit;
|
|
88
|
+
}
|
|
89
|
+
// 3. Read the answer, through the ordinary billable read path. The grant
|
|
90
|
+
// comes from the request just approved; read resolves the owner and the
|
|
91
|
+
// server from it.
|
|
92
|
+
const grantId = findGrantForScope(options.derived, network.name);
|
|
93
|
+
if (!grantId) {
|
|
94
|
+
return emitAppOutcome(options, {
|
|
95
|
+
status: "failed",
|
|
96
|
+
code: "grant_invalid",
|
|
97
|
+
message: "The request was approved but no grant id was recorded.",
|
|
98
|
+
remedy: "vana app requests list",
|
|
99
|
+
network: network.name,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
const readOptions = {
|
|
103
|
+
...options,
|
|
104
|
+
grant: grantId,
|
|
105
|
+
pay: options.pay,
|
|
106
|
+
maxFee: options.maxFee,
|
|
107
|
+
};
|
|
108
|
+
return (deps.read ?? runAppRead)(options.derived, readOptions);
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=ask.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ask.js","sourceRoot":"","sources":["../../../src/cli/app/ask.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `vana app ask | status | lineage` - questions over a person's data.
|
|
3
|
+
*
|
|
4
|
+
* A question is computed on the owner's own Personal Server over source
|
|
5
|
+
* scopes the app never reads, and the answer is written into a derived
|
|
6
|
+
* scope the app does read. That is why `ask` goes through consent: the
|
|
7
|
+
* question travels inside the access request, so the app holds a grant on
|
|
8
|
+
* the answer rather than on the sources.
|
|
9
|
+
*
|
|
10
|
+
* Pricing note. Two separate costs live here and the CLI reports them
|
|
11
|
+
* separately rather than folding them into one number, because only one of
|
|
12
|
+
* them exists today and the other is an open decision:
|
|
13
|
+
*
|
|
14
|
+
* - the compute itself emits no fee event today, so it is reported as
|
|
15
|
+
* `computeCost: null` rather than as free; when a price appears it is a
|
|
16
|
+
* number in a field that already exists
|
|
17
|
+
* - reading the derived scope afterwards is an ordinary billable read and
|
|
18
|
+
* goes through the same escrow path, gates and receipts as any other
|
|
19
|
+
*
|
|
20
|
+
* No price is hardcoded anywhere: every amount comes from what the
|
|
21
|
+
* protocol quotes.
|
|
22
|
+
*/
|
|
23
|
+
import { getDerivativeStatus, getLineage } from "@opendatalabs/vana-sdk";
|
|
24
|
+
import { resolveAppKey } from "../../core/app-key.js";
|
|
25
|
+
import { type RequestsStore } from "../../core/requests-store.js";
|
|
26
|
+
import { type AppCommandOptions } from "./outcome.js";
|
|
27
|
+
export interface DerivativeCommandOptions extends AppCommandOptions {
|
|
28
|
+
/** Grant covering the derived scope; resolved from the store when absent. */
|
|
29
|
+
grant?: string;
|
|
30
|
+
/** Personal Server URL; resolved from the stored request when absent. */
|
|
31
|
+
server?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface DerivativeDeps {
|
|
34
|
+
resolveKey?: typeof resolveAppKey;
|
|
35
|
+
requests?: RequestsStore;
|
|
36
|
+
status?: typeof getDerivativeStatus;
|
|
37
|
+
lineage?: typeof getLineage;
|
|
38
|
+
}
|
|
39
|
+
export declare function runAppStatus(derivedScope: string, options: DerivativeCommandOptions, deps?: DerivativeDeps): Promise<number>;
|
|
40
|
+
export declare function runAppLineage(scope: string, options: DerivativeCommandOptions, deps?: DerivativeDeps): Promise<number>;
|
|
41
|
+
//# sourceMappingURL=derivatives.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derivatives.d.ts","sourceRoot":"","sources":["../../../src/cli/app/derivatives.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EACL,mBAAmB,EACnB,UAAU,EAEX,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAEL,aAAa,EAEd,MAAM,uBAAuB,CAAC;AAM/B,OAAO,EAEL,KAAK,aAAa,EAEnB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAkB,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtE,MAAM,WAAW,wBAAyB,SAAQ,iBAAiB;IACjE,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,OAAO,aAAa,CAAC;IAClC,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,mBAAmB,CAAC;IACpC,OAAO,CAAC,EAAE,OAAO,UAAU,CAAC;CAC7B;AAwHD,wBAAsB,YAAY,CAChC,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,wBAAwB,EACjC,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,MAAM,CAAC,CA6DjB;AAED,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,wBAAwB,EACjC,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,MAAM,CAAC,CAgCjB"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `vana app ask | status | lineage` - questions over a person's data.
|
|
3
|
+
*
|
|
4
|
+
* A question is computed on the owner's own Personal Server over source
|
|
5
|
+
* scopes the app never reads, and the answer is written into a derived
|
|
6
|
+
* scope the app does read. That is why `ask` goes through consent: the
|
|
7
|
+
* question travels inside the access request, so the app holds a grant on
|
|
8
|
+
* the answer rather than on the sources.
|
|
9
|
+
*
|
|
10
|
+
* Pricing note. Two separate costs live here and the CLI reports them
|
|
11
|
+
* separately rather than folding them into one number, because only one of
|
|
12
|
+
* them exists today and the other is an open decision:
|
|
13
|
+
*
|
|
14
|
+
* - the compute itself emits no fee event today, so it is reported as
|
|
15
|
+
* `computeCost: null` rather than as free; when a price appears it is a
|
|
16
|
+
* number in a field that already exists
|
|
17
|
+
* - reading the derived scope afterwards is an ordinary billable read and
|
|
18
|
+
* goes through the same escrow path, gates and receipts as any other
|
|
19
|
+
*
|
|
20
|
+
* No price is hardcoded anywhere: every amount comes from what the
|
|
21
|
+
* protocol quotes.
|
|
22
|
+
*/
|
|
23
|
+
import { getDerivativeStatus, getLineage, isDerivativeStatusSettled, } from "@opendatalabs/vana-sdk";
|
|
24
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
25
|
+
import { AppKeyMissingError, resolveAppKey, } from "../../core/app-key.js";
|
|
26
|
+
import { UnknownNetworkError, resolveNetwork, } from "../../core/network.js";
|
|
27
|
+
import { createRequestsStore, } from "../../core/requests-store.js";
|
|
28
|
+
import { emitAppOutcome } from "./outcome.js";
|
|
29
|
+
/**
|
|
30
|
+
* Resolve what a derivative call needs: the network, the app key, a grant
|
|
31
|
+
* covering the derived scope and the server that holds it. Explicit flags
|
|
32
|
+
* win; otherwise the newest approved request that covers the scope answers
|
|
33
|
+
* both, which is how `ask` hands off to `status` without the caller
|
|
34
|
+
* carrying ids around.
|
|
35
|
+
*/
|
|
36
|
+
function resolveContext(derivedScope, options, deps) {
|
|
37
|
+
let network;
|
|
38
|
+
try {
|
|
39
|
+
network = resolveNetwork(options.network);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
if (error instanceof UnknownNetworkError) {
|
|
43
|
+
return {
|
|
44
|
+
ok: false,
|
|
45
|
+
exitCode: emitAppOutcome(options, {
|
|
46
|
+
status: "failed",
|
|
47
|
+
code: "bad_usage",
|
|
48
|
+
message: error.message,
|
|
49
|
+
}),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
throw error;
|
|
53
|
+
}
|
|
54
|
+
let key;
|
|
55
|
+
try {
|
|
56
|
+
key = (deps.resolveKey ?? resolveAppKey)({});
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
if (error instanceof AppKeyMissingError) {
|
|
60
|
+
return {
|
|
61
|
+
ok: false,
|
|
62
|
+
exitCode: emitAppOutcome(options, {
|
|
63
|
+
status: "failed",
|
|
64
|
+
code: "bad_usage",
|
|
65
|
+
message: "No app key on this machine yet.",
|
|
66
|
+
remedy: "vana app register",
|
|
67
|
+
network: network.name,
|
|
68
|
+
}),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
let grantId = options.grant;
|
|
74
|
+
let personalServerUrl = options.server;
|
|
75
|
+
if (!grantId || !personalServerUrl) {
|
|
76
|
+
const match = findApprovedRequest(derivedScope, network.name, key.address, deps.requests ?? createRequestsStore());
|
|
77
|
+
grantId ??= match?.grantId;
|
|
78
|
+
personalServerUrl ??= match?.personalServerUrl;
|
|
79
|
+
}
|
|
80
|
+
if (!grantId) {
|
|
81
|
+
return {
|
|
82
|
+
ok: false,
|
|
83
|
+
exitCode: emitAppOutcome(options, {
|
|
84
|
+
status: "failed",
|
|
85
|
+
code: "grant_invalid",
|
|
86
|
+
message: `No approved grant covering ${derivedScope}.`,
|
|
87
|
+
remedy: `vana app request --scopes ${derivedScope} --question "..." --derived ${derivedScope} --sources <scopes>`,
|
|
88
|
+
network: network.name,
|
|
89
|
+
}),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
if (!personalServerUrl) {
|
|
93
|
+
return {
|
|
94
|
+
ok: false,
|
|
95
|
+
exitCode: emitAppOutcome(options, {
|
|
96
|
+
status: "failed",
|
|
97
|
+
code: "owner_not_ready",
|
|
98
|
+
message: "No Personal Server URL for this grant; the owner may serve through the enclave path, which derivatives do not use yet.",
|
|
99
|
+
remedy: "pass --server explicitly if you know the URL",
|
|
100
|
+
network: network.name,
|
|
101
|
+
}),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
ok: true,
|
|
106
|
+
context: { network, key, grantId, personalServerUrl },
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function findApprovedRequest(derivedScope, network, appAddress, requests) {
|
|
110
|
+
return (requests
|
|
111
|
+
.list({ network, appAddress })
|
|
112
|
+
.find((entry) => Boolean(entry.grantId) &&
|
|
113
|
+
(entry.approvedScopes ?? entry.scopes).includes(derivedScope)) ?? null);
|
|
114
|
+
}
|
|
115
|
+
export async function runAppStatus(derivedScope, options, deps = {}) {
|
|
116
|
+
const resolved = resolveContext(derivedScope, options, deps);
|
|
117
|
+
if (!resolved.ok) {
|
|
118
|
+
return resolved.exitCode;
|
|
119
|
+
}
|
|
120
|
+
const { network, key, grantId, personalServerUrl } = resolved.context;
|
|
121
|
+
if (!options.quiet && !options.json) {
|
|
122
|
+
// The route is free to the caller and triggers a recompute, so a loop
|
|
123
|
+
// here spends the inference budget without reading anything.
|
|
124
|
+
process.stderr.write("Note: this route can trigger a recompute. Poll on the interval the server names, not faster.\n");
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
const status = await (deps.status ?? getDerivativeStatus)({
|
|
128
|
+
personalServerUrl,
|
|
129
|
+
derivedScope,
|
|
130
|
+
grantId,
|
|
131
|
+
signer: privateKeyToAccount(key.privateKey),
|
|
132
|
+
});
|
|
133
|
+
const settled = isDerivativeStatusSettled(status);
|
|
134
|
+
const ready = status.status === "ready";
|
|
135
|
+
return emitAppOutcome(options, {
|
|
136
|
+
status: ready || settled ? "done" : "failed",
|
|
137
|
+
code: ready
|
|
138
|
+
? "ok"
|
|
139
|
+
: status.status === "failed"
|
|
140
|
+
? mapDerivativeError(status.errorCode)
|
|
141
|
+
: "not_ready",
|
|
142
|
+
message: derivativeMessage(status),
|
|
143
|
+
remedy: ready
|
|
144
|
+
? `vana app read ${derivedScope} --grant ${grantId}`
|
|
145
|
+
: status.retryAfterSeconds
|
|
146
|
+
? `retry in ${status.retryAfterSeconds}s`
|
|
147
|
+
: undefined,
|
|
148
|
+
network: network.name,
|
|
149
|
+
data: {
|
|
150
|
+
derivedScope,
|
|
151
|
+
state: status.status,
|
|
152
|
+
version: status.derivedVersion,
|
|
153
|
+
lastComputedAt: status.lastComputedAt,
|
|
154
|
+
errorCode: status.errorCode,
|
|
155
|
+
retryAfterSeconds: status.retryAfterSeconds,
|
|
156
|
+
// Compute emits no fee event today; null says "unknown/unpriced",
|
|
157
|
+
// not "free". A price lands here as a number without a shape change.
|
|
158
|
+
computeCost: null,
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
return emitAppOutcome(options, {
|
|
164
|
+
status: "failed",
|
|
165
|
+
code: "server_unavailable",
|
|
166
|
+
message: `Could not read the derivative status: ${error instanceof Error ? error.message : String(error)}`,
|
|
167
|
+
network: network.name,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
export async function runAppLineage(scope, options, deps = {}) {
|
|
172
|
+
const resolved = resolveContext(scope, options, deps);
|
|
173
|
+
if (!resolved.ok) {
|
|
174
|
+
return resolved.exitCode;
|
|
175
|
+
}
|
|
176
|
+
const { network, key, grantId, personalServerUrl } = resolved.context;
|
|
177
|
+
try {
|
|
178
|
+
const result = await (deps.lineage ?? getLineage)({
|
|
179
|
+
personalServerUrl,
|
|
180
|
+
scope,
|
|
181
|
+
grantId,
|
|
182
|
+
signer: privateKeyToAccount(key.privateKey),
|
|
183
|
+
});
|
|
184
|
+
return emitAppOutcome(options, {
|
|
185
|
+
status: "done",
|
|
186
|
+
code: "ok",
|
|
187
|
+
message: `Lineage for ${scope}.`,
|
|
188
|
+
network: network.name,
|
|
189
|
+
data: { scope, lineage: result },
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
return emitAppOutcome(options, {
|
|
194
|
+
status: "failed",
|
|
195
|
+
code: "server_unavailable",
|
|
196
|
+
message: `Could not read the lineage: ${error instanceof Error ? error.message : String(error)}`,
|
|
197
|
+
network: network.name,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
function mapDerivativeError(code) {
|
|
202
|
+
switch (code) {
|
|
203
|
+
case "grant_invalid":
|
|
204
|
+
return "grant_invalid";
|
|
205
|
+
case "source_missing":
|
|
206
|
+
return "scope_not_found";
|
|
207
|
+
case "inference_unavailable":
|
|
208
|
+
return "not_ready";
|
|
209
|
+
default:
|
|
210
|
+
return "internal";
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
function derivativeMessage(status) {
|
|
214
|
+
switch (status.status) {
|
|
215
|
+
case "ready":
|
|
216
|
+
return `Answer is ready (version ${status.derivedVersion ?? "?"}).`;
|
|
217
|
+
case "pending":
|
|
218
|
+
return "The answer is being computed.";
|
|
219
|
+
case "stale":
|
|
220
|
+
return "A source changed; the answer is being recomputed.";
|
|
221
|
+
case "failed":
|
|
222
|
+
return `The computation failed: ${status.errorCode ?? "unknown"}.`;
|
|
223
|
+
default:
|
|
224
|
+
return `State: ${status.status}.`;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=derivatives.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derivatives.js","sourceRoot":"","sources":["../../../src/cli/app/derivatives.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `vana app escrow balance|fund` - what the app can spend, and funding it.
|
|
3
|
+
*
|
|
4
|
+
* Funding is deliberately one command for both halves: the on-chain
|
|
5
|
+
* `depositNative(account)` transaction and the gateway deposit
|
|
6
|
+
* registration. Either half alone produces a contract that looks funded
|
|
7
|
+
* while every read still answers 402.
|
|
8
|
+
*/
|
|
9
|
+
import { type GatewayClient } from "@opendatalabs/vana-sdk";
|
|
10
|
+
import { resolveAppKey, type ResolvedAppKey } from "../../core/app-key.js";
|
|
11
|
+
import { type ResolvedNetwork } from "../../core/network.js";
|
|
12
|
+
import { type AppCommandOptions } from "./outcome.js";
|
|
13
|
+
export interface EscrowFundOptions extends AppCommandOptions {
|
|
14
|
+
/** Amount to deposit, decimal, in units of the chosen asset. */
|
|
15
|
+
amount?: string;
|
|
16
|
+
/**
|
|
17
|
+
* ERC20 to deposit instead of native VANA. Reads are priced in USDC.e on
|
|
18
|
+
* mainnet, so funding native alone leaves every read answering 402.
|
|
19
|
+
*/
|
|
20
|
+
asset?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface EscrowDeps {
|
|
23
|
+
createClient?: (gatewayUrl: string) => GatewayClient;
|
|
24
|
+
resolveKey?: typeof resolveAppKey;
|
|
25
|
+
/** Injectable chain senders for tests. */
|
|
26
|
+
sendDeposit?: (params: {
|
|
27
|
+
network: ResolvedNetwork;
|
|
28
|
+
key: ResolvedAppKey;
|
|
29
|
+
escrowContract: `0x${string}`;
|
|
30
|
+
amountWei: bigint;
|
|
31
|
+
asset?: string;
|
|
32
|
+
}) => Promise<{
|
|
33
|
+
txHash: `0x${string}`;
|
|
34
|
+
}>;
|
|
35
|
+
}
|
|
36
|
+
export declare function runAppEscrowBalance(options: AppCommandOptions, deps?: EscrowDeps): Promise<number>;
|
|
37
|
+
export declare class InsufficientFundsError extends Error {
|
|
38
|
+
readonly balanceWei: bigint;
|
|
39
|
+
readonly neededWei: bigint;
|
|
40
|
+
readonly asset?: string | undefined;
|
|
41
|
+
constructor(balanceWei: bigint, neededWei: bigint, asset?: string | undefined);
|
|
42
|
+
}
|
|
43
|
+
export declare function runAppEscrowFund(options: EscrowFundOptions, deps?: EscrowDeps): Promise<number>;
|
|
44
|
+
//# sourceMappingURL=escrow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"escrow.d.ts","sourceRoot":"","sources":["../../../src/cli/app/escrow.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAKL,KAAK,aAAa,EACnB,MAAM,wBAAwB,CAAC;AAiBhC,OAAO,EAEL,aAAa,EACb,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAkB,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtE,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;IAC1D,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,aAAa,CAAC;IACrD,UAAU,CAAC,EAAE,OAAO,aAAa,CAAC;IAClC,0CAA0C;IAC1C,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE;QACrB,OAAO,EAAE,eAAe,CAAC;QACzB,GAAG,EAAE,cAAc,CAAC;QACpB,cAAc,EAAE,KAAK,MAAM,EAAE,CAAC;QAC9B,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,KAAK,OAAO,CAAC;QAAE,MAAM,EAAE,KAAK,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CAC1C;AA4CD,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,iBAAiB,EAC1B,IAAI,GAAE,UAAe,GACpB,OAAO,CAAC,MAAM,CAAC,CA0CjB;AA2ED,qBAAa,sBAAuB,SAAQ,KAAK;aAE7B,UAAU,EAAE,MAAM;aAClB,SAAS,EAAE,MAAM;aACjB,KAAK,CAAC,EAAE,MAAM;gBAFd,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,KAAK,CAAC,EAAE,MAAM,YAAA;CASjC;AAED,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,iBAAiB,EAC1B,IAAI,GAAE,UAAe,GACpB,OAAO,CAAC,MAAM,CAAC,CAkHjB"}
|