kloudy 1.0.0 → 1.0.2

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/AGENTS.md ADDED
@@ -0,0 +1,83 @@
1
+ ## For AI agents: how to use Kloudy
2
+
3
+ The catalog is **kloudy 1.0**: 13,440 bots and 44 modality tags, bundled in this package (npm version 1.0.2). `recommend` / `stack` and `bots ... --offline` read that snapshot (or the local cache if one exists). Kloudy never runs an LLM. Ranking is deterministic: the same goal and the same score overrides return the same JSON.
4
+
5
+ When a network is available, `recommend` may GET `https://kloudy.ai/api/feedback/scores` and cache those overrides for about 24 hours in the Kloudy data directory (`~/.kloudy`, or `KLOUDY_DATA_DIR`). Overrides demote, exclude, or boost a bot after the class tier. `--offline`, a failed request, or a missing scores file leaves ranking on the bundled catalog order.
6
+
7
+ Classes:
8
+
9
+ - **A** — live HTTP MCP endpoints.
10
+ - **B** — npx or uvx packages.
11
+ - **O** — open source and Hugging Face listings.
12
+
13
+ List modalities:
14
+
15
+ ```sh
16
+ npx kloudy@latest bots modalities --offline
17
+ ```
18
+
19
+ Commands:
20
+
21
+ ```sh
22
+ npx kloudy@latest recommend "<goal>" --json
23
+ npx kloudy@latest recommend "<goal>" --json --limit 5
24
+ npx kloudy@latest stack "<goal>" --json --limit 5 --offline
25
+ npx kloudy@latest feedback --stack <stackId> --bot <botId> --result worked|failed|partial [--reason <short>] [--client <name>]
26
+ npx kloudy@latest feedback --flush
27
+ npx kloudy@latest bots search <words> --offline
28
+ npx kloudy@latest bots get <id> --offline
29
+ npx kloudy@latest agents
30
+ npx kloudy@latest --help
31
+ ```
32
+
33
+ `recommend` and `stack` are aliases. `--json` prints only a JSON object on stdout (`schema`: `kloudy.recommend/1`, `catalog`: `kloudy 1.0`, `version`: the package version). Without `--json` you get the same sections as text, including an Unmatched section when a part did not match. `--limit <n>` sets the per-part cap. `n` is an integer from 1 to 20. The default is 5. `--offline` skips the score-override request.
34
+
35
+ Each bot has `id`, `name`, `class` (`A`, `B`, or `O`), `command`, `license`, `description`, `why`, and `modalities`. `command` is what you run or connect to: an `npx ...` command, a `uvx ...` command, or a URL. `recommend` does not install or download anything. Use `bots get <id> --offline` to inspect a pick, then run the command only when you intend to.
36
+
37
+ Write the goal as one sentence per need, or as a comma-separated list of needs. A long sentence is still accepted. Clearer parts produce a clearer stack.
38
+
39
+ The goal is decomposed before matching. Clauses split on commas, semicolons, and the words `and` and `then`. Inside a clause, distinct modality keywords become separate parts. Each part gets the top bots for each modality it needs, then the list is capped per part. Each part includes `candidatesTotal` (how many eligible candidates existed before the cap) and `bots` (the capped list). Narrow that capped list with the project you have open: language, frameworks, licenses, and tools already in the repo. Kloudy never runs an LLM and does not read the project to pick a bot.
40
+
41
+ Familiar modality words such as transcribe, summarize, and database still return the top bots in that modality. A narrower need, such as a watch, a timer, Android sync, a meal plan, or a social post, keeps only bots that share a real keyword or a clearly related catalog name, id, or cap with that part. Unrelated bots are not added as filler. Order is class A, then B, then O, then score override (boost, then unchanged, then demote), then primary-modality hint, keyword hits, catalog score, and catalog index. Exclude removes a bot before the cap. A part with no modality or no catalog row is returned in `unmatched` with the part text and the reason `no modality or catalog match`. Parts are not dropped to make a partial stack look complete.
42
+
43
+ `phone`, `call`, and `calls` map to `audio` only when an audio cue is in the same part or clause: transcribe, transcription, voice, speech, audio, whisper, microphone, asr, phone call, or call audio. Otherwise phone, Android, and mobile are a device-sync need, not audio.
44
+
45
+ Every part has `confidence`: `match`, `weak`, or `none`. Top-level `complete` is true only when every part is `match` and `gaps` is empty. `complete` false means the stack is partial. `gaps` lists unmatched and weak parts. Each gap has the part text, `confidence`, and a reason. `kind` is `catalog integration` when a catalog bot with an install or run command is a real but weak hit. `kind` is `suggestion: build yourself / platform API` when the catalog does not cover the need, such as Wear OS sensor APIs, Health Connect, or the Facebook Graph API. That suggestion is unverified non-catalog guidance. It is not a catalog bot.
46
+
47
+ Every recommend result includes `limit`, `stackId`, and `feedback`. `stackId` is a sha256 of the goal's parts plus the chosen bot ids. The same parts and the same picks always produce the same `stackId`. `feedback` is the command to run after you try a bot. Put that bot's id in place of `<id>`.
48
+
49
+ After you try a stack, report whether it worked:
50
+
51
+ ```sh
52
+ kloudy feedback --stack <stackId> --bot <botId> --result worked|failed|partial [--reason <short>] [--client <name>]
53
+ ```
54
+
55
+ `--result` is `worked`, `failed`, or `partial`. `--reason` is optional and short: it is truncated to 80 characters, and a path, token, or email is dropped. `--client` is an optional tool name such as `cursor`, `claude`, `codex`, or `vscode`. It counts distinct clients. Do not pass a person, email, or account. The report is opt-in and anonymous. The payload may include only `stackId`, `botId`, `result`, an optional short `reason`, the kloudy version, and an optional client name. It never includes the goal text, personal info, file paths, environment, or tokens. The POST goes to `https://kloudy.ai/api/feedback`. If the network is down or the POST fails, the report is queued in the Kloudy data directory and sent on the next `kloudy feedback` or `kloudy feedback --flush`.
56
+
57
+ Score overrides come from those anonymous reports. `scripts/aggregate-feedback-scores.mjs` is meant to run weekly Sunday 3:00 America/Phoenix. It writes `feedback-scores.json`. Bots with fewer than 3 reports are ignored. A bot is demoted after it fails for 3 or more distinct clients with a failure ratio of 60% or more. A bot is excluded after 10 or more reports with a failure ratio of 80% or more. A bot is boosted at 5 or more reports when at least 80% are `worked` and it is not demoted or excluded. `partial` counts as a report and counts as neither worked nor failed. Failure ratio is `failed` divided by all reports. Reports without a client still count toward ratios. They do not add a distinct client.
58
+
59
+ Without `--json`, the text includes Confidence, Candidates, Gaps, `limit`, `stackId`, `feedback`, and `complete=true` or `complete=false`. `--json` still prints only the JSON object (`schema`: `kloudy.recommend/1`, `catalog`: `kloudy 1.0`, `version`: `1.0.2`).
60
+
61
+ Single-part example:
62
+
63
+ ```sh
64
+ npx kloudy@latest recommend "voice assistant that transcribes phone calls" --json
65
+ ```
66
+
67
+ One part, modality `audio`. First bot: `httpk:npm:mendelio-voice-mcp`, class B, MIT, command `npx -y mendelio-voice-mcp`.
68
+
69
+ Multi-part example:
70
+
71
+ ```sh
72
+ npx kloudy@latest recommend "voice assistant that transcribes calls, summarizes them, and stores them in a database" --json
73
+ ```
74
+
75
+ Three parts:
76
+
77
+ 1. `voice assistant that transcribes calls` — `audio` — `httpk:npm:mendelio-voice-mcp` — `npx -y mendelio-voice-mcp`
78
+ 2. `summarizes them` — `text` — `httpk:mcp:ai.liquidagent.api:liquid-agent` — `https://api.liquidagent.ai/mcp`
79
+ 3. `stores them in a database` — `database_access` — `httpk:npm:microsoft:postgres-mcp` — `npx -y @microsoft/postgres-mcp`
80
+
81
+ That control stack is `complete` true: each part is confidence `match`, and `gaps` is empty.
82
+
83
+ `weave a basket` in a larger goal is unmatched. It is reported, not omitted. The goal is then `complete` false.
package/README.md CHANGED
@@ -20,7 +20,94 @@ Interactive cards require a host that supports MCP Apps. The proxy relays the su
20
20
 
21
21
  The existing SDK exports remain available under `kloudy/*`. For the pre-0.4 specialized engine CLI commands documented below, use `kloudy legacy <command>` (for example, `kloudy legacy init my-app`). The original CLI is retained in `bin/kloudy.mjs`.
22
22
 
23
- Offline bot catalog: `npx kloudy bots list|search|get|sync|works|broken`. Kloudy 1.0 bundles the full passing catalog (13,440 listings: 26 verified class A, 11,528 untested class B, 1,886 OSS/HF). Search uses that bundled snapshot, then the local cache. `get` uses a live hit when the API has one, and falls back to that snapshot when the live call misses, including HTTP 404. `--offline` stays on the snapshot. Default `kloudy bots sync` still fetches `https://kloudy.ai/api/deployable-bots/export`; that production URL will not have this 1.0 catalog until a later deploy, so the published tarball does not depend on sync for class B.
23
+ Offline bot catalog: `npx kloudy bots list|search|get|sync|works|broken|modalities`. Kloudy 1.0 bundles the full passing catalog (13,440 listings: 26 verified class A, 11,528 untested class B, 1,886 OSS/HF). Search uses that bundled snapshot, then the local cache. `get` uses a live hit when the API has one, and falls back to that snapshot when the live call misses, including HTTP 404. `--offline` stays on the snapshot. Default `kloudy bots sync` still fetches `https://kloudy.ai/api/deployable-bots/export`; that production URL will not have this 1.0 catalog until a later deploy, so the published tarball does not depend on sync for class B.
24
+
25
+ ## For AI agents: how to use Kloudy
26
+
27
+ The catalog is **kloudy 1.0**: 13,440 bots and 44 modality tags, shipped in this package (npm version 1.0.2). Recommend and the offline bots commands read that bundled snapshot, then the local cache. Kloudy never runs an LLM. Ranking is deterministic: the same goal and the same score overrides return the same JSON.
28
+
29
+ When a network is available, `recommend` may GET `https://kloudy.ai/api/feedback/scores` and cache those overrides for about 24 hours in the Kloudy data directory (`~/.kloudy`, or `KLOUDY_DATA_DIR`). Overrides demote, exclude, or boost a bot after the class tier. `--offline`, a failed request, or a missing scores file leaves ranking on the bundled catalog order.
30
+
31
+ Classes:
32
+
33
+ - **A** — live HTTP MCP endpoints.
34
+ - **B** — npx or uvx packages.
35
+ - **O** — open source and Hugging Face listings.
36
+
37
+ List the modality tags:
38
+
39
+ ```sh
40
+ npx kloudy@latest bots modalities --offline
41
+ ```
42
+
43
+ Turn a plain-language goal into a stack. `recommend` and `stack` are the same command. Add `--json` when you need parseable output (`schema` is `kloudy.recommend/1`). `--limit <n>` caps each part (`n` is an integer from 1 to 20; the default is 5). `--offline` skips the score-override request.
44
+
45
+ ```sh
46
+ npx kloudy@latest recommend "<goal>" --json
47
+ npx kloudy@latest recommend "<goal>" --json --limit 5
48
+ npx kloudy@latest stack "<goal>" --json --limit 5 --offline
49
+ npx kloudy@latest feedback --stack <stackId> --bot <botId> --result worked|failed|partial [--reason <short>] [--client <name>]
50
+ npx kloudy@latest feedback --flush
51
+ npx kloudy@latest bots search <words> --offline
52
+ npx kloudy@latest bots get <id> --offline
53
+ ```
54
+
55
+ Each recommended bot includes `id`, `class` (A, B, or O), `command`, `license`, a one-line `description`, and `why`. `command` is an `npx` or `uvx` invocation, or a URL for a live endpoint or source repo. Run or open that command when you want to install or connect. `recommend` itself does not install anything. Inspect a pick with `bots get` before running it.
56
+
57
+ Write the goal as one sentence per need, or as a comma-separated list of needs. A long sentence is still accepted. Clearer parts produce a clearer stack.
58
+
59
+ `recommend` splits the goal on commas, semicolons, and the words `and` and `then`, and it also splits a clause when keywords hit different modalities. You get one section per part. Each part includes `candidatesTotal` (how many eligible candidates existed before the cap) and `bots` (the capped list). Narrow that capped list with the project you have open: language, frameworks, licenses, and tools already in the repo. Kloudy never runs an LLM and does not read the project to pick a bot.
60
+
61
+ Order is class A, then B, then O, then score override (boost, then unchanged, then demote), then the same primary-modality, keyword, score, and index ordering as catalog search. Exclude removes a bot before the cap. Familiar modality words such as transcribe, summarize, and database still return the top bots in that modality. A narrower need, such as a watch, a timer, Android sync, a meal plan, or a social post, keeps only bots that share a real keyword or a clearly related catalog name, id, or cap with that part. Unrelated bots are not filler. A part with no modality or no catalog row stays in `unmatched` with the part text and a reason. It is not dropped.
62
+
63
+ `phone`, `call`, and `calls` are `audio` only when an audio cue is in the same part or clause (transcribe, transcription, voice, speech, audio, whisper, microphone, asr, phone call, or call audio). Otherwise phone, Android, and mobile are device sync, not audio.
64
+
65
+ Each part includes `confidence` (`match`, `weak`, or `none`). Top-level `complete` is true only when every part is `match` and `gaps` is empty. `complete` false means the stack is partial. `gaps` lists unmatched and weak parts with the part text, confidence, and a reason. `kind` `catalog integration` means a catalog bot with an install or run command is a real but weak hit. `kind` `suggestion: build yourself / platform API` means the catalog does not cover the need (Wear OS sensor APIs, Health Connect, or the Facebook Graph API, for example). That suggestion is unverified non-catalog guidance, not a catalog bot.
66
+
67
+ Every recommend result includes `limit`, `stackId`, and `feedback`. `stackId` is a sha256 of the goal's parts plus the chosen bot ids. The same parts and the same picks always produce the same `stackId`. `feedback` is the command to run after you try a bot. Put that bot's id in place of `<id>`.
68
+
69
+ After you try a stack, report whether it worked:
70
+
71
+ ```sh
72
+ kloudy feedback --stack <stackId> --bot <botId> --result worked|failed|partial [--reason <short>] [--client <name>]
73
+ ```
74
+
75
+ `--result` is `worked`, `failed`, or `partial`. `--reason` is optional and short: it is truncated to 80 characters, and a path, token, or email is dropped. `--client` is an optional tool name such as `cursor`, `claude`, `codex`, or `vscode`. It counts distinct clients. Do not pass a person, email, or account. The report is opt-in and anonymous. The payload may include only `stackId`, `botId`, `result`, an optional short `reason`, the kloudy version, and an optional client name. It never includes the goal text, personal info, file paths, environment, or tokens. The POST goes to `https://kloudy.ai/api/feedback`. If the network is down or the POST fails, the report is queued in the Kloudy data directory and sent on the next `kloudy feedback` or `kloudy feedback --flush`.
76
+
77
+ Score overrides come from those anonymous reports. `scripts/aggregate-feedback-scores.mjs` is meant to run weekly Sunday 3:00 America/Phoenix. It writes `feedback-scores.json`. Bots with fewer than 3 reports are ignored. A bot is demoted after it fails for 3 or more distinct clients with a failure ratio of 60% or more. A bot is excluded after 10 or more reports with a failure ratio of 80% or more. A bot is boosted at 5 or more reports when at least 80% are `worked` and it is not demoted or excluded. `partial` counts as a report and counts as neither worked nor failed. Failure ratio is `failed` divided by all reports. Reports without a client still count toward ratios. They do not add a distinct client.
78
+
79
+ Text output includes Confidence, Candidates, Gaps, `limit`, `stackId`, `feedback`, and `complete=true` or `complete=false`. `--json` still prints only the JSON object.
80
+
81
+ Single-part example:
82
+
83
+ ```sh
84
+ npx kloudy@latest recommend "voice assistant that transcribes phone calls" --json
85
+ ```
86
+
87
+ That goal is one audio part. The first bot in the capped list is `httpk:npm:mendelio-voice-mcp` (class B, MIT, `npx -y mendelio-voice-mcp`).
88
+
89
+ Multi-part example:
90
+
91
+ ```sh
92
+ npx kloudy@latest recommend "voice assistant that transcribes calls, summarizes them, and stores them in a database" --json
93
+ ```
94
+
95
+ That becomes three parts, not one blended search:
96
+
97
+ 1. `voice assistant that transcribes calls` — `audio` — `httpk:npm:mendelio-voice-mcp` — `npx -y mendelio-voice-mcp`
98
+ 2. `summarizes them` — `text` — `httpk:mcp:ai.liquidagent.api:liquid-agent` — `https://api.liquidagent.ai/mcp`
99
+ 3. `stores them in a database` — `database_access` — `httpk:npm:microsoft:postgres-mcp` — `npx -y @microsoft/postgres-mcp`
100
+
101
+ That control stack is complete (`complete` true). Each part is confidence `match`.
102
+
103
+ A leftover clause such as `weave a basket` is listed under Unmatched (`no modality or catalog match`) and under Gaps. The goal is then `complete` false.
104
+
105
+ On first contact, read the agent guide and the command list:
106
+
107
+ ```sh
108
+ npx kloudy@latest agents
109
+ npx kloudy@latest --help
110
+ ```
24
111
 
25
112
  One-click Cursor / VS Code setup: https://kloudy.ai/install. Browser deep links ask the editor to install; opening a link is not proof that installation completed. ChatGPT requires its directory program; this package does not modify ChatGPT.
26
113
 
package/bin/entry.mjs CHANGED
@@ -16,8 +16,11 @@ try{
16
16
  if(results.some(r=>r.state==='unchanged_error'))process.exitCode=1;
17
17
  }else if(args[0]==='mcp'&&args.length===1){await serveRemote();}
18
18
  else if(args[0]==='--version'){console.log(version);}
19
- else if(['--help','help'].includes(args[0]))console.log('npx kloudy Add to detected editors (asks before each write)\nnpx kloudy <question> Ask the public Kloudy MCP endpoint\nnpx kloudy mcp Remote MCP over local stdio\nnpx kloudy bots list|search|get|sync|works|broken|modalities\nnpx kloudy legacy <args> Existing SDK/engine CLI commands\n\nFree discovery needs no key. For authorized account actions set KLOUDY_MCP_TOKEN privately; never put a key in command arguments. Node 20.19+ required.');
19
+ else if(['--help','help'].includes(args[0]))console.log('npx kloudy Add to detected editors (asks before each write)\nnpx kloudy <question> Ask the public Kloudy MCP endpoint\nnpx kloudy mcp Remote MCP over local stdio\nnpx kloudy recommend "<goal>" [--json] [--limit N] [--offline]\nnpx kloudy stack "<goal>" [--json] [--limit N] [--offline]\nnpx kloudy feedback --stack ID --bot ID --result worked|failed|partial [--reason TEXT] [--client NAME] [--flush]\nnpx kloudy agents\nnpx kloudy bots list|search|get|sync|works|broken|modalities [--offline]\nnpx kloudy legacy <args> Existing SDK/engine CLI commands\n\nFree discovery needs no key. For authorized account actions set KLOUDY_MCP_TOKEN privately; never put a key in command arguments. Node 20.19+ required.');
20
20
  else if(args[0]==='bots'){const {botsCommand}=await import('../src/bots.mjs');try{await botsCommand(args.slice(1));}catch(error){process.stderr.write((error?.message||'bots failed')+'\n');process.exitCode=1;}}
21
+ else if(args[0]==='recommend'||args[0]==='stack'){const {recommendCommand}=await import('../src/recommend.mjs');try{await recommendCommand(args.slice(1));}catch(error){process.stderr.write((error?.message||'recommend failed')+'\n');process.exitCode=1;}}
22
+ else if(args[0]==='feedback'){const {feedbackCommand}=await import('../src/feedback.mjs');try{await feedbackCommand(args.slice(1));}catch(error){process.stderr.write((error?.message||'feedback failed')+'\n');process.exitCode=1;}}
23
+ else if(args[0]==='agents'||args[0]==='agent'){const {agentsCommand}=await import('../src/recommend.mjs');try{agentsCommand();}catch(error){process.stderr.write((error?.message||'agents failed')+'\n');process.exitCode=1;}}
21
24
  else if(args[0]==='legacy'){process.argv.splice(2,1);await import('./kloudy.mjs');}
22
25
  else{if(args[0]?.startsWith('--'))throw Error('Unknown option');const result=await askRemote(args.join(' '));for(const c of result.content||[])if(c.type==='text')process.stdout.write((process.env.KLOUDY_MCP_TOKEN?c.text.replaceAll(process.env.KLOUDY_MCP_TOKEN,'[redacted]'):c.text)+'\n');if(result.isError)process.exitCode=1;}
23
26
  }catch{process.stderr.write('Kloudy could not complete the request. Check your connection or authorized key. No action was retried. Run npx kloudy --help.\n');process.exitCode=1;}
package/bin/kloudy.mjs CHANGED
@@ -19,7 +19,7 @@ try{
19
19
  const connection=option('connection')||process.env.KLOUDY_CONNECTION;
20
20
  const project=option('project')||process.cwd(),decision=option('decision');
21
21
  if(command==='help'||command==='--help'){
22
- console.log('Ask for Kloudy. One CLI, one MCP, tools appear when needed.\n\nkloudy models list [--endpoint URL] [--key-env NAME]\nkloudy models run NAME --prompt-file FILE [--max-tokens 128] [--allow-provider-charge]\nkloudy init my-app\nkloudy read https://example.com\nkloudy card /world\nkloudy convert https://example.com\nkloudy query "need" --connection FILE\nkloudy ask "goal" --connection FILE [--candidates FILE]\nkloudy assemble --selections FILE --connection FILE\nkloudy call NAME --inputs FILE [--selection ID] --connection FILE\nkloudy action chain.head --inputs FILE --connection FILE [--idempotency-key KEY]\nkloudy wallet-connect ethereum --connection FILE\nkloudy hosting [--budget-micros 100000000] --connection FILE\nkloudy wallet balance --connection FILE\nkloudy wallet top_up --amount 10.00 --connection FILE\nkloudy conversation read|append|sync --inputs FILE --connection FILE\nkloudy host --connection FILE\nkloudy status --connection FILE\nkloudy cancel --connection FILE\nkloudy mcp --connection FILE\nkloudy introduce [--project DIR] [--decision yes|no]\nkloudy install [--ide cursor|claude|vscode|codex] [--url HTTPS_URL] [--token-env NAME] [--connection FILE]\nkloudy wrap --config FILE [--port 8796]\nkloudy strings save NAME --selections FILE\nkloudy strings use NAME\nkloudy strings call NAME --tool ALIAS --inputs FILE\nkloudy strings list|prune\nkloudy strings keep|remove NAME\nkloudy login\nkloudy bots list|search|get|sync|works|broken\n\nRegister with email + short 2FA through the Core account service. Existing engine connections remain usable. Hosted registration is not supplied by this client package.');
22
+ console.log('Ask for Kloudy. One CLI, one MCP, tools appear when needed.\n\nkloudy models list [--endpoint URL] [--key-env NAME]\nkloudy models run NAME --prompt-file FILE [--max-tokens 128] [--allow-provider-charge]\nkloudy init my-app\nkloudy read https://example.com\nkloudy card /world\nkloudy convert https://example.com\nkloudy query "need" --connection FILE\nkloudy ask "goal" --connection FILE [--candidates FILE]\nkloudy assemble --selections FILE --connection FILE\nkloudy call NAME --inputs FILE [--selection ID] --connection FILE\nkloudy action chain.head --inputs FILE --connection FILE [--idempotency-key KEY]\nkloudy wallet-connect ethereum --connection FILE\nkloudy hosting [--budget-micros 100000000] --connection FILE\nkloudy wallet balance --connection FILE\nkloudy wallet top_up --amount 10.00 --connection FILE\nkloudy conversation read|append|sync --inputs FILE --connection FILE\nkloudy host --connection FILE\nkloudy status --connection FILE\nkloudy cancel --connection FILE\nkloudy mcp --connection FILE\nkloudy introduce [--project DIR] [--decision yes|no]\nkloudy install [--ide cursor|claude|vscode|codex] [--url HTTPS_URL] [--token-env NAME] [--connection FILE]\nkloudy wrap --config FILE [--port 8796]\nkloudy strings save NAME --selections FILE\nkloudy strings use NAME\nkloudy strings call NAME --tool ALIAS --inputs FILE\nkloudy strings list|prune\nkloudy strings keep|remove NAME\nkloudy login\nkloudy recommend <goal> [--json] [--limit N] [--offline]\nkloudy stack <goal> [--json] [--limit N] [--offline]\nkloudy feedback --stack ID --bot ID --result worked|failed|partial [--reason TEXT] [--client NAME] [--flush]\nkloudy agents\nkloudy bots list|search|get|sync|works|broken|modalities [--offline]\n\nRegister with email + short 2FA through the Core account service. Existing engine connections remain usable. Hosted registration is not supplied by this client package.');
23
23
  }else if(command==='models'){
24
24
  const action=args.shift(),endpoint=option('endpoint'),keyEnv=option('key-env'),file=option('prompt-file'),max=option('max-tokens');
25
25
  const allow=args.includes('--allow-provider-charge');if(allow)args.splice(args.indexOf('--allow-provider-charge'),1);
@@ -51,6 +51,15 @@ try{
51
51
  }else if(command==='bots'){
52
52
  const {botsCommand}=await import('../src/bots.mjs');
53
53
  try{await botsCommand(args);}catch(error){process.stderr.write((error?.message||'bots failed')+'\n');process.exitCode=1;}
54
+ }else if(command==='recommend'||command==='stack'){
55
+ const {recommendCommand}=await import('../src/recommend.mjs');
56
+ try{await recommendCommand(args);}catch(error){process.stderr.write((error?.message||'recommend failed')+'\n');process.exitCode=1;}
57
+ }else if(command==='feedback'){
58
+ const {feedbackCommand}=await import('../src/feedback.mjs');
59
+ try{await feedbackCommand(args);}catch(error){process.stderr.write((error?.message||'feedback failed')+'\n');process.exitCode=1;}
60
+ }else if(command==='agents'||command==='agent'){
61
+ const {agentsCommand}=await import('../src/recommend.mjs');
62
+ try{agentsCommand();}catch(error){process.stderr.write((error?.message||'agents failed')+'\n');process.exitCode=1;}
54
63
  }else{
55
64
  const walletAmount=option('amount'),budgetMicros=option('budget-micros'),idempotencyKey=option('idempotency-key');
56
65
  const candidatesFile=option('candidates'),inputsFile=option('inputs'),selectionsFile=option('selections'),selectionId=option('selection'),lane=option('lane')||'non_medical';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kloudy",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Ask for Kloudy: CLI, MCP and SDK clients for the same scoped engine session.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -33,12 +33,13 @@
33
33
  "src",
34
34
  "schemas",
35
35
  "README.md",
36
+ "AGENTS.md",
36
37
  "MCP-DEFAULT.md",
37
38
  "LICENSE"
38
39
  ],
39
40
  "scripts": {
40
41
  "test": "node --test test/*.test.mjs",
41
- "check": "node --check bin/kloudy.mjs && node --check bin/entry.mjs && node --check src/bots.mjs && node --check src/client.mjs && npm test",
42
+ "check": "node --check bin/kloudy.mjs && node --check bin/entry.mjs && node --check src/bots.mjs && node --check src/recommend.mjs && node --check src/scores.mjs && node --check src/feedback.mjs && node --check scripts/aggregate-feedback-scores.mjs && node --check src/client.mjs && npm test",
42
43
  "bots:bundle": "node scripts/bundle-bots-catalog.mjs --subset full",
43
44
  "start": "node bin/kloudy.mjs",
44
45
  "proof": "node scripts/prove.mjs",
@@ -1,80 +1,80 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://kloudy.ai/schemas/kloudy.deployable-bot.schema.json",
4
- "title": "kloudy.deployable-bot/1",
5
- "type": "object",
6
- "required": [
7
- "id",
8
- "name",
9
- "kind",
10
- "modalities"
11
- ],
12
- "properties": {
13
- "id": {
14
- "type": "string"
15
- },
16
- "name": {
17
- "type": "string"
18
- },
19
- "kind": {
20
- "type": "string",
21
- "enum": [
22
- "http",
23
- "npx",
24
- "uvx",
25
- "botboozle",
26
- "hf"
27
- ]
28
- },
29
- "tier": {
30
- "type": "string"
31
- },
32
- "status": {
33
- "type": "string"
34
- },
35
- "endpoints": {
36
- "type": "array"
37
- },
38
- "free": {
39
- "type": "boolean"
40
- },
41
- "devices": {
42
- "type": "array",
43
- "items": {
44
- "type": "string"
45
- }
46
- },
47
- "caps": {
48
- "type": "array",
49
- "items": {
50
- "type": "string"
51
- }
52
- },
53
- "license": {
54
- "type": "string"
55
- },
56
- "source_url": {
57
- "type": "string"
58
- },
59
- "score": {
60
- "type": "number"
61
- },
62
- "modalities": {
63
- "type": "array",
64
- "minItems": 1,
65
- "items": {
66
- "type": "string",
67
- "minLength": 1
68
- },
69
- "description": "Every fitting modality tag. Multi-select. Known values include text, code, code_execution, embedding, image, image_generation, audio, voice_generation, video, multimodal, translation, search, database_access, file_system, browser_automation, api_calls, scheduling, notifications, auth_encryption, data_analysis, document_processing, robotics, agent_tools; other tags that appear are allowed."
70
- },
71
- "modality_primary": {
72
- "type": [
73
- "string",
74
- "null"
75
- ],
76
- "description": "Sort hint only; never used as a filter."
77
- }
78
- },
79
- "additionalProperties": true
80
- }
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://kloudy.ai/schemas/kloudy.deployable-bot.schema.json",
4
+ "title": "kloudy.deployable-bot/1",
5
+ "type": "object",
6
+ "required": [
7
+ "id",
8
+ "name",
9
+ "kind",
10
+ "modalities"
11
+ ],
12
+ "properties": {
13
+ "id": {
14
+ "type": "string"
15
+ },
16
+ "name": {
17
+ "type": "string"
18
+ },
19
+ "kind": {
20
+ "type": "string",
21
+ "enum": [
22
+ "http",
23
+ "npx",
24
+ "uvx",
25
+ "botboozle",
26
+ "hf"
27
+ ]
28
+ },
29
+ "tier": {
30
+ "type": "string"
31
+ },
32
+ "status": {
33
+ "type": "string"
34
+ },
35
+ "endpoints": {
36
+ "type": "array"
37
+ },
38
+ "free": {
39
+ "type": "boolean"
40
+ },
41
+ "devices": {
42
+ "type": "array",
43
+ "items": {
44
+ "type": "string"
45
+ }
46
+ },
47
+ "caps": {
48
+ "type": "array",
49
+ "items": {
50
+ "type": "string"
51
+ }
52
+ },
53
+ "license": {
54
+ "type": "string"
55
+ },
56
+ "source_url": {
57
+ "type": "string"
58
+ },
59
+ "score": {
60
+ "type": "number"
61
+ },
62
+ "modalities": {
63
+ "type": "array",
64
+ "minItems": 1,
65
+ "items": {
66
+ "type": "string",
67
+ "minLength": 1
68
+ },
69
+ "description": "Every fitting modality tag. Multi-select. Known values include text, code, code_execution, embedding, image, image_generation, audio, voice_generation, video, multimodal, translation, search, database_access, file_system, browser_automation, api_calls, scheduling, notifications, auth_encryption, data_analysis, document_processing, robotics, agent_tools; other tags that appear are allowed."
70
+ },
71
+ "modality_primary": {
72
+ "type": [
73
+ "string",
74
+ "null"
75
+ ],
76
+ "description": "Sort hint only; never used as a filter."
77
+ }
78
+ },
79
+ "additionalProperties": true
80
+ }