@falari/harness 0.0.0-stage → 0.8.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +456 -0
- package/LICENSE +21 -0
- package/README.md +219 -2
- package/client.js +3303 -0
- package/cordis.patch.yml +6 -0
- package/icon.png +0 -0
- package/index.js +52 -0
- package/lib/config.js +103 -0
- package/lib/errors.js +40 -0
- package/lib/falari-sdk.cjs +39775 -0
- package/lib/pin.js +126 -0
- package/lib/routes.js +311 -0
- package/lib/sdk.js +13 -0
- package/lib/service.js +1429 -0
- package/lib/tools.js +193 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +61 -4
package/README.md
CHANGED
|
@@ -1,3 +1,220 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Falari Harness
|
|
2
|
+
|
|
3
|
+
Falari Data client for **DeepSeek Harness** (DSH): upload files to Falari
|
|
4
|
+
storage and download them back, with an Agent Key as the only credential. The
|
|
5
|
+
same six operations are exposed to the model as tools and to the user as a
|
|
6
|
+
panel.
|
|
7
|
+
|
|
8
|
+
- Design and milestone log: [docs/plan.md](docs/plan.md)
|
|
9
|
+
- Test plan: [docs/test-plan.md](docs/test-plan.md)
|
|
10
|
+
- Release notes: [CHANGELOG.md](CHANGELOG.md)
|
|
11
|
+
|
|
12
|
+
The plugin wears the Falari mark: `icon.png` is the rendered logo with a
|
|
13
|
+
transparent background for the plugin list; the panel header shows the original
|
|
14
|
+
render (dark backdrop, cropped to the cube); the sidebar draws crisp vector art
|
|
15
|
+
so the `>_` survives at 20 px.
|
|
16
|
+
|
|
17
|
+
## Status
|
|
18
|
+
|
|
19
|
+
| Phase | Scope | State |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| M0 | Bundle scaffold, install, panel/settings placeholders | done — installed in the `desktop` profile (2026-11-09) |
|
|
22
|
+
| M1 | Agent Key storage, `falari_status` tool, settings page | done (v0.2.0) |
|
|
23
|
+
| M2 | Quotes, upload queue, upload panel, `falari_quote` / `falari_upload` / `falari_task` | done (v0.3.0) |
|
|
24
|
+
| M3 | Intent list, download/decrypt, `falari_list` / `falari_download` | done (v0.4.0) |
|
|
25
|
+
| M4 | Editable settings, unit tests, test plan | done (v0.5.0); live acceptance pending a testnet key |
|
|
26
|
+
| M5 | Repository layout, changelog, license, manifest check | done (v0.5.0) |
|
|
27
|
+
|
|
28
|
+
Live-chain verification still needs a real testnet Agent Key: the settings page
|
|
29
|
+
and every route/tool path are covered by the offline smoke tests, but nothing
|
|
30
|
+
here has performed a paid upload against the testnet yet.
|
|
31
|
+
|
|
32
|
+
The full design is in [docs/plan.md](docs/plan.md).
|
|
33
|
+
|
|
34
|
+
## Project
|
|
35
|
+
|
|
36
|
+
- Developer: **falari_labs**
|
|
37
|
+
- Website: <https://falari.xyz>
|
|
38
|
+
- Package: `@falari/harness`
|
|
39
|
+
|
|
40
|
+
## Install (development)
|
|
41
|
+
|
|
42
|
+
Open **Plugins → Add** in DeepSeek Harness and point it at this directory, or
|
|
43
|
+
from an agent session call the plugin manager tool:
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
plugin_manager action=install_bundle target=/path/to/clients/harness
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The bundle is installed as a local link (`link:...`). For a release build use
|
|
50
|
+
`plugin_manager action=install_bundle target=@falari/harness@0.8.9`. Host code changes need the
|
|
51
|
+
plugin row to reload (toggle the bundle off/on, or restart DSH); client code
|
|
52
|
+
changes need a page refresh.
|
|
53
|
+
|
|
54
|
+
Storage duration can be a preset (permanent / 30d / 90d / 1y / 5y / 10y) or any
|
|
55
|
+
custom term in days, months or years. Fees follow the chain's `RequiredFee`:
|
|
56
|
+
whole days rounded up, minimum one day, and any term past 36 years is charged the
|
|
57
|
+
permanent price instead of growing forever.
|
|
58
|
+
|
|
59
|
+
Cancelling an upload opens a confirmation dialog with the refund breakdown
|
|
60
|
+
(escrow, cancellation rate, withheld compensation, terminate service fee, amount
|
|
61
|
+
returned) read from the chain before anything is signed.
|
|
62
|
+
|
|
63
|
+
Status reads are cached: the Host answers from `<dataDir>/status-cache.json` and
|
|
64
|
+
refreshes the chain in the background (a 15 s window), and the panel keeps its own
|
|
65
|
+
`localStorage` copy so the card renders before the first request returns.
|
|
66
|
+
|
|
67
|
+
The Agent Key is stored **encrypted under a PIN**, never in clear text: scrypt
|
|
68
|
+
derives the AES-256-GCM key from the PIN, the decrypted key lives only in memory,
|
|
69
|
+
and the panel locks it on demand or after `lockIdleMinutes` of inactivity
|
|
70
|
+
(default 60, presets or any value from 0 to 10080 minutes). A plugin row reload
|
|
71
|
+
keeps the unlock while the process lives. A
|
|
72
|
+
profile that already holds a plaintext key is flagged and re-sealed in place.
|
|
73
|
+
|
|
74
|
+
The Agent Key and the storage defaults are configured in the plugin itself, never
|
|
75
|
+
in the global Settings dialog:
|
|
76
|
+
|
|
77
|
+
- **Falari Data panel → Settings tab** — always available, whatever the plugin
|
|
78
|
+
page renders.
|
|
79
|
+
- **Plugins → Falari Data** — the bundle page card, or the row's **Configure**
|
|
80
|
+
control, driven by the `plugins.bundle.config` / `plugins.row.config` slots.
|
|
81
|
+
Both may take a browser refresh to appear after an install.
|
|
82
|
+
|
|
83
|
+
## Configuration
|
|
84
|
+
|
|
85
|
+
The row accepts an optional `config` block (defaults shown). Put overrides in the
|
|
86
|
+
profile patch:
|
|
87
|
+
|
|
88
|
+
```yaml
|
|
89
|
+
- id: falari-harness
|
|
90
|
+
name: '@falari/harness'
|
|
91
|
+
config:
|
|
92
|
+
network: testnet # testnet | mainnet (mainnet is not live yet)
|
|
93
|
+
defaultPrivacy: public # public | private
|
|
94
|
+
defaultDuration: permanent # permanent | 30d | 90d | 1y | 5y | 10y
|
|
95
|
+
maxFileSizeBytes: 2147483648
|
|
96
|
+
allowUploadOutsideWorkspace: false
|
|
97
|
+
allowRemoteRoutes: false # keep the panel routes on loopback only
|
|
98
|
+
# gatewayUrl / retrievalUrl / explorerUrl override the network presets
|
|
99
|
+
# timeoutMs defaults to 60000
|
|
100
|
+
# dataDir defaults to <DSH_PROFILE_DIR>/falari-harness
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The Agent Key is **not** configuration: it lives in the DSH credential store as
|
|
104
|
+
the record `falari-harness/agent-key`.
|
|
105
|
+
|
|
106
|
+
## Tools
|
|
107
|
+
|
|
108
|
+
| Tool | Purpose |
|
|
109
|
+
|---|---|
|
|
110
|
+
| `falari_status` | Key state, tiers, allowance, balance, miners (`refresh: true` bypasses the cache) |
|
|
111
|
+
| `falari_quote` | Price an upload (`path` or `size_bytes`) and check the budget |
|
|
112
|
+
| `falari_upload` | Queue a workspace file; `wait: true` waits up to two minutes |
|
|
113
|
+
| `falari_task` | Read one task or the recent list |
|
|
114
|
+
| `falari_list` | This account's intents, newest first |
|
|
115
|
+
| `falari_download` | Download one intent, verify roots, decrypt when private |
|
|
116
|
+
|
|
117
|
+
The plugin configuration page writes these values back through the profile's
|
|
118
|
+
config editor, so saving restarts the plugin row.
|
|
119
|
+
|
|
120
|
+
Agent uploads are restricted to the Session working directory unless
|
|
121
|
+
`allowUploadOutsideWorkspace` is enabled. Files the user picks in the panel are
|
|
122
|
+
not subject to that guard.
|
|
123
|
+
|
|
124
|
+
## Build
|
|
125
|
+
|
|
126
|
+
The Host half bundles the unpublished Falari SDK (`@falari/agent`) and the
|
|
127
|
+
precompiles package into `lib/falari-sdk.cjs`, so installing the bundle needs no
|
|
128
|
+
npm package for them:
|
|
129
|
+
|
|
130
|
+
```sh
|
|
131
|
+
npm run build:sdk
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Run this after pulling a newer `sdk/sdk-agent-ts`.
|
|
135
|
+
|
|
136
|
+
## Repository
|
|
137
|
+
|
|
138
|
+
The project lives in this directory and is published as the npm package
|
|
139
|
+
`@falari/harness`; the surrounding Falari checkout only hosts the SDK it builds
|
|
140
|
+
against and the docs it follows. Project home: <https://falari.xyz>.
|
|
141
|
+
|
|
142
|
+
The package name `@falari/harness` is the bundle identity: `package.json` `name`,
|
|
143
|
+
the Loader row in `cordis.patch.yml` and the `id` passed to
|
|
144
|
+
`window.__ModuleLoader__.load` must all stay equal, because the client-modules
|
|
145
|
+
scan matches the installed manifest name against the Loader specifier.
|
|
146
|
+
|
|
147
|
+
`package.json` exports `.`, `./client`, `./cordis.patch.yml`, `./package.json`,
|
|
148
|
+
`./locale/*.json` and `./icon`, and ships `index.js`, `client.js`, `lib/**`, the
|
|
149
|
+
patch, locales, icon, README, CHANGELOG and LICENSE. Everything else
|
|
150
|
+
(`scripts/`, `docs/`) is repository-only. `npm pack --dry-run` lists 18 files.
|
|
151
|
+
|
|
152
|
+
Publishing is a push of this directory to a new repository; nothing else in the
|
|
153
|
+
manifest needs to change.
|
|
154
|
+
|
|
155
|
+
## Layout
|
|
156
|
+
|
|
157
|
+
```text
|
|
158
|
+
clients/harness/
|
|
159
|
+
├── .gitignore
|
|
160
|
+
├── CHANGELOG.md # release notes per milestone
|
|
161
|
+
├── LICENSE # MIT, © 2026 falari_labs
|
|
162
|
+
├── README.md
|
|
163
|
+
├── package.json # dsh.bundle + dsh.client manifest, exports, files
|
|
164
|
+
├── cordis.patch.yml # inserts the falari-harness row
|
|
165
|
+
├── icon.png
|
|
166
|
+
├── index.js # Host entry: wiring
|
|
167
|
+
├── client.js # Web client half: panel, tabs, settings
|
|
168
|
+
├── lib/
|
|
169
|
+
│ ├── config.js # row config resolution + edit validation
|
|
170
|
+
│ ├── errors.js # shared error shape and mapping
|
|
171
|
+
│ ├── routes.js # /api/falari-harness/* (same-origin, loopback)
|
|
172
|
+
│ ├── sdk.js # loads the bundled SDK
|
|
173
|
+
│ ├── service.js # FalariDataService: key, quote, budget, uploads, downloads
|
|
174
|
+
│ ├── tools.js # six falari_* Agent tools
|
|
175
|
+
│ └── falari-sdk.cjs # generated by npm run build:sdk (committed on purpose)
|
|
176
|
+
├── scripts/
|
|
177
|
+
│ ├── build-sdk.sh # esbuild bundle of @falari/agent + precompiles
|
|
178
|
+
│ ├── unit-host.mjs # pure-helper unit tests
|
|
179
|
+
│ ├── smoke-host.mjs # HTTP route smoke tests against a patched SDK
|
|
180
|
+
│ └── smoke-client.mjs # client.js render smoke test in a VM
|
|
181
|
+
├── locale/{en,zh}.json # plugin metadata
|
|
182
|
+
└── docs/
|
|
183
|
+
├── plan.md # v0.1 design and milestone log
|
|
184
|
+
└── test-plan.md # automated, live and panel checks
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Test
|
|
188
|
+
|
|
189
|
+
```sh
|
|
190
|
+
npm test # unit + Host routes + client render, all offline
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
| Suite | What it does |
|
|
194
|
+
|---|---|
|
|
195
|
+
| `scripts/unit-host.mjs` | config validation/defaults, name sanitizing, status and error mapping |
|
|
196
|
+
| `scripts/smoke-host.mjs` | patches the SDK client and drives every HTTP route: status, key, quote, raw upload, task actions, intents, download, config save, origin and loopback guards |
|
|
197
|
+
| `scripts/smoke-client.mjs` | loads `client.js` in a VM and server-renders the three slot components |
|
|
198
|
+
|
|
199
|
+
83 checks pass today. The manual and live testnet steps are in
|
|
200
|
+
[docs/test-plan.md](docs/test-plan.md).
|
|
201
|
+
|
|
202
|
+
## Security
|
|
203
|
+
|
|
204
|
+
- The Agent Key is a bearer credential with upload rights. It is stored only in
|
|
205
|
+
the Host credential store; the browser never receives or persists the raw
|
|
206
|
+
`far_...` string, and no route returns it.
|
|
207
|
+
- Upload routes accept only same-origin requests; cross-origin writes are
|
|
208
|
+
rejected with 403.
|
|
209
|
+
- Routes answer loopback peers only unless `allowRemoteRoutes` is enabled, so a
|
|
210
|
+
listener bound to a wider address cannot be used to change the key or pay for
|
|
211
|
+
uploads.
|
|
212
|
+
- Browser uploads stream into a 0600 temp file under the plugin data directory
|
|
213
|
+
and are deleted once the task completes or is cancelled; files older than 24
|
|
214
|
+
hours are swept at startup.
|
|
215
|
+
- The panel shows a private file's Data Key once the upload completes, because
|
|
216
|
+
losing it makes the ciphertext unrecoverable.
|
|
217
|
+
- Downloads are written only inside the configured `downloadDir` (default
|
|
218
|
+
`<dataDir>/downloads`); an `out_path` that escapes it is refused, and an
|
|
219
|
+
existing file name gains a ` (1)` suffix instead of being overwritten.
|
|
2
220
|
|
|
3
|
-
This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
|