kira-wallet 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +116 -0
- package/THIRD_PARTY_NOTICES.md +13 -0
- package/bin/kira.cjs +8 -0
- package/curve_pricing.py +86 -0
- package/docs/AGENT_TOOLS.md +53 -0
- package/docs/CLI.md +144 -0
- package/docs/JOB_CONTRACT.md +111 -0
- package/docs/KIRA_JOBS_BUILD_REPORT.md +92 -0
- package/docs/KIRA_REDESIGN_REPORT.md +125 -0
- package/docs/ONBOARDING_CHAT_CONTRACT.md +36 -0
- package/docs/RELEASE.md +45 -0
- package/docs/WALLET_CAPABILITIES.md +98 -0
- package/docs/character/brand-generation.json +20 -0
- package/docs/character/workspace-generation.json +29 -0
- package/docs/screenshots/kira-jobs-desktop.jpg +0 -0
- package/kira_agent.py +280 -0
- package/kira_cli.py +263 -0
- package/kira_config.py +98 -0
- package/kira_jobs.py +504 -0
- package/kira_tools.py +104 -0
- package/networks.json +214 -0
- package/onchain.cjs +34 -0
- package/package.json +78 -0
- package/pipeline-onchain.cjs +284 -0
- package/research.py +39 -0
- package/sources/job-envelope-v1.schema.json +469 -0
- package/sources/job-request-v1.schema.json +352 -0
- package/sources/mintclub-bond-abi.json +1457 -0
- package/sources/rpc-candidates.json +294 -0
- package/sources/uniswap-deployments.json +18261 -0
- package/viewer/README.md +119 -0
- package/viewer/chain_images.py +21 -0
- package/viewer/details.py +119 -0
- package/viewer/model.py +216 -0
- package/viewer/refresh-curve-prices.cjs +35 -0
- package/viewer/refresh_prices.py +97 -0
- package/viewer/server.py +153 -0
- package/viewer/static/agent.css +100 -0
- package/viewer/static/agent.js +203 -0
- package/viewer/static/app.js +252 -0
- package/viewer/static/favicon.svg +1 -0
- package/viewer/static/index.html +139 -0
- package/viewer/static/jobs.js +113 -0
- package/viewer/static/kira-attention.png +0 -0
- package/viewer/static/kira-explain.png +0 -0
- package/viewer/static/kira-logo.png +0 -0
- package/viewer/static/kira-research.png +0 -0
- package/viewer/static/kira-review.png +0 -0
- package/viewer/static/kira.png +0 -0
- package/viewer/static/style.css +51 -0
- package/viewer/static/watching-model.js +129 -0
- package/viewer/static/watching.js +167 -0
- package/viewer/static/workspace-model.js +43 -0
- package/viewer/static/workspace.css +463 -0
- package/viewer/static/workspace.js +102 -0
- package/viewer/token_images.py +137 -0
- package/wallet.py +389 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kira Wallet contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Kira Wallet
|
|
2
|
+
|
|
3
|
+
A local EVM wallet research workspace with Kira and durable research jobs.
|
|
4
|
+
It records direct holdings, Mint Club bonding curves and DEX liquidity evidence.
|
|
5
|
+
Missing coverage and prices stay unknown.
|
|
6
|
+
|
|
7
|
+
Original code and character assets are open source under MIT. Third-party
|
|
8
|
+
references retain their own terms; see [notices](THIRD_PARTY_NOTICES.md). The npm
|
|
9
|
+
first npm publication is prepared for the operator. No signing, transfers or trades
|
|
10
|
+
are implemented.
|
|
11
|
+
|
|
12
|
+
## Local installation
|
|
13
|
+
|
|
14
|
+
Requirements: Node.js 22 or newer and Python 3.11 or newer. macOS is verified.
|
|
15
|
+
Analysis and daemon lifecycle currently require POSIX process and file-lock APIs.
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
npm install --ignore-scripts
|
|
19
|
+
node bin/kira.cjs init
|
|
20
|
+
node bin/kira.cjs doctor
|
|
21
|
+
node bin/kira.cjs setup
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The viewer starts at http://127.0.0.1:8787. Data defaults to
|
|
25
|
+
`~/.local/share/kira-wallet`, separate from the installed package. Use
|
|
26
|
+
`--data-dir /absolute/private/directory` before the command for another portfolio.
|
|
27
|
+
The existing workspace viewer can still run at port 8765.
|
|
28
|
+
|
|
29
|
+
For an isolated sample with synthetic data:
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
node bin/kira.cjs --data-dir /tmp/kira-sample demo --port 8790
|
|
33
|
+
node bin/kira.cjs --data-dir /tmp/kira-sample stop
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Research
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
kira add <operator-supplied-address> --tag '<exact tag>'
|
|
40
|
+
kira refresh '<registered address or tag>'
|
|
41
|
+
kira prices '<registered address or tag>'
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
From source, substitute `node bin/kira.cjs` for `kira`. Commands create private
|
|
45
|
+
runtime data. The viewer detects local updates within five seconds; it does
|
|
46
|
+
not poll providers. Resume a failed analysis with the same command and
|
|
47
|
+
`--resume <relative snapshot directory>`.
|
|
48
|
+
|
|
49
|
+
The engine checks official Mint Club deployment scope, discovers indexed held
|
|
50
|
+
tokens when configured, pins chain reads to blocks, enumerates reachable bond
|
|
51
|
+
registries, queries ERC20 and registered ERC1155 token ID 0 balances, records
|
|
52
|
+
curve reserves and burn quotes, and verifies supported DEX pool contracts.
|
|
53
|
+
Shared caches contain asset identities, never another wallet's balances.
|
|
54
|
+
Registry publication is atomic and analysis writers are serialized.
|
|
55
|
+
|
|
56
|
+
Public RPC can read native balances, known tokens and reachable bond registries.
|
|
57
|
+
General ERC20 discovery requires an indexed provider and successful responses.
|
|
58
|
+
Testnets, pool TVL and shared curve backing are excluded from wallet USD totals.
|
|
59
|
+
Spot value is distinct from an executable redemption estimate.
|
|
60
|
+
|
|
61
|
+
See [CLI and provider configuration](docs/CLI.md) and
|
|
62
|
+
[viewer behavior](viewer/README.md). Development reports, design concepts and
|
|
63
|
+
generation records remain in the source checkout under `docs/` and `prototype/`.
|
|
64
|
+
|
|
65
|
+
## Verification
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
npm test
|
|
69
|
+
node --check pipeline-onchain.cjs
|
|
70
|
+
node --check onchain.cjs
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
UI changes also require responsive browser and keyboard checks. Installation
|
|
74
|
+
checks must use a fresh directory without operator credentials or data.
|
|
75
|
+
|
|
76
|
+
## Durable local workspace
|
|
77
|
+
|
|
78
|
+
Development build 0.1.0-dev.2 adds persisted research jobs and opt-in protected
|
|
79
|
+
browser controls. Start with `kira start --controls`; the usual start stays
|
|
80
|
+
read-only. CLI and browser use the same typed job service for research, exact
|
|
81
|
+
wallet names and connection references. Jobs preserve prior results, retain
|
|
82
|
+
partial evidence and require explicit interruption recovery. Price jobs keep
|
|
83
|
+
immutable overlays. Saved analyses can be compared with exact decimal balance
|
|
84
|
+
changes and missing records remain unknown.
|
|
85
|
+
|
|
86
|
+
`kira tools` is a read-only local MCP adapter, with no automatic account or
|
|
87
|
+
model connection. See [CLI usage](docs/CLI.md), [job contract](docs/JOB_CONTRACT.md),
|
|
88
|
+
[tool setup gate](docs/AGENT_TOOLS.md) and [continuation evidence](docs/KIRA_JOBS_BUILD_REPORT.md).
|
|
89
|
+
|
|
90
|
+
## Kira research workspace
|
|
91
|
+
|
|
92
|
+
The workspace places Kira's local briefing and connected conversation
|
|
93
|
+
beside the evidence. The brand link returns Home. Overview, All tokens
|
|
94
|
+
and Activity have distinct tabs; wallet controls stay together. On small
|
|
95
|
+
screens, switch directly between Portfolio and Kira.
|
|
96
|
+
|
|
97
|
+
All tokens uses existing recorded aggregates with chain-plus-contract identity,
|
|
98
|
+
search, network and pricing filters, and 50 rows per page. It does not query
|
|
99
|
+
providers. Activity separates active work from persisted job history and shows
|
|
100
|
+
state, elapsed time, last progress and recovery controls. Missing progress does
|
|
101
|
+
not silently turn a running job into a completed or failed job.
|
|
102
|
+
|
|
103
|
+
Run `kira setup` to connect your installed Codex or Claude Code CLI account.
|
|
104
|
+
Choose no wallet context, one registered wallet or the whole portfolio. A real
|
|
105
|
+
response check verifies the selected model before permissions are saved. Drafts
|
|
106
|
+
stay in memory. Kira-local conversation retention is opt-in; provider and native
|
|
107
|
+
CLI policies remain separate. Context or model changes start a fresh conversation.
|
|
108
|
+
Chat does not sign, trade or automatically start research. See the
|
|
109
|
+
[onboarding and conversation contract](docs/ONBOARDING_CHAT_CONTRACT.md), the
|
|
110
|
+
[redesign report](docs/KIRA_REDESIGN_REPORT.md) and
|
|
111
|
+
[agreed wallet capability direction](docs/WALLET_CAPABILITIES.md).
|
|
112
|
+
|
|
113
|
+
For a contribution, use synthetic data and run `python3 scripts/check-public.py`
|
|
114
|
+
before a push. Never attach a personal portfolio screenshot, registry, snapshot,
|
|
115
|
+
job, credential, local path or log to an issue or PR. Repository history uses a
|
|
116
|
+
public noreply identity. The `kira-workspace-v1` tag preserves the prior UI.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Third-party reference material
|
|
2
|
+
|
|
3
|
+
Kira's original code and character assets are provided under the root MIT
|
|
4
|
+
license. Third-party reference files retain their original terms. The root
|
|
5
|
+
license does not relicense them.
|
|
6
|
+
|
|
7
|
+
- `sources/mintclub-multitoken.sol` retains its `BUSL-1.1` SPDX identifier.
|
|
8
|
+
It is a research reference, not a contract deployed by Kira.
|
|
9
|
+
- `sources/uniswap-state-view.sol` retains its MIT SPDX identifier.
|
|
10
|
+
- Mint Club ABI and contract metadata are research references to
|
|
11
|
+
[Mint Club](https://github.com/Steemhunt/mint.club-v2-contract).
|
|
12
|
+
- Installed dependencies retain their package licenses. Remote token and chain
|
|
13
|
+
artwork is referenced from its provider; the app does not claim ownership.
|
package/bin/kira.cjs
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Keep the existing read-only Python engine and ship its Node dependency here.
|
|
3
|
+
const {spawnSync}=require('node:child_process');
|
|
4
|
+
const path=require('node:path');
|
|
5
|
+
const result=spawnSync(process.env.KIRA_PYTHON || 'python3',
|
|
6
|
+
[path.join(__dirname,'../kira_cli.py'),...process.argv.slice(2)],{stdio:'inherit'});
|
|
7
|
+
if(result.error){console.error('Kira needs Python 3.11 or newer. Set KIRA_PYTHON to its executable.');process.exitCode=1;}
|
|
8
|
+
else process.exitCode=result.status ?? 1;
|
package/curve_pricing.py
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""Resolve spot prices through external Mint Club reserve curves."""
|
|
2
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
3
|
+
import json
|
|
4
|
+
import math
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
8
|
+
import research as h
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def resolve(graph, prices):
|
|
12
|
+
nodes={(r['chain_id'],r['address'].lower()):r for r in graph if r.get('address')}
|
|
13
|
+
known={(r['chain_id'],r['address'].lower()):r for r in prices}
|
|
14
|
+
cache={}
|
|
15
|
+
def visit(key,seen):
|
|
16
|
+
if key in cache:return cache[key]
|
|
17
|
+
if key in seen:return None
|
|
18
|
+
existing=known.get(key)
|
|
19
|
+
node=nodes.get(key)
|
|
20
|
+
if existing and existing.get('usd') is not None and existing.get('quality')!='unreliable':
|
|
21
|
+
cache[key]=existing;return existing
|
|
22
|
+
if not node or node.get('error') or not node.get('is_curve'):return None
|
|
23
|
+
if not node['funded']:
|
|
24
|
+
return {'chain_id':key[0],'address':node['address'],'usd':None,'basis':'Curve spot','quality':'unfunded'}
|
|
25
|
+
parent=visit((key[0],node['reserve_token'].lower()),seen|{key})
|
|
26
|
+
if not parent or parent.get('usd') is None:return None
|
|
27
|
+
usd=float(node['price_in_reserve'])*parent['usd']
|
|
28
|
+
if not math.isfinite(usd) or usd<0:return None
|
|
29
|
+
record={'chain_id':key[0],'address':node['address'],'usd':usd,'basis':'Curve spot','quality':'estimated',
|
|
30
|
+
'source':node['source'],'observed_at':node['observed_at'],'block_number':node['block_number'],
|
|
31
|
+
'curve_price_in_reserve':node['price_in_reserve'],'curve_reserve':node['curve_reserve'],'reserve_symbol':node['reserve_symbol'],
|
|
32
|
+
'price_path':[node['address']]+parent.get('price_path',[node['reserve_token']])}
|
|
33
|
+
cache[key]=record
|
|
34
|
+
return record
|
|
35
|
+
for key in nodes:visit(key,set())
|
|
36
|
+
return list(cache.values())
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def enrich(snapshot,market,folder):
|
|
40
|
+
from wallet import ALCHEMY, DEX, atomic, fetch, pool_row, run_node
|
|
41
|
+
sys.path.insert(0,str(h.ASSETS/'viewer'))
|
|
42
|
+
from model import dex_price
|
|
43
|
+
networks=json.loads((h.ASSETS/'sources/rpc-candidates.json').read_text())
|
|
44
|
+
input_path=folder/'reserve-graph-input.json'
|
|
45
|
+
atomic(input_path,{'wallet':snapshot['wallet_address'],'tokens':snapshot['tokens'],'networks':networks})
|
|
46
|
+
run_node('reserves',input_path,folder/'reserve-graph.json')
|
|
47
|
+
graph=json.loads((folder/'reserve-graph.json').read_text())['tokens']
|
|
48
|
+
ordinary=[r for r in graph if r.get('address') and r.get('is_curve') is False and r['chain_id'] in ALCHEMY]
|
|
49
|
+
prices=list(market.get('tokens',[]))
|
|
50
|
+
# Only reserve assets are requested. Identify prices by network and contract, never symbol.
|
|
51
|
+
requests=[{'network':ALCHEMY[r['chain_id']],'address':r['address']} for r in ordinary]
|
|
52
|
+
inverse={value:key for key,value in ALCHEMY.items()}
|
|
53
|
+
responses=[]
|
|
54
|
+
key=h.secrets().get('ALCHEMY_CUSTOM_APY_KEY')
|
|
55
|
+
for i in range(0,len(requests) if key else 0,25):
|
|
56
|
+
response=fetch('https://api.g.alchemy.com/prices/v1/'+h.secrets()['ALCHEMY_CUSTOM_APY_KEY']+'/tokens/by-address',{'addresses':requests[i:i+25]})
|
|
57
|
+
responses.append({'observed_at':h.now(),'source':'Alchemy token prices by address','request':requests[i:i+25],'response':response})
|
|
58
|
+
for record in response.get('data') or []:
|
|
59
|
+
p=next((p for p in record.get('prices',[]) if p.get('currency')=='usd' and p.get('value') is not None),None)
|
|
60
|
+
if p and not record.get('error'):
|
|
61
|
+
value=float(p['value'])
|
|
62
|
+
if math.isfinite(value) and value>0:
|
|
63
|
+
prices.append({'chain_id':inverse[record['network']],'address':record['address'],'usd':value,'basis':'Market index','quality':'estimated',
|
|
64
|
+
'observed_at':p.get('lastUpdatedAt'),'source':'https://www.alchemy.com/docs/data/prices-api/prices-api-endpoints/prices-api-endpoints/get-token-prices-by-address'})
|
|
65
|
+
atomic(folder/'reserve-market-prices.json',responses)
|
|
66
|
+
def get(row):
|
|
67
|
+
chain=DEX.get(row['chain_id'])
|
|
68
|
+
if not chain:return None
|
|
69
|
+
url='https://api.dexscreener.com/token-pairs/v1/'+chain+'/'+row['address']
|
|
70
|
+
return {'row':row,'source':url,'observed_at':h.now(),'response':fetch(url)}
|
|
71
|
+
keys={(p['chain_id'],p['address'].lower()) for p in prices if p.get('usd') is not None}
|
|
72
|
+
missing=[r for r in ordinary if (r['chain_id'],r['address'].lower()) not in keys]
|
|
73
|
+
with ThreadPoolExecutor(max_workers=4) as executor:fetched=list(executor.map(get,missing))
|
|
74
|
+
atomic(folder/'reserve-dex-prices.json',fetched)
|
|
75
|
+
for r in fetched:
|
|
76
|
+
if not r or not isinstance(r['response'],list):continue
|
|
77
|
+
row=r['row'];shadow={'token_address':row['address'],'dex_pools':[pool_row(p,r['observed_at']) for p in r['response']],'indexer_price_references':[]}
|
|
78
|
+
p=dex_price(shadow,r['observed_at'])
|
|
79
|
+
if p and p.get('usd') is not None:prices.append({'chain_id':row['chain_id'],'address':row['address'],**p})
|
|
80
|
+
# Keep a supported DEX price for held tokens. Add external curve references for their children.
|
|
81
|
+
resolved=resolve(graph,prices)
|
|
82
|
+
by_key={(p['chain_id'],p['address'].lower()):p for p in prices}
|
|
83
|
+
for p in resolved:by_key[(p['chain_id'],p['address'].lower())]=p
|
|
84
|
+
market['tokens']=list(by_key.values())
|
|
85
|
+
market['reserve_price_graph']={'source_file':'reserve-graph.json','observed_at':h.now(),'curve_count':sum(r.get('is_curve') is True for r in graph),'errors':sum(bool(r.get('error')) for r in graph)}
|
|
86
|
+
return market
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Recorded research tools
|
|
2
|
+
|
|
3
|
+
`kira --data-dir <private-portfolio> tools` serves a read-only MCP adapter over
|
|
4
|
+
newline-delimited JSON on stdin/stdout. Protocol version is pinned to
|
|
5
|
+
2025-06-18. It performs no login, model turn, provider request or research
|
|
6
|
+
mutation. Diagnostics stay out of stdout. The process exits on EOF.
|
|
7
|
+
|
|
8
|
+
Tools: portfolio_read, wallet_read, token_read, network_read, job_list,
|
|
9
|
+
job_read, snapshot_read and snapshots_compare. Arguments reject extra fields.
|
|
10
|
+
Tokens use chain ID and exact contract, or `native`. Missing records remain
|
|
11
|
+
unknown. Snapshots expose facts and safe source links, with fixed provider
|
|
12
|
+
errors. No arbitrary files, shell commands, credentials or mutation tools are
|
|
13
|
+
available. Local access to this process grants access to the selected portfolio.
|
|
14
|
+
Only connect it to an explicitly chosen client and data directory.
|
|
15
|
+
|
|
16
|
+
Example client-side stdio configuration, after operator approval:
|
|
17
|
+
|
|
18
|
+
```toml
|
|
19
|
+
[mcp_servers.kira]
|
|
20
|
+
command = "kira"
|
|
21
|
+
args = ["--data-dir", "<private-portfolio>", "tools"]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Replace the placeholder locally. Do not commit portfolio paths or credentials.
|
|
25
|
+
Kira does not edit the operator's Codex configuration automatically.
|
|
26
|
+
|
|
27
|
+
## Account connection gate
|
|
28
|
+
|
|
29
|
+
The browser's Kira notes remain deterministic. Connected chat, OAuth handling
|
|
30
|
+
and conversation reconnect are not delivered by this adapter.
|
|
31
|
+
|
|
32
|
+
Before connecting a Kira-owned model session, the operator must select the
|
|
33
|
+
account/authentication route and approve which portfolio facts may reach the
|
|
34
|
+
model. The current official ChatGPT-plan app-server guide describes an app-owned
|
|
35
|
+
OAuth access token, Responses provider configuration and token renewal. It does
|
|
36
|
+
not establish this account's eligibility. Client registration, consent and
|
|
37
|
+
login are operator actions. Do not copy desktop authentication files or use the
|
|
38
|
+
internal-only external ChatGPT-token schema variant. No billing claim follows
|
|
39
|
+
from a tool handshake or model catalog.
|
|
40
|
+
|
|
41
|
+
After the gate, implement the selected auth route and app-server session driver
|
|
42
|
+
with saved thread IDs, terminal turn states, reconnect and interruption. Keep
|
|
43
|
+
those states distinct from engine jobs. Pin the installed protocol again and
|
|
44
|
+
independently review permissions before connecting real private data.
|
|
45
|
+
|
|
46
|
+
Sources checked on 2026-10-03:
|
|
47
|
+
|
|
48
|
+
- [Official Codex app-server guidance](https://developers.openai.com/siwc/token-sharing-open-source/codex-app-server)
|
|
49
|
+
- [Official Codex MCP guidance](https://learn.chatgpt.com/docs/extend/mcp?surface=cli)
|
|
50
|
+
- [MCP stdio transport contract](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports)
|
|
51
|
+
|
|
52
|
+
Local verification uses synthetic portfolios and a stdin transcript only.
|
|
53
|
+
It does not verify a live Codex/MCP client connection or model access.
|
package/docs/CLI.md
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# CLI and provider configuration
|
|
2
|
+
|
|
3
|
+
The npm package carries the Python engine, browser assets and declared viem
|
|
4
|
+
dependency. It needs no Python packages and no sibling project. The package
|
|
5
|
+
file list excludes wallets, snapshots, conversations, caches, logs and private settings.
|
|
6
|
+
The first release is prepared as a tarball. Registry publication remains an
|
|
7
|
+
operator action. The code and original character assets use the MIT license.
|
|
8
|
+
|
|
9
|
+
## Lifecycle
|
|
10
|
+
|
|
11
|
+
`kira init` prepares an empty private data directory. `kira start --port 8787`
|
|
12
|
+
starts a loopback-only read-only viewer. `kira status` identifies the managed
|
|
13
|
+
instance. `kira stop` checks its live instance ID and OS process identity.
|
|
14
|
+
Another portfolio never silently reuses that server.
|
|
15
|
+
|
|
16
|
+
`kira setup` starts the loopback viewer with local controls and opens its setup
|
|
17
|
+
screen. Use `--no-open` to print its URL instead. If a read-only viewer is already
|
|
18
|
+
running, stop it explicitly before setup. The normal `kira start` remains read-only.
|
|
19
|
+
|
|
20
|
+
## Your model account
|
|
21
|
+
|
|
22
|
+
Install and sign in to the official Codex CLI or Claude Code CLI first. Kira
|
|
23
|
+
detects the installed binary and native subscription login without copying its
|
|
24
|
+
authentication. Verified adapter versions are Codex 0.158.x and Claude Code
|
|
25
|
+
2.1.259 through 2.1.x. Other versions are blocked until their restrictions are
|
|
26
|
+
verified. This is a native CLI connection, with no Kira account, API-key proxy or
|
|
27
|
+
hosted portfolio backend.
|
|
28
|
+
|
|
29
|
+
In setup, choose the CLI account and an optional model ID. The blank model field
|
|
30
|
+
uses the CLI default. Choose no automatic wallet context, one registered wallet,
|
|
31
|
+
or the whole recorded portfolio. A generic response check sends no wallet data
|
|
32
|
+
and must pass before these settings are saved.
|
|
33
|
+
|
|
34
|
+
Your entered message and approved context go through the CLI to its model
|
|
35
|
+
service. Context includes recorded balances, wallet names and addresses, chain
|
|
36
|
+
and contract identities, timestamps, unknown prices and coverage. Credentials,
|
|
37
|
+
RPC endpoints, raw provider errors and local paths are excluded. Changing the
|
|
38
|
+
provider, model, context or selected wallet creates a new conversation.
|
|
39
|
+
|
|
40
|
+
Kira-local history is opt-in and uses private `conversations/` files. With history
|
|
41
|
+
off, conversations and drafts stay in memory. A new server process starts a fresh
|
|
42
|
+
conversation; saved files remain available locally and are not automatically
|
|
43
|
+
replayed. Native CLI, administrator policy and provider data policies remain a
|
|
44
|
+
separate trust boundary. Chat cannot sign, trade or automatically start research.
|
|
45
|
+
See [the conversation contract](ONBOARDING_CHAT_CONTRACT.md).
|
|
46
|
+
|
|
47
|
+
Global `--data-dir` precedes the command. `KIRA_DATA_DIR` provides the same
|
|
48
|
+
override. `KIRA_PYTHON` selects Python. Direct historical scripts keep their
|
|
49
|
+
workspace default. The supported CLI uses the user data directory. Installed
|
|
50
|
+
assets and writable runtime files use separate roots.
|
|
51
|
+
|
|
52
|
+
## Public RPC
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
kira rpc public
|
|
56
|
+
kira discovery none
|
|
57
|
+
kira doctor
|
|
58
|
+
kira doctor --live --chains 1,8453,81457 --budget 30
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
No credential file is required. Live doctor performs bounded identity, block,
|
|
62
|
+
deployed bond bytecode, Multicall3 bytecode and historical bytecode probes.
|
|
63
|
+
It reports endpoint indexes. These samples do not guarantee broad archive
|
|
64
|
+
history, multicall execution or wallet coverage. Exit code 2 means at least one
|
|
65
|
+
sampled chain is unavailable or limited. Failed endpoints stop after their
|
|
66
|
+
first failure; at most three are tried per chain. There are no hidden retries.
|
|
67
|
+
The budget limits JSON-RPC method calls in that invocation. Full analysis has
|
|
68
|
+
no global request cap yet.
|
|
69
|
+
|
|
70
|
+
## Custom RPC and discovery
|
|
71
|
+
|
|
72
|
+
Set an endpoint in your shell or private environment file. Keep the value out
|
|
73
|
+
of command arguments. Configuration stores references only.
|
|
74
|
+
|
|
75
|
+
```sh
|
|
76
|
+
export KIRA_BASE_RPC='<your HTTPS endpoint>'
|
|
77
|
+
kira rpc set --chain 8453 --url-env KIRA_BASE_RPC
|
|
78
|
+
export ALCHEMY_API_KEY='<your key>'
|
|
79
|
+
kira discovery alchemy --key-env ALCHEMY_API_KEY --explorers
|
|
80
|
+
kira config show
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Custom mode disables public fallback by default. Add `--public-fallback` to
|
|
84
|
+
explicitly enable it. That preference applies to all custom-mode chains.
|
|
85
|
+
Chains without a configured endpoint remain unavailable while fallback is
|
|
86
|
+
disabled. Plain HTTP is accepted only for loopback endpoints.
|
|
87
|
+
|
|
88
|
+
Discovery is independent. Without an indexer, native and reachable Mint Club
|
|
89
|
+
reads still run and general discovery stays incomplete. Configuring an RPC
|
|
90
|
+
does not prove ERC20 discovery completeness.
|
|
91
|
+
|
|
92
|
+
## Explicit compatibility import
|
|
93
|
+
|
|
94
|
+
```sh
|
|
95
|
+
kira config import-env --file /absolute/private/rpc.env --key-env ALCHEMY_API_KEY
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The import references the file instead of copying keys. It configures Alchemy
|
|
99
|
+
RPC and portfolio discovery separately, with public fallback enabled to match
|
|
100
|
+
the historical engine. Environment overrides the file. Missing files or keys
|
|
101
|
+
produce limited coverage; malformed configuration fails with safe errors.
|
|
102
|
+
The import does not contact providers. Private settings are never served.
|
|
103
|
+
|
|
104
|
+
Analysis output contains wallet addresses and tags. Keep runtime directories
|
|
105
|
+
outside repositories or ignored. Never publish operator holdings as demos.
|
|
106
|
+
The demo command uses synthetic addresses and sample prices only.
|
|
107
|
+
|
|
108
|
+
## Durable research and local controls
|
|
109
|
+
|
|
110
|
+
Normal `kira add`, `kira refresh` and `kira prices` now save a version 1 job
|
|
111
|
+
before running the existing engine. Use `--idempotency-key <stable-key>` to
|
|
112
|
+
retry a submission without duplicating work. Add `--enqueue` to return after
|
|
113
|
+
queuing the job and start a separate worker. `--resume <snapshot-directory>`
|
|
114
|
+
remains the legacy unpublished-snapshot interface. New durable jobs resume by
|
|
115
|
+
job ID:
|
|
116
|
+
|
|
117
|
+
```sh
|
|
118
|
+
kira jobs list
|
|
119
|
+
kira jobs read <job-id>
|
|
120
|
+
kira jobs cancel <job-id>
|
|
121
|
+
kira jobs resume <job-id> --idempotency-key <stable-resume-key>
|
|
122
|
+
kira jobs run
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
An interrupted job needs an explicit resume. Published partial results retain
|
|
126
|
+
coverage gaps and require a new refresh to investigate again. Failed and
|
|
127
|
+
cancelled jobs retain their last good result and unpublished evidence.
|
|
128
|
+
`jobs run` starts queued work and reconciles crash receipts; it does not replay
|
|
129
|
+
interrupted jobs. Price jobs retain immutable overlays before updating the
|
|
130
|
+
viewer projection. A viewer stop does not cancel research jobs.
|
|
131
|
+
|
|
132
|
+
Start with `kira start --controls` to enable protected browser actions. The
|
|
133
|
+
usual start remains read-only. Stop an existing read-only instance before
|
|
134
|
+
starting one with controls. Actions need the local session and same origin.
|
|
135
|
+
The supported URL uses 127.0.0.1. Browser controls offer wallet registration,
|
|
136
|
+
exact names, holdings/price refresh, cancel/resume, saved analysis comparison,
|
|
137
|
+
RPC references and discovery references. The synthetic demo cannot start
|
|
138
|
+
provider research. Enter endpoint credential references in Connections;
|
|
139
|
+
secrets and URLs remain outside the browser.
|
|
140
|
+
|
|
141
|
+
Use `kira --data-dir <private-portfolio> tools` for the read-only stdio adapter.
|
|
142
|
+
See [the tool guide](AGENT_TOOLS.md) and [job contract](JOB_CONTRACT.md).
|
|
143
|
+
Connected chat still requires the operator's account setup and a later session
|
|
144
|
+
integration. The local development package remains private and unlicensed.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Persisted jobs, version 1
|
|
2
|
+
|
|
3
|
+
The engine owns financial facts. CLI and protected local browser actions share
|
|
4
|
+
this contract. Chat interruption never cancels an engine job.
|
|
5
|
+
|
|
6
|
+
## Request and identity
|
|
7
|
+
|
|
8
|
+
Mutations use `{schema_version: 1, operation, input, idempotency_key}`.
|
|
9
|
+
Supported operations are `wallet.add` (address, exact tag), `wallet.refresh`
|
|
10
|
+
(wallet address or exact tag), `prices.refresh` (same), `wallet.setTags`
|
|
11
|
+
(wallet, exact tags), `job.resume` and `job.cancel` (job_id).
|
|
12
|
+
Read operations are `job.read`, `job.list`, `snapshot.read`, and
|
|
13
|
+
`snapshots.compare`. The portfolio projection retains its existing schema.
|
|
14
|
+
|
|
15
|
+
Inputs reject unknown fields and invalid identifiers. Wallet selectors resolve
|
|
16
|
+
to a unique registered address before persistence. Ambiguous tags fail.
|
|
17
|
+
Idempotency keys are private, bounded strings. Persist only their SHA-256 hash.
|
|
18
|
+
The hash maps to one job across operations. Reusing it with different normalized
|
|
19
|
+
input fails with `idempotency_conflict`. Terminal duplicate submission returns
|
|
20
|
+
the same job without rerunning providers. Resume requeues the same job ID and
|
|
21
|
+
increments its attempt on execution. Retain the key until the job is removed
|
|
22
|
+
by a future explicit retention policy. Version mismatches fail closed.
|
|
23
|
+
|
|
24
|
+
## Envelope
|
|
25
|
+
|
|
26
|
+
Each private `jobs/<uuid>.json` records schema_version, job_id, operation,
|
|
27
|
+
input, request_hash, key_hash, state, attempt, created_at, updated_at,
|
|
28
|
+
sequence, cancel_requested, stage, events, checkpoint, result, errors and
|
|
29
|
+
previous_result. Events contain only allowed stage names and real counts.
|
|
30
|
+
Unknown totals stay null. Result references use paths relative to snapshots/;
|
|
31
|
+
no absolute paths or arbitrary file reads are supported.
|
|
32
|
+
|
|
33
|
+
The optional `started_at` timestamp records when the current attempt was
|
|
34
|
+
claimed by the worker. Resuming replaces it on the next claim. Older envelopes
|
|
35
|
+
remain valid without it. The viewer then labels its timer "Since request"
|
|
36
|
+
instead of claiming an exact execution time. Terminal timers stop at the last
|
|
37
|
+
recorded update. A queued job uses its latest queue transition, not a previous
|
|
38
|
+
attempt's start.
|
|
39
|
+
|
|
40
|
+
States: queued -> running -> succeeded | partial | failed | cancelled.
|
|
41
|
+
Recovery converts unfinished running jobs to interrupted. Explicit resume may
|
|
42
|
+
move interrupted, failed or cancelled to queued. Succeeded and partial jobs
|
|
43
|
+
retain their result; a new refresh is a new job. Partial is a published result
|
|
44
|
+
with documented coverage gaps, not a failed result or proof of zero holdings.
|
|
45
|
+
|
|
46
|
+
Updates use private files, replace, file fsync and directory fsync under a
|
|
47
|
+
process lock. One worker owns a portfolio. Existing analysis/config locks
|
|
48
|
+
serialize writers. A worker lease is inherited by its engine child, preventing
|
|
49
|
+
another worker from replaying a still-running orphan engine after a supervisor
|
|
50
|
+
crash. A busy legacy writer leaves the new job queued.
|
|
51
|
+
|
|
52
|
+
## Publication and recovery
|
|
53
|
+
|
|
54
|
+
Analysis jobs allocate `snapshots/jobs/<job_id>` before executing. The existing
|
|
55
|
+
engine resumes only matching, unpublished evidence; completed per-chain reads
|
|
56
|
+
retain their recorded blocks. Partial stages retain missing information.
|
|
57
|
+
No global block is invented. Engine publication atomically updates the registry
|
|
58
|
+
pointer after results exist. A saved result plus a matching registry pointer
|
|
59
|
+
or research-history entry is authoritative even if the final manifest update
|
|
60
|
+
was interrupted. A published result whose
|
|
61
|
+
pointer has since moved remains readable from its immutable directory.
|
|
62
|
+
|
|
63
|
+
Price jobs save an immutable overlay and publication receipt before replacing
|
|
64
|
+
the viewer's market-prices projection. Recovery can finish this projection
|
|
65
|
+
without provider calls. Failed or cancelled work retains previous_result and
|
|
66
|
+
saved evidence. Cancellation stops the subprocess group, waits for the writer
|
|
67
|
+
to release, then records its outcome. If publication won the race, record the
|
|
68
|
+
published result rather than claim it was cancelled.
|
|
69
|
+
|
|
70
|
+
Provider exception text, URLs and credentials never enter public job events.
|
|
71
|
+
Safe errors use fixed codes and messages. Pinned blocks and coverage remain in
|
|
72
|
+
the engine result. Stage progress is evidence from emitted engine events;
|
|
73
|
+
there is no simulated timer or fabricated percentage.
|
|
74
|
+
|
|
75
|
+
## Local transport
|
|
76
|
+
|
|
77
|
+
Writes require the exact loopback Host, same Origin, JSON content type and an
|
|
78
|
+
in-memory session token obtained from the same-origin session endpoint. No
|
|
79
|
+
CORS or credential files are exposed. Session tokens rotate on server restart.
|
|
80
|
+
Bound request size and reject foreign origins and DNS-rebinding Host values.
|
|
81
|
+
The legacy viewer remains read-only unless explicitly launched with --controls.
|
|
82
|
+
Synthetic demo controls never start provider requests.
|
|
83
|
+
|
|
84
|
+
## Acceptance cases
|
|
85
|
+
|
|
86
|
+
Synthetic tests cover duplicate requests, key conflicts, invalid versions and
|
|
87
|
+
fields, concurrent submit, restart before execution, interruption before and
|
|
88
|
+
after publication, immutable partial results, previous-result preservation,
|
|
89
|
+
cancel/resume, independent worker leases, snapshot path escape, ambiguous tags,
|
|
90
|
+
unknown values and cross-chain coin identity. HTTP checks cover unauthorized
|
|
91
|
+
writes, foreign origins/Host, malformed bodies and safe static allowlists.
|
|
92
|
+
No operator wallet is analysed by this verification.
|
|
93
|
+
|
|
94
|
+
## Implemented adapters
|
|
95
|
+
|
|
96
|
+
`kira_jobs.py` contains typed request and persisted envelope definitions, strict
|
|
97
|
+
operation validation and the worker. `sources/job-envelope-v1.schema.json`
|
|
98
|
+
is the versioned envelope artifact. `sources/job-request-v1.schema.json`
|
|
99
|
+
defines the typed mutation request variants. `settings.rpc` and `settings.discovery`
|
|
100
|
+
are also durable operations; they accept environment references only and share
|
|
101
|
+
the portfolio writer lock. `wallet.setTags` records exact tag changes.
|
|
102
|
+
|
|
103
|
+
Chain events retain actual endpoint ordinal, configured reference identity,
|
|
104
|
+
status and pinned block as a decimal string. Completed cached chain stages emit
|
|
105
|
+
the same saved block on resume. Recorded stage details stay available in the
|
|
106
|
+
browser. A registry publication receipt is authoritative even if a crash
|
|
107
|
+
precedes the final run manifest update. A completed price overlay can reconstruct
|
|
108
|
+
its projection receipt without another provider request.
|
|
109
|
+
|
|
110
|
+
The read-only stdio MCP adapter uses the same job and snapshot service. It has
|
|
111
|
+
no mutation tools and requires separate operator-approved client setup.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Kira durable workspace delivery
|
|
2
|
+
|
|
3
|
+
Completed locally on 2026-10-03 as private development build 0.1.0-dev.2.
|
|
4
|
+
The continuation reached the operator account-connection gate. Connected chat,
|
|
5
|
+
publication and independent release review remain pending.
|
|
6
|
+
|
|
7
|
+
## Delivered behavior
|
|
8
|
+
|
|
9
|
+
CLI and opt-in browser controls share versioned typed requests and persisted
|
|
10
|
+
jobs. Same-key retries return one job. Saved work survives a worker restart;
|
|
11
|
+
unfinished engine work requires explicit resume. Published partial results
|
|
12
|
+
remain available and cannot be resumed over their immutable analysis. Failure
|
|
13
|
+
and cancellation preserve the previous published result and saved evidence.
|
|
14
|
+
Cancellation terminates the engine process group, including descendants.
|
|
15
|
+
A worker lease survives a supervisor crash while its engine is still active.
|
|
16
|
+
|
|
17
|
+
Analysis publication reconciles the registry/manifest crash boundary without
|
|
18
|
+
rerunning providers. Price jobs keep an immutable overlay before replacing the
|
|
19
|
+
viewer projection; restart can finish that projection without provider calls.
|
|
20
|
+
Recorded stages retain actual counts, endpoint identity references and decimal
|
|
21
|
+
pinned blocks. Model interruption is separate from engine cancellation.
|
|
22
|
+
|
|
23
|
+
The browser provides wallet registration, exact names, holdings and price
|
|
24
|
+
refresh, stop/resume, saved analysis comparison and separate RPC/discovery
|
|
25
|
+
references. Host, Origin, session, content type and request-size checks protect
|
|
26
|
+
local actions. Session tokens rotate with the server. The usual launch stays
|
|
27
|
+
read-only; `--controls` explicitly enables actions. The primary local instance
|
|
28
|
+
now has controls enabled. Synthetic demo research cannot contact providers.
|
|
29
|
+
|
|
30
|
+
The first-wallet screen and connection forms keep unknown values visible.
|
|
31
|
+
Comparison preserves decimal quantities, chain/contract identity and absent
|
|
32
|
+
records as unknown. It reports balance, reference and coverage differences;
|
|
33
|
+
it does not attribute USD changes or compare historical price-overlay values.
|
|
34
|
+
|
|
35
|
+
The local read-only MCP adapter exposes eight typed tools through `kira tools`.
|
|
36
|
+
It reads recorded facts and jobs without a login, model turn, shell tool or
|
|
37
|
+
provider request. Its stdio transcript and packaged runtime are verified;
|
|
38
|
+
live client attachment is not yet verified.
|
|
39
|
+
|
|
40
|
+
Kira's new original character icon appears in the brand home link, Home button,
|
|
41
|
+
notes, empty state, wallet dialog and concept studio. Browser and touch icons
|
|
42
|
+
are installed. A tiny editable notebook mark complements the adult portrait.
|
|
43
|
+
Built-in imagegen produced the master and cleaned its transparent exterior.
|
|
44
|
+
[Exact prompts and provenance](character/brand-generation.json) are saved.
|
|
45
|
+
|
|
46
|
+
## Verification evidence
|
|
47
|
+
|
|
48
|
+
| Check | Result and scope |
|
|
49
|
+
| --- | --- |
|
|
50
|
+
| `npm test` | Passed 41 engine/configuration/job/tool tests and 24 viewer/HTTP tests, Node cache/outage checks and both viewer JavaScript syntax checks |
|
|
51
|
+
| Node syntax | Passed pipeline-onchain.cjs, onchain.cjs and prototype/app.js |
|
|
52
|
+
| `python3 scripts/check-install.py` | Passed fresh npm pack/install without operator configuration; logo route, read-only lifecycle, protected controls, actual synthetic names job and stdio tool facts |
|
|
53
|
+
| Durable process cases | Passed supervisor SIGKILL recovery with one engine invocation; cancellation stopped a SIGTERM-resistant descendant and preserved prior evidence; publication won a simultaneous cancellation |
|
|
54
|
+
| Browser interaction | Passed actual synthetic names mutation and completion; saved analysis comparison displayed 100 -> 120 with exact delta 20; invalid onboarding address blocked before submission; connection settings separated RPC from discovery |
|
|
55
|
+
| Responsive and keyboard | Checked desktop, 320 px Home/wallet/history and 375 px add form; no document overflow; Escape closes dialogs and returns to the trigger |
|
|
56
|
+
| Preservation | All 682 original runtime JSON hashes unchanged; primary portfolio `/api/state` bytes unchanged across upgrade |
|
|
57
|
+
| Privacy | Source/package allowlists and audit exclude operator registry, snapshots, settings, jobs, logs, authentication and real portfolio screenshots |
|
|
58
|
+
| Independent review / model access | Not performed; no account connection, live Codex/MCP-client attachment, model turn or release claim |
|
|
59
|
+
|
|
60
|
+
All research tests used synthetic portfolios and local subprocesses. No new
|
|
61
|
+
operator wallet, holdings refresh, price refresh or additional JSON-RPC probe
|
|
62
|
+
was performed in this continuation.
|
|
63
|
+
|
|
64
|
+
## Open the result
|
|
65
|
+
|
|
66
|
+
Primary local workspace: `http://127.0.0.1:8765/#/home`.
|
|
67
|
+
Synthetic control preview: `http://127.0.0.1:8793/#/home` while its server runs.
|
|
68
|
+
The empty first-launch preview used a separate private directory at port 8794.
|
|
69
|
+
The original concept studio remains available at port 8792 while running.
|
|
70
|
+
|
|
71
|
+

|
|
72
|
+
|
|
73
|
+
## Operator boundary and limits
|
|
74
|
+
|
|
75
|
+
The operator must choose an approved account/authentication route and consent
|
|
76
|
+
to the portfolio scope before connected Kira chat. The current official
|
|
77
|
+
[app-server guide](https://developers.openai.com/siwc/token-sharing-open-source/codex-app-server)
|
|
78
|
+
describes app-owned OAuth handling. This does not establish this account's
|
|
79
|
+
eligibility or billing. The [tool guide](AGENT_TOOLS.md) records the concrete
|
|
80
|
+
setup boundary. No desktop authentication files were copied or used.
|
|
81
|
+
|
|
82
|
+
Independent security/release review, platform testing beyond macOS, a global
|
|
83
|
+
provider-call cap and an external pilot remain outstanding. Legacy direct
|
|
84
|
+
engine scripts keep their earlier interfaces; immutable price history is
|
|
85
|
+
provided by the durable CLI/browser job path. Read-only model tools do not
|
|
86
|
+
automatically connect a client. Full connected chat and session persistence
|
|
87
|
+
remain future work after account setup. This package remains private and
|
|
88
|
+
unlicensed. No remote, PR, merge, main push, package publication or deployment
|
|
89
|
+
was created.
|
|
90
|
+
|
|
91
|
+
[Selected design evidence](https://www.lazyweb.com/agentic-search/b98ba70d-d7d2-408b-b6b0-f529201e4365)
|
|
92
|
+
informed the per-job state and recovery UI. It is not a growth or demand claim.
|