aweshare 0.3.9 → 0.4.1

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.
Files changed (58) hide show
  1. package/README.md +42 -39
  2. package/apps/agent/dist/cli.js +80 -77
  3. package/apps/agent/dist/cli.js.map +1 -1
  4. package/apps/agent/dist/config.d.ts +5 -1
  5. package/apps/agent/dist/config.js +23 -2
  6. package/apps/agent/dist/config.js.map +1 -1
  7. package/apps/agent/dist/connection.js +7 -2
  8. package/apps/agent/dist/connection.js.map +1 -1
  9. package/apps/agent/dist/daemon.d.ts +35 -0
  10. package/apps/agent/dist/daemon.js +175 -0
  11. package/apps/agent/dist/daemon.js.map +1 -0
  12. package/apps/agent/dist/doctor.d.ts +10 -3
  13. package/apps/agent/dist/doctor.js +41 -6
  14. package/apps/agent/dist/doctor.js.map +1 -1
  15. package/apps/agent/dist/hub.d.ts +0 -2
  16. package/apps/agent/dist/hub.js +3 -13
  17. package/apps/agent/dist/hub.js.map +1 -1
  18. package/apps/consumer/dist/cli.js +31 -5
  19. package/apps/consumer/dist/cli.js.map +1 -1
  20. package/apps/consumer/dist/hub.d.ts +3 -0
  21. package/apps/consumer/dist/hub.js +11 -0
  22. package/apps/consumer/dist/hub.js.map +1 -1
  23. package/apps/consumer/dist/table.d.ts +11 -0
  24. package/apps/consumer/dist/table.js +23 -0
  25. package/apps/consumer/dist/table.js.map +1 -0
  26. package/apps/hub/dist/admin.d.ts +3 -3
  27. package/apps/hub/dist/admin.js +5 -169
  28. package/apps/hub/dist/admin.js.map +1 -1
  29. package/apps/hub/dist/cli.js +10 -4
  30. package/apps/hub/dist/cli.js.map +1 -1
  31. package/apps/hub/dist/consumer.d.ts +5 -1
  32. package/apps/hub/dist/consumer.js +38 -10
  33. package/apps/hub/dist/consumer.js.map +1 -1
  34. package/apps/hub/dist/db.d.ts +26 -30
  35. package/apps/hub/dist/db.js +96 -65
  36. package/apps/hub/dist/db.js.map +1 -1
  37. package/apps/hub/dist/invites.js +9 -5
  38. package/apps/hub/dist/invites.js.map +1 -1
  39. package/apps/hub/dist/limiter.d.ts +8 -0
  40. package/apps/hub/dist/limiter.js +26 -0
  41. package/apps/hub/dist/limiter.js.map +1 -1
  42. package/apps/hub/dist/server.js +3 -8
  43. package/apps/hub/dist/server.js.map +1 -1
  44. package/apps/hub/dist/table.d.ts +5 -1
  45. package/apps/hub/dist/table.js +16 -8
  46. package/apps/hub/dist/table.js.map +1 -1
  47. package/apps/hub/dist/tunnel.js +14 -0
  48. package/apps/hub/dist/tunnel.js.map +1 -1
  49. package/bin/aweshare.mjs +1 -1
  50. package/package.json +1 -1
  51. package/packages/protocol/dist/errors.d.ts +0 -2
  52. package/packages/protocol/dist/errors.js +0 -2
  53. package/packages/protocol/dist/errors.js.map +1 -1
  54. package/packages/protocol/dist/messages.d.ts +4 -0
  55. package/packages/protocol/dist/messages.js.map +1 -1
  56. package/apps/agent/dist/table.d.ts +0 -12
  57. package/apps/agent/dist/table.js +0 -26
  58. package/apps/agent/dist/table.js.map +0 -1
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
  <img src="./logo/logo.png" alt="aweshare" width="760">
3
3
  <h1>aweshare: Local-first AI Capability Relay</h1>
4
4
  <p><strong>An open-source, local-first AI capability relay.</strong></p>
5
- <p>Share local Ollama/vLLM or authorized OpenAI/Anthropic backends through a grant-based hub, consumed with standard SDKs via <code>namespace/alias</code>.</p>
5
+ <p>Share local Ollama/vLLM or authorized OpenAI/Anthropic backends through a self-hosted hub, consumed with standard SDKs via <code>namespace/alias</code>.</p>
6
6
  <p><strong>Upstream API keys never leave the producer's device.</strong></p>
7
7
  <p>
8
8
  <strong>English</strong> ·
@@ -14,7 +14,7 @@
14
14
  <a href="https://ko-fi.com/mugpeng"><img src="https://img.shields.io/badge/Ko--fi-Buy%20me%20a%20coffee-FF5E5B?style=flat-square&logo=ko-fi&logoColor=white" alt="Ko-fi"></a>
15
15
  </p>
16
16
  <p>
17
- <a href="https://github.com/wehuman01/aweshare-source/releases"><img src="https://img.shields.io/badge/version-0.3.9-7C3AED?style=flat-square" alt="Version"></a>
17
+ <a href="https://github.com/wehuman01/aweshare-source/releases"><img src="https://img.shields.io/badge/version-0.4.1-7C3AED?style=flat-square" alt="Version"></a>
18
18
  <a href="https://github.com/wehuman01/aweshare"><img src="https://img.shields.io/badge/node-%E2%89%A522-0EA5E9?style=flat-square" alt="Node"></a>
19
19
  <a href="https://github.com/wehuman01/aweshare/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-proprietary-E34F26?style=flat-square" alt="License"></a>
20
20
  <a href="https://www.npmjs.com/package/aweshare"><img src="https://img.shields.io/badge/npm-aweshare-7C3AED?style=flat-square" alt="npm package"></a>
@@ -44,19 +44,19 @@ Consumer (standard SDK, zero changes) Producer side
44
44
  ▼ │
45
45
  ┌─────────────────────────────┐ │
46
46
  │ aweshare hub (public, 1 node)│◄───── WSS reverse tunnel (agent dials out)
47
- │ auth / grants / route / meter│ no public IP, no port forwarding needed
47
+ │ auth / route / meter │ no public IP, no port forwarding needed
48
48
  └─────────────────────────────┘
49
49
  ```
50
50
 
51
- - **Grant-based trust**: consumers can only use aliases explicitly granted to them. No payments, no marketplace.
51
+ - **Invite-only trust**: admission runs through one-time invite codes the operator mints; every admitted consumer may call every offering. No payments, no marketplace.
52
52
  - **Namespaced aliases**: `peng/gpt-4o` is globally unique with one owner — routing is a deterministic lookup.
53
53
  - v1 relays **native transparent SSE** for OpenAI↔OpenAI (chat completions and Responses), Anthropic↔Anthropic. No cross-protocol conversion, no smart routing, no web console.
54
54
 
55
55
  ## Trust boundary (read this first)
56
56
 
57
57
  - To route and meter, **consumer prompts and model responses transit the hub in plaintext — this is not end-to-end encryption**. The hub persists no request/response content, but the hub operator can technically see it. Only use a hub instance you trust — which is why the hub is open source and self-hostable.
58
- - Upstream API keys never leave the producer's device and are never sent to consumers. Tokens are stored **hash-only** (peppered SHA-256): the plaintext is shown exactly once at issue/redeem and can never be re-displayed. Invite codes are the deliberate exception — their plaintext is kept so the operator can re-view them with `hub list --reveal`; a DB leak exposes unredeemed codes, but no tokens.
59
- - Token revocation is **reversible suspension** (`hub revoke --id N` / `hub restore --id N`, by invite), and an invite and the producer it minted move together: revoking a redeemed code suspends that producer (and closes its tunnel), and restoring from either handle revives both. Nothing is deleted on revoke — grants, offerings and usage history survive a suspension.
58
+ - Upstream API keys never leave the producer's device and are never sent to consumers. Tokens are stored twice on purpose: a **peppered SHA-256 hash** drives authentication, and the plaintext is kept so the operator can hand a lost one back (`hub list --token`). Invite codes work the same way — their plaintext is re-viewable with `hub list --reveal`. A DB leak therefore exposes every identity, so guard the data dir.
59
+ - Token revocation is **reversible suspension** (`hub revoke --id N` / `hub restore --id N`, by invite), and an invite and the producer it minted move together: revoking a redeemed code suspends that producer (and closes its tunnel), and restoring from either handle revives both. Nothing is deleted on revoke — offerings and usage history survive a suspension.
60
60
 
61
61
  ### Compliance and disclaimer
62
62
 
@@ -114,25 +114,17 @@ aweshare consumer join --hub https://hub.example.com --code asi_...
114
114
  # -H 'content-type: application/json' -d '{"code":"asi_..."}'
115
115
  ```
116
116
 
117
- Prefer hand-delivering keys? Direct issuance still works via the admin API:
118
-
119
- ```bash
120
- curl -X POST https://hub.example.com/admin/v1/tokens \
121
- -H "Authorization: Bearer asa_... (the admin token)" -H "content-type: application/json" \
122
- -d '{"role":"consumer","name":"alice"}' # → asc_..., give to the consumer
123
- ```
124
-
125
117
  Three token roles, one per party:
126
118
 
127
119
  | Role | Who holds it | How it's used |
128
120
  |---|---|---|
129
121
  | `admin` | hub operator (you only) | the admin REST API (`/admin/v1/*`); CLI side: `hub invite` / `list [invites\|producers\|consumers]` / `revoke` / `restore` |
130
122
  | `producer` (`asp_...`) | the agent on the producer's machine | set as `token` in `~/.aweshare/config.toml`; the agent registers its offerings with it |
131
- | `consumer` (`asc_...`) | whoever calls the models | set in SDK env vars (`ANTHROPIC_AUTH_TOKEN` / `OPENAI_API_KEY`); the hub uses it to decide which aliases they may call |
123
+ | `consumer` (`asc_...`) | whoever calls the models | set in SDK env vars (`ANTHROPIC_AUTH_TOKEN` / `OPENAI_API_KEY`); it identifies the consumer for metering, limits and suspension |
132
124
 
133
125
  The producer's `name` becomes their alias namespace (the `peng/` in `peng/gpt-4o`).
134
126
 
135
- Identity and permission are deliberately split. The operator issues identities invite codes for producers, `asc_…` keys for consumers while each producer alone decides who may call their own aliases (`aweshare producer grant`; the admin API can read grants for audit but cannot write them). A fresh consumer key can call nothing until a producer grants it, so the hub works the same whether you run everything yourself (private hub) or producers who don't know each other share yours (community hub).
127
+ The operator owns admission: one-time invite codes for both roles, the only admission path (every identity carries its invite handle for its whole lifecycle). A redeemed consumer key may call **every** offering on the hub if you let someone in, they can use what is shared. Guardrails: per-consumer `hub limits` (rate, concurrency, token budgets), per-offering caps (`maxConcurrentUsers`, `dailyTokens`) and `hub revoke` suspension, all enforced by the hub.
136
128
 
137
129
  ### 2. Producer first run (in this order)
138
130
 
@@ -149,12 +141,10 @@ aweshare producer init --hub https://hub.example.com --token asp_...
149
141
  # ③ doctor: pre-flight checks, ordered to find the first failing link
150
142
  aweshare producer doctor
151
143
 
152
- # ④ Grant a consumer
153
- aweshare producer grant --alias peng/qwen2.5.7b --consumer alice
154
- # time-limited trial: add --expires-in 7d (re-granting refreshes the expiry)
155
-
156
- # ⑤ Start (long-running; when it stops, aliases go offline and consumers get 503)
157
- aweshare producer start
144
+ # ④ Start (long-running; when it stops, aliases go offline and consumers get 503)
145
+ aweshare producer start # foreground; add --background to detach it
146
+ # detached runs are checked with 'aweshare producer doctor --status'
147
+ # and stopped with 'aweshare producer stop'
158
148
  ```
159
149
 
160
150
  ### 3. Consumer first run (in this order)
@@ -200,7 +190,7 @@ If Claude Code has a stale OAuth login it overrides env config — switch with `
200
190
  base_url = "https://hub.example.com/v1"
201
191
  ```
202
192
 
203
- **Discovering models**: `GET /v1/models` (OpenAI SDK `client.models.list()`) returns every alias granted to the key, with online status.
193
+ **Discovering models**: `GET /v1/models` (OpenAI SDK `client.models.list()`) returns every alias registered on the hub, with online status.
204
194
 
205
195
  ## Producer config reference (~/.aweshare/config.toml)
206
196
 
@@ -230,8 +220,21 @@ alias = "peng/qwen2.5.7b" # namespace must be your producer name
230
220
  backend = "ollama"
231
221
  upstreamModel = "qwen2.5:7b" # the real backend id (full tag from `ollama list`)
232
222
  maxConcurrency = 1 # start at 1 for local models; raise for cloud APIs
223
+ # maxConcurrentUsers = 3 # distinct concurrent consumers (hub default 3)
224
+ # dailyTokens = 1000000 # shared tokens per UTC day (default 1M; 0 = unlimited)
233
225
  ```
234
226
 
227
+ One offering exposes exactly one upstream model: consumers call the alias and the hub rewrites the request's model to `upstreamModel` before dispatch — they can never pick another model. To share more models, add more `[[offerings]]`.
228
+
229
+ **Per-offering usage caps** ride along in the same block; both are optional and enforced by the hub (defaults apply when unset, including for agents that predate them):
230
+
231
+ | Key | Default | Meaning | Enforcement |
232
+ |---|---|---|---|
233
+ | `maxConcurrentUsers` | 3 | distinct consumers with a request in flight on this alias | 429 `PRODUCER_MAX_USERS` |
234
+ | `dailyTokens` | 1000000 | tokens (prompt + completion) shared across all consumers on this alias, per UTC day; `0` = unlimited | 429 `QUOTA_EXCEEDED` (resets at UTC midnight) |
235
+
236
+ `maxConcurrency` caps in-flight **requests**; `maxConcurrentUsers` caps in-flight **people** — a single consumer firing 5 parallel requests needs `maxConcurrency ≥ 5` but still counts as one user. Daily caps count recorded usage (see "Honest limits" below).
237
+
235
238
  Key hygiene: use dedicated, least-privilege, revocable keys with budget alerts; keep `secrets.json` at 0600 and out of git/screenshots; rotate on suspected leaks. Before sharing, check the upstream's terms: account rules, subscription limits, forwarding and commercial-use constraints.
236
239
 
237
240
  ## Consumer limits (hub-wide defaults + per-consumer overrides)
@@ -255,8 +258,6 @@ curl -X PUT https://hub.example.com/admin/v1/consumers/alice/limits \
255
258
  | `tpm` | max tokens (prompt + completion) in any sliding 60s window | 429 `RATE_LIMITED` (in-memory window, like the RPS bucket) |
256
259
  | `maxTotalTokens` | lifetime token budget for this consumer | 429 `QUOTA_EXCEEDED` (sums `usage_events`) |
257
260
 
258
- Grants can also carry an expiry: `aweshare producer grant --alias peng/gpt-4o --consumer alice --expires-in 7d`. Grant writes are producer-owned — the admin API keeps read-only audit access but rejects admin-token writes with `403 NOT_GRANTED`. An expired grant returns `403 GRANT_EXPIRED`; re-granting refreshes the expiry.
259
-
260
261
  Honest limits: token-based caps count what upstreams report — Ollama streams report no usage, so they contribute 0. Both TPM and the lifetime budget are observed-usage thresholds, not hard reservations: one request can cross the threshold, and concurrent requests that start before earlier usage is recorded can overshoot it further. Once recorded usage has reached the threshold, new requests are rejected.
261
262
 
262
263
  ## Endpoints and errors
@@ -264,13 +265,14 @@ Honest limits: token-based caps count what upstreams report — Ollama streams r
264
265
  | Endpoint | Purpose |
265
266
  |---|---|
266
267
  | `POST /v1/chat/completions` · `POST /v1/messages` · `POST /v1/responses` | inference (Bearer or `x-api-key`) |
267
- | `GET /v1/models` | aliases visible to this key, with status |
268
+ | `GET /v1/models` | every alias registered on the hub, with status |
269
+ | `GET /v1/catalog` | every offering on the hub — producer, alias, protocol, status, the per-offering caps (discovery view for `aweshare consumer list`) |
268
270
  | `GET /healthz` | liveness |
269
- | `/admin/v1/*` | token/limit/usage management (admin or producer token) · grants: writes producer-only, admin reads for audit · consumer limit overrides: `GET`/`PUT`/`DELETE /admin/v1/consumers/{name}/limits` (admin only) |
271
+ | `/admin/v1/*` | token/limit/usage management (admin or producer token) · consumer limit overrides: `GET`/`PUT`/`DELETE /admin/v1/consumers/{name}/limits` (admin only) |
270
272
 
271
- Error semantics: `401` invalid key · `401 TOKEN_REVOKED` suspended token (ask the operator to restore it) · `403` not granted or `GRANT_EXPIRED` · `403 HUB_FULL` producer capacity reached · `404` unknown alias · `400 PROTOCOL_MISMATCH` protocol/alias mismatch · `429` rate limit, TPM or producer concurrency cap (`QUOTA_EXCEEDED` = lifetime token budget hit) · `502` upstream/tunnel failure (upstream 4xx/5xx passes through verbatim) · `503` producer offline / backend degraded · `504` timeout. Errors carry `{error:{code,message,requestId}}`; the requestId spans both sides' logs.
273
+ Error semantics: `401` invalid key · `401 TOKEN_REVOKED` suspended token (ask the operator to restore it) · `403 HUB_FULL` producer capacity reached · `404` unknown alias · `400 PROTOCOL_MISMATCH` protocol/alias mismatch · `429` rate limit, TPM or producer concurrency cap (`PRODUCER_MAX_USERS` = distinct-consumer cap; `QUOTA_EXCEEDED` = lifetime or daily token budget hit) · `502` upstream/tunnel failure (upstream 4xx/5xx passes through verbatim) · `503` producer offline / backend degraded · `504` timeout. Errors carry `{error:{code,message,requestId}}`; the requestId spans both sides' logs.
272
274
 
273
- Usage metering: one row per request (alias, real model, status, duration, byte counts, best-effort token counts), **zero content stored**. Producers list grants with `aweshare producer list`; usage is queried with `aweshare hub usage` or `GET /admin/v1/usage` (admin sees everything, producers and consumers their own slice).
275
+ Usage metering: one row per request (alias, real model, status, duration, byte counts, best-effort token counts), **zero content stored**. Usage is queried with `aweshare hub usage` or `GET /admin/v1/usage` (admin sees everything, producers and consumers their own slice).
274
276
 
275
277
  ## Command reference
276
278
 
@@ -283,12 +285,12 @@ Both sides at a glance — details in the sections above.
283
285
  | `aweshare hub init` | create data dir + admin token (printed once) |
284
286
  | `aweshare hub serve [--host H] [--port N]` | run the hub |
285
287
  | `aweshare hub invite [--role producer\|consumer] [--name NAME] [--count N] [--expires-in 7d]` | mint one-time invite codes (`asi_…`, printed once; re-view with `list --reveal`); producer codes: bound (`--name`) or unbound (name + email at redeem, `--count` batches); consumer codes: always bound to one name |
286
- | `aweshare hub list [invites\|producers\|consumers] [--reveal] [--token] [--json]` | read hub state: invite lifecycle (ROLE + who redeemed, `--reveal` codes, `--token` minted tokens), or the producer/consumer rosters with status and last seen |
288
+ | `aweshare hub list [invites\|producers\|consumers] [--reveal] [--token] [--json]` | read hub state: invite lifecycle (ROLE + who redeemed, `--reveal` codes, `--token` the minted tokens), or the producer/consumer rosters with status and last seen |
287
289
  | `aweshare hub limits NAME [--rps N] [--burst N] [--max-concurrent N] [--tpm N] [--max-total-tokens N] [--clear] [--json]` | show, merge or clear one consumer's limit overrides (unset keys keep the hub-wide defaults) |
288
290
  | `aweshare hub usage [--consumer NAME] [--alias ns/model] [--limit N] [--json]` | recent requests, newest first — one row per request, zero content stored |
289
291
  | `aweshare hub revoke --id N` · `aweshare hub restore --id N` | kill an invite / undo — a redeemed code suspends the producer it minted, restore revives both |
290
292
 
291
- Token issuance runs through invites (both roles). `limits` and `usage` are thin wrappers over the admin REST API (`/admin/v1/*`, see Endpoints and errors) — curl works too. Grants are producer-owned and were never the operator's CLI: manage them with `aweshare producer grant`/`revoke`/`list` on the producer machine (the admin API keeps read-only audit access).
293
+ Token issuance runs through invites (both roles). `limits` and `usage` are thin wrappers over the admin REST API (`/admin/v1/*`, see Endpoints and errors) — curl works too.
292
294
 
293
295
  `list` prints an aligned table by default; append `--json` for the raw API response.
294
296
 
@@ -299,22 +301,23 @@ Token issuance runs through invites (both roles). `limits` and `usage` are thin
299
301
  | `aweshare producer init [--hub URL] [--token asp_…]` | write config templates into `~/.aweshare` |
300
302
  | `aweshare producer join --hub URL --code asi_… [--name NAME --email YOU@EXAMPLE.COM]` | redeem an invite code into a producer token and write it into the config (`--name`/`--email` for unbound codes; probes the hub first — plain HTTP outside the LAN needs `--allow-http`) |
301
303
  | `aweshare producer config path` · `config show` · `config edit` | locate / inspect (secrets redacted) / edit the config |
302
- | `aweshare producer doctor` | pre-flight checks fix the first FAIL, re-run |
303
- | `aweshare producer grant --alias ns/model --consumer NAME [--expires-in 7d]` | grant a consumer access |
304
- | `aweshare producer revoke --alias ns/model --consumer NAME` | revoke access |
305
- | `aweshare producer list` | list grants for your namespace |
306
- | `aweshare producer start` | connect and relay (long-running; run it in your own terminal) |
304
+ | `aweshare producer doctor [--status]` | diagnose end to end: background instance, config, backend probes, hub, recent log (`--status` skips the network probes for an instant answer) |
305
+ | `aweshare producer start [--background]` | connect and relay (long-running; `--background` detaches it logs to `~/.aweshare/producer.log`, pid to `producer.pid`) |
306
+ | `aweshare producer stop` | stop the background producer (SIGTERM, SIGKILL after 10s) and clean up its pidfile |
307
307
 
308
- **Consumer** — one command, on the consumer's machine; day-to-day they point a standard SDK at the hub (see Consumer tool configuration):
308
+ **Consumer** — two commands, on the consumer's machine; day-to-day they point a standard SDK at the hub (see Consumer tool configuration):
309
309
 
310
310
  | Command | Purpose |
311
311
  |---|---|
312
- | `aweshare consumer join --hub URL --code asi_… [--allow-http]` | redeem a consumer invite into an `asc_` token — printed once with ready-to-paste SDK env vars (save it: the hub stores only a hash) |
312
+ | `aweshare consumer join --hub URL --code asi_… [--allow-http]` | redeem a consumer invite into an `asc_` token — printed once with ready-to-paste SDK env vars (save it; the operator can re-view it with `hub list --token`) |
313
+ | `aweshare consumer list --hub URL --token asc_… [--json]` | discovery view of the hub: every producer, alias, protocol, status, the per-offering caps |
313
314
 
314
315
  CLI maintenance: `aweshare self-update [--check]` updates the npm-installed CLI (`--check` only compares versions).
315
316
 
316
317
  ## Operations
317
318
 
319
+ No always-on box to share from, or looking for models others share? The project's developer runs a community hub at **https://aweshare.wehuman.top** (invite-based — request a code at peng@wehuman.top); [docs/community-hub/](./docs/community-hub/README.md) is a step-by-step guide for connecting as a producer or consumer (中文版).
320
+
318
321
  The hub reads `config.toml` from its data dir (`~/.aweshare-hub/config.toml`; Docker: `/data/config.toml`). `aweshare hub init` writes the template with every key commented out — uncomment to override a default. Keys use the same names as below, camelCase (`consumerRps`, `headTimeoutMs`, …). Precedence: `serve` flags (`--host`/`--port`) > env vars > config.toml > defaults. A broken file (invalid TOML, unknown key, non-positive value) fails fast at startup with the key named; `AWESHARE_HUB_DATA_DIR` itself stays env-only (it locates the file).
319
322
 
320
323
  | Env var | Default | Purpose |
@@ -343,7 +346,7 @@ Updating a npm install: `aweshare self-update` (asks before installing; `--check
343
346
 
344
347
  ```bash
345
348
  pnpm install
346
- pnpm test # 98 tests: protocol / hub contract (fake agent vs real hub) / agent unit / e2e (real SDKs)
349
+ pnpm test # 197 tests: protocol / hub contract (fake agent vs real hub) / agent unit / e2e (real SDKs)
347
350
  pnpm build # tsc -b, whole monorepo
348
351
  pnpm check # biome
349
352
  ```
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // Command set: init, join, config (path|show|edit), doctor, start, grant,
3
- // revoke, list.
2
+ // Command set: init, join, config (path|show|edit), doctor, start, stop.
4
3
  // Everything that talks to the hub goes through src/hub.ts (one UA, one
5
4
  // timeout policy, one error shape).
6
5
  import { spawn } from 'node:child_process';
@@ -10,9 +9,9 @@ import { INVITE_PATTERN } from '../../../packages/protocol/dist/index.js';
10
9
  import pino from 'pino';
11
10
  import { agentDir, applyJoinToConfig, CONFIG_TEMPLATE, loadAgentConfig, redactConfig, SECRETS_TEMPLATE, writeFileAtomic, } from './config.js';
12
11
  import { AgentConnection } from './connection.js';
12
+ import { clearPidIfMine, formatLogLine, isProducerAlive, logFileOf, readPid, spawnBackground, stopBackground, tailLog, } from './daemon.js';
13
13
  import { runDoctor } from './doctor.js';
14
- import { assertWireCompatible, errorMessage, hostIsLocal, plainHttpHost, probeHub, producerApi, redeemInvite, } from './hub.js';
15
- import { renderGrants } from './table.js';
14
+ import { assertWireCompatible, errorMessage, hostIsLocal, plainHttpHost, probeHub, redeemInvite, } from './hub.js';
16
15
  const VERSION = JSON.parse(readFileSync(new URL('../../../package.json', import.meta.url), 'utf8')).version;
17
16
  // One-liners only; flags per command live in their own -h, everything else in README.
18
17
  const USAGE = `Usage: aweshare producer [OPTIONS] COMMAND [ARGS]...
@@ -27,11 +26,9 @@ Commands:
27
26
  init Write the config template and empty secrets.
28
27
  join Redeem an invite code into a producer token.
29
28
  config Show or edit the config (path | show | edit).
30
- doctor Pre-flight checks: config, backends, hub.
31
- start Connect, register offerings, relay requests.
32
- grant Allow a consumer to call your offering.
33
- revoke Remove a grant.
34
- list List grants for your namespace.`;
29
+ doctor Diagnose: instance, config, backends, hub (--status for the quick view).
30
+ start Connect, register offerings, relay (--background to daemonize).
31
+ stop Stop the background producer and clean up its pidfile.`;
35
32
  const COMMAND_HELP = {
36
33
  init: `Usage: aweshare producer init [OPTIONS]
37
34
 
@@ -63,41 +60,32 @@ Commands:
63
60
  path Print the config path.
64
61
  show Show the config with secrets redacted.
65
62
  edit Open the config in $VISUAL, $EDITOR or vi.`,
66
- doctor: `Usage: aweshare producer doctor
63
+ doctor: `Usage: aweshare producer doctor [OPTIONS]
67
64
 
68
- Pre-flight checks: config validity, backend reachability, hub connectivity.
65
+ Diagnose this producer end to end: the background instance (running/died),
66
+ config validity, backend reachability, hub connectivity — plus the recent
67
+ log of a background instance. Fix the first FAIL, then re-run.
69
68
 
70
69
  Options:
71
- -h, --help Show this message and exit.`,
72
- start: `Usage: aweshare producer start
73
-
74
- Connect to the hub, register offerings, relay requests (runs in the foreground).
75
-
76
- Options:
77
- -h, --help Show this message and exit.`,
78
- grant: `Usage: aweshare producer grant [OPTIONS]
70
+ --status Quick view: instance state and recent log only; skips every
71
+ network probe, so it always answers instantly.
72
+ -h, --help Show this message and exit.`,
73
+ start: `Usage: aweshare producer start [OPTIONS]
79
74
 
80
- Allow a consumer to call your offering.
75
+ Connect to the hub, register offerings, relay requests.
76
+ Runs in the foreground; --background detaches it (logs go to
77
+ ~/.aweshare/producer.log, the pid to ~/.aweshare/producer.pid).
81
78
 
82
79
  Options:
83
- --alias ALIAS The offering alias, e.g. your-name/model (required).
84
- --consumer NAME Who may call it (required).
85
- --expires-in D Optional expiry: 90s, 30m, 12h or 7d.
86
- -h, --help Show this message and exit.`,
87
- revoke: `Usage: aweshare producer revoke [OPTIONS]
88
-
89
- Remove a grant.
90
-
91
- Options:
92
- --alias ALIAS The offering alias (required).
93
- --consumer NAME Whose grant to remove (required).
94
- -h, --help Show this message and exit.`,
95
- list: `Usage: aweshare producer list [OPTIONS]
80
+ --background Run detached; check on it with 'aweshare producer doctor --status',
81
+ stop it with 'aweshare producer stop'.
82
+ -h, --help Show this message and exit.`,
83
+ stop: `Usage: aweshare producer stop
96
84
 
97
- List grants for your namespace.
85
+ Stop the background producer (SIGTERM, SIGKILL after 10s) and clean up
86
+ its pidfile. A stale pidfile is removed even when nothing is running.
98
87
 
99
88
  Options:
100
- --json Print the raw API response instead of a table.
101
89
  -h, --help Show this message and exit.`,
102
90
  };
103
91
  function parseFlags(argv) {
@@ -133,14 +121,6 @@ function noPositionals(cmd, positional) {
133
121
  if (arg)
134
122
  fail(`unexpected argument '${arg}' — this command takes flags only (see: aweshare producer ${cmd} -h)`);
135
123
  }
136
- /** Parse a human duration like 90s, 30m, 12h, 7d into milliseconds. */
137
- function parseDuration(raw) {
138
- const m = /^(\d+)([smhd])$/.exec(raw);
139
- if (!m)
140
- fail(`--expires-in must look like 90s, 30m, 12h or 7d, got '${raw}'`);
141
- const unit = { s: 1000, m: 60_000, h: 3_600_000, d: 86_400_000 }[m[2]];
142
- return Number(m[1]) * unit;
143
- }
144
124
  // --- commands (one function each; hub errors bubble to main's catch) ---
145
125
  async function runInit(flags, dir) {
146
126
  const configPath = join(dir, 'config.toml');
@@ -170,8 +150,7 @@ async function runInit(flags, dir) {
170
150
  console.log(' 1. edit config.toml: backends + offerings (namespace must be your producer name)');
171
151
  console.log(' 2. put upstream keys in secrets.json (they never leave this machine)');
172
152
  console.log(' 3. aweshare producer doctor # find the first failing link');
173
- console.log(' 4. aweshare producer grant --alias YOU/model --consumer NAME');
174
- console.log(' 5. aweshare producer start');
153
+ console.log(' 4. aweshare producer start');
175
154
  }
176
155
  /** Refuse silent plain-HTTP pairing with a non-local hub: the producer token
177
156
  * would cross the network unencrypted. */
@@ -229,8 +208,7 @@ async function runJoin(flags, dir) {
229
208
  console.log(` 1. edit config.toml: backends + offerings (aliases must start with ${name}/)`);
230
209
  console.log(' 2. put upstream keys in secrets.json (they never leave this machine)');
231
210
  console.log(' 3. aweshare producer doctor # find the first failing link');
232
- console.log(` 4. aweshare producer grant --alias ${name}/model --consumer NAME`);
233
- console.log(' 5. aweshare producer start');
211
+ console.log(' 4. aweshare producer start');
234
212
  }
235
213
  async function runConfig(dir, positional) {
236
214
  const sub = positional[0] ?? 'path';
@@ -238,6 +216,7 @@ async function runConfig(dir, positional) {
238
216
  const secretsPath = join(dir, 'secrets.json');
239
217
  if (sub === 'path') {
240
218
  console.log(configPath);
219
+ console.log(secretsPath);
241
220
  }
242
221
  else if (sub === 'show') {
243
222
  if (!existsSync(configPath)) {
@@ -258,16 +237,45 @@ async function runConfig(dir, positional) {
258
237
  fail(`unknown config subcommand: ${sub} (expected path, show or edit)`);
259
238
  }
260
239
  }
261
- async function printDoctorReport(dir) {
262
- const report = await runDoctor(dir);
240
+ async function printDoctorReport(dir, flags) {
241
+ const report = await runDoctor(dir, { statusOnly: flags.get('status') === 'true' });
263
242
  for (const check of report.checks) {
264
243
  console.log(`${check.ok ? ' ok ' : 'FAIL '} ${check.name}: ${check.detail}`);
265
244
  }
245
+ if (report.logTail && report.logTail.length > 0) {
246
+ console.log(`\nrecent log (${report.logTail.length} line(s)):`);
247
+ for (const line of report.logTail)
248
+ console.log(` ${line}`);
249
+ }
266
250
  console.log(report.ok ? '\ndoctor: all green' : '\ndoctor: fix the first FAIL above, then re-run');
267
251
  process.exitCode = report.ok ? 0 : 1;
268
252
  }
269
- async function runStart(dir) {
253
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
254
+ async function runStart(dir, flags) {
255
+ // Validate before daemonizing so config errors hit the terminal, not the log file.
270
256
  const { config, secrets } = loadAgentConfig(dir);
257
+ const existing = readPid(dir);
258
+ // The detached child re-enters here and finds its own pid on file — that is us, not a clash.
259
+ if (existing !== null && existing !== process.pid && isProducerAlive(existing)) {
260
+ fail(`a background producer is already running (pid ${existing}) — inspect it with 'aweshare producer doctor --status', stop it with 'aweshare producer stop'`);
261
+ }
262
+ if (flags.get('background') === 'true') {
263
+ const pid = spawnBackground(dir);
264
+ console.log(`started in the background (pid ${pid})`);
265
+ console.log(`log: ${logFileOf(dir)}`);
266
+ console.log("stop it with 'aweshare producer stop'");
267
+ // Give instant exits (bad backend URL, port taken, …) a moment to surface
268
+ // here instead of leaving the user with a dead "running" instance.
269
+ await sleep(2000);
270
+ if (!isProducerAlive(pid)) {
271
+ console.error('background producer exited immediately — last log lines:');
272
+ for (const line of tailLog(logFileOf(dir), 10))
273
+ console.error(` ${formatLogLine(line)}`);
274
+ clearPidIfMine(dir, pid);
275
+ process.exit(1);
276
+ }
277
+ return;
278
+ }
271
279
  const connection = new AgentConnection({
272
280
  config,
273
281
  secrets,
@@ -275,33 +283,30 @@ async function runStart(dir) {
275
283
  });
276
284
  const shutdown = () => {
277
285
  console.error('\nshutting down…');
278
- void connection.stop().then(() => process.exit(0));
286
+ void connection.stop().then(() => {
287
+ clearPidIfMine(dir, process.pid); // no-op for foreground runs
288
+ process.exit(0);
289
+ });
279
290
  };
280
291
  process.on('SIGINT', shutdown);
281
292
  process.on('SIGTERM', shutdown);
282
293
  await connection.start();
283
294
  }
284
- async function runGrants(cmd, flags) {
285
- const { config } = loadAgentConfig(agentDir());
286
- const api = producerApi(config.hubUrl, config.token);
287
- if (cmd === 'grant' || cmd === 'revoke') {
288
- const alias = flags.get('alias');
289
- const consumer = flags.get('consumer');
290
- if (!alias || !consumer)
291
- fail('--alias and --consumer are required');
292
- const body = { alias, consumer };
293
- const expiresIn = flags.get('expires-in');
294
- if (cmd === 'grant' && expiresIn) {
295
- body.expiresAt = new Date(Date.now() + parseDuration(expiresIn)).toISOString();
296
- }
297
- const data = cmd === 'grant'
298
- ? await api('PUT', '/admin/v1/grants', body)
299
- : await api('DELETE', `/admin/v1/grants?alias=${encodeURIComponent(alias)}&consumer=${encodeURIComponent(consumer)}`);
300
- console.log(JSON.stringify(data));
301
- return;
295
+ /** Stop needs neither config nor secrets — a stale pidfile must stay cleanable
296
+ * even when config.toml is broken. */
297
+ async function runStop(dir) {
298
+ try {
299
+ const result = await stopBackground(dir);
300
+ if (result === 'stopped')
301
+ console.log('background producer stopped');
302
+ else if (result === 'killed')
303
+ console.log('background producer killed (did not exit within 10s of SIGTERM)');
304
+ else
305
+ console.log('not running (stale pidfile cleaned up)');
306
+ }
307
+ catch (err) {
308
+ fail(errorMessage(err));
302
309
  }
303
- const data = await api('GET', '/admin/v1/grants');
304
- console.log(flags.get('json') === 'true' ? JSON.stringify(data, null, 2) : renderGrants(data));
305
310
  }
306
311
  async function main() {
307
312
  const [cmd, ...rest] = process.argv.slice(2);
@@ -331,16 +336,14 @@ async function main() {
331
336
  return await runConfig(dir, positional);
332
337
  case 'doctor': {
333
338
  noPositionals(cmd, positional);
334
- return await printDoctorReport(dir);
339
+ return await printDoctorReport(dir, flags);
335
340
  }
336
341
  case 'start':
337
342
  noPositionals(cmd, positional);
338
- return await runStart(dir);
339
- case 'grant':
340
- case 'revoke':
341
- case 'list':
343
+ return await runStart(dir, flags);
344
+ case 'stop':
342
345
  noPositionals(cmd, positional);
343
- return await runGrants(cmd, flags);
346
+ return await runStop(dir);
344
347
  default:
345
348
  fail(`unknown command: ${cmd}\n\n${USAGE}`);
346
349
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,yEAAyE;AACzE,wEAAwE;AACxE,oCAAoC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EACL,QAAQ,EACR,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,eAAe,GAChB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EACL,cAAc,EACd,aAAa,EACb,eAAe,EACf,SAAS,EACT,OAAO,EACP,eAAe,EACf,cAAc,EACd,OAAO,GACR,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EACL,oBAAoB,EACpB,YAAY,EACZ,WAAW,EAEX,aAAa,EACb,QAAQ,EACR,YAAY,GACb,MAAM,UAAU,CAAA;AAEjB,MAAM,OAAO,GACX,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,uBAAuB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAGnF,CAAC,OAAO,CAAA;AAET,sFAAsF;AACtF,MAAM,KAAK,GAAG;;;;;;;;;;;;;;iEAcmD,CAAA;AAEjE,MAAM,YAAY,GAA2B;IAC3C,IAAI,EAAE;;;;;;;6CAOqC;IAC3C,IAAI,EAAE;;;;;;;;;;;;;+CAauC;IAC7C,MAAM,EAAE;;;;;;;mDAOyC;IACjD,MAAM,EAAE;;;;;;;;;2CASiC;IACzC,KAAK,EAAE;;;;;;;;;4CASmC;IAC1C,IAAI,EAAE;;;;;;0CAMkC;CACzC,CAAA;AAED,SAAS,UAAU,CAAC,IAAc;IAChC,MAAM,UAAU,GAAa,EAAE,CAAA;IAC/B,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAA;IACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAW,CAAA;QAC3B,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACvB,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;YACzB,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;gBACZ,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;YAC5C,CAAC;iBAAM,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,CAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAY,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC5E,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,CAAW,CAAC,CAAA;YAC5C,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;YAC/B,CAAC;QACH,CAAC;aAAM,CAAC;YACN,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACpB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,CAAA;AAC9B,CAAC;AAED,SAAS,IAAI,CAAC,OAAe;IAC3B,OAAO,CAAC,KAAK,CAAC,UAAU,OAAO,EAAE,CAAC,CAAA;IAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC;AAED,4FAA4F;AAC5F,SAAS,aAAa,CAAC,GAAW,EAAE,UAAoB;IACtD,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,CAAA;IACzB,IAAI,GAAG;QACL,IAAI,CACF,wBAAwB,GAAG,6DAA6D,GAAG,MAAM,CAClG,CAAA;AACL,CAAC;AAED,0EAA0E;AAE1E,KAAK,UAAU,OAAO,CAAC,KAA0B,EAAE,GAAW;IAC5D,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,CAAA;IAC3C,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAA;IAC7C,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,IAAI,QAAQ,GAAG,eAAe,CAAA;QAC9B,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACrB,QAAQ,GAAG,QAAQ,CAAC,OAAO,CACzB,kCAAkC,EAClC,aAAa,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CACjC,CAAA;QACH,CAAC;QACD,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACvB,QAAQ,GAAG,QAAQ,CAAC,OAAO,CACzB,oCAAoC,EACpC,YAAY,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAClC,CAAA;QACH,CAAC;QACD,eAAe,CAAC,UAAU,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAA;QAC5C,OAAO,CAAC,GAAG,CAAC,SAAS,UAAU,EAAE,CAAC,CAAA;IACpC,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,iBAAiB,UAAU,EAAE,CAAC,CAAA;IAC5C,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7B,eAAe,CAAC,WAAW,EAAE,gBAAgB,EAAE,KAAK,CAAC,CAAA;QACrD,OAAO,CAAC,GAAG,CAAC,SAAS,WAAW,EAAE,CAAC,CAAA;IACrC,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,iBAAiB,WAAW,EAAE,CAAC,CAAA;IAC7C,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;IAC5B,OAAO,CAAC,GAAG,CAAC,oFAAoF,CAAC,CAAA;IACjG,OAAO,CAAC,GAAG,CAAC,wEAAwE,CAAC,CAAA;IACrF,OAAO,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAA;IAC5E,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAA;AAC7C,CAAC;AAED;0CAC0C;AAC1C,SAAS,cAAc,CAAC,GAAW,EAAE,KAA0B;IAC7D,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,CAAA;IAC/B,IAAI,IAAI,KAAK,IAAI,IAAI,WAAW,CAAC,IAAI,CAAC;QAAE,OAAM;IAC9C,IAAI,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,MAAM,EAAE,CAAC;QACvC,IAAI,CACF,GAAG,GAAG,6EAA6E;YACjF,uIAAuI,CAC1I,CAAA;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,KAA0B,EAAE,GAAW;IAC5D,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IAC9B,IAAI,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,IAAI,CAAC,8BAA8B,CAAC,CAAA;IAC3E,IAAI,CAAC,IAAI,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,IAAI,CAAC,yCAAyC,CAAC,CAAA;IACxF,cAAc,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IAC1B,4EAA4E;IAC5E,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAA;IAChC,oBAAoB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IAC/B,uEAAuE;IACvE,MAAM,UAAU,GAAa,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,CAAA;IAC7D,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC;QAAE,UAAU,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAW,CAAA;IACpE,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;QAAE,UAAU,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAAW,CAAA;IACvE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,UAAU,CAAC,CAAA;IAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,CAAA;IAC3C,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAA;IAC7C,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,iBAAiB,CAAC,eAAe,EAAE,GAAG,EAAE,KAAK,CAAC,IAAI,eAAe,CAAA;QAChF,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,CAAA;QAC1C,OAAO,CAAC,GAAG,CAAC,SAAS,UAAU,EAAE,CAAC,CAAA;IACpC,CAAC;SAAM,CAAC;QACN,MAAM,OAAO,GAAG,iBAAiB,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAA;QAC/E,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,+DAA+D;YAC/D,IAAI,CACF,+DAA+D,UAAU,mCAAmC,KAAK,IAAI;gBACnH,mFAAmF,CACtF,CAAA;QACH,CAAC;QACD,eAAe,CAAC,UAAU,EAAE,OAAO,EAAE,KAAK,CAAC,CAAA;QAC3C,OAAO,CAAC,GAAG,CAAC,WAAW,UAAU,EAAE,CAAC,CAAA;IACtC,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7B,eAAe,CAAC,WAAW,EAAE,gBAAgB,EAAE,KAAK,CAAC,CAAA;QACrD,OAAO,CAAC,GAAG,CAAC,SAAS,WAAW,EAAE,CAAC,CAAA;IACrC,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK,CAAA;IAC3D,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK,iBAAiB,IAAI,iBAAiB,IAAI,OAAO,CAAC,CAAA;IAC7E,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;IAC5B,OAAO,CAAC,GAAG,CAAC,wEAAwE,IAAI,IAAI,CAAC,CAAA;IAC7F,OAAO,CAAC,GAAG,CAAC,wEAAwE,CAAC,CAAA;IACrF,OAAO,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAA;IAC5E,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAA;AAC7C,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,GAAW,EAAE,UAAoB;IACxD,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,MAAM,CAAA;IACnC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,CAAA;IAC3C,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAA;IAC7C,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACnB,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;QACvB,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;IAC1B,CAAC;SAAM,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QAC1B,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5B,IAAI,CAAC,gBAAgB,UAAU,uCAAuC,CAAC,CAAA;QACzE,CAAC;QACD,OAAO,CAAC,GAAG,CACT,YAAY,CACV,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,EAChC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CACxE,CACF,CAAA;IACH,CAAC;SAAM,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QAC1B,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5B,IAAI,CAAC,gBAAgB,UAAU,uCAAuC,CAAC,CAAA;QACzE,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,IAAI,CAAA;QAC/D,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;QAC/D,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAA;QACnD,OAAO,MAAM,IAAI,OAAO,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;IACpC,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,8BAA8B,GAAG,gCAAgC,CAAC,CAAA;IACzE,CAAC;AACH,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,GAAW,EAAE,KAA0B;IACtE,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,MAAM,EAAE,CAAC,CAAA;IACnF,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC,CAAA;IAC/E,CAAC;IACD,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChD,OAAO,CAAC,GAAG,CAAC,iBAAiB,MAAM,CAAC,OAAO,CAAC,MAAM,YAAY,CAAC,CAAA;QAC/D,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,OAAO;YAAE,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAA;IAC7D,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,iDAAiD,CAAC,CAAA;IAClG,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AACtC,CAAC;AAED,MAAM,KAAK,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAA;AAE/E,KAAK,UAAU,QAAQ,CAAC,GAAW,EAAE,KAA0B;IAC7D,mFAAmF;IACnF,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,eAAe,CAAC,GAAG,CAAC,CAAA;IAChD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;IAC7B,6FAA6F;IAC7F,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,OAAO,CAAC,GAAG,IAAI,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/E,IAAI,CACF,iDAAiD,QAAQ,gGAAgG,CAC1J,CAAA;IACH,CAAC;IACD,IAAI,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,MAAM,EAAE,CAAC;QACvC,MAAM,GAAG,GAAG,eAAe,CAAC,GAAG,CAAC,CAAA;QAChC,OAAO,CAAC,GAAG,CAAC,kCAAkC,GAAG,GAAG,CAAC,CAAA;QACrD,OAAO,CAAC,GAAG,CAAC,QAAQ,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACrC,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAA;QACpD,0EAA0E;QAC1E,mEAAmE;QACnE,MAAM,KAAK,CAAC,IAAI,CAAC,CAAA;QACjB,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,OAAO,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAA;YACzE,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBAAE,OAAO,CAAC,KAAK,CAAC,KAAK,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YACzF,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;YACxB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;QACD,OAAM;IACR,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,eAAe,CAAC;QACrC,MAAM;QACN,OAAO;QACP,GAAG,EAAE,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,MAAM,EAAE,CAAC;KACzD,CAAC,CAAA;IACF,MAAM,QAAQ,GAAG,GAAG,EAAE;QACpB,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAA;QACjC,KAAK,UAAU,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;YAC/B,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,CAAA,CAAC,4BAA4B;YAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC,CAAC,CAAA;IACJ,CAAC,CAAA;IACD,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IAC9B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;IAC/B,MAAM,UAAU,CAAC,KAAK,EAAE,CAAA;AAC1B,CAAC;AAED;sCACsC;AACtC,KAAK,UAAU,OAAO,CAAC,GAAW;IAChC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,GAAG,CAAC,CAAA;QACxC,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAA;aAC/D,IAAI,MAAM,KAAK,QAAQ;YAC1B,OAAO,CAAC,GAAG,CAAC,iEAAiE,CAAC,CAAA;;YAC3E,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAA;IAC5D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAA;IACzB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAC5C,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,CAAA;IAC9C,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,qBAAqB,OAAO,EAAE,CAAC,CAAA;QAC3C,OAAM;IACR,CAAC;IACD,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QAClB,OAAM;IACR,CAAC;IACD,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,CAAA;IAC9B,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,MAAM,CAAC,EAAE,CAAC;QACxE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACjB,OAAM;IACR,CAAC;IACD,MAAM,GAAG,GAAG,QAAQ,EAAE,CAAA;IAEtB,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,MAAM;YACT,aAAa,CAAC,GAAG,EAAE,UAAU,CAAC,CAAA;YAC9B,OAAO,MAAM,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QAClC,KAAK,MAAM;YACT,aAAa,CAAC,GAAG,EAAE,UAAU,CAAC,CAAA;YAC9B,OAAO,MAAM,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QAClC,KAAK,QAAQ;YACX,OAAO,MAAM,SAAS,CAAC,GAAG,EAAE,UAAU,CAAC,CAAA;QACzC,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,aAAa,CAAC,GAAG,EAAE,UAAU,CAAC,CAAA;YAC9B,OAAO,MAAM,iBAAiB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QAC5C,CAAC;QACD,KAAK,OAAO;YACV,aAAa,CAAC,GAAG,EAAE,UAAU,CAAC,CAAA;YAC9B,OAAO,MAAM,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QACnC,KAAK,MAAM;YACT,aAAa,CAAC,GAAG,EAAE,UAAU,CAAC,CAAA;YAC9B,OAAO,MAAM,OAAO,CAAC,GAAG,CAAC,CAAA;QAC3B;YACE,IAAI,CAAC,oBAAoB,GAAG,OAAO,KAAK,EAAE,CAAC,CAAA;IAC/C,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA"}
@@ -16,6 +16,10 @@ export interface AgentOffering {
16
16
  backend: string;
17
17
  upstreamModel: string;
18
18
  maxConcurrency: number;
19
+ /** Distinct concurrent consumers the hub admits on this alias; hub default 3. */
20
+ maxConcurrentUsers?: number;
21
+ /** Shared per-alias tokens per UTC day; hub default 1000000, 0 = unlimited. */
22
+ dailyTokens?: number;
19
23
  }
20
24
  export interface AgentConfig {
21
25
  hubUrl: string;
@@ -42,5 +46,5 @@ export declare function redactConfig(configToml: string, secretsJson: string | u
42
46
  export declare function applyJoinToConfig(content: string, hubUrl: string, token: string): string | null;
43
47
  /** tmp+rename atomic write with owner-only permissions. */
44
48
  export declare function writeFileAtomic(path: string, content: string, mode?: number): void;
45
- export declare const CONFIG_TEMPLATE = "# aweshare producer configuration (~/.aweshare/config.toml)\n# Secrets live in ~/.aweshare/secrets.json and never leave this machine.\n\nhubUrl = \"http://127.0.0.1:8787\"\ntoken = \"asp_PASTE_PRODUCER_TOKEN\"\n\n# Backends hold the upstream API. baseUrl follows the SDK convention:\n# openai-style (OpenAI/Ollama/vLLM/LM Studio) includes /v1, e.g. http://127.0.0.1:11434/v1\n# anthropic-style excludes /v1, e.g. https://api.anthropic.com\n# responses-style includes the version path, e.g. https://open.bigmodel.cn/api/v1\n[[backends]]\nid = \"ollama\"\nprotocol = \"openai\"\nbaseUrl = \"http://127.0.0.1:11434/v1\"\n# keyRef = \"ollama-key\" # optional; keys live in secrets.json\n\n[[backends]]\nid = \"openai\"\nprotocol = \"openai\"\nbaseUrl = \"https://api.openai.com/v1\"\nkeyRef = \"openai-key\"\n\n# Offerings map a public alias (namespace/name) to a backend model.\n# The namespace must match your producer name on the hub.\n[[offerings]]\nalias = \"YOUR_NAME/qwen2.5.7b\"\nbackend = \"ollama\"\nupstreamModel = \"qwen2.5:7b\" # must match 'ollama list' exactly, including the tag\nmaxConcurrency = 1 # start at 1 for local models\n\n[[offerings]]\nalias = \"YOUR_NAME/gpt-4o\"\nbackend = \"openai\"\nupstreamModel = \"gpt-4o-2024-11-20\"\nmaxConcurrency = 4\n";
49
+ export declare const CONFIG_TEMPLATE = "# aweshare producer configuration (~/.aweshare/config.toml)\n# Secrets live in ~/.aweshare/secrets.json and never leave this machine.\n\nhubUrl = \"http://127.0.0.1:8787\"\ntoken = \"asp_PASTE_PRODUCER_TOKEN\"\n\n# Backends hold the upstream API. baseUrl follows the SDK convention:\n# openai-style (OpenAI/Ollama/vLLM/LM Studio) includes /v1, e.g. http://127.0.0.1:11434/v1\n# anthropic-style excludes /v1, e.g. https://api.anthropic.com\n# responses-style includes the version path, e.g. https://open.bigmodel.cn/api/v1\n[[backends]]\nid = \"ollama\"\nprotocol = \"openai\"\nbaseUrl = \"http://127.0.0.1:11434/v1\"\n# keyRef = \"ollama-key\" # optional; keys live in secrets.json\n\n[[backends]]\nid = \"openai\"\nprotocol = \"openai\"\nbaseUrl = \"https://api.openai.com/v1\"\nkeyRef = \"openai-key\"\n\n# Offerings map a public alias (namespace/name) to a backend model \u2014 exactly one\n# upstream model per offering; consumers call the alias and can never pick another model.\n# The namespace must match your producer name on the hub.\n[[offerings]]\nalias = \"YOUR_NAME/qwen2.5.7b\"\nbackend = \"ollama\"\nupstreamModel = \"qwen2.5:7b\" # must match 'ollama list' exactly, including the tag\nmaxConcurrency = 1 # start at 1 for local models\n# maxConcurrentUsers = 3 # distinct concurrent consumers on this alias (hub default 3)\n# dailyTokens = 1000000 # shared tokens per UTC day (hub default 1M; 0 = unlimited)\n\n[[offerings]]\nalias = \"YOUR_NAME/gpt-4o\"\nbackend = \"openai\"\nupstreamModel = \"gpt-4o-2024-11-20\"\nmaxConcurrency = 4\n";
46
50
  export declare const SECRETS_TEMPLATE = "{\n \"openai-key\": \"sk-PASTE_YOUR_KEY\"\n}\n";
@@ -93,7 +93,25 @@ export function loadAgentConfig(dir) {
93
93
  problems.push(`offering '${alias}': maxConcurrency must be an integer 1..64`);
94
94
  continue;
95
95
  }
96
- offerings.push({ alias, backend, upstreamModel, maxConcurrency });
96
+ const maxConcurrentUsers = o.maxConcurrentUsers === undefined ? undefined : Number(o.maxConcurrentUsers);
97
+ if (maxConcurrentUsers !== undefined &&
98
+ (!Number.isInteger(maxConcurrentUsers) || maxConcurrentUsers < 1 || maxConcurrentUsers > 64)) {
99
+ problems.push(`offering '${alias}': maxConcurrentUsers must be an integer 1..64`);
100
+ continue;
101
+ }
102
+ const dailyTokens = o.dailyTokens === undefined ? undefined : Number(o.dailyTokens);
103
+ if (dailyTokens !== undefined && (!Number.isInteger(dailyTokens) || dailyTokens < 0)) {
104
+ problems.push(`offering '${alias}': dailyTokens must be an integer >= 0 (0 = unlimited)`);
105
+ continue;
106
+ }
107
+ offerings.push({
108
+ alias,
109
+ backend,
110
+ upstreamModel,
111
+ maxConcurrency,
112
+ maxConcurrentUsers,
113
+ dailyTokens,
114
+ });
97
115
  }
98
116
  if (problems.length > 0) {
99
117
  throw new ConfigError(`config.toml has problems:\n - ${problems.join('\n - ')}`, problems);
@@ -152,13 +170,16 @@ protocol = "openai"
152
170
  baseUrl = "https://api.openai.com/v1"
153
171
  keyRef = "openai-key"
154
172
 
155
- # Offerings map a public alias (namespace/name) to a backend model.
173
+ # Offerings map a public alias (namespace/name) to a backend model — exactly one
174
+ # upstream model per offering; consumers call the alias and can never pick another model.
156
175
  # The namespace must match your producer name on the hub.
157
176
  [[offerings]]
158
177
  alias = "YOUR_NAME/qwen2.5.7b"
159
178
  backend = "ollama"
160
179
  upstreamModel = "qwen2.5:7b" # must match 'ollama list' exactly, including the tag
161
180
  maxConcurrency = 1 # start at 1 for local models
181
+ # maxConcurrentUsers = 3 # distinct concurrent consumers on this alias (hub default 3)
182
+ # dailyTokens = 1000000 # shared tokens per UTC day (hub default 1M; 0 = unlimited)
162
183
 
163
184
  [[offerings]]
164
185
  alias = "YOUR_NAME/gpt-4o"