kloudy 0.4.4 → 0.4.6

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/bin/entry.mjs CHANGED
@@ -1,22 +1,22 @@
1
- #!/usr/bin/env node
2
- import {readFileSync} from 'node:fs';
3
- const version=JSON.parse(readFileSync(new URL('../package.json',import.meta.url),'utf8')).version;
4
- import {createInterface} from 'node:readline/promises';
5
- import {installEditors} from '../src/editor-install.mjs';
6
- import {askRemote,serveRemote} from '../src/remote.mjs';
7
- const args=process.argv.slice(2);
8
- try{
9
- if(!args.length||args[0]==='install'&&args.length===1){
10
- console.log('Kloudy · Add to your editor\nFree public discovery. Account actions require an authorized Kloudy key.');
11
- let rl;
12
- const confirm=async({client,path,authenticated})=>{if(!process.stdin.isTTY){console.log(`${client}: skipped — run in an interactive terminal to approve ${path}`);return false;}rl??=createInterface({input:process.stdin,output:process.stdout});return /^(y|yes)$/i.test((await rl.question(`Add Kloudy to ${client}? ${path}${authenticated?' (stores your key)':''} [y/N] `)).trim());};
13
- let results;try{results=await installEditors({confirm,key:process.env.KLOUDY_MCP_TOKEN,onResult:r=>console.log(`${r.client}: ${r.state}`)});}finally{rl?.close();}
14
- if(!results.length)console.log('No supported editor configuration found. Open https://kloudy.ai/install for setup help.');
15
- else console.log('Existing servers were preserved. Restart configured clients to connect.');
16
- if(results.some(r=>r.state==='unchanged_error'))process.exitCode=1;
17
- }else if(args[0]==='mcp'&&args.length===1){await serveRemote();}
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 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
- else if(args[0]==='legacy'){process.argv.splice(2,1);await import('./kloudy.mjs');}
21
- 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;}
22
- }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;}
1
+ #!/usr/bin/env node
2
+ import {readFileSync} from 'node:fs';
3
+ const version=JSON.parse(readFileSync(new URL('../package.json',import.meta.url),'utf8')).version;
4
+ import {createInterface} from 'node:readline/promises';
5
+ import {installEditors} from '../src/editor-install.mjs';
6
+ import {askRemote,serveRemote} from '../src/remote.mjs';
7
+ const args=process.argv.slice(2);
8
+ try{
9
+ if(!args.length||args[0]==='install'&&args.length===1){
10
+ console.log('Kloudy · Add to your editor\nFree public discovery. Account actions require an authorized Kloudy key.');
11
+ let rl;
12
+ const confirm=async({client,path,authenticated})=>{if(!process.stdin.isTTY){console.log(`${client}: skipped — run in an interactive terminal to approve ${path}`);return false;}rl??=createInterface({input:process.stdin,output:process.stdout});return /^(y|yes)$/i.test((await rl.question(`Add Kloudy to ${client}? ${path}${authenticated?' (stores your key)':''} [y/N] `)).trim());};
13
+ let results;try{results=await installEditors({confirm,key:process.env.KLOUDY_MCP_TOKEN,onResult:r=>console.log(`${r.client}: ${r.state}`)});}finally{rl?.close();}
14
+ if(!results.length)console.log('No supported editor configuration found. Open https://kloudy.ai/install for setup help.');
15
+ else console.log('Existing servers were preserved. Restart configured clients to connect.');
16
+ if(results.some(r=>r.state==='unchanged_error'))process.exitCode=1;
17
+ }else if(args[0]==='mcp'&&args.length===1){await serveRemote();}
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 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
+ else if(args[0]==='legacy'){process.argv.splice(2,1);await import('./kloudy.mjs');}
21
+ 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;}
22
+ }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
@@ -1,71 +1,71 @@
1
- #!/usr/bin/env node
2
- import {configuredModels} from '../src/models.mjs';
3
- import {terminalStatus} from '../src/terminal-status.mjs';
4
- import {readFile} from 'node:fs/promises';
5
- import {withConnection} from '../src/connection.mjs';
6
- import {serveMcp} from '../src/mcp.mjs';
7
- import {createWrapper} from '../src/wrap.mjs';
8
- import {install} from '../src/install.mjs';
9
- import {introduce,isAttachIntent} from '../src/introduce.mjs';
10
- import {readPublicPage,readCard,convertPage} from '../src/public.mjs';
11
- import {localStrings} from '../src/strings.mjs';
12
- import {createStarter} from '../src/starter.mjs';
13
- const indicator=terminalStatus();
14
- const args=process.argv.slice(2),command=args.shift()||'introduce';
15
- function option(name){const index=args.indexOf('--'+name);if(index<0)return null;if(index===args.length-1||args[index+1].startsWith('--'))throw new Error('Option value required');const value=args[index+1];args.splice(index,2);return value;}
16
- const output=value=>process.stdout.write(JSON.stringify(value,null,2)+'\n');
17
- try{
18
- if(args.includes('--mode')||args.includes('--revision')||command==='approve')throw new Error('CLI is autonomous-only');
19
- const connection=option('connection')||process.env.KLOUDY_CONNECTION;
20
- const project=option('project')||process.cwd(),decision=option('decision');
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\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
- }else if(command==='models'){
24
- const action=args.shift(),endpoint=option('endpoint'),keyEnv=option('key-env'),file=option('prompt-file'),max=option('max-tokens');
25
- const allow=args.includes('--allow-provider-charge');if(allow)args.splice(args.indexOf('--allow-provider-charge'),1);
26
- const client=configuredModels({...process.env,...(endpoint?{KLOUDY_MODEL_ENDPOINT:endpoint}:{}),...(keyEnv?{KLOUDY_MODEL_KEY_ENV:keyEnv}:{})});
27
- if(action==='list'&&!args.length&&!file&&!max&&!allow)output(await client.list());
28
- else if(action==='run'&&args.length===1&&file&&(!max||/^[1-9]\d{0,3}$/.test(max)))output(await client.complete({model:args[0],prompt:await readFile(file,'utf8'),maxTokens:max?Number(max):128,allowProviderCharge:allow}));
29
- else throw Error('Invalid models arguments');
30
- }else if(['init','read','card','convert'].includes(command)){const resolution=option('resolution')||'compact';if(args.length!==1||args[0].startsWith('--'))throw Error('One argument required');output(command==='init'?await createStarter(args[0]):command==='read'?await readPublicPage(args[0]):command==='convert'?await convertPage(args[0],{resolution}):await readCard(args[0]));}
31
- else if(command==='introduce'||isAttachIntent(command)||(command==='ask'&&isAttachIntent(args.join(' ')))){if(decision&&!['yes','no'].includes(decision))throw Error('Choose yes or no');if(decision==='yes')output(await install({ide:option('ide')||'auto',connection,url:option('url')||undefined,tokenEnv:option('token-env')||undefined}));else output(await introduce({project,decision,connection}));}
32
- else if(command==='install'){option('project');output(await install({ide:option('ide')||'auto',connection,url:option('url')||undefined,tokenEnv:option('token-env')||undefined}));}
33
- else if(command==='mcp'){await serveMcp(connection);}
34
- else if(command==='wrap'){
35
- const file=option('config'),port=Number(option('port')||8796);if(!file||!Number.isSafeInteger(port)||port<1024||port>65535)throw new Error('Invalid wrapper options');
36
- const config=JSON.parse(await readFile(file,'utf8'));const token=process.env.KLOUDY_WRAP_TOKEN;
37
- const server=createWrapper({...config,token});server.listen(port,'127.0.0.1',()=>process.stderr.write('Kloudy local HTTPK wrapper listening.\n'));
38
- }else if(command==='strings'){
39
- const action=args.shift(),name=args.shift(),file=option('selections'),tool=option('tool'),inputs=option('inputs'),selectionId=option('selection'),store=localStrings({project});
40
- if(args.length)throw Error('Unexpected strings arguments');
41
- if(action==='save'){if(!file)throw Error('Selections file required');output(await store.save(name,JSON.parse(await readFile(file,'utf8'))));}
42
- else if(action==='list')output(await store.list());
43
- else if(action==='use'){output(await store.use(name));}
44
- else if(action==='call'){if(!inputs||!tool)throw Error('Tool and inputs required');output(await store.call(name,tool,JSON.parse(await readFile(inputs,'utf8')),{selectionId}));}
45
- else if(action==='keep')output(await store.keep(name));
46
- else if(action==='remove')output(await store.remove(name));
47
- else if(action==='prune')output(await store.prune());
48
- else throw Error('Unknown strings action');
49
- }else if(command==='login'){
50
- output({status:'registration_unavailable',message:'Ask for Kloudy. Email + short 2FA, then a session cookie/tag or OAuth, belongs to the Core account service. No registration endpoint is published yet. No email or code was collected.',url:'https://kloudy.ai/connect'});process.exitCode=3;
51
- }else{
52
- const walletAmount=option('amount'),budgetMicros=option('budget-micros'),idempotencyKey=option('idempotency-key');
53
- const candidatesFile=option('candidates'),inputsFile=option('inputs'),selectionsFile=option('selections'),selectionId=option('selection'),lane=option('lane')||'non_medical';
54
- if(args.some(x=>x.startsWith('--')))throw new Error('Unknown option');
55
- const result=await withConnection(connection,async client=>{
1
+ #!/usr/bin/env node
2
+ import {configuredModels} from '../src/models.mjs';
3
+ import {terminalStatus} from '../src/terminal-status.mjs';
4
+ import {readFile} from 'node:fs/promises';
5
+ import {withConnection} from '../src/connection.mjs';
6
+ import {serveMcp} from '../src/mcp.mjs';
7
+ import {createWrapper} from '../src/wrap.mjs';
8
+ import {install} from '../src/install.mjs';
9
+ import {introduce,isAttachIntent} from '../src/introduce.mjs';
10
+ import {readPublicPage,readCard,convertPage} from '../src/public.mjs';
11
+ import {localStrings} from '../src/strings.mjs';
12
+ import {createStarter} from '../src/starter.mjs';
13
+ const indicator=terminalStatus();
14
+ const args=process.argv.slice(2),command=args.shift()||'introduce';
15
+ function option(name){const index=args.indexOf('--'+name);if(index<0)return null;if(index===args.length-1||args[index+1].startsWith('--'))throw new Error('Option value required');const value=args[index+1];args.splice(index,2);return value;}
16
+ const output=value=>process.stdout.write(JSON.stringify(value,null,2)+'\n');
17
+ try{
18
+ if(args.includes('--mode')||args.includes('--revision')||command==='approve')throw new Error('CLI is autonomous-only');
19
+ const connection=option('connection')||process.env.KLOUDY_CONNECTION;
20
+ const project=option('project')||process.cwd(),decision=option('decision');
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\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
+ }else if(command==='models'){
24
+ const action=args.shift(),endpoint=option('endpoint'),keyEnv=option('key-env'),file=option('prompt-file'),max=option('max-tokens');
25
+ const allow=args.includes('--allow-provider-charge');if(allow)args.splice(args.indexOf('--allow-provider-charge'),1);
26
+ const client=configuredModels({...process.env,...(endpoint?{KLOUDY_MODEL_ENDPOINT:endpoint}:{}),...(keyEnv?{KLOUDY_MODEL_KEY_ENV:keyEnv}:{})});
27
+ if(action==='list'&&!args.length&&!file&&!max&&!allow)output(await client.list());
28
+ else if(action==='run'&&args.length===1&&file&&(!max||/^[1-9]\d{0,3}$/.test(max)))output(await client.complete({model:args[0],prompt:await readFile(file,'utf8'),maxTokens:max?Number(max):128,allowProviderCharge:allow}));
29
+ else throw Error('Invalid models arguments');
30
+ }else if(['init','read','card','convert'].includes(command)){const resolution=option('resolution')||'compact';if(args.length!==1||args[0].startsWith('--'))throw Error('One argument required');output(command==='init'?await createStarter(args[0]):command==='read'?await readPublicPage(args[0]):command==='convert'?await convertPage(args[0],{resolution}):await readCard(args[0]));}
31
+ else if(command==='introduce'||isAttachIntent(command)||(command==='ask'&&isAttachIntent(args.join(' ')))){if(decision&&!['yes','no'].includes(decision))throw Error('Choose yes or no');if(decision==='yes')output(await install({ide:option('ide')||'auto',connection,url:option('url')||undefined,tokenEnv:option('token-env')||undefined}));else output(await introduce({project,decision,connection}));}
32
+ else if(command==='install'){option('project');output(await install({ide:option('ide')||'auto',connection,url:option('url')||undefined,tokenEnv:option('token-env')||undefined}));}
33
+ else if(command==='mcp'){await serveMcp(connection);}
34
+ else if(command==='wrap'){
35
+ const file=option('config'),port=Number(option('port')||8796);if(!file||!Number.isSafeInteger(port)||port<1024||port>65535)throw new Error('Invalid wrapper options');
36
+ const config=JSON.parse(await readFile(file,'utf8'));const token=process.env.KLOUDY_WRAP_TOKEN;
37
+ const server=createWrapper({...config,token});server.listen(port,'127.0.0.1',()=>process.stderr.write('Kloudy local HTTPK wrapper listening.\n'));
38
+ }else if(command==='strings'){
39
+ const action=args.shift(),name=args.shift(),file=option('selections'),tool=option('tool'),inputs=option('inputs'),selectionId=option('selection'),store=localStrings({project});
40
+ if(args.length)throw Error('Unexpected strings arguments');
41
+ if(action==='save'){if(!file)throw Error('Selections file required');output(await store.save(name,JSON.parse(await readFile(file,'utf8'))));}
42
+ else if(action==='list')output(await store.list());
43
+ else if(action==='use'){output(await store.use(name));}
44
+ else if(action==='call'){if(!inputs||!tool)throw Error('Tool and inputs required');output(await store.call(name,tool,JSON.parse(await readFile(inputs,'utf8')),{selectionId}));}
45
+ else if(action==='keep')output(await store.keep(name));
46
+ else if(action==='remove')output(await store.remove(name));
47
+ else if(action==='prune')output(await store.prune());
48
+ else throw Error('Unknown strings action');
49
+ }else if(command==='login'){
50
+ output({status:'registration_unavailable',message:'Ask for Kloudy. Email + short 2FA, then a session cookie/tag or OAuth, belongs to the Core account service. No registration endpoint is published yet. No email or code was collected.',url:'https://kloudy.ai/connect'});process.exitCode=3;
51
+ }else{
52
+ const walletAmount=option('amount'),budgetMicros=option('budget-micros'),idempotencyKey=option('idempotency-key');
53
+ const candidatesFile=option('candidates'),inputsFile=option('inputs'),selectionsFile=option('selections'),selectionId=option('selection'),lane=option('lane')||'non_medical';
54
+ if(args.some(x=>x.startsWith('--')))throw new Error('Unknown option');
55
+ const result=await withConnection(connection,async client=>{
56
56
  if(command==='conversation'){if(!client.conversation||args.length!==1||!inputsFile)throw Error('Use conversation read|append|sync --inputs FILE with a scoped connection');return client.conversation(args[0],JSON.parse(await readFile(inputsFile,'utf8')));}
57
- if(command==='action'){if(!client.action||args.length!==1||!inputsFile)throw Error('Action name and inputs file required');return client.action(args[0],JSON.parse(await readFile(inputsFile,'utf8')),{idempotencyKey:idempotencyKey??undefined});}
58
- if(command==='wallet-connect'){if(!client.walletConnection||args.length!==1)throw Error('Chain required');return client.walletConnection(args[0]);}
59
- if(command==='hosting'){if(!client.hosting||args.length||budgetMicros!==null&&!/^[1-9]\d*$/.test(budgetMicros))throw Error('Use an integer USD-micros budget');return client.hosting({budgetUsdMicros:budgetMicros===null?undefined:Number(budgetMicros)});}
60
- if(command==='wallet'){if(!client.wallet||args.length!==1)throw Error('HTTPK wallet operation required');return client.wallet({operation:args[0],amount_usd:walletAmount??undefined});}
61
- if(command==='query'){if(!client.query)throw Error('Query needs an HTTPK connection');return client.query(args.join(' '));}
62
- if(command==='ask'){const supplied=candidatesFile?JSON.parse(await readFile(candidatesFile,'utf8')):[];return client.ask(args.join(' '),{candidates:Array.isArray(supplied)?supplied:supplied.candidates,lane});}
63
- if(command==='assemble'){if(!client.assemble||!selectionsFile)throw Error('HTTPK connection and selections file required');return client.assemble(JSON.parse(await readFile(selectionsFile,'utf8')));}
64
- if(command==='call'){if(args.length!==1||!inputsFile)throw new Error('Tool and inputs file required');if(selectionId&&!client.assemble)throw Error('Explicit selection requires HTTPK');return client.call(args[0],JSON.parse(await readFile(inputsFile,'utf8')),{selectionId});}
65
- if(command==='host'){if(args.length||!client.negotiateHost)throw Error('HTTPK host required');return client.negotiateHost();}
66
- if(command==='status')return client.status();
67
- if(command==='cancel')return client.decide('cancel');
68
- throw new Error('Unknown command');
69
- },{onActivity:event=>indicator.update(event)});output(result);
70
- }
71
- }catch(error){output({error:error.code||'invalid_request',message:error.code?error.message:'The request could not be completed. Run kloudy help.'});process.exitCode=1;}finally{indicator.dispose();}
57
+ if(command==='action'){if(!client.action||args.length!==1||!inputsFile)throw Error('Action name and inputs file required');return client.action(args[0],JSON.parse(await readFile(inputsFile,'utf8')),{idempotencyKey:idempotencyKey??undefined});}
58
+ if(command==='wallet-connect'){if(!client.walletConnection||args.length!==1)throw Error('Chain required');return client.walletConnection(args[0]);}
59
+ if(command==='hosting'){if(!client.hosting||args.length||budgetMicros!==null&&!/^[1-9]\d*$/.test(budgetMicros))throw Error('Use an integer USD-micros budget');return client.hosting({budgetUsdMicros:budgetMicros===null?undefined:Number(budgetMicros)});}
60
+ if(command==='wallet'){if(!client.wallet||args.length!==1)throw Error('HTTPK wallet operation required');return client.wallet({operation:args[0],amount_usd:walletAmount??undefined});}
61
+ if(command==='query'){if(!client.query)throw Error('Query needs an HTTPK connection');return client.query(args.join(' '));}
62
+ if(command==='ask'){const supplied=candidatesFile?JSON.parse(await readFile(candidatesFile,'utf8')):[];return client.ask(args.join(' '),{candidates:Array.isArray(supplied)?supplied:supplied.candidates,lane});}
63
+ if(command==='assemble'){if(!client.assemble||!selectionsFile)throw Error('HTTPK connection and selections file required');return client.assemble(JSON.parse(await readFile(selectionsFile,'utf8')));}
64
+ if(command==='call'){if(args.length!==1||!inputsFile)throw new Error('Tool and inputs file required');if(selectionId&&!client.assemble)throw Error('Explicit selection requires HTTPK');return client.call(args[0],JSON.parse(await readFile(inputsFile,'utf8')),{selectionId});}
65
+ if(command==='host'){if(args.length||!client.negotiateHost)throw Error('HTTPK host required');return client.negotiateHost();}
66
+ if(command==='status')return client.status();
67
+ if(command==='cancel')return client.decide('cancel');
68
+ throw new Error('Unknown command');
69
+ },{onActivity:event=>indicator.update(event)});output(result);
70
+ }
71
+ }catch(error){output({error:error.code||'invalid_request',message:error.code?error.message:'The request could not be completed. Run kloudy help.'});process.exitCode=1;}finally{indicator.dispose();}
package/package.json CHANGED
@@ -1,68 +1,68 @@
1
- {
2
- "name": "kloudy",
3
- "version": "0.4.4",
4
- "description": "Ask for Kloudy: CLI, MCP and SDK clients for the same scoped engine session.",
5
- "type": "module",
6
- "license": "Apache-2.0",
7
- "engines": {
8
- "node": ">=20.19.0"
9
- },
10
- "bin": {
11
- "kloudy": "bin/entry.mjs"
12
- },
13
- "exports": {
14
- ".": "./src/client.mjs",
15
- "./mcp": "./src/mcp.mjs",
16
- "./wrap": "./src/wrap.mjs",
17
- "./session": "./src/connection.mjs",
18
- "./httpk": "./src/httpk.mjs",
19
- "./hosted": "./src/hosted.mjs",
20
- "./public": "./src/public.mjs",
21
- "./strings": "./src/strings.mjs",
22
- "./sdf": "./src/sdf.mjs",
23
- "./query": "./src/query.mjs",
24
- "./activity": "./src/activity.mjs",
25
- "./status-indicator.css": "./src/status-indicator.css",
26
- "./models": "./src/models.mjs",
27
- "./host-interface": "./src/host-interface.mjs",
28
- "./replies": "./src/replies.mjs",
29
- "./conversation": "./src/conversation.mjs"
30
- },
31
- "files": [
32
- "bin",
33
- "src",
34
- "schemas",
35
- "README.md",
36
- "MCP-DEFAULT.md",
37
- "LICENSE"
38
- ],
39
- "scripts": {
40
- "test": "node --test test/*.test.mjs",
41
- "check": "node --check bin/kloudy.mjs && node --check src/client.mjs && npm test",
42
- "start": "node bin/kloudy.mjs",
43
- "proof": "node scripts/prove.mjs",
44
- "build:approval": "node scripts/build-approval.mjs"
45
- },
46
- "dependencies": {
47
- "@modelcontextprotocol/ext-apps": "2.0.3",
48
- "@modelcontextprotocol/sdk": "1.31.0",
49
- "ajv": "8.20.0",
50
- "ajv-formats": "3.0.1",
51
- "js-tiktoken": "1.0.21",
52
- "jsonc-parser": "3.3.1",
53
- "smol-toml": "1.9.0",
54
- "zod": "4.6.5"
55
- },
56
- "devDependencies": {
57
- "esbuild": "0.28.2"
58
- },
59
- "mcpName": "ai.kloudy/kloudy",
60
- "homepage": "https://kloudy.ai/install",
61
- "publishConfig": {
62
- "access": "public",
63
- "registry": "https://registry.npmjs.org"
64
- },
65
- "bugs": {
66
- "url": "https://kloudy.ai/support"
67
- }
68
- }
1
+ {
2
+ "name": "kloudy",
3
+ "version": "0.4.6",
4
+ "description": "Ask for Kloudy: CLI, MCP and SDK clients for the same scoped engine session.",
5
+ "type": "module",
6
+ "license": "Apache-2.0",
7
+ "engines": {
8
+ "node": ">=20.19.0"
9
+ },
10
+ "bin": {
11
+ "kloudy": "bin/entry.mjs"
12
+ },
13
+ "exports": {
14
+ ".": "./src/client.mjs",
15
+ "./mcp": "./src/mcp.mjs",
16
+ "./wrap": "./src/wrap.mjs",
17
+ "./session": "./src/connection.mjs",
18
+ "./httpk": "./src/httpk.mjs",
19
+ "./hosted": "./src/hosted.mjs",
20
+ "./public": "./src/public.mjs",
21
+ "./strings": "./src/strings.mjs",
22
+ "./sdf": "./src/sdf.mjs",
23
+ "./query": "./src/query.mjs",
24
+ "./activity": "./src/activity.mjs",
25
+ "./status-indicator.css": "./src/status-indicator.css",
26
+ "./models": "./src/models.mjs",
27
+ "./host-interface": "./src/host-interface.mjs",
28
+ "./replies": "./src/replies.mjs",
29
+ "./conversation": "./src/conversation.mjs"
30
+ },
31
+ "files": [
32
+ "bin",
33
+ "src",
34
+ "schemas",
35
+ "README.md",
36
+ "MCP-DEFAULT.md",
37
+ "LICENSE"
38
+ ],
39
+ "scripts": {
40
+ "test": "node --test test/*.test.mjs",
41
+ "check": "node --check bin/kloudy.mjs && node --check src/client.mjs && npm test",
42
+ "start": "node bin/kloudy.mjs",
43
+ "proof": "node scripts/prove.mjs",
44
+ "build:approval": "node scripts/build-approval.mjs"
45
+ },
46
+ "dependencies": {
47
+ "@modelcontextprotocol/ext-apps": "2.0.3",
48
+ "@modelcontextprotocol/sdk": "1.31.0",
49
+ "ajv": "8.20.0",
50
+ "ajv-formats": "3.0.1",
51
+ "js-tiktoken": "1.0.21",
52
+ "jsonc-parser": "3.3.1",
53
+ "smol-toml": "1.9.0",
54
+ "zod": "4.6.5"
55
+ },
56
+ "devDependencies": {
57
+ "esbuild": "0.28.2"
58
+ },
59
+ "mcpName": "ai.kloudy/kloudy",
60
+ "homepage": "https://kloudy.ai/install",
61
+ "publishConfig": {
62
+ "access": "public",
63
+ "registry": "https://registry.npmjs.org"
64
+ },
65
+ "bugs": {
66
+ "url": "https://kloudy.ai/support"
67
+ }
68
+ }
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Pranab Sarkar
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Pranab Sarkar
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.