@fargowealth/fargo-ai-cli 1.4.1 → 1.5.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/CHANGELOG.md +57 -0
- package/README.md +235 -52
- package/THIRD_PARTY_NOTICES.md +28 -0
- package/package.json +6 -6
- package/src/cli.mjs +58 -7
- package/src/constants.mjs +1 -1
- package/src/loopback-receiver.mjs +2 -1
- package/src/mcp-client.mjs +3 -1
- package/src/mcp-proxy.mjs +15 -1
- package/src/upload-transfer.mjs +422 -0
- package/src/yida-auth.mjs +309 -0
- package/src/yida-bundle-format.mjs +77 -0
- package/src/yida-business.mjs +128 -0
- package/src/yida-cancellation.mjs +121 -0
- package/src/yida-cli.mjs +65 -0
- package/src/yida-confirmation.mjs +86 -0
- package/src/yida-expense-contract.mjs +86 -0
- package/src/yida-expense.mjs +261 -0
- package/src/yida-lookup-plan.mjs +59 -0
- package/src/yida-operation.mjs +64 -0
- package/src/yida-rules.mjs +101 -0
- package/src/yida-runtime.mjs +63 -0
- package/src/yida-schema.mjs +111 -0
- package/src/yida-task.mjs +38 -0
- package/src/yida-tools.mjs +91 -0
- package/src/yida-workflow-contract.mjs +18 -0
- package/node_modules/@fargowealth/website-connector-runtime/README.md +0 -15
- package/node_modules/@fargowealth/website-connector-runtime/package.json +0 -24
- package/node_modules/@fargowealth/website-connector-runtime/src/index.d.mts +0 -136
- package/node_modules/@fargowealth/website-connector-runtime/src/index.mjs +0 -825
- package/src/website-browser-profile.mjs +0 -389
- package/src/website-cli.mjs +0 -365
- package/src/website-connector-definition.d.mts +0 -1
- package/src/website-connector-definition.mjs +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,62 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.5.0 — 2026-10-15
|
|
4
|
+
|
|
5
|
+
- Align the Portal and Fargo Pass displayed CLI version with this package.
|
|
6
|
+
- Discover the selected employee business directory by Chinese name, group and aliases; load background dictionaries only through the selected business's dependencies.
|
|
7
|
+
|
|
8
|
+
- Return a two-part Markdown confirmation (overall parameters + item rows) from
|
|
9
|
+
expense preview. Require explicit caller attestation of human confirmation
|
|
10
|
+
plus the unchanged preview pin before execution. Add schema-backed display
|
|
11
|
+
templates for expense, travel reimbursement and external payment; those display
|
|
12
|
+
templates do not enable unreviewed submission branches.
|
|
13
|
+
|
|
14
|
+
- Reuse one online Fargo identity within an expense tool task. Concurrent reads
|
|
15
|
+
share the result; local credential changes, logout and task expiry invalidate it.
|
|
16
|
+
Revalidate online before a mutation, and discard the context on completion.
|
|
17
|
+
- Permit a fresh independent expense after matching prior attempts are confirmed
|
|
18
|
+
terminated by detail read-back. Preserve active/completed duplicate blocking and
|
|
19
|
+
durable one-shot journals; never add a business association or erase old receipts.
|
|
20
|
+
|
|
21
|
+
- Share one own-HR response and one checked definition per expense preparation;
|
|
22
|
+
schedule 13 live lookups by schema dependencies with a concurrency limit of four.
|
|
23
|
+
Keep identity/admission and pre-write schema checks; never cache bank/rate values
|
|
24
|
+
across operations. Add a versioned execution contract to the expense bundle.
|
|
25
|
+
- Use decimal half-up currency multiplication, reject impossible invoice dates,
|
|
26
|
+
and verify persisted rates, accounting items and attachment names/sizes as well
|
|
27
|
+
as amounts and file UUIDs. Document pending/unknown/duplicate recovery outcomes.
|
|
28
|
+
|
|
29
|
+
- Add the local `yida_submit_expense` adapter for the reviewed ordinary,
|
|
30
|
+
non-project expense form: own HR bank details, live company/accounting/rate
|
|
31
|
+
lookups, uploaded PDF receipt, pinned preview, invoice/order duplicate checks,
|
|
32
|
+
durable one-shot submission and read-back. Generic form submission stays disabled.
|
|
33
|
+
- Add one local `yida_cancel_request` MCP tool shared across declared process
|
|
34
|
+
businesses: preview and version pinning, own-originator/form/process checks,
|
|
35
|
+
one-shot termination, durable duplicate protection and API read-back. Keep
|
|
36
|
+
completed/ordinary forms blocked and ambiguous results out of automatic retries.
|
|
37
|
+
- Capture calculation, option-loading, linkage, visibility, dataset-query and
|
|
38
|
+
script-reference metadata in YiDA model v2; retain legacy model support.
|
|
39
|
+
- Add the local read-only `yida_resolve_field` tool and reviewed self/department
|
|
40
|
+
initialization adapters. Preserve the originating form context and reject
|
|
41
|
+
write functions, raw MCP expressions and unrelated HR fields.
|
|
42
|
+
- Verify one explicitly authorized 0.06 HKD synthetic payment via API, with
|
|
43
|
+
recorded duplicate protection and exact amount/currency/attachment readback.
|
|
44
|
+
|
|
45
|
+
- Add local personal YiDA OAuth, account-isolated credential profiles, refresh
|
|
46
|
+
and logout commands, and read-only schema modeling.
|
|
47
|
+
- Add `yida_connection_status` and `yida_describe_form` to the local MCP bridge;
|
|
48
|
+
keep YiDA authorization and execution on the client computer.
|
|
49
|
+
- Include OpenYida attribution and its MIT license for adapted protocol and
|
|
50
|
+
schema conventions.
|
|
51
|
+
- Add local business catalog/package commands and MCP tools backed by the
|
|
52
|
+
LEGO publisher, atomic paired schema/handbook cache, immutable workflow pins,
|
|
53
|
+
enterprise isolation, integrity/version checks and live schema drift detection.
|
|
54
|
+
|
|
55
|
+
## 1.4.2
|
|
56
|
+
|
|
57
|
+
- Add generic large-file upload to Media and R2 resources with resumable TUS and optional local FFmpeg compression.
|
|
58
|
+
- Remove the obsolete Website Connector commands and bundled runtime.
|
|
59
|
+
|
|
3
60
|
## 1.4.1
|
|
4
61
|
|
|
5
62
|
- Capture Connector-declared refresh-only localStorage values without exposing
|
package/README.md
CHANGED
|
@@ -37,7 +37,8 @@ reused by both MCP and local CLI operations.
|
|
|
37
37
|
deploy composition, and migration-file ordering.
|
|
38
38
|
- CLI has no generic R2 or Cloudflare administration commands.
|
|
39
39
|
- `fargo mcp serve` is the local stdio bridge for WorkBuddy, Claude Code,
|
|
40
|
-
Codex, and Cursor.
|
|
40
|
+
Codex, and Cursor. It executes the reserved `yida_*` tools locally and
|
|
41
|
+
forwards other tools to hosted Fargo Pass.
|
|
41
42
|
- `fargo mcp tools` and `fargo mcp call` support scripts and one-shot
|
|
42
43
|
diagnostics without starting an MCP host.
|
|
43
44
|
|
|
@@ -47,60 +48,157 @@ fargo mcp call lego_app_read --args '{"action":"get","appId":"app_xxx"}'
|
|
|
47
48
|
fargo mcp call lego_app_read --args-file ./arguments.json
|
|
48
49
|
```
|
|
49
50
|
|
|
50
|
-
##
|
|
51
|
+
## Personal YiDA connection
|
|
51
52
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
Website Bridge; per-user Cookie/localStorage remains encrypted in BrowserGateway
|
|
55
|
-
and is never written to the CLI credential store or emitted as a JSON file. The
|
|
56
|
-
CLI keeps a dedicated local Chrome Profile so the user can log in locally and
|
|
57
|
-
synchronize later; that Profile is isolated from the user's normal Chrome data.
|
|
53
|
+
YiDA runs in the local CLI for client Agents. Sign in to Fargo first, then
|
|
54
|
+
authorize your own DingTalk/YiDA account:
|
|
58
55
|
|
|
59
56
|
```sh
|
|
60
|
-
fargo
|
|
61
|
-
fargo
|
|
62
|
-
fargo
|
|
63
|
-
fargo website list
|
|
64
|
-
fargo website operations --connector earningshub
|
|
65
|
-
fargo website connect --connector earningshub
|
|
66
|
-
fargo website sync --connector earningshub
|
|
67
|
-
fargo website sync --connector earningshub --no-prompt --settle-ms 5000
|
|
68
|
-
fargo website connection-status --connector earningshub
|
|
69
|
-
fargo website call --connector earningshub --operation get_symbol --args '{"symbol":"AMZN"}'
|
|
70
|
-
fargo website call --mode local --file connector.json --operation get_symbol --args '{"symbol":"AMZN"}'
|
|
71
|
-
fargo website binding
|
|
57
|
+
fargo yida auth login --endpoint https://xdlonl.aliwork.com --corp-id ding376dac86ffe9d2dbf2c783f7214b6d69
|
|
58
|
+
fargo yida auth status
|
|
59
|
+
fargo yida schema APP_GITLRTH76PM6J4M29F5D FORM-0AE7D3E4C01D45AC97D8C68DF7FF6B6CH3LQ
|
|
72
60
|
```
|
|
73
61
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
`
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
62
|
+
Login uses the OpenYida-compatible public client, `openid corpid`, an ephemeral
|
|
63
|
+
IPv4 loopback callback at `/oauth/callback`, and the YiDA service's token
|
|
64
|
+
exchange. It requires that the target YiDA environment accept this client
|
|
65
|
+
and callback. The OAuth screen identifies the provider as YiDA. This is
|
|
66
|
+
YiDA's personal Bearer-token channel, distinct from the DingTalk server API
|
|
67
|
+
`x-acs-dingtalk-access-token` / `systemToken` channel.
|
|
68
|
+
|
|
69
|
+
Each operation verifies the current Fargo identity with `ping_who_am_i`.
|
|
70
|
+
YiDA credentials stay in owner-restricted local files under `~/.fargo/yida`
|
|
71
|
+
(`%APPDATA%/Fargo AI/yida` on Windows), isolated by Fargo issuer, account and
|
|
72
|
+
organization, then by YiDA enterprise and member. They are not sent to Fargo
|
|
73
|
+
servers or printed in CLI/MCP output. State checks, a refresh lock, and identity
|
|
74
|
+
checks protect callback handling and rotating tokens. These are restricted
|
|
75
|
+
files, not an OS keychain or encrypted credential vault.
|
|
76
|
+
|
|
77
|
+
`auth status` and `auth profiles` report local metadata only. If multiple
|
|
78
|
+
profiles exist, select the exact returned `profile` ID with `--profile` for
|
|
79
|
+
schema reads and logout. Logout attempts provider revocation and always removes
|
|
80
|
+
the selected local credentials; `remoteRevoked` reports whether the provider
|
|
81
|
+
confirmed success. `fargo auth logout` alone does not revoke YiDA credentials.
|
|
82
|
+
|
|
83
|
+
The client MCP connection adds five read-only tools and two workflow write tools:
|
|
84
|
+
|
|
85
|
+
| Tool | Result |
|
|
86
|
+
| --- | --- |
|
|
87
|
+
| `yida_connection_status` | Current Fargo account's local YiDA profiles; no tokens |
|
|
88
|
+
| `yida_describe_form` | Field IDs, labels, aliases, parent fields, static options, detected source/association references and event bindings |
|
|
89
|
+
| `yida_resolve_field` | Live options or linked defaults from a reviewed read-only expression and its originating form |
|
|
90
|
+
| `yida_business_list` | Admitted business packages matching the selected local enterprise |
|
|
91
|
+
| `yida_business_bundle` | Versioned Schema and Handbook, cached as one package and checked against the live YiDA schema |
|
|
92
|
+
| `yida_cancel_request` | Preview, then terminate the current member's own running process; requires a declared business capability and final YiDA permission |
|
|
93
|
+
| `yida_submit_expense` | Preview, then submit the current member's own ordinary non-project expense using one reviewed form adapter, live HR/bank/default/rate lookups, a registered PDF upload receipt and invoice/order duplicate checks |
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
fargo mcp call yida_describe_form --args '{"appType":"APP_GITLRTH76PM6J4M29F5D","formUuid":"FORM-0AE7D3E4C01D45AC97D8C68DF7FF6B6CH3LQ"}'
|
|
97
|
+
fargo yida auth logout --profile <profileId>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The LEGO publisher is App `app_5c7114fa1a53`; the App is published
|
|
101
|
+
for company-account access without a marketplace listing. These commands require
|
|
102
|
+
CLI 1.5.0 or later:
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
fargo yida business list
|
|
106
|
+
fargo yida business get external_payment
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
`business list` returns catalog summaries (Chinese name, business ID, version
|
|
110
|
+
and capability flags), not all Schema/Handbook bodies. Agents should match the
|
|
111
|
+
user's request against this directory, ask the user to choose when ambiguous,
|
|
112
|
+
and fetch only the selected business. There is no keyword/search flag yet.
|
|
113
|
+
The YiDA publisher selects 14 homepage business entries, grouped as finance,
|
|
114
|
+
business, assets and other applications, with Chinese display names and aliases.
|
|
115
|
+
Enterprise matching does not prove personal permission to submit, and catalog
|
|
116
|
+
presence does not enable an unimplemented submission adapter. Department,
|
|
117
|
+
currency, exchange-rate, accounting, company and supplier sources are business
|
|
118
|
+
dependencies, not standalone employee entries. Query only a selected business's
|
|
119
|
+
configured fields with `yida_resolve_field`; adapters resolve the applicant and
|
|
120
|
+
department through that form's reviewed personal connector. Copied/test forms
|
|
121
|
+
and retired HR workflows do not appear in the employee directory.
|
|
122
|
+
|
|
123
|
+
Each fetch checks App access online, validates the enterprise, package hash and
|
|
124
|
+
minimum CLI version, then caches the pair atomically under `~/.fargo/yida-business`
|
|
125
|
+
(`%APPDATA%/Fargo AI/yida-business` on Windows). Cache keys include the verified
|
|
126
|
+
Fargo account/organization, publisher App and YiDA profile. Cache hits still
|
|
127
|
+
check authorization; network and permission errors have no offline fallback.
|
|
128
|
+
The returned `pin` contains `businessId`, `revision` and `bundleHash`; pass all
|
|
129
|
+
three to `yida_business_bundle` for subsequent calls within the same workflow.
|
|
130
|
+
The CLI equivalent is `business get <businessId> --revision <n> --bundle-hash <hash>`.
|
|
131
|
+
An unpinned lookup checks the latest release; a pinned lookup retains its exact
|
|
132
|
+
version. Published revisions are immutable and latest-version downgrades fail.
|
|
133
|
+
|
|
134
|
+
Every package lookup also reads the live YiDA schema. `status=schema_changed`
|
|
135
|
+
requires model and handbook review before a new business revision is published.
|
|
136
|
+
No package currently enables generic submission. Dynamic dictionary values are
|
|
137
|
+
queried at runtime, rather than cached in the handbook. All admitted
|
|
138
|
+
App users use one default role; YiDA data access still follows personal grants.
|
|
139
|
+
See [publisher maintenance](../../apps/yida-connector/README.md) for release steps.
|
|
140
|
+
|
|
141
|
+
All 45 captured process businesses declare the same cancellation capability;
|
|
142
|
+
42 receipt tables do not. `yida_cancel_request` defaults to a read-only preview.
|
|
143
|
+
Pass its `pin.revision`, `pin.bundleHash` and `previewHash` back with `dryRun:false`
|
|
144
|
+
only when the user requests cancellation. Execution verifies live schema and
|
|
145
|
+
form/process binding, enterprise/member and originator, current state and unchanged
|
|
146
|
+
preview; YiDA still decides whether the member can terminate. This retains the
|
|
147
|
+
record and does not reverse completed downstream business effects. Already
|
|
148
|
+
terminated/canceled returns `already_cancelled`; completed requests are blocked.
|
|
149
|
+
Active termination has mock coverage, but has not yet been tested on a live active
|
|
150
|
+
instance. A preview and no-op read of the user's manually terminated test do not
|
|
151
|
+
prove active-write permission. Accepted or ambiguous writes are never resent;
|
|
152
|
+
only proven pre-dispatch failures and authorization rejections permit a later
|
|
153
|
+
explicit attempt after a fresh preview. Journals live under `~/.fargo/yida-operations`
|
|
154
|
+
(Windows: `%APPDATA%/Fargo AI/yida-operations`). These tools require this updated
|
|
155
|
+
CLI 1.5.0 or later.
|
|
156
|
+
|
|
157
|
+
The expense adapter supports only ordinary expense form
|
|
158
|
+
`FORM-6EB2E57A94CF4445BB28508DC45262E3MDDX` at its reviewed live schema hash.
|
|
159
|
+
It does not accept raw form payloads, an alternative originator, projects or other
|
|
160
|
+
forms. Its payment company follows the member's configured default and its payment
|
|
161
|
+
currency/rates follow live definitions; `amount` and `currency` are the original
|
|
162
|
+
expense. Bank fields come only from the member's own HR record. Pass a local JSON
|
|
163
|
+
receipt from the registered YiDA PDF upload as `attachmentReceiptPath`. Preview
|
|
164
|
+
first, then pass `dryRun:false`, `previewHash`, `revision` and `bundleHash` to execute.
|
|
165
|
+
One invoice gets one durable operation record; an ambiguous write must be reconciled
|
|
166
|
+
instead of retried. This local reviewed adapter is separate from the still-disabled
|
|
167
|
+
generic submission capability in business packages.
|
|
168
|
+
|
|
169
|
+
Schema reads use the user's permission to read YiDA design schemas. Dynamic
|
|
170
|
+
options and effective employee permissions need runtime verification; formula
|
|
171
|
+
and event detection does not reconstruct all business logic. Model output omits
|
|
172
|
+
default values and executable source, reports traversal/option truncation, and
|
|
173
|
+
does not submit or modify any business record. Only public-cloud HTTPS
|
|
174
|
+
`aliwork.com` / `yidaapps.com` origins are supported in this first version.
|
|
175
|
+
|
|
176
|
+
Restart the client MCP process after updating the CLI to discover the new tools.
|
|
177
|
+
Hosted-only MCP connections do not expose these local tools. For an unpublished
|
|
178
|
+
checkout, use `node packages/fargo-cli/bin/fargo.mjs` in place of `fargo`.
|
|
179
|
+
|
|
180
|
+
Implementation references and the upstream MIT notice are included in
|
|
181
|
+
[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
|
|
182
|
+
|
|
183
|
+
Run the local connector and CLI tests with `npm test` from this package.
|
|
184
|
+
|
|
185
|
+
## Large-file transfer
|
|
186
|
+
|
|
187
|
+
`fargo upload` transfers a local file using an upload descriptor supplied by
|
|
188
|
+
the target Media or R2 resource. The descriptor contains the resource's
|
|
189
|
+
upload URL and, when needed, preparation and completion actions. Keep it
|
|
190
|
+
private because it may contain short-lived upload credentials.
|
|
191
|
+
|
|
192
|
+
```sh
|
|
193
|
+
fargo upload --file ./video.mov --request-file ./upload-request.json
|
|
194
|
+
fargo upload --file ./video.mov --request-file ./upload-request.json --compress
|
|
195
|
+
fargo upload --resume /path/to/checkpoint.json
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Media uploads support resumable TUS or direct multipart transfer; R2 uploads
|
|
199
|
+
use a signed PUT URL. `--compress` uses a locally installed FFmpeg. For a TUS
|
|
200
|
+
transfer, the CLI prints a private checkpoint path that can resume an interrupted
|
|
201
|
+
upload. Run `fargo upload --help` for the complete options.
|
|
104
202
|
|
|
105
203
|
## LEGO source snapshots
|
|
106
204
|
|
|
@@ -133,7 +231,7 @@ fargo lego deploy \
|
|
|
133
231
|
--entrypoint index.html \
|
|
134
232
|
--version 1.4.0 \
|
|
135
233
|
--name "Navigation refresh" \
|
|
136
|
-
--notes-file
|
|
234
|
+
--notes-file RELEASE_NOTES.md
|
|
137
235
|
```
|
|
138
236
|
|
|
139
237
|
For Workers use `--target worker`; the default entrypoint becomes `index.js`.
|
|
@@ -159,9 +257,15 @@ fargo lego deploy \
|
|
|
159
257
|
--login-required yes \
|
|
160
258
|
--version 1.4.0 \
|
|
161
259
|
--name "Full-stack release" \
|
|
162
|
-
--notes-file
|
|
260
|
+
--notes-file RELEASE_NOTES.md
|
|
163
261
|
```
|
|
164
262
|
|
|
263
|
+
Release notes are limited to 4,000 characters by both the CLI and hosted
|
|
264
|
+
deployment service. Pass concise notes for one version with `--notes`, or keep
|
|
265
|
+
them in a per-release file such as `RELEASE_NOTES.md`. Do not pass an entire
|
|
266
|
+
multi-version changelog unless it is within the limit and intentionally belongs
|
|
267
|
+
to the new release.
|
|
268
|
+
|
|
165
269
|
Use repeated `--assets-run-worker-first-route <glob>` options instead of the
|
|
166
270
|
boolean flag when only selected routes should invoke the Worker first. The
|
|
167
271
|
hosted LEGO publisher uploads the assets and attaches the binding; Cloudflare
|
|
@@ -201,6 +305,18 @@ MCP deployment contract. The result is `ready`, never automatically published.
|
|
|
201
305
|
Use `--dry-run` to validate both local packages without authentication or
|
|
202
306
|
network writes.
|
|
203
307
|
|
|
308
|
+
After reviewing the returned deployment and receiving explicit approval,
|
|
309
|
+
publish that exact deployment through Fargo Pass MCP:
|
|
310
|
+
|
|
311
|
+
```sh
|
|
312
|
+
fargo mcp call lego_deployment_release --args \
|
|
313
|
+
'{"action":"publish","appId":"app_xxx","deploymentId":"dep_xxx"}'
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Publication is a separate production write. The prepared deployment already
|
|
317
|
+
contains its security-checked access policy, so callers normally do not need to
|
|
318
|
+
repeat `visibility`, `loginRequired`, or `accessTargets` at publish time.
|
|
319
|
+
|
|
204
320
|
Deployment artifacts preserve binary bytes and include
|
|
205
321
|
`.fargo-deploy/manifest.json`. Default limits are 1,000 files, 25 MB total,
|
|
206
322
|
20 MB per file, and a 25 MB ZIP.
|
|
@@ -269,3 +385,70 @@ serialized across CLI processes.
|
|
|
269
385
|
|
|
270
386
|
Never copy, upload, commit, or print the credential file. Use
|
|
271
387
|
`fargo auth logout` when a device is no longer trusted.
|
|
388
|
+
|
|
389
|
+
## YiDA runtime rules
|
|
390
|
+
|
|
391
|
+
The local `yida_describe_form` response now includes `runtime.rules` with the
|
|
392
|
+
configured calculation expressions, dependent fields, lookup source fields,
|
|
393
|
+
conditions and triggers. Page JavaScript is not executed. Distributed business
|
|
394
|
+
packages carry configuration-read and runtime-verification states separately.
|
|
395
|
+
|
|
396
|
+
Use the local MCP tool `yida_resolve_field` with `appType`, `formUuid`, `fieldId`,
|
|
397
|
+
`kind` (`options` or `linked_value`), the dependent field `values`, and an exact
|
|
398
|
+
`profile` when needed. The tool re-reads the actual schema and uses its configured
|
|
399
|
+
read-only lookup expression with the originating form context. It rejects raw
|
|
400
|
+
expressions, unsupported functions and cross-app queries. No arbitrary POST or
|
|
401
|
+
general submission tool is exposed. A related-option response reaching 100 items
|
|
402
|
+
is possibly truncated and must not be treated as a complete dictionary.
|
|
403
|
+
|
|
404
|
+
The reviewed payment initialization adapter queries only the token member's HR
|
|
405
|
+
record, filters the returned fields, validates department membership, and resolves
|
|
406
|
+
the first department manager according to the page implementation. It does not
|
|
407
|
+
return unrelated HR fields or accept another user's identity.
|
|
408
|
+
|
|
409
|
+
`docs/yida/process-center/README.md` indexes every captured page and its paired
|
|
410
|
+
Schema/Handbook; the LEGO App distributes the 87 process/receipt business packages.
|
|
411
|
+
The local source implements these capabilities; this CLI update is not yet
|
|
412
|
+
published to npm. The specifically authorized 0.06 HKD payment smoke test is
|
|
413
|
+
recorded separately and does not enable general submission.
|
|
414
|
+
|
|
415
|
+
The reviewed expense execution contract lives in `schema.execution` of the ordinary
|
|
416
|
+
expense business package. It records semantic inputs, source rules and dependencies,
|
|
417
|
+
rounding, currencies, upload/read-back representation, and recovery states. Its
|
|
418
|
+
13 lookups run by dependency with at most four concurrent queries; a single own-HR
|
|
419
|
+
response supplies applicant and bank fields within each preparation. No live values
|
|
420
|
+
are cached between preview and execution. Currency multiplication uses decimal
|
|
421
|
+
half-up cents; the API read-back checks rates, accounting categories and file metadata.
|
|
422
|
+
|
|
423
|
+
Update the contract source in `src/yida-expense-contract.mjs`, materialize it with
|
|
424
|
+
`node scripts/yida-update-expense-contract.mjs` from the repository root, then freeze
|
|
425
|
+
a new immutable Schema/Handbook revision. The capture script reapplies this contract
|
|
426
|
+
only for the exact reviewed schema hash. Publishing a business package does not
|
|
427
|
+
update the local CLI executable. See `docs/yida/expense-workflow-review.md` for the
|
|
428
|
+
measured request count, remaining upload/recovery gaps and validation limits.
|
|
429
|
+
|
|
430
|
+
Expense identity checks now share an internal task context for one MCP invocation
|
|
431
|
+
(preparation or execution), not the lifetime of a chat or the MCP process. It is
|
|
432
|
+
never an externally supplied identity or persistent permission cache. Reads share
|
|
433
|
+
one online result while local credential changes invalidate the task; execution
|
|
434
|
+
performs an additional online check immediately before writing. Contexts expire
|
|
435
|
+
within five minutes and are closed on success or failure. Credential rotation
|
|
436
|
+
requires a fresh task, including same-account token refresh during the task.
|
|
437
|
+
|
|
438
|
+
A matching prior expense may be excluded from duplicate blocking only after its
|
|
439
|
+
details confirm the same owner/form/process and TERMINATED/CANCELED state. A fresh
|
|
440
|
+
application has no business linkage to the terminated one. The local replay guard
|
|
441
|
+
uses the verified terminal history to distinguish a new attempt without deleting
|
|
442
|
+
or bypassing the earlier operation journal. Active/completed/uncertain records
|
|
443
|
+
continue to block duplicates; no mutation is automatically retried.
|
|
444
|
+
|
|
445
|
+
### User confirmation before expense submission
|
|
446
|
+
|
|
447
|
+
The three main business Handbooks contain their own overall-parameter and detail-row
|
|
448
|
+
Markdown tables. `yida_submit_expense` returns the rendered table in
|
|
449
|
+
`confirmation.markdown`; show both parts to the user and wait for an explicit
|
|
450
|
+
Confirm of that exact preview. Only then pass `userConfirmed: true` with
|
|
451
|
+
`dryRun: false`, `revision`, `bundleHash`, and `previewHash`. A change to data,
|
|
452
|
+
attachments or the preview requires a fresh user confirmation. This Boolean is
|
|
453
|
+
caller attestation, not independent proof of a human signature. Travel and external
|
|
454
|
+
payment display templates do not enable new submission adapters.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# OpenYida
|
|
2
|
+
|
|
3
|
+
The YiDA OAuth/token protocol, schema conventions and endpoint usage in
|
|
4
|
+
`src/yida-auth.mjs` and `src/yida-schema.mjs` are adapted from OpenYida:
|
|
5
|
+
https://github.com/openyida/openyida
|
|
6
|
+
Revision: bdd45f54605cc7239ff8db116b2ef1b506179c70
|
|
7
|
+
|
|
8
|
+
MIT License
|
|
9
|
+
|
|
10
|
+
Copyright (c) 2026 Alibaba Group Holding Limited
|
|
11
|
+
|
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
13
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
14
|
+
in the Software without restriction, including without limitation the rights
|
|
15
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
16
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
17
|
+
furnished to do so, subject to the following conditions:
|
|
18
|
+
|
|
19
|
+
The above copyright notice and this permission notice shall be included in all
|
|
20
|
+
copies or substantial portions of the Software.
|
|
21
|
+
|
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
28
|
+
SOFTWARE.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fargowealth/fargo-ai-cli",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.5.0",
|
|
4
|
+
"description": "Fargo Pass CLI and local MCP with personal YiDA authorization, business definitions and confirmed expense requests",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"fargo": "bin/fargo.mjs",
|
|
@@ -11,19 +11,19 @@
|
|
|
11
11
|
"bin",
|
|
12
12
|
"src",
|
|
13
13
|
"CHANGELOG.md",
|
|
14
|
+
"THIRD_PARTY_NOTICES.md",
|
|
14
15
|
"README.md"
|
|
15
16
|
],
|
|
16
17
|
"engines": {
|
|
17
18
|
"node": ">=20.19.0"
|
|
18
19
|
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"test": "node --test test/*.test.mjs"
|
|
22
|
+
},
|
|
19
23
|
"dependencies": {
|
|
20
|
-
"@fargowealth/website-connector-runtime": "^1.1.0",
|
|
21
24
|
"fflate": "^0.8.2",
|
|
22
25
|
"ignore": "^7.0.6"
|
|
23
26
|
},
|
|
24
|
-
"bundleDependencies": [
|
|
25
|
-
"@fargowealth/website-connector-runtime"
|
|
26
|
-
],
|
|
27
27
|
"license": "UNLICENSED",
|
|
28
28
|
"publishConfig": {
|
|
29
29
|
"access": "public"
|
package/src/cli.mjs
CHANGED
|
@@ -9,13 +9,18 @@ import { applyLegoMigrations, planLegoMigrations } from "./lego-migrations.mjs";
|
|
|
9
9
|
import { callMcpTool, listMcpTools } from "./mcp-client.mjs";
|
|
10
10
|
import { runMcpProxy } from "./mcp-proxy.mjs";
|
|
11
11
|
import { installAgentMcp } from "./agent-install.mjs";
|
|
12
|
-
import {
|
|
12
|
+
import { transferUpload } from "./upload-transfer.mjs";
|
|
13
|
+
import { runYidaCli } from "./yida-cli.mjs";
|
|
13
14
|
|
|
14
15
|
export async function runCli(args, options = {}) {
|
|
15
16
|
const stdout = options.stdout ?? process.stdout;
|
|
16
17
|
const stderr = options.stderr ?? process.stderr;
|
|
17
18
|
const store = options.store ?? createCredentialStore(options.storeOptions);
|
|
18
19
|
try {
|
|
20
|
+
if (args[0] === "yida") {
|
|
21
|
+
await runYidaCli(args.slice(1), store, { ...options, stdout, stderr });
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
19
24
|
if (isHelpOption(args) && args[0] === "lego" && args[1] === "deploy") {
|
|
20
25
|
stdout.write(LEGO_DEPLOY_HELP);
|
|
21
26
|
return;
|
|
@@ -24,6 +29,10 @@ export async function runCli(args, options = {}) {
|
|
|
24
29
|
stdout.write(ROOT_HELP);
|
|
25
30
|
return;
|
|
26
31
|
}
|
|
32
|
+
if (args[0] === "upload" && isHelpOption(args)) {
|
|
33
|
+
stdout.write(UPLOAD_HELP);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
27
36
|
if (args[0] === "version" || args[0] === "--version" || args[0] === "-v") {
|
|
28
37
|
stdout.write(`fargo-cli version ${CLI_VERSION}\n`);
|
|
29
38
|
return;
|
|
@@ -62,8 +71,23 @@ export async function runCli(args, options = {}) {
|
|
|
62
71
|
stdout.write(`${JSON.stringify(await callMcpTool(store, toolName, toolArgs, options))}\n`);
|
|
63
72
|
return;
|
|
64
73
|
}
|
|
65
|
-
if (args[0] === "
|
|
66
|
-
|
|
74
|
+
if (args[0] === "upload") {
|
|
75
|
+
const input = {
|
|
76
|
+
compress: args.includes("--compress"),
|
|
77
|
+
ffmpegBin: optionValue(args, "--ffmpeg-bin")?.trim(),
|
|
78
|
+
filePath: optionValue(args, "--file")?.trim(),
|
|
79
|
+
requestPath: optionValue(args, "--request-file")?.trim(),
|
|
80
|
+
resumePath: optionValue(args, "--resume")?.trim(),
|
|
81
|
+
};
|
|
82
|
+
if (input.resumePath) {
|
|
83
|
+
if (input.compress || input.ffmpegBin || input.requestPath) throw new Error("--resume cannot be combined with --compress, --ffmpeg-bin, or --request-file");
|
|
84
|
+
} else {
|
|
85
|
+
for (const [key, optionName] of [["filePath", "--file"], ["requestPath", "--request-file"]]) {
|
|
86
|
+
if (!input[key] || input[key].startsWith("--")) throw new Error(`Missing required option ${optionName}`);
|
|
87
|
+
}
|
|
88
|
+
if (input.ffmpegBin && !input.compress) throw new Error("--ffmpeg-bin requires --compress");
|
|
89
|
+
}
|
|
90
|
+
stdout.write(`${JSON.stringify(await transferUpload(input, { ...options, stderr, store }))}\n`);
|
|
67
91
|
return;
|
|
68
92
|
}
|
|
69
93
|
if (args[0] === "lego" && args[1] === "snapshot") {
|
|
@@ -131,7 +155,7 @@ export async function runCli(args, options = {}) {
|
|
|
131
155
|
await installAgentConnection(args, "workbuddy", stdout, store, options);
|
|
132
156
|
return;
|
|
133
157
|
}
|
|
134
|
-
throw new Error("Usage: fargo auth login|device|status|logout | fargo agent install --agent <agent> | fargo mcp serve|tools|call | fargo
|
|
158
|
+
throw new Error("Usage: fargo auth login|device|status|logout | fargo yida auth|schema|business | fargo agent install --agent <agent> | fargo mcp serve|tools|call | fargo upload | fargo lego snapshot upload|list|download | fargo lego deploy | fargo lego d1 migrate plan|apply | fargo workbuddy install | fargo version");
|
|
135
159
|
} catch (error) {
|
|
136
160
|
stderr.write(`fargo: ${error instanceof Error ? error.message : "unknown error"}\n`);
|
|
137
161
|
if (options.throwOnError) throw error;
|
|
@@ -143,9 +167,10 @@ const ROOT_HELP = `Usage: fargo <command> [options]
|
|
|
143
167
|
|
|
144
168
|
Commands:
|
|
145
169
|
auth login|device|status|logout
|
|
170
|
+
yida auth login|status|profiles|logout | schema <appType> <formUuid>
|
|
146
171
|
agent install --agent <codex|claude-code|cursor|workbuddy>
|
|
147
172
|
mcp serve|tools|call
|
|
148
|
-
|
|
173
|
+
upload --file <path> --request-file <path>
|
|
149
174
|
lego snapshot upload|list|download
|
|
150
175
|
lego deploy
|
|
151
176
|
lego d1 migrate plan|apply
|
|
@@ -155,6 +180,26 @@ Commands:
|
|
|
155
180
|
Run "fargo lego deploy --help" for deployment options.
|
|
156
181
|
`;
|
|
157
182
|
|
|
183
|
+
const UPLOAD_HELP = `Usage: fargo upload [options]
|
|
184
|
+
|
|
185
|
+
Required for a new upload:
|
|
186
|
+
--file <path> Local file to transfer
|
|
187
|
+
--request-file <path> JSON upload descriptor supplied by a resource
|
|
188
|
+
|
|
189
|
+
Optional:
|
|
190
|
+
--compress Transcode a video to H.264/AAC MP4 with local FFmpeg
|
|
191
|
+
--ffmpeg-bin <path> FFmpeg executable (default: FFMPEG_PATH or ffmpeg)
|
|
192
|
+
--resume <checkpoint.json> Resume an interrupted Media TUS upload
|
|
193
|
+
|
|
194
|
+
Supported resource providers:
|
|
195
|
+
media TUS for resumable uploads, or multipart direct upload
|
|
196
|
+
r2 Signed HTTP PUT upload
|
|
197
|
+
|
|
198
|
+
FFmpeg is optional and is never bundled with Fargo CLI. If --compress is selected
|
|
199
|
+
and FFmpeg is missing, Fargo prints install instructions for the current OS.
|
|
200
|
+
The resource prepares its upload descriptor using the final file size after compression.
|
|
201
|
+
`;
|
|
202
|
+
|
|
158
203
|
const LEGO_DEPLOY_HELP = `Usage: fargo lego deploy [options]
|
|
159
204
|
|
|
160
205
|
Required:
|
|
@@ -163,7 +208,8 @@ Required:
|
|
|
163
208
|
--target <pages|worker> Deployment target
|
|
164
209
|
--version <version> Release version
|
|
165
210
|
--name <name> Release name
|
|
166
|
-
--notes <text>
|
|
211
|
+
--notes <text> One release's notes, maximum 4000 characters
|
|
212
|
+
--notes-file <path> Read one release's notes from a file; same limit
|
|
167
213
|
|
|
168
214
|
Source and execution:
|
|
169
215
|
--source <directory> Source snapshot root (default: .)
|
|
@@ -194,13 +240,18 @@ Worker Runtime Topology:
|
|
|
194
240
|
--queue-max-concurrency <n> Optional maximum concurrent consumers
|
|
195
241
|
--queue-retry-delay <s> Optional retry delay in seconds
|
|
196
242
|
|
|
243
|
+
Result and publication:
|
|
244
|
+
This command creates a ready, unpublished deployment. Production traffic is
|
|
245
|
+
unchanged. After review and explicit approval, publish the returned deployment
|
|
246
|
+
with Fargo Pass MCP lego_deployment_release(action=publish).
|
|
247
|
+
|
|
197
248
|
Example:
|
|
198
249
|
fargo lego deploy --app app_xxx --source . \\
|
|
199
250
|
--deploy-dir .build/worker --target worker --entrypoint index.js \\
|
|
200
251
|
--assets-dir dist --assets-binding ASSETS \\
|
|
201
252
|
--assets-not-found-handling single-page-application \\
|
|
202
253
|
--assets-run-worker-first --version 1.4.0 --name "Full-stack release" \\
|
|
203
|
-
--notes-file
|
|
254
|
+
--notes-file RELEASE_NOTES.md
|
|
204
255
|
|
|
205
256
|
.fargo-assets/ is an internal archive directory reserved for Fargo CLI.
|
|
206
257
|
Do not create or copy it manually; always pass browser output with --assets-dir.
|
package/src/constants.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const CLI_VERSION = "1.
|
|
1
|
+
export const CLI_VERSION = "1.5.0";
|
|
2
2
|
export const DEVICE_CODE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
|
|
3
3
|
export const DEFAULT_AUTH_URL = "https://auth.fargowealth.app";
|
|
4
4
|
export const DEFAULT_API_URL = "https://mcp.fargowealth.app";
|
|
@@ -4,7 +4,8 @@ import { createServer } from "node:http";
|
|
|
4
4
|
const LOOPBACK_HOST = "127.0.0.1";
|
|
5
5
|
|
|
6
6
|
export async function createLoopbackReceiver(options = {}) {
|
|
7
|
-
const callbackPath = `/oauth/callback/${(options.randomBytes ?? randomBytes)(18).toString("base64url")}`;
|
|
7
|
+
const callbackPath = options.callbackPath ?? `/oauth/callback/${(options.randomBytes ?? randomBytes)(18).toString("base64url")}`;
|
|
8
|
+
if (!/^\/oauth\/callback(?:\/[A-Za-z0-9_-]+)?$/.test(callbackPath)) throw new Error("Invalid OAuth loopback callback path");
|
|
8
9
|
const timeoutMs = Math.max(1_000, Number(options.timeoutMs) || 10 * 60 * 1_000);
|
|
9
10
|
let address;
|
|
10
11
|
let settled = false;
|
package/src/mcp-client.mjs
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { DEFAULT_MCP_URL } from "./constants.mjs";
|
|
2
2
|
import { authenticatedRequest, responsePayload } from "./api-client.mjs";
|
|
3
|
+
import { callLocalYidaTool, isLocalYidaTool, localYidaTools } from "./yida-tools.mjs";
|
|
3
4
|
|
|
4
5
|
export async function listMcpTools(store, options = {}) {
|
|
5
6
|
const result = await mcpRequest(store, "tools/list", {}, options);
|
|
6
|
-
return result;
|
|
7
|
+
return { ...result, tools: [...(result.tools ?? []).filter(tool => !isLocalYidaTool(tool.name)), ...localYidaTools()] };
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
export async function callMcpTool(store, name, args, options = {}) {
|
|
11
|
+
if (isLocalYidaTool(name)) return callLocalYidaTool(store, name, args, options);
|
|
10
12
|
return mcpRequest(store, "tools/call", { name, arguments: args }, options);
|
|
11
13
|
}
|
|
12
14
|
|