synara 0.1.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/README.md +129 -0
- package/dist/auth.js +50 -0
- package/dist/index.js +70 -0
- package/dist/permissions.js +56 -0
- package/dist/protocol.js +4 -0
- package/dist/tools/executor.js +84 -0
- package/dist/ui/terminal.js +215 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Synapse CLI
|
|
2
|
+
|
|
3
|
+
AI-powered coding assistant. Cloud brain, local hands.
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
Local CLI (thin client) Cloud Container (thick server)
|
|
9
|
+
┌─────────────────────┐ ┌──────────────────────────────┐
|
|
10
|
+
│ Terminal UI │ │ Harness Engine │
|
|
11
|
+
│ Tool Executor │◄───WS────►│ System Prompt Assembly │
|
|
12
|
+
│ Permission Control │ │ Guardrails / Skills │
|
|
13
|
+
│ SYNAPSE.md Reader │ │ Context Compact (LLM) │
|
|
14
|
+
└─────────────────────┘ │ Streaming LLM (Kimi K2.5) │
|
|
15
|
+
│ AI Gateway → Workers AI │
|
|
16
|
+
│ Trace Recording │
|
|
17
|
+
└──────────────────────────────┘
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
CLI only does three things: **display, execute, confirm**.
|
|
21
|
+
All intelligence lives on the cloud.
|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install -g synapse-cli
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
synapse login # Login with username/password
|
|
33
|
+
synapse # Start coding session in current directory
|
|
34
|
+
synapse logout # Remove stored credentials
|
|
35
|
+
synapse --help # Show help
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Session Commands
|
|
39
|
+
|
|
40
|
+
| Command | Description |
|
|
41
|
+
|------------|------------------------------------------|
|
|
42
|
+
| `/compact` | Compress conversation history (LLM summarization) |
|
|
43
|
+
| `/context` | Show context usage (tokens, messages, compactions) |
|
|
44
|
+
| `/tools` | List available tools and permission levels |
|
|
45
|
+
| `/quit` | End session |
|
|
46
|
+
|
|
47
|
+
## Permission Model
|
|
48
|
+
|
|
49
|
+
| Tool | Permission |
|
|
50
|
+
|-------------------------------|---------------------|
|
|
51
|
+
| read_file, grep, glob, list_dir | Auto (in-project only) |
|
|
52
|
+
| read outside project dir | Ask each time |
|
|
53
|
+
| write_file, edit_file | Ask (trustable via `t`) |
|
|
54
|
+
| bash | Ask every time (never trustable) |
|
|
55
|
+
| Destructive commands (rm -rf /, mkfs, etc.) | Blocked entirely |
|
|
56
|
+
|
|
57
|
+
When prompted:
|
|
58
|
+
- `y` — approve this operation
|
|
59
|
+
- `n` — deny (AI will ask you what to do instead)
|
|
60
|
+
- `t` — trust this tool type for the rest of the session (not available for bash)
|
|
61
|
+
|
|
62
|
+
## Streaming
|
|
63
|
+
|
|
64
|
+
- LLM responses stream token-by-token via WebSocket
|
|
65
|
+
- Content appears in real-time as the model generates it
|
|
66
|
+
- Reasoning (thinking) is hidden by default
|
|
67
|
+
|
|
68
|
+
## Context Management
|
|
69
|
+
|
|
70
|
+
**Iron rule: NEVER truncate data.**
|
|
71
|
+
|
|
72
|
+
Context compression uses LLM summarization, not mechanical truncation:
|
|
73
|
+
- **autoCompact** — triggers at 80% of 256k context window, summarizes older messages in batches
|
|
74
|
+
- **reactiveCompact** — triggers on API 413 error, compresses and retries (max 3 attempts)
|
|
75
|
+
- **`/compact`** — manual trigger
|
|
76
|
+
|
|
77
|
+
Each batch of messages is sent to LLM in full for summarization. The LLM decides what's important. No data is cut by character count.
|
|
78
|
+
|
|
79
|
+
## Project Configuration
|
|
80
|
+
|
|
81
|
+
Place `SYNAPSE.md` in your project root. It's automatically read and sent to the cloud as project-specific instructions (similar to Claude Code's `CLAUDE.md`).
|
|
82
|
+
|
|
83
|
+
## Model
|
|
84
|
+
|
|
85
|
+
- **Kimi K2.5** via Cloudflare AI Gateway
|
|
86
|
+
- 256k context window
|
|
87
|
+
- temperature 1.0, top_p 0.95
|
|
88
|
+
- Streaming with reasoning support
|
|
89
|
+
|
|
90
|
+
## Tools
|
|
91
|
+
|
|
92
|
+
| Tool | Description |
|
|
93
|
+
|------------|------------------------------------------------|
|
|
94
|
+
| read_file | Read a file from the project |
|
|
95
|
+
| write_file | Create or overwrite a file (shows content first)|
|
|
96
|
+
| edit_file | Precise string replacement in existing files |
|
|
97
|
+
| grep | Regex search across files |
|
|
98
|
+
| glob | Find files by name pattern |
|
|
99
|
+
| list_dir | List directory contents |
|
|
100
|
+
| bash | Execute shell commands |
|
|
101
|
+
|
|
102
|
+
## File Structure
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
synapse-cli/ # Local client (npm package)
|
|
106
|
+
├── src/
|
|
107
|
+
│ ├── index.ts # Entry: subcommands, WS connection, REPL
|
|
108
|
+
│ ├── auth.ts # Login/logout → JWT stored in ~/.synapse/token
|
|
109
|
+
│ ├── protocol.ts # CLI ↔ Cloud message protocol
|
|
110
|
+
│ ├── permissions.ts # t/y/n permission control
|
|
111
|
+
│ ├── tools/executor.ts # Local tool execution
|
|
112
|
+
│ └── ui/terminal.ts # Terminal output formatting
|
|
113
|
+
├── package.json
|
|
114
|
+
└── tsconfig.json
|
|
115
|
+
|
|
116
|
+
harness-agent/ # Cloud server (Cloudflare Worker + Container)
|
|
117
|
+
├── src/worker/index.ts # /cli/ws route → JWT auth → Container proxy
|
|
118
|
+
└── src/services/cli_session.py # CLI session: LLM loop, streaming, compact
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Design References
|
|
122
|
+
|
|
123
|
+
- **Claude Code** (March 2026 leak) — tool permission model, temperature 1.0, four-tier context compression
|
|
124
|
+
- **Kiro CLI** — /compact command, streaming UX, session management
|
|
125
|
+
- **Synapse Harness** — guardrails + skills injection, Dreaming pipeline
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
Powered by Cloudflare · Built by Bowen Liu
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Login flow — username/password → D1 auth → JWT stored locally
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
import * as readline from "readline";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
const API_URL = process.env.SYNAPSE_API || "https://api.synapse.cloudc.top";
|
|
7
|
+
const TOKEN_DIR = path.join(process.env.HOME || "~", ".synapse");
|
|
8
|
+
const TOKEN_PATH = path.join(TOKEN_DIR, "token");
|
|
9
|
+
function prompt(question, hidden = false) {
|
|
10
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
11
|
+
return new Promise((resolve) => {
|
|
12
|
+
rl.question(question, (answer) => {
|
|
13
|
+
rl.close();
|
|
14
|
+
resolve(answer.trim());
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
export async function login() {
|
|
19
|
+
console.log(chalk.cyan.bold("\n ⚡ Synapse Login\n"));
|
|
20
|
+
const username = await prompt(" Username: ");
|
|
21
|
+
const password = await prompt(" Password: ");
|
|
22
|
+
try {
|
|
23
|
+
const resp = await fetch(`${API_URL}/api/login`, {
|
|
24
|
+
method: "POST",
|
|
25
|
+
headers: { "Content-Type": "application/json" },
|
|
26
|
+
body: JSON.stringify({ username, password }),
|
|
27
|
+
});
|
|
28
|
+
const data = await resp.json();
|
|
29
|
+
if (!resp.ok || !data.token) {
|
|
30
|
+
console.log(chalk.red(`\n ❌ ${data.error || "Login failed"}`));
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
fs.mkdirSync(TOKEN_DIR, { recursive: true });
|
|
34
|
+
fs.writeFileSync(TOKEN_PATH, data.token, { mode: 0o600 });
|
|
35
|
+
console.log(chalk.green("\n ✓ Logged in. Token saved to ~/.synapse/token"));
|
|
36
|
+
}
|
|
37
|
+
catch (e) {
|
|
38
|
+
console.log(chalk.red(`\n ❌ Connection failed: ${e.message}`));
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export function logout() {
|
|
43
|
+
try {
|
|
44
|
+
fs.unlinkSync(TOKEN_PATH);
|
|
45
|
+
console.log(chalk.green(" ✓ Logged out."));
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
console.log(chalk.gray(" Already logged out."));
|
|
49
|
+
}
|
|
50
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";var or=Object.create;var xt=Object.defineProperty;var ar=Object.getOwnPropertyDescriptor;var lr=Object.getOwnPropertyNames;var cr=Object.getPrototypeOf,fr=Object.prototype.hasOwnProperty;var C=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var ur=(t,e,s,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of lr(e))!fr.call(t,n)&&n!==s&&xt(t,n,{get:()=>e[n],enumerable:!(r=ar(e,n))||r.enumerable});return t};var x=(t,e,s)=>(s=t!=null?or(cr(t)):{},ur(e||!t||!t.__esModule?xt(s,"default",{value:t,enumerable:!0}):s,t));var F=C((_i,vt)=>{"use strict";var bt=["nodebuffer","arraybuffer","fragments"],Et=typeof Blob<"u";Et&&bt.push("blob");vt.exports={BINARY_TYPES:bt,CLOSE_TIMEOUT:3e4,EMPTY_BUFFER:Buffer.alloc(0),GUID:"258EAFA5-E914-47DA-95CA-C5AB0DC85B11",hasBlob:Et,kForOnEventAttribute:Symbol("kIsForOnEventAttribute"),kListener:Symbol("kListener"),kStatusCode:Symbol("status-code"),kWebSocket:Symbol("websocket"),NOOP:()=>{}}});var ce=C((mi,xe)=>{"use strict";var{EMPTY_BUFFER:hr}=F(),Ge=Buffer[Symbol.species];function dr(t,e){if(t.length===0)return hr;if(t.length===1)return t[0];let s=Buffer.allocUnsafe(e),r=0;for(let n=0;n<t.length;n++){let i=t[n];s.set(i,r),r+=i.length}return r<e?new Ge(s.buffer,s.byteOffset,r):s}function wt(t,e,s,r,n){for(let i=0;i<n;i++)s[r+i]=t[i]^e[i&3]}function Tt(t,e){for(let s=0;s<t.length;s++)t[s]^=e[s&3]}function pr(t){return t.length===t.buffer.byteLength?t.buffer:t.buffer.slice(t.byteOffset,t.byteOffset+t.length)}function Ve(t){if(Ve.readOnly=!0,Buffer.isBuffer(t))return t;let e;return t instanceof ArrayBuffer?e=new Ge(t):ArrayBuffer.isView(t)?e=new Ge(t.buffer,t.byteOffset,t.byteLength):(e=Buffer.from(t),Ve.readOnly=!1),e}xe.exports={concat:dr,mask:wt,toArrayBuffer:pr,toBuffer:Ve,unmask:Tt};if(!process.env.WS_NO_BUFFER_UTIL)try{let t=require("bufferutil");xe.exports.mask=function(e,s,r,n,i){i<48?wt(e,s,r,n,i):t.mask(e,s,r,n,i)},xe.exports.unmask=function(e,s){e.length<32?Tt(e,s):t.unmask(e,s)}}catch{}});var Ct=C((gi,kt)=>{"use strict";var Ot=Symbol("kDone"),Ye=Symbol("kRun"),He=class{constructor(e){this[Ot]=()=>{this.pending--,this[Ye]()},this.concurrency=e||1/0,this.jobs=[],this.pending=0}add(e){this.jobs.push(e),this[Ye]()}[Ye](){if(this.pending!==this.concurrency&&this.jobs.length){let e=this.jobs.shift();this.pending++,e(this[Ot])}}};kt.exports=He});var ee=C((yi,Pt)=>{"use strict";var fe=require("zlib"),Nt=ce(),_r=Ct(),{kStatusCode:Lt}=F(),mr=Buffer[Symbol.species],gr=Buffer.from([0,0,255,255]),Ee=Symbol("permessage-deflate"),U=Symbol("total-length"),Z=Symbol("callback"),j=Symbol("buffers"),Q=Symbol("error"),be,ze=class{constructor(e){if(this._options=e||{},this._threshold=this._options.threshold!==void 0?this._options.threshold:1024,this._maxPayload=this._options.maxPayload|0,this._isServer=!!this._options.isServer,this._deflate=null,this._inflate=null,this.params=null,!be){let s=this._options.concurrencyLimit!==void 0?this._options.concurrencyLimit:10;be=new _r(s)}}static get extensionName(){return"permessage-deflate"}offer(){let e={};return this._options.serverNoContextTakeover&&(e.server_no_context_takeover=!0),this._options.clientNoContextTakeover&&(e.client_no_context_takeover=!0),this._options.serverMaxWindowBits&&(e.server_max_window_bits=this._options.serverMaxWindowBits),this._options.clientMaxWindowBits?e.client_max_window_bits=this._options.clientMaxWindowBits:this._options.clientMaxWindowBits==null&&(e.client_max_window_bits=!0),e}accept(e){return e=this.normalizeParams(e),this.params=this._isServer?this.acceptAsServer(e):this.acceptAsClient(e),this.params}cleanup(){if(this._inflate&&(this._inflate.close(),this._inflate=null),this._deflate){let e=this._deflate[Z];this._deflate.close(),this._deflate=null,e&&e(new Error("The deflate stream was closed while data was being processed"))}}acceptAsServer(e){let s=this._options,r=e.find(n=>!(s.serverNoContextTakeover===!1&&n.server_no_context_takeover||n.server_max_window_bits&&(s.serverMaxWindowBits===!1||typeof s.serverMaxWindowBits=="number"&&s.serverMaxWindowBits>n.server_max_window_bits)||typeof s.clientMaxWindowBits=="number"&&!n.client_max_window_bits));if(!r)throw new Error("None of the extension offers can be accepted");return s.serverNoContextTakeover&&(r.server_no_context_takeover=!0),s.clientNoContextTakeover&&(r.client_no_context_takeover=!0),typeof s.serverMaxWindowBits=="number"&&(r.server_max_window_bits=s.serverMaxWindowBits),typeof s.clientMaxWindowBits=="number"?r.client_max_window_bits=s.clientMaxWindowBits:(r.client_max_window_bits===!0||s.clientMaxWindowBits===!1)&&delete r.client_max_window_bits,r}acceptAsClient(e){let s=e[0];if(this._options.clientNoContextTakeover===!1&&s.client_no_context_takeover)throw new Error('Unexpected parameter "client_no_context_takeover"');if(!s.client_max_window_bits)typeof this._options.clientMaxWindowBits=="number"&&(s.client_max_window_bits=this._options.clientMaxWindowBits);else if(this._options.clientMaxWindowBits===!1||typeof this._options.clientMaxWindowBits=="number"&&s.client_max_window_bits>this._options.clientMaxWindowBits)throw new Error('Unexpected or invalid parameter "client_max_window_bits"');return s}normalizeParams(e){return e.forEach(s=>{Object.keys(s).forEach(r=>{let n=s[r];if(n.length>1)throw new Error(`Parameter "${r}" must have only a single value`);if(n=n[0],r==="client_max_window_bits"){if(n!==!0){let i=+n;if(!Number.isInteger(i)||i<8||i>15)throw new TypeError(`Invalid value for parameter "${r}": ${n}`);n=i}else if(!this._isServer)throw new TypeError(`Invalid value for parameter "${r}": ${n}`)}else if(r==="server_max_window_bits"){let i=+n;if(!Number.isInteger(i)||i<8||i>15)throw new TypeError(`Invalid value for parameter "${r}": ${n}`);n=i}else if(r==="client_no_context_takeover"||r==="server_no_context_takeover"){if(n!==!0)throw new TypeError(`Invalid value for parameter "${r}": ${n}`)}else throw new Error(`Unknown parameter "${r}"`);s[r]=n})}),e}decompress(e,s,r){be.add(n=>{this._decompress(e,s,(i,o)=>{n(),r(i,o)})})}compress(e,s,r){be.add(n=>{this._compress(e,s,(i,o)=>{n(),r(i,o)})})}_decompress(e,s,r){let n=this._isServer?"client":"server";if(!this._inflate){let i=`${n}_max_window_bits`,o=typeof this.params[i]!="number"?fe.Z_DEFAULT_WINDOWBITS:this.params[i];this._inflate=fe.createInflateRaw({...this._options.zlibInflateOptions,windowBits:o}),this._inflate[Ee]=this,this._inflate[U]=0,this._inflate[j]=[],this._inflate.on("error",Sr),this._inflate.on("data",Rt)}this._inflate[Z]=r,this._inflate.write(e),s&&this._inflate.write(gr),this._inflate.flush(()=>{let i=this._inflate[Q];if(i){this._inflate.close(),this._inflate=null,r(i);return}let o=Nt.concat(this._inflate[j],this._inflate[U]);this._inflate._readableState.endEmitted?(this._inflate.close(),this._inflate=null):(this._inflate[U]=0,this._inflate[j]=[],s&&this.params[`${n}_no_context_takeover`]&&this._inflate.reset()),r(null,o)})}_compress(e,s,r){let n=this._isServer?"server":"client";if(!this._deflate){let i=`${n}_max_window_bits`,o=typeof this.params[i]!="number"?fe.Z_DEFAULT_WINDOWBITS:this.params[i];this._deflate=fe.createDeflateRaw({...this._options.zlibDeflateOptions,windowBits:o}),this._deflate[U]=0,this._deflate[j]=[],this._deflate.on("data",yr)}this._deflate[Z]=r,this._deflate.write(e),this._deflate.flush(fe.Z_SYNC_FLUSH,()=>{if(!this._deflate)return;let i=Nt.concat(this._deflate[j],this._deflate[U]);s&&(i=new mr(i.buffer,i.byteOffset,i.length-4)),this._deflate[Z]=null,this._deflate[U]=0,this._deflate[j]=[],s&&this.params[`${n}_no_context_takeover`]&&this._deflate.reset(),r(null,i)})}};Pt.exports=ze;function yr(t){this[j].push(t),this[U]+=t.length}function Rt(t){if(this[U]+=t.length,this[Ee]._maxPayload<1||this[U]<=this[Ee]._maxPayload){this[j].push(t);return}this[Q]=new RangeError("Max payload size exceeded"),this[Q].code="WS_ERR_UNSUPPORTED_MESSAGE_LENGTH",this[Q][Lt]=1009,this.removeListener("data",Rt),this.reset()}function Sr(t){if(this[Ee]._inflate=null,this[Q]){this[Z](this[Q]);return}t[Lt]=1007,this[Z](t)}});var te=C((Si,ve)=>{"use strict";var{isUtf8:Bt}=require("buffer"),{hasBlob:xr}=F(),br=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0];function Er(t){return t>=1e3&&t<=1014&&t!==1004&&t!==1005&&t!==1006||t>=3e3&&t<=4999}function Ke(t){let e=t.length,s=0;for(;s<e;)if((t[s]&128)===0)s++;else if((t[s]&224)===192){if(s+1===e||(t[s+1]&192)!==128||(t[s]&254)===192)return!1;s+=2}else if((t[s]&240)===224){if(s+2>=e||(t[s+1]&192)!==128||(t[s+2]&192)!==128||t[s]===224&&(t[s+1]&224)===128||t[s]===237&&(t[s+1]&224)===160)return!1;s+=3}else if((t[s]&248)===240){if(s+3>=e||(t[s+1]&192)!==128||(t[s+2]&192)!==128||(t[s+3]&192)!==128||t[s]===240&&(t[s+1]&240)===128||t[s]===244&&t[s+1]>143||t[s]>244)return!1;s+=4}else return!1;return!0}function vr(t){return xr&&typeof t=="object"&&typeof t.arrayBuffer=="function"&&typeof t.type=="string"&&typeof t.stream=="function"&&(t[Symbol.toStringTag]==="Blob"||t[Symbol.toStringTag]==="File")}ve.exports={isBlob:vr,isValidStatusCode:Er,isValidUTF8:Ke,tokenChars:br};if(Bt)ve.exports.isValidUTF8=function(t){return t.length<24?Ke(t):Bt(t)};else if(!process.env.WS_NO_UTF_8_VALIDATE)try{let t=require("utf-8-validate");ve.exports.isValidUTF8=function(e){return e.length<32?Ke(e):t(e)}}catch{}});var et=C((xi,Dt)=>{"use strict";var{Writable:wr}=require("stream"),It=ee(),{BINARY_TYPES:Tr,EMPTY_BUFFER:At,kStatusCode:Or,kWebSocket:kr}=F(),{concat:Je,toArrayBuffer:Cr,unmask:Nr}=ce(),{isValidStatusCode:Lr,isValidUTF8:Mt}=te(),we=Buffer[Symbol.species],L=0,$t=1,Ft=2,Ut=3,Xe=4,Ze=5,Te=6,Qe=class extends wr{constructor(e={}){super(),this._allowSynchronousEvents=e.allowSynchronousEvents!==void 0?e.allowSynchronousEvents:!0,this._binaryType=e.binaryType||Tr[0],this._extensions=e.extensions||{},this._isServer=!!e.isServer,this._maxPayload=e.maxPayload|0,this._skipUTF8Validation=!!e.skipUTF8Validation,this[kr]=void 0,this._bufferedBytes=0,this._buffers=[],this._compressed=!1,this._payloadLength=0,this._mask=void 0,this._fragmented=0,this._masked=!1,this._fin=!1,this._opcode=0,this._totalPayloadLength=0,this._messageLength=0,this._fragments=[],this._errored=!1,this._loop=!1,this._state=L}_write(e,s,r){if(this._opcode===8&&this._state==L)return r();this._bufferedBytes+=e.length,this._buffers.push(e),this.startLoop(r)}consume(e){if(this._bufferedBytes-=e,e===this._buffers[0].length)return this._buffers.shift();if(e<this._buffers[0].length){let r=this._buffers[0];return this._buffers[0]=new we(r.buffer,r.byteOffset+e,r.length-e),new we(r.buffer,r.byteOffset,e)}let s=Buffer.allocUnsafe(e);do{let r=this._buffers[0],n=s.length-e;e>=r.length?s.set(this._buffers.shift(),n):(s.set(new Uint8Array(r.buffer,r.byteOffset,e),n),this._buffers[0]=new we(r.buffer,r.byteOffset+e,r.length-e)),e-=r.length}while(e>0);return s}startLoop(e){this._loop=!0;do switch(this._state){case L:this.getInfo(e);break;case $t:this.getPayloadLength16(e);break;case Ft:this.getPayloadLength64(e);break;case Ut:this.getMask();break;case Xe:this.getData(e);break;case Ze:case Te:this._loop=!1;return}while(this._loop);this._errored||e()}getInfo(e){if(this._bufferedBytes<2){this._loop=!1;return}let s=this.consume(2);if((s[0]&48)!==0){let n=this.createError(RangeError,"RSV2 and RSV3 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_2_3");e(n);return}let r=(s[0]&64)===64;if(r&&!this._extensions[It.extensionName]){let n=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");e(n);return}if(this._fin=(s[0]&128)===128,this._opcode=s[0]&15,this._payloadLength=s[1]&127,this._opcode===0){if(r){let n=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");e(n);return}if(!this._fragmented){let n=this.createError(RangeError,"invalid opcode 0",!0,1002,"WS_ERR_INVALID_OPCODE");e(n);return}this._opcode=this._fragmented}else if(this._opcode===1||this._opcode===2){if(this._fragmented){let n=this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,"WS_ERR_INVALID_OPCODE");e(n);return}this._compressed=r}else if(this._opcode>7&&this._opcode<11){if(!this._fin){let n=this.createError(RangeError,"FIN must be set",!0,1002,"WS_ERR_EXPECTED_FIN");e(n);return}if(r){let n=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");e(n);return}if(this._payloadLength>125||this._opcode===8&&this._payloadLength===1){let n=this.createError(RangeError,`invalid payload length ${this._payloadLength}`,!0,1002,"WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH");e(n);return}}else{let n=this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,"WS_ERR_INVALID_OPCODE");e(n);return}if(!this._fin&&!this._fragmented&&(this._fragmented=this._opcode),this._masked=(s[1]&128)===128,this._isServer){if(!this._masked){let n=this.createError(RangeError,"MASK must be set",!0,1002,"WS_ERR_EXPECTED_MASK");e(n);return}}else if(this._masked){let n=this.createError(RangeError,"MASK must be clear",!0,1002,"WS_ERR_UNEXPECTED_MASK");e(n);return}this._payloadLength===126?this._state=$t:this._payloadLength===127?this._state=Ft:this.haveLength(e)}getPayloadLength16(e){if(this._bufferedBytes<2){this._loop=!1;return}this._payloadLength=this.consume(2).readUInt16BE(0),this.haveLength(e)}getPayloadLength64(e){if(this._bufferedBytes<8){this._loop=!1;return}let s=this.consume(8),r=s.readUInt32BE(0);if(r>Math.pow(2,21)-1){let n=this.createError(RangeError,"Unsupported WebSocket frame: payload length > 2^53 - 1",!1,1009,"WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH");e(n);return}this._payloadLength=r*Math.pow(2,32)+s.readUInt32BE(4),this.haveLength(e)}haveLength(e){if(this._payloadLength&&this._opcode<8&&(this._totalPayloadLength+=this._payloadLength,this._totalPayloadLength>this._maxPayload&&this._maxPayload>0)){let s=this.createError(RangeError,"Max payload size exceeded",!1,1009,"WS_ERR_UNSUPPORTED_MESSAGE_LENGTH");e(s);return}this._masked?this._state=Ut:this._state=Xe}getMask(){if(this._bufferedBytes<4){this._loop=!1;return}this._mask=this.consume(4),this._state=Xe}getData(e){let s=At;if(this._payloadLength){if(this._bufferedBytes<this._payloadLength){this._loop=!1;return}s=this.consume(this._payloadLength),this._masked&&(this._mask[0]|this._mask[1]|this._mask[2]|this._mask[3])!==0&&Nr(s,this._mask)}if(this._opcode>7){this.controlMessage(s,e);return}if(this._compressed){this._state=Ze,this.decompress(s,e);return}s.length&&(this._messageLength=this._totalPayloadLength,this._fragments.push(s)),this.dataMessage(e)}decompress(e,s){this._extensions[It.extensionName].decompress(e,this._fin,(n,i)=>{if(n)return s(n);if(i.length){if(this._messageLength+=i.length,this._messageLength>this._maxPayload&&this._maxPayload>0){let o=this.createError(RangeError,"Max payload size exceeded",!1,1009,"WS_ERR_UNSUPPORTED_MESSAGE_LENGTH");s(o);return}this._fragments.push(i)}this.dataMessage(s),this._state===L&&this.startLoop(s)})}dataMessage(e){if(!this._fin){this._state=L;return}let s=this._messageLength,r=this._fragments;if(this._totalPayloadLength=0,this._messageLength=0,this._fragmented=0,this._fragments=[],this._opcode===2){let n;this._binaryType==="nodebuffer"?n=Je(r,s):this._binaryType==="arraybuffer"?n=Cr(Je(r,s)):this._binaryType==="blob"?n=new Blob(r):n=r,this._allowSynchronousEvents?(this.emit("message",n,!0),this._state=L):(this._state=Te,setImmediate(()=>{this.emit("message",n,!0),this._state=L,this.startLoop(e)}))}else{let n=Je(r,s);if(!this._skipUTF8Validation&&!Mt(n)){let i=this.createError(Error,"invalid UTF-8 sequence",!0,1007,"WS_ERR_INVALID_UTF8");e(i);return}this._state===Ze||this._allowSynchronousEvents?(this.emit("message",n,!1),this._state=L):(this._state=Te,setImmediate(()=>{this.emit("message",n,!1),this._state=L,this.startLoop(e)}))}}controlMessage(e,s){if(this._opcode===8){if(e.length===0)this._loop=!1,this.emit("conclude",1005,At),this.end();else{let r=e.readUInt16BE(0);if(!Lr(r)){let i=this.createError(RangeError,`invalid status code ${r}`,!0,1002,"WS_ERR_INVALID_CLOSE_CODE");s(i);return}let n=new we(e.buffer,e.byteOffset+2,e.length-2);if(!this._skipUTF8Validation&&!Mt(n)){let i=this.createError(Error,"invalid UTF-8 sequence",!0,1007,"WS_ERR_INVALID_UTF8");s(i);return}this._loop=!1,this.emit("conclude",r,n),this.end()}this._state=L;return}this._allowSynchronousEvents?(this.emit(this._opcode===9?"ping":"pong",e),this._state=L):(this._state=Te,setImmediate(()=>{this.emit(this._opcode===9?"ping":"pong",e),this._state=L,this.startLoop(s)}))}createError(e,s,r,n,i){this._loop=!1,this._errored=!0;let o=new e(r?`Invalid WebSocket frame: ${s}`:s);return Error.captureStackTrace(o,this.createError),o.code=i,o[Or]=n,o}};Dt.exports=Qe});var rt=C((Ei,qt)=>{"use strict";var{Duplex:bi}=require("stream"),{randomFillSync:Rr}=require("crypto"),Wt=ee(),{EMPTY_BUFFER:Pr,kWebSocket:Br,NOOP:Ir}=F(),{isBlob:se,isValidStatusCode:Ar}=te(),{mask:jt,toBuffer:V}=ce(),R=Symbol("kByteLength"),Mr=Buffer.alloc(4),Oe=8*1024,Y,re=Oe,I=0,$r=1,Fr=2,tt=class t{constructor(e,s,r){this._extensions=s||{},r&&(this._generateMask=r,this._maskBuffer=Buffer.alloc(4)),this._socket=e,this._firstFragment=!0,this._compress=!1,this._bufferedBytes=0,this._queue=[],this._state=I,this.onerror=Ir,this[Br]=void 0}static frame(e,s){let r,n=!1,i=2,o=!1;s.mask&&(r=s.maskBuffer||Mr,s.generateMask?s.generateMask(r):(re===Oe&&(Y===void 0&&(Y=Buffer.alloc(Oe)),Rr(Y,0,Oe),re=0),r[0]=Y[re++],r[1]=Y[re++],r[2]=Y[re++],r[3]=Y[re++]),o=(r[0]|r[1]|r[2]|r[3])===0,i=6);let a;typeof e=="string"?(!s.mask||o)&&s[R]!==void 0?a=s[R]:(e=Buffer.from(e),a=e.length):(a=e.length,n=s.mask&&s.readOnly&&!o);let c=a;a>=65536?(i+=8,c=127):a>125&&(i+=2,c=126);let l=Buffer.allocUnsafe(n?a+i:i);return l[0]=s.fin?s.opcode|128:s.opcode,s.rsv1&&(l[0]|=64),l[1]=c,c===126?l.writeUInt16BE(a,2):c===127&&(l[2]=l[3]=0,l.writeUIntBE(a,4,6)),s.mask?(l[1]|=128,l[i-4]=r[0],l[i-3]=r[1],l[i-2]=r[2],l[i-1]=r[3],o?[l,e]:n?(jt(e,r,l,i,a),[l]):(jt(e,r,e,0,a),[l,e])):[l,e]}close(e,s,r,n){let i;if(e===void 0)i=Pr;else{if(typeof e!="number"||!Ar(e))throw new TypeError("First argument must be a valid error code number");if(s===void 0||!s.length)i=Buffer.allocUnsafe(2),i.writeUInt16BE(e,0);else{let a=Buffer.byteLength(s);if(a>123)throw new RangeError("The message must not be greater than 123 bytes");i=Buffer.allocUnsafe(2+a),i.writeUInt16BE(e,0),typeof s=="string"?i.write(s,2):i.set(s,2)}}let o={[R]:i.length,fin:!0,generateMask:this._generateMask,mask:r,maskBuffer:this._maskBuffer,opcode:8,readOnly:!1,rsv1:!1};this._state!==I?this.enqueue([this.dispatch,i,!1,o,n]):this.sendFrame(t.frame(i,o),n)}ping(e,s,r){let n,i;if(typeof e=="string"?(n=Buffer.byteLength(e),i=!1):se(e)?(n=e.size,i=!1):(e=V(e),n=e.length,i=V.readOnly),n>125)throw new RangeError("The data size must not be greater than 125 bytes");let o={[R]:n,fin:!0,generateMask:this._generateMask,mask:s,maskBuffer:this._maskBuffer,opcode:9,readOnly:i,rsv1:!1};se(e)?this._state!==I?this.enqueue([this.getBlobData,e,!1,o,r]):this.getBlobData(e,!1,o,r):this._state!==I?this.enqueue([this.dispatch,e,!1,o,r]):this.sendFrame(t.frame(e,o),r)}pong(e,s,r){let n,i;if(typeof e=="string"?(n=Buffer.byteLength(e),i=!1):se(e)?(n=e.size,i=!1):(e=V(e),n=e.length,i=V.readOnly),n>125)throw new RangeError("The data size must not be greater than 125 bytes");let o={[R]:n,fin:!0,generateMask:this._generateMask,mask:s,maskBuffer:this._maskBuffer,opcode:10,readOnly:i,rsv1:!1};se(e)?this._state!==I?this.enqueue([this.getBlobData,e,!1,o,r]):this.getBlobData(e,!1,o,r):this._state!==I?this.enqueue([this.dispatch,e,!1,o,r]):this.sendFrame(t.frame(e,o),r)}send(e,s,r){let n=this._extensions[Wt.extensionName],i=s.binary?2:1,o=s.compress,a,c;typeof e=="string"?(a=Buffer.byteLength(e),c=!1):se(e)?(a=e.size,c=!1):(e=V(e),a=e.length,c=V.readOnly),this._firstFragment?(this._firstFragment=!1,o&&n&&n.params[n._isServer?"server_no_context_takeover":"client_no_context_takeover"]&&(o=a>=n._threshold),this._compress=o):(o=!1,i=0),s.fin&&(this._firstFragment=!0);let l={[R]:a,fin:s.fin,generateMask:this._generateMask,mask:s.mask,maskBuffer:this._maskBuffer,opcode:i,readOnly:c,rsv1:o};se(e)?this._state!==I?this.enqueue([this.getBlobData,e,this._compress,l,r]):this.getBlobData(e,this._compress,l,r):this._state!==I?this.enqueue([this.dispatch,e,this._compress,l,r]):this.dispatch(e,this._compress,l,r)}getBlobData(e,s,r,n){this._bufferedBytes+=r[R],this._state=Fr,e.arrayBuffer().then(i=>{if(this._socket.destroyed){let a=new Error("The socket was closed while the blob was being read");process.nextTick(st,this,a,n);return}this._bufferedBytes-=r[R];let o=V(i);s?this.dispatch(o,s,r,n):(this._state=I,this.sendFrame(t.frame(o,r),n),this.dequeue())}).catch(i=>{process.nextTick(Ur,this,i,n)})}dispatch(e,s,r,n){if(!s){this.sendFrame(t.frame(e,r),n);return}let i=this._extensions[Wt.extensionName];this._bufferedBytes+=r[R],this._state=$r,i.compress(e,r.fin,(o,a)=>{if(this._socket.destroyed){let c=new Error("The socket was closed while data was being compressed");st(this,c,n);return}this._bufferedBytes-=r[R],this._state=I,r.readOnly=!1,this.sendFrame(t.frame(a,r),n),this.dequeue()})}dequeue(){for(;this._state===I&&this._queue.length;){let e=this._queue.shift();this._bufferedBytes-=e[3][R],Reflect.apply(e[0],this,e.slice(1))}}enqueue(e){this._bufferedBytes+=e[3][R],this._queue.push(e)}sendFrame(e,s){e.length===2?(this._socket.cork(),this._socket.write(e[0]),this._socket.write(e[1],s),this._socket.uncork()):this._socket.write(e[0],s)}};qt.exports=tt;function st(t,e,s){typeof s=="function"&&s(e);for(let r=0;r<t._queue.length;r++){let n=t._queue[r],i=n[n.length-1];typeof i=="function"&&i(e)}}function Ur(t,e,s){st(t,e,s),t.onerror(e)}});var Zt=C((vi,Xt)=>{"use strict";var{kForOnEventAttribute:ue,kListener:nt}=F(),Gt=Symbol("kCode"),Vt=Symbol("kData"),Yt=Symbol("kError"),Ht=Symbol("kMessage"),zt=Symbol("kReason"),ne=Symbol("kTarget"),Kt=Symbol("kType"),Jt=Symbol("kWasClean"),D=class{constructor(e){this[ne]=null,this[Kt]=e}get target(){return this[ne]}get type(){return this[Kt]}};Object.defineProperty(D.prototype,"target",{enumerable:!0});Object.defineProperty(D.prototype,"type",{enumerable:!0});var H=class extends D{constructor(e,s={}){super(e),this[Gt]=s.code===void 0?0:s.code,this[zt]=s.reason===void 0?"":s.reason,this[Jt]=s.wasClean===void 0?!1:s.wasClean}get code(){return this[Gt]}get reason(){return this[zt]}get wasClean(){return this[Jt]}};Object.defineProperty(H.prototype,"code",{enumerable:!0});Object.defineProperty(H.prototype,"reason",{enumerable:!0});Object.defineProperty(H.prototype,"wasClean",{enumerable:!0});var ie=class extends D{constructor(e,s={}){super(e),this[Yt]=s.error===void 0?null:s.error,this[Ht]=s.message===void 0?"":s.message}get error(){return this[Yt]}get message(){return this[Ht]}};Object.defineProperty(ie.prototype,"error",{enumerable:!0});Object.defineProperty(ie.prototype,"message",{enumerable:!0});var he=class extends D{constructor(e,s={}){super(e),this[Vt]=s.data===void 0?null:s.data}get data(){return this[Vt]}};Object.defineProperty(he.prototype,"data",{enumerable:!0});var Dr={addEventListener(t,e,s={}){for(let n of this.listeners(t))if(!s[ue]&&n[nt]===e&&!n[ue])return;let r;if(t==="message")r=function(i,o){let a=new he("message",{data:o?i:i.toString()});a[ne]=this,ke(e,this,a)};else if(t==="close")r=function(i,o){let a=new H("close",{code:i,reason:o.toString(),wasClean:this._closeFrameReceived&&this._closeFrameSent});a[ne]=this,ke(e,this,a)};else if(t==="error")r=function(i){let o=new ie("error",{error:i,message:i.message});o[ne]=this,ke(e,this,o)};else if(t==="open")r=function(){let i=new D("open");i[ne]=this,ke(e,this,i)};else return;r[ue]=!!s[ue],r[nt]=e,s.once?this.once(t,r):this.on(t,r)},removeEventListener(t,e){for(let s of this.listeners(t))if(s[nt]===e&&!s[ue]){this.removeListener(t,s);break}}};Xt.exports={CloseEvent:H,ErrorEvent:ie,Event:D,EventTarget:Dr,MessageEvent:he};function ke(t,e,s){typeof t=="object"&&t.handleEvent?t.handleEvent.call(t,s):t.call(e,s)}});var Ce=C((wi,Qt)=>{"use strict";var{tokenChars:de}=te();function M(t,e,s){t[e]===void 0?t[e]=[s]:t[e].push(s)}function Wr(t){let e=Object.create(null),s=Object.create(null),r=!1,n=!1,i=!1,o,a,c=-1,l=-1,h=-1,p=0;for(;p<t.length;p++)if(l=t.charCodeAt(p),o===void 0)if(h===-1&&de[l]===1)c===-1&&(c=p);else if(p!==0&&(l===32||l===9))h===-1&&c!==-1&&(h=p);else if(l===59||l===44){if(c===-1)throw new SyntaxError(`Unexpected character at index ${p}`);h===-1&&(h=p);let w=t.slice(c,h);l===44?(M(e,w,s),s=Object.create(null)):o=w,c=h=-1}else throw new SyntaxError(`Unexpected character at index ${p}`);else if(a===void 0)if(h===-1&&de[l]===1)c===-1&&(c=p);else if(l===32||l===9)h===-1&&c!==-1&&(h=p);else if(l===59||l===44){if(c===-1)throw new SyntaxError(`Unexpected character at index ${p}`);h===-1&&(h=p),M(s,t.slice(c,h),!0),l===44&&(M(e,o,s),s=Object.create(null),o=void 0),c=h=-1}else if(l===61&&c!==-1&&h===-1)a=t.slice(c,p),c=h=-1;else throw new SyntaxError(`Unexpected character at index ${p}`);else if(n){if(de[l]!==1)throw new SyntaxError(`Unexpected character at index ${p}`);c===-1?c=p:r||(r=!0),n=!1}else if(i)if(de[l]===1)c===-1&&(c=p);else if(l===34&&c!==-1)i=!1,h=p;else if(l===92)n=!0;else throw new SyntaxError(`Unexpected character at index ${p}`);else if(l===34&&t.charCodeAt(p-1)===61)i=!0;else if(h===-1&&de[l]===1)c===-1&&(c=p);else if(c!==-1&&(l===32||l===9))h===-1&&(h=p);else if(l===59||l===44){if(c===-1)throw new SyntaxError(`Unexpected character at index ${p}`);h===-1&&(h=p);let w=t.slice(c,h);r&&(w=w.replace(/\\/g,""),r=!1),M(s,a,w),l===44&&(M(e,o,s),s=Object.create(null),o=void 0),a=void 0,c=h=-1}else throw new SyntaxError(`Unexpected character at index ${p}`);if(c===-1||i||l===32||l===9)throw new SyntaxError("Unexpected end of input");h===-1&&(h=p);let g=t.slice(c,h);return o===void 0?M(e,g,s):(a===void 0?M(s,g,!0):r?M(s,a,g.replace(/\\/g,"")):M(s,a,g),M(e,o,s)),e}function jr(t){return Object.keys(t).map(e=>{let s=t[e];return Array.isArray(s)||(s=[s]),s.map(r=>[e].concat(Object.keys(r).map(n=>{let i=r[n];return Array.isArray(i)||(i=[i]),i.map(o=>o===!0?n:`${n}=${o}`).join("; ")})).join("; ")).join(", ")}).join(", ")}Qt.exports={format:jr,parse:Wr}});var Pe=C((ki,us)=>{"use strict";var qr=require("events"),Gr=require("https"),Vr=require("http"),ss=require("net"),Yr=require("tls"),{randomBytes:Hr,createHash:zr}=require("crypto"),{Duplex:Ti,Readable:Oi}=require("stream"),{URL:it}=require("url"),q=ee(),Kr=et(),Jr=rt(),{isBlob:Xr}=te(),{BINARY_TYPES:es,CLOSE_TIMEOUT:Zr,EMPTY_BUFFER:Ne,GUID:Qr,kForOnEventAttribute:ot,kListener:en,kStatusCode:tn,kWebSocket:O,NOOP:rs}=F(),{EventTarget:{addEventListener:sn,removeEventListener:rn}}=Zt(),{format:nn,parse:on}=Ce(),{toBuffer:an}=ce(),ns=Symbol("kAborted"),at=[8,13],W=["CONNECTING","OPEN","CLOSING","CLOSED"],ln=/^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/,b=class t extends qr{constructor(e,s,r){super(),this._binaryType=es[0],this._closeCode=1006,this._closeFrameReceived=!1,this._closeFrameSent=!1,this._closeMessage=Ne,this._closeTimer=null,this._errorEmitted=!1,this._extensions={},this._paused=!1,this._protocol="",this._readyState=t.CONNECTING,this._receiver=null,this._sender=null,this._socket=null,e!==null?(this._bufferedAmount=0,this._isServer=!1,this._redirects=0,s===void 0?s=[]:Array.isArray(s)||(typeof s=="object"&&s!==null?(r=s,s=[]):s=[s]),is(this,e,s,r)):(this._autoPong=r.autoPong,this._closeTimeout=r.closeTimeout,this._isServer=!0)}get binaryType(){return this._binaryType}set binaryType(e){es.includes(e)&&(this._binaryType=e,this._receiver&&(this._receiver._binaryType=e))}get bufferedAmount(){return this._socket?this._socket._writableState.length+this._sender._bufferedBytes:this._bufferedAmount}get extensions(){return Object.keys(this._extensions).join()}get isPaused(){return this._paused}get onclose(){return null}get onerror(){return null}get onopen(){return null}get onmessage(){return null}get protocol(){return this._protocol}get readyState(){return this._readyState}get url(){return this._url}setSocket(e,s,r){let n=new Kr({allowSynchronousEvents:r.allowSynchronousEvents,binaryType:this.binaryType,extensions:this._extensions,isServer:this._isServer,maxPayload:r.maxPayload,skipUTF8Validation:r.skipUTF8Validation}),i=new Jr(e,this._extensions,r.generateMask);this._receiver=n,this._sender=i,this._socket=e,n[O]=this,i[O]=this,e[O]=this,n.on("conclude",un),n.on("drain",hn),n.on("error",dn),n.on("message",pn),n.on("ping",_n),n.on("pong",mn),i.onerror=gn,e.setTimeout&&e.setTimeout(0),e.setNoDelay&&e.setNoDelay(),s.length>0&&e.unshift(s),e.on("close",ls),e.on("data",Re),e.on("end",cs),e.on("error",fs),this._readyState=t.OPEN,this.emit("open")}emitClose(){if(!this._socket){this._readyState=t.CLOSED,this.emit("close",this._closeCode,this._closeMessage);return}this._extensions[q.extensionName]&&this._extensions[q.extensionName].cleanup(),this._receiver.removeAllListeners(),this._readyState=t.CLOSED,this.emit("close",this._closeCode,this._closeMessage)}close(e,s){if(this.readyState!==t.CLOSED){if(this.readyState===t.CONNECTING){N(this,this._req,"WebSocket was closed before the connection was established");return}if(this.readyState===t.CLOSING){this._closeFrameSent&&(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end();return}this._readyState=t.CLOSING,this._sender.close(e,s,!this._isServer,r=>{r||(this._closeFrameSent=!0,(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end())}),as(this)}}pause(){this.readyState===t.CONNECTING||this.readyState===t.CLOSED||(this._paused=!0,this._socket.pause())}ping(e,s,r){if(this.readyState===t.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof e=="function"?(r=e,e=s=void 0):typeof s=="function"&&(r=s,s=void 0),typeof e=="number"&&(e=e.toString()),this.readyState!==t.OPEN){lt(this,e,r);return}s===void 0&&(s=!this._isServer),this._sender.ping(e||Ne,s,r)}pong(e,s,r){if(this.readyState===t.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof e=="function"?(r=e,e=s=void 0):typeof s=="function"&&(r=s,s=void 0),typeof e=="number"&&(e=e.toString()),this.readyState!==t.OPEN){lt(this,e,r);return}s===void 0&&(s=!this._isServer),this._sender.pong(e||Ne,s,r)}resume(){this.readyState===t.CONNECTING||this.readyState===t.CLOSED||(this._paused=!1,this._receiver._writableState.needDrain||this._socket.resume())}send(e,s,r){if(this.readyState===t.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof s=="function"&&(r=s,s={}),typeof e=="number"&&(e=e.toString()),this.readyState!==t.OPEN){lt(this,e,r);return}let n={binary:typeof e!="string",mask:!this._isServer,compress:!0,fin:!0,...s};this._extensions[q.extensionName]||(n.compress=!1),this._sender.send(e||Ne,n,r)}terminate(){if(this.readyState!==t.CLOSED){if(this.readyState===t.CONNECTING){N(this,this._req,"WebSocket was closed before the connection was established");return}this._socket&&(this._readyState=t.CLOSING,this._socket.destroy())}}};Object.defineProperty(b,"CONNECTING",{enumerable:!0,value:W.indexOf("CONNECTING")});Object.defineProperty(b.prototype,"CONNECTING",{enumerable:!0,value:W.indexOf("CONNECTING")});Object.defineProperty(b,"OPEN",{enumerable:!0,value:W.indexOf("OPEN")});Object.defineProperty(b.prototype,"OPEN",{enumerable:!0,value:W.indexOf("OPEN")});Object.defineProperty(b,"CLOSING",{enumerable:!0,value:W.indexOf("CLOSING")});Object.defineProperty(b.prototype,"CLOSING",{enumerable:!0,value:W.indexOf("CLOSING")});Object.defineProperty(b,"CLOSED",{enumerable:!0,value:W.indexOf("CLOSED")});Object.defineProperty(b.prototype,"CLOSED",{enumerable:!0,value:W.indexOf("CLOSED")});["binaryType","bufferedAmount","extensions","isPaused","protocol","readyState","url"].forEach(t=>{Object.defineProperty(b.prototype,t,{enumerable:!0})});["open","error","close","message"].forEach(t=>{Object.defineProperty(b.prototype,`on${t}`,{enumerable:!0,get(){for(let e of this.listeners(t))if(e[ot])return e[en];return null},set(e){for(let s of this.listeners(t))if(s[ot]){this.removeListener(t,s);break}typeof e=="function"&&this.addEventListener(t,e,{[ot]:!0})}})});b.prototype.addEventListener=sn;b.prototype.removeEventListener=rn;us.exports=b;function is(t,e,s,r){let n={allowSynchronousEvents:!0,autoPong:!0,closeTimeout:Zr,protocolVersion:at[1],maxPayload:104857600,skipUTF8Validation:!1,perMessageDeflate:!0,followRedirects:!1,maxRedirects:10,...r,socketPath:void 0,hostname:void 0,protocol:void 0,timeout:void 0,method:"GET",host:void 0,path:void 0,port:void 0};if(t._autoPong=n.autoPong,t._closeTimeout=n.closeTimeout,!at.includes(n.protocolVersion))throw new RangeError(`Unsupported protocol version: ${n.protocolVersion} (supported versions: ${at.join(", ")})`);let i;if(e instanceof it)i=e;else try{i=new it(e)}catch{throw new SyntaxError(`Invalid URL: ${e}`)}i.protocol==="http:"?i.protocol="ws:":i.protocol==="https:"&&(i.protocol="wss:"),t._url=i.href;let o=i.protocol==="wss:",a=i.protocol==="ws+unix:",c;if(i.protocol!=="ws:"&&!o&&!a?c=`The URL's protocol must be one of "ws:", "wss:", "http:", "https:", or "ws+unix:"`:a&&!i.pathname?c="The URL's pathname is empty":i.hash&&(c="The URL contains a fragment identifier"),c){let _=new SyntaxError(c);if(t._redirects===0)throw _;Le(t,_);return}let l=o?443:80,h=Hr(16).toString("base64"),p=o?Gr.request:Vr.request,g=new Set,w;if(n.createConnection=n.createConnection||(o?fn:cn),n.defaultPort=n.defaultPort||l,n.port=i.port||l,n.host=i.hostname.startsWith("[")?i.hostname.slice(1,-1):i.hostname,n.headers={...n.headers,"Sec-WebSocket-Version":n.protocolVersion,"Sec-WebSocket-Key":h,Connection:"Upgrade",Upgrade:"websocket"},n.path=i.pathname+i.search,n.timeout=n.handshakeTimeout,n.perMessageDeflate&&(w=new q({...n.perMessageDeflate,isServer:!1,maxPayload:n.maxPayload}),n.headers["Sec-WebSocket-Extensions"]=nn({[q.extensionName]:w.offer()})),s.length){for(let _ of s){if(typeof _!="string"||!ln.test(_)||g.has(_))throw new SyntaxError("An invalid or duplicated subprotocol was specified");g.add(_)}n.headers["Sec-WebSocket-Protocol"]=s.join(",")}if(n.origin&&(n.protocolVersion<13?n.headers["Sec-WebSocket-Origin"]=n.origin:n.headers.Origin=n.origin),(i.username||i.password)&&(n.auth=`${i.username}:${i.password}`),a){let _=n.path.split(":");n.socketPath=_[0],n.path=_[1]}let m;if(n.followRedirects){if(t._redirects===0){t._originalIpc=a,t._originalSecure=o,t._originalHostOrSocketPath=a?n.socketPath:i.host;let _=r&&r.headers;if(r={...r,headers:{}},_)for(let[f,d]of Object.entries(_))r.headers[f.toLowerCase()]=d}else if(t.listenerCount("redirect")===0){let _=a?t._originalIpc?n.socketPath===t._originalHostOrSocketPath:!1:t._originalIpc?!1:i.host===t._originalHostOrSocketPath;(!_||t._originalSecure&&!o)&&(delete n.headers.authorization,delete n.headers.cookie,_||delete n.headers.host,n.auth=void 0)}n.auth&&!r.headers.authorization&&(r.headers.authorization="Basic "+Buffer.from(n.auth).toString("base64")),m=t._req=p(n),t._redirects&&t.emit("redirect",t.url,m)}else m=t._req=p(n);n.timeout&&m.on("timeout",()=>{N(t,m,"Opening handshake has timed out")}),m.on("error",_=>{m===null||m[ns]||(m=t._req=null,Le(t,_))}),m.on("response",_=>{let f=_.headers.location,d=_.statusCode;if(f&&n.followRedirects&&d>=300&&d<400){if(++t._redirects>n.maxRedirects){N(t,m,"Maximum redirects exceeded");return}m.abort();let S;try{S=new it(f,e)}catch{let y=new SyntaxError(`Invalid URL: ${f}`);Le(t,y);return}is(t,S,s,r)}else t.emit("unexpected-response",m,_)||N(t,m,`Unexpected server response: ${_.statusCode}`)}),m.on("upgrade",(_,f,d)=>{if(t.emit("upgrade",_),t.readyState!==b.CONNECTING)return;m=t._req=null;let S=_.headers.upgrade;if(S===void 0||S.toLowerCase()!=="websocket"){N(t,f,"Invalid Upgrade header");return}let T=zr("sha1").update(h+Qr).digest("base64");if(_.headers["sec-websocket-accept"]!==T){N(t,f,"Invalid Sec-WebSocket-Accept header");return}let y=_.headers["sec-websocket-protocol"],B;if(y!==void 0?g.size?g.has(y)||(B="Server sent an invalid subprotocol"):B="Server sent a subprotocol but none was requested":g.size&&(B="Server sent no subprotocol"),B){N(t,f,B);return}y&&(t._protocol=y);let X=_.headers["sec-websocket-extensions"];if(X!==void 0){if(!w){N(t,f,"Server sent a Sec-WebSocket-Extensions header but no extension was requested");return}let G;try{G=on(X)}catch{N(t,f,"Invalid Sec-WebSocket-Extensions header");return}let St=Object.keys(G);if(St.length!==1||St[0]!==q.extensionName){N(t,f,"Server indicated an extension that was not requested");return}try{w.accept(G[q.extensionName])}catch{N(t,f,"Invalid Sec-WebSocket-Extensions header");return}t._extensions[q.extensionName]=w}t.setSocket(f,d,{allowSynchronousEvents:n.allowSynchronousEvents,generateMask:n.generateMask,maxPayload:n.maxPayload,skipUTF8Validation:n.skipUTF8Validation})}),n.finishRequest?n.finishRequest(m,t):m.end()}function Le(t,e){t._readyState=b.CLOSING,t._errorEmitted=!0,t.emit("error",e),t.emitClose()}function cn(t){return t.path=t.socketPath,ss.connect(t)}function fn(t){return t.path=void 0,!t.servername&&t.servername!==""&&(t.servername=ss.isIP(t.host)?"":t.host),Yr.connect(t)}function N(t,e,s){t._readyState=b.CLOSING;let r=new Error(s);Error.captureStackTrace(r,N),e.setHeader?(e[ns]=!0,e.abort(),e.socket&&!e.socket.destroyed&&e.socket.destroy(),process.nextTick(Le,t,r)):(e.destroy(r),e.once("error",t.emit.bind(t,"error")),e.once("close",t.emitClose.bind(t)))}function lt(t,e,s){if(e){let r=Xr(e)?e.size:an(e).length;t._socket?t._sender._bufferedBytes+=r:t._bufferedAmount+=r}if(s){let r=new Error(`WebSocket is not open: readyState ${t.readyState} (${W[t.readyState]})`);process.nextTick(s,r)}}function un(t,e){let s=this[O];s._closeFrameReceived=!0,s._closeMessage=e,s._closeCode=t,s._socket[O]!==void 0&&(s._socket.removeListener("data",Re),process.nextTick(os,s._socket),t===1005?s.close():s.close(t,e))}function hn(){let t=this[O];t.isPaused||t._socket.resume()}function dn(t){let e=this[O];e._socket[O]!==void 0&&(e._socket.removeListener("data",Re),process.nextTick(os,e._socket),e.close(t[tn])),e._errorEmitted||(e._errorEmitted=!0,e.emit("error",t))}function ts(){this[O].emitClose()}function pn(t,e){this[O].emit("message",t,e)}function _n(t){let e=this[O];e._autoPong&&e.pong(t,!this._isServer,rs),e.emit("ping",t)}function mn(t){this[O].emit("pong",t)}function os(t){t.resume()}function gn(t){let e=this[O];e.readyState!==b.CLOSED&&(e.readyState===b.OPEN&&(e._readyState=b.CLOSING,as(e)),this._socket.end(),e._errorEmitted||(e._errorEmitted=!0,e.emit("error",t)))}function as(t){t._closeTimer=setTimeout(t._socket.destroy.bind(t._socket),t._closeTimeout)}function ls(){let t=this[O];if(this.removeListener("close",ls),this.removeListener("data",Re),this.removeListener("end",cs),t._readyState=b.CLOSING,!this._readableState.endEmitted&&!t._closeFrameReceived&&!t._receiver._writableState.errorEmitted&&this._readableState.length!==0){let e=this.read(this._readableState.length);t._receiver.write(e)}t._receiver.end(),this[O]=void 0,clearTimeout(t._closeTimer),t._receiver._writableState.finished||t._receiver._writableState.errorEmitted?t.emitClose():(t._receiver.on("error",ts),t._receiver.on("finish",ts))}function Re(t){this[O]._receiver.write(t)||this.pause()}function cs(){let t=this[O];t._readyState=b.CLOSING,t._receiver.end(),this.end()}function fs(){let t=this[O];this.removeListener("error",fs),this.on("error",rs),t&&(t._readyState=b.CLOSING,this.destroy())}});var _s=C((Ni,ps)=>{"use strict";var Ci=Pe(),{Duplex:yn}=require("stream");function hs(t){t.emit("close")}function Sn(){!this.destroyed&&this._writableState.finished&&this.destroy()}function ds(t){this.removeListener("error",ds),this.destroy(),this.listenerCount("error")===0&&this.emit("error",t)}function xn(t,e){let s=!0,r=new yn({...e,autoDestroy:!1,emitClose:!1,objectMode:!1,writableObjectMode:!1});return t.on("message",function(i,o){let a=!o&&r._readableState.objectMode?i.toString():i;r.push(a)||t.pause()}),t.once("error",function(i){r.destroyed||(s=!1,r.destroy(i))}),t.once("close",function(){r.destroyed||r.push(null)}),r._destroy=function(n,i){if(t.readyState===t.CLOSED){i(n),process.nextTick(hs,r);return}let o=!1;t.once("error",function(c){o=!0,i(c)}),t.once("close",function(){o||i(n),process.nextTick(hs,r)}),s&&t.terminate()},r._final=function(n){if(t.readyState===t.CONNECTING){t.once("open",function(){r._final(n)});return}t._socket!==null&&(t._socket._writableState.finished?(n(),r._readableState.endEmitted&&r.destroy()):(t._socket.once("finish",function(){n()}),t.close()))},r._read=function(){t.isPaused&&t.resume()},r._write=function(n,i,o){if(t.readyState===t.CONNECTING){t.once("open",function(){r._write(n,i,o)});return}t.send(n,o)},r.on("end",Sn),r.on("error",ds),r}ps.exports=xn});var ct=C((Li,ms)=>{"use strict";var{tokenChars:bn}=te();function En(t){let e=new Set,s=-1,r=-1,n=0;for(n;n<t.length;n++){let o=t.charCodeAt(n);if(r===-1&&bn[o]===1)s===-1&&(s=n);else if(n!==0&&(o===32||o===9))r===-1&&s!==-1&&(r=n);else if(o===44){if(s===-1)throw new SyntaxError(`Unexpected character at index ${n}`);r===-1&&(r=n);let a=t.slice(s,r);if(e.has(a))throw new SyntaxError(`The "${a}" subprotocol is duplicated`);e.add(a),s=r=-1}else throw new SyntaxError(`Unexpected character at index ${n}`)}if(s===-1||r!==-1)throw new SyntaxError("Unexpected end of input");let i=t.slice(s,n);if(e.has(i))throw new SyntaxError(`The "${i}" subprotocol is duplicated`);return e.add(i),e}ms.exports={parse:En}});var vs=C((Pi,Es)=>{"use strict";var vn=require("events"),Be=require("http"),{Duplex:Ri}=require("stream"),{createHash:wn}=require("crypto"),gs=Ce(),z=ee(),Tn=ct(),On=Pe(),{CLOSE_TIMEOUT:kn,GUID:Cn,kWebSocket:Nn}=F(),Ln=/^[+/0-9A-Za-z]{22}==$/,ys=0,Ss=1,bs=2,ft=class extends vn{constructor(e,s){if(super(),e={allowSynchronousEvents:!0,autoPong:!0,maxPayload:100*1024*1024,skipUTF8Validation:!1,perMessageDeflate:!1,handleProtocols:null,clientTracking:!0,closeTimeout:kn,verifyClient:null,noServer:!1,backlog:null,server:null,host:null,path:null,port:null,WebSocket:On,...e},e.port==null&&!e.server&&!e.noServer||e.port!=null&&(e.server||e.noServer)||e.server&&e.noServer)throw new TypeError('One and only one of the "port", "server", or "noServer" options must be specified');if(e.port!=null?(this._server=Be.createServer((r,n)=>{let i=Be.STATUS_CODES[426];n.writeHead(426,{"Content-Length":i.length,"Content-Type":"text/plain"}),n.end(i)}),this._server.listen(e.port,e.host,e.backlog,s)):e.server&&(this._server=e.server),this._server){let r=this.emit.bind(this,"connection");this._removeListeners=Rn(this._server,{listening:this.emit.bind(this,"listening"),error:this.emit.bind(this,"error"),upgrade:(n,i,o)=>{this.handleUpgrade(n,i,o,r)}})}e.perMessageDeflate===!0&&(e.perMessageDeflate={}),e.clientTracking&&(this.clients=new Set,this._shouldEmitClose=!1),this.options=e,this._state=ys}address(){if(this.options.noServer)throw new Error('The server is operating in "noServer" mode');return this._server?this._server.address():null}close(e){if(this._state===bs){e&&this.once("close",()=>{e(new Error("The server is not running"))}),process.nextTick(pe,this);return}if(e&&this.once("close",e),this._state!==Ss)if(this._state=Ss,this.options.noServer||this.options.server)this._server&&(this._removeListeners(),this._removeListeners=this._server=null),this.clients?this.clients.size?this._shouldEmitClose=!0:process.nextTick(pe,this):process.nextTick(pe,this);else{let s=this._server;this._removeListeners(),this._removeListeners=this._server=null,s.close(()=>{pe(this)})}}shouldHandle(e){if(this.options.path){let s=e.url.indexOf("?");if((s!==-1?e.url.slice(0,s):e.url)!==this.options.path)return!1}return!0}handleUpgrade(e,s,r,n){s.on("error",xs);let i=e.headers["sec-websocket-key"],o=e.headers.upgrade,a=+e.headers["sec-websocket-version"];if(e.method!=="GET"){K(this,e,s,405,"Invalid HTTP method");return}if(o===void 0||o.toLowerCase()!=="websocket"){K(this,e,s,400,"Invalid Upgrade header");return}if(i===void 0||!Ln.test(i)){K(this,e,s,400,"Missing or invalid Sec-WebSocket-Key header");return}if(a!==13&&a!==8){K(this,e,s,400,"Missing or invalid Sec-WebSocket-Version header",{"Sec-WebSocket-Version":"13, 8"});return}if(!this.shouldHandle(e)){_e(s,400);return}let c=e.headers["sec-websocket-protocol"],l=new Set;if(c!==void 0)try{l=Tn.parse(c)}catch{K(this,e,s,400,"Invalid Sec-WebSocket-Protocol header");return}let h=e.headers["sec-websocket-extensions"],p={};if(this.options.perMessageDeflate&&h!==void 0){let g=new z({...this.options.perMessageDeflate,isServer:!0,maxPayload:this.options.maxPayload});try{let w=gs.parse(h);w[z.extensionName]&&(g.accept(w[z.extensionName]),p[z.extensionName]=g)}catch{K(this,e,s,400,"Invalid or unacceptable Sec-WebSocket-Extensions header");return}}if(this.options.verifyClient){let g={origin:e.headers[`${a===8?"sec-websocket-origin":"origin"}`],secure:!!(e.socket.authorized||e.socket.encrypted),req:e};if(this.options.verifyClient.length===2){this.options.verifyClient(g,(w,m,_,f)=>{if(!w)return _e(s,m||401,_,f);this.completeUpgrade(p,i,l,e,s,r,n)});return}if(!this.options.verifyClient(g))return _e(s,401)}this.completeUpgrade(p,i,l,e,s,r,n)}completeUpgrade(e,s,r,n,i,o,a){if(!i.readable||!i.writable)return i.destroy();if(i[Nn])throw new Error("server.handleUpgrade() was called more than once with the same socket, possibly due to a misconfiguration");if(this._state>ys)return _e(i,503);let l=["HTTP/1.1 101 Switching Protocols","Upgrade: websocket","Connection: Upgrade",`Sec-WebSocket-Accept: ${wn("sha1").update(s+Cn).digest("base64")}`],h=new this.options.WebSocket(null,void 0,this.options);if(r.size){let p=this.options.handleProtocols?this.options.handleProtocols(r,n):r.values().next().value;p&&(l.push(`Sec-WebSocket-Protocol: ${p}`),h._protocol=p)}if(e[z.extensionName]){let p=e[z.extensionName].params,g=gs.format({[z.extensionName]:[p]});l.push(`Sec-WebSocket-Extensions: ${g}`),h._extensions=e}this.emit("headers",l,n),i.write(l.concat(`\r
|
|
3
|
+
`).join(`\r
|
|
4
|
+
`)),i.removeListener("error",xs),h.setSocket(i,o,{allowSynchronousEvents:this.options.allowSynchronousEvents,maxPayload:this.options.maxPayload,skipUTF8Validation:this.options.skipUTF8Validation}),this.clients&&(this.clients.add(h),h.on("close",()=>{this.clients.delete(h),this._shouldEmitClose&&!this.clients.size&&process.nextTick(pe,this)})),a(h,n)}};Es.exports=ft;function Rn(t,e){for(let s of Object.keys(e))t.on(s,e[s]);return function(){for(let r of Object.keys(e))t.removeListener(r,e[r])}}function pe(t){t._state=bs,t.emit("close")}function xs(){this.destroy()}function _e(t,e,s,r){s=s||Be.STATUS_CODES[e],r={Connection:"close","Content-Type":"text/html","Content-Length":Buffer.byteLength(s),...r},t.once("finish",t.destroy),t.end(`HTTP/1.1 ${e} ${Be.STATUS_CODES[e]}\r
|
|
5
|
+
`+Object.keys(r).map(n=>`${n}: ${r[n]}`).join(`\r
|
|
6
|
+
`)+`\r
|
|
7
|
+
\r
|
|
8
|
+
`+s)}function K(t,e,s,r,n,i){if(t.listenerCount("wsClientError")){let o=new Error(n);Error.captureStackTrace(o,K),t.emit("wsClientError",o,s,e)}else _e(s,r,n,i)}});var Pn=x(_s(),1),Bn=x(Ce(),1),In=x(ee(),1),An=x(et(),1),Mn=x(rt(),1),$n=x(ct(),1),ws=x(Pe(),1),Fn=x(vs(),1);var Ts=ws.default;var nr=x(require("readline")),k=x(require("fs")),J=x(require("path"));var Os=(t=0)=>e=>`\x1B[${e+t}m`,ks=(t=0)=>e=>`\x1B[${38+t};5;${e}m`,Cs=(t=0)=>(e,s,r)=>`\x1B[${38+t};2;${e};${s};${r}m`,E={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],overline:[53,55],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],gray:[90,39],grey:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgGray:[100,49],bgGrey:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]}},Ii=Object.keys(E.modifier),Un=Object.keys(E.color),Dn=Object.keys(E.bgColor),Ai=[...Un,...Dn];function Wn(){let t=new Map;for(let[e,s]of Object.entries(E)){for(let[r,n]of Object.entries(s))E[r]={open:`\x1B[${n[0]}m`,close:`\x1B[${n[1]}m`},s[r]=E[r],t.set(n[0],n[1]);Object.defineProperty(E,e,{value:s,enumerable:!1})}return Object.defineProperty(E,"codes",{value:t,enumerable:!1}),E.color.close="\x1B[39m",E.bgColor.close="\x1B[49m",E.color.ansi=Os(),E.color.ansi256=ks(),E.color.ansi16m=Cs(),E.bgColor.ansi=Os(10),E.bgColor.ansi256=ks(10),E.bgColor.ansi16m=Cs(10),Object.defineProperties(E,{rgbToAnsi256:{value(e,s,r){return e===s&&s===r?e<8?16:e>248?231:Math.round((e-8)/247*24)+232:16+36*Math.round(e/255*5)+6*Math.round(s/255*5)+Math.round(r/255*5)},enumerable:!1},hexToRgb:{value(e){let s=/[a-f\d]{6}|[a-f\d]{3}/i.exec(e.toString(16));if(!s)return[0,0,0];let[r]=s;r.length===3&&(r=[...r].map(i=>i+i).join(""));let n=Number.parseInt(r,16);return[n>>16&255,n>>8&255,n&255]},enumerable:!1},hexToAnsi256:{value:e=>E.rgbToAnsi256(...E.hexToRgb(e)),enumerable:!1},ansi256ToAnsi:{value(e){if(e<8)return 30+e;if(e<16)return 90+(e-8);let s,r,n;if(e>=232)s=((e-232)*10+8)/255,r=s,n=s;else{e-=16;let a=e%36;s=Math.floor(e/36)/5,r=Math.floor(a/6)/5,n=a%6/5}let i=Math.max(s,r,n)*2;if(i===0)return 30;let o=30+(Math.round(n)<<2|Math.round(r)<<1|Math.round(s));return i===2&&(o+=60),o},enumerable:!1},rgbToAnsi:{value:(e,s,r)=>E.ansi256ToAnsi(E.rgbToAnsi256(e,s,r)),enumerable:!1},hexToAnsi:{value:e=>E.ansi256ToAnsi(E.hexToAnsi256(e)),enumerable:!1}}),E}var jn=Wn(),A=jn;var Ae=x(require("node:process"),1),Ls=x(require("node:os"),1),ut=x(require("node:tty"),1);function P(t,e=globalThis.Deno?globalThis.Deno.args:Ae.default.argv){let s=t.startsWith("-")?"":t.length===1?"-":"--",r=e.indexOf(s+t),n=e.indexOf("--");return r!==-1&&(n===-1||r<n)}var{env:v}=Ae.default,Ie;P("no-color")||P("no-colors")||P("color=false")||P("color=never")?Ie=0:(P("color")||P("colors")||P("color=true")||P("color=always"))&&(Ie=1);function qn(){if("FORCE_COLOR"in v)return v.FORCE_COLOR==="true"?1:v.FORCE_COLOR==="false"?0:v.FORCE_COLOR.length===0?1:Math.min(Number.parseInt(v.FORCE_COLOR,10),3)}function Gn(t){return t===0?!1:{level:t,hasBasic:!0,has256:t>=2,has16m:t>=3}}function Vn(t,{streamIsTTY:e,sniffFlags:s=!0}={}){let r=qn();r!==void 0&&(Ie=r);let n=s?Ie:r;if(n===0)return 0;if(s){if(P("color=16m")||P("color=full")||P("color=truecolor"))return 3;if(P("color=256"))return 2}if("TF_BUILD"in v&&"AGENT_NAME"in v)return 1;if(t&&!e&&n===void 0)return 0;let i=n||0;if(v.TERM==="dumb")return i;if(Ae.default.platform==="win32"){let o=Ls.default.release().split(".");return Number(o[0])>=10&&Number(o[2])>=10586?Number(o[2])>=14931?3:2:1}if("CI"in v)return["GITHUB_ACTIONS","GITEA_ACTIONS","CIRCLECI"].some(o=>o in v)?3:["TRAVIS","APPVEYOR","GITLAB_CI","BUILDKITE","DRONE"].some(o=>o in v)||v.CI_NAME==="codeship"?1:i;if("TEAMCITY_VERSION"in v)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(v.TEAMCITY_VERSION)?1:0;if(v.COLORTERM==="truecolor"||v.TERM==="xterm-kitty"||v.TERM==="xterm-ghostty"||v.TERM==="wezterm")return 3;if("TERM_PROGRAM"in v){let o=Number.parseInt((v.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(v.TERM_PROGRAM){case"iTerm.app":return o>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(v.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(v.TERM)||"COLORTERM"in v?1:i}function Ns(t,e={}){let s=Vn(t,{streamIsTTY:t&&t.isTTY,...e});return Gn(s)}var Yn={stdout:Ns({isTTY:ut.default.isatty(1)}),stderr:Ns({isTTY:ut.default.isatty(2)})},Rs=Yn;function Ps(t,e,s){let r=t.indexOf(e);if(r===-1)return t;let n=e.length,i=0,o="";do o+=t.slice(i,r)+e+s,i=r+n,r=t.indexOf(e,i);while(r!==-1);return o+=t.slice(i),o}function Bs(t,e,s,r){let n=0,i="";do{let o=t[r-1]==="\r";i+=t.slice(n,o?r-1:r)+e+(o?`\r
|
|
9
|
+
`:`
|
|
10
|
+
`)+s,n=r+1,r=t.indexOf(`
|
|
11
|
+
`,n)}while(r!==-1);return i+=t.slice(n),i}var{stdout:Is,stderr:As}=Rs,ht=Symbol("GENERATOR"),oe=Symbol("STYLER"),me=Symbol("IS_EMPTY"),Ms=["ansi","ansi","ansi256","ansi16m"],ae=Object.create(null),Hn=(t,e={})=>{if(e.level&&!(Number.isInteger(e.level)&&e.level>=0&&e.level<=3))throw new Error("The `level` option should be an integer from 0 to 3");let s=Is?Is.level:0;t.level=e.level===void 0?s:e.level};var zn=t=>{let e=(...s)=>s.join(" ");return Hn(e,t),Object.setPrototypeOf(e,ge.prototype),e};function ge(t){return zn(t)}Object.setPrototypeOf(ge.prototype,Function.prototype);for(let[t,e]of Object.entries(A))ae[t]={get(){let s=Me(this,pt(e.open,e.close,this[oe]),this[me]);return Object.defineProperty(this,t,{value:s}),s}};ae.visible={get(){let t=Me(this,this[oe],!0);return Object.defineProperty(this,"visible",{value:t}),t}};var dt=(t,e,s,...r)=>t==="rgb"?e==="ansi16m"?A[s].ansi16m(...r):e==="ansi256"?A[s].ansi256(A.rgbToAnsi256(...r)):A[s].ansi(A.rgbToAnsi(...r)):t==="hex"?dt("rgb",e,s,...A.hexToRgb(...r)):A[s][t](...r),Kn=["rgb","hex","ansi256"];for(let t of Kn){ae[t]={get(){let{level:s}=this;return function(...r){let n=pt(dt(t,Ms[s],"color",...r),A.color.close,this[oe]);return Me(this,n,this[me])}}};let e="bg"+t[0].toUpperCase()+t.slice(1);ae[e]={get(){let{level:s}=this;return function(...r){let n=pt(dt(t,Ms[s],"bgColor",...r),A.bgColor.close,this[oe]);return Me(this,n,this[me])}}}}var Jn=Object.defineProperties(()=>{},{...ae,level:{enumerable:!0,get(){return this[ht].level},set(t){this[ht].level=t}}}),pt=(t,e,s)=>{let r,n;return s===void 0?(r=t,n=e):(r=s.openAll+t,n=e+s.closeAll),{open:t,close:e,openAll:r,closeAll:n,parent:s}},Me=(t,e,s)=>{let r=(...n)=>Xn(r,n.length===1?""+n[0]:n.join(" "));return Object.setPrototypeOf(r,Jn),r[ht]=t,r[oe]=e,r[me]=s,r},Xn=(t,e)=>{if(t.level<=0||!e)return t[me]?"":e;let s=t[oe];if(s===void 0)return e;let{openAll:r,closeAll:n}=s;if(e.includes("\x1B"))for(;s!==void 0;)e=Ps(e,s.close,s.open),s=s.parent;let i=e.indexOf(`
|
|
12
|
+
`);return i!==-1&&(e=Bs(e,n,r,i)),r+e+n};Object.defineProperties(ge.prototype,ae);var Zn=ge(),ji=ge({level:As?As.level:0});var u=Zn;var $e=require("child_process"),$=x(require("fs")),Fe=x(require("path")),Ue=process.cwd();async function _t(t,e){try{switch(t){case"read_file":return Qn(e);case"write_file":return ei(e);case"edit_file":return ti(e);case"grep":return si(e);case"glob":return ri(e);case"list_dir":return ni(e);case"bash":return ii(e);default:return{success:!1,output:`Unknown tool: ${t}`}}}catch(s){return{success:!1,output:s.message}}}function De(t){return Fe.resolve(Ue,t)}function Qn(t){return{success:!0,output:$.readFileSync(De(t.path),"utf-8")}}function ei(t){let e=De(t.path);return $.mkdirSync(Fe.dirname(e),{recursive:!0}),$.writeFileSync(e,t.content,"utf-8"),{success:!0,output:`Written ${t.path} (${t.content.length} chars)`}}function ti(t){let e=De(t.path),s=$.readFileSync(e,"utf-8");if(!s.includes(t.old_str))return{success:!1,output:`old_str not found in ${t.path}`};let r=s.split(t.old_str).length-1;return r>1?{success:!1,output:`old_str found ${r} times in ${t.path}, must be unique`}:($.writeFileSync(e,s.replace(t.old_str,t.new_str),"utf-8"),{success:!0,output:`Edited ${t.path}`})}function si(t){let e=t.path||".",s=`grep -rn --include='${t.include||"*"}' '${t.pattern}' ${e} 2>/dev/null | head -50`;return{success:!0,output:(0,$e.execSync)(s,{cwd:Ue,encoding:"utf-8",timeout:1e4})||"(no matches)"}}function ri(t){let e=`find . -name '${t.pattern}' -not -path '*/node_modules/*' -not -path '*/.git/*' 2>/dev/null | head -100`;return{success:!0,output:(0,$e.execSync)(e,{cwd:Ue,encoding:"utf-8",timeout:1e4})||"(no files found)"}}function ni(t){let e=De(t.path||".");return{success:!0,output:$.readdirSync(e,{withFileTypes:!0}).filter(n=>!n.name.startsWith(".")&&n.name!=="node_modules").map(n=>`${n.isDirectory()?"\u{1F4C1}":"\u{1F4C4}"} ${n.name}`).join(`
|
|
13
|
+
`)||"(empty)"}}function ii(t){let e=t.command.trim();return[/\brm\s+-rf\s+[\/~]/,/\bmkfs\b/,/\bdd\s+if=/,/\b>\s*\/dev\/sd/,/\bchmod\s+-R\s+777\s+\//,/\bsudo\s+rm\b/].some(n=>n.test(e))?{success:!1,output:"Blocked: dangerous command detected"}:{success:!0,output:(0,$e.execSync)(e,{cwd:Ue,encoding:"utf-8",timeout:t.timeout||3e4,maxBuffer:1024*1024})}}var ye=x(require("path")),$s=x(require("fs")),Fs=x(require("readline")),We=process.cwd(),Us=new Set;function oi(t){let e=ye.resolve(We,t);return e.startsWith(We+ye.sep)||e===We}var ai=new Set(["read_file","grep","glob","list_dir"]);async function Ds(t,e,s){if(ai.has(t)){let r=e.path||e.pattern||".";if(oi(r))return"y"}return t!=="bash"&&Us.has(t)?"t":"ask"}async function Ws(t,e,s){let i=(await li(`
|
|
14
|
+
`+(t==="bash"?"Allow this action? [y/n]: ":"Allow this action? Use 't' to trust (always allow) this tool for the session. [y/n/t]: "))).trim().toLowerCase()[0]||"n";return i==="t"&&t!=="bash"?(Us.add(t),"t"):i==="y"?"y":"n"}function js(t){try{let e=ye.resolve(We,t);return $s.readFileSync(e,"utf-8")}catch{return}}function li(t){return new Promise(e=>{let s=Fs.createInterface({input:process.stdin,output:process.stdout,terminal:!0});s.question(t,r=>{s.close(),e(r)})})}var Gs=x(require("fs")),Vs=x(require("path"));function ci(t){return t.replace(/\x1b\[[0-9;]*m/g,"")}function Ys(){let t=process.stdout.columns||60,e=Math.min(t-4,62),s=u.gray,r=u.cyan,n=u.cyanBright.bold,i=u.white,o=r("\u2502"),a=(l,h)=>l+" ".repeat(Math.max(0,h-ci(l).length)),c=l=>` ${o} ${a(l,e-4)} ${o}`;console.log(""),console.log(r(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557")),console.log(r(" \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u255A\u2588\u2588\u2557 \u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D")),console.log(n(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u255A\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2557 ")),console.log(r(" \u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551 \u255A\u2588\u2588\u2554\u255D \u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255D ")),console.log(n(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557")),console.log(r(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D")),console.log(""),console.log(` ${r("\u250C"+"\u2500".repeat(e-2)+"\u2510")}`),console.log(c(s("AI-powered coding assistant")+" ".repeat(Math.max(0,e-38))+s("v0.1.2"))),console.log(c("")),console.log(c(s("model ")+i("Kimi K2.5")+s(" context ")+i("256k"))),console.log(c(s("location ")+i(process.cwd()))),console.log(c("")),console.log(c(s("/save save session /load restore session"))),console.log(c(s("/compact compress history /context show usage"))),console.log(c(s("/tools list tools /quit exit"))),console.log(c("")),console.log(c(s("Powered by Cloudflare \xB7 Built by Bowen Liu"))),console.log(` ${r("\u2514"+"\u2500".repeat(e-2)+"\u2518")}`),console.log("")}function Hs(t){console.log(u.white(t))}function zs(t){console.log(u.gray(` \u{1F4AD} ${t}`))}function mt(t,e,s){if(s){console.log(u.yellow(`
|
|
15
|
+
\u{1F527} `)+s+u.gray(` (using tool: ${t})`));return}let r="",n=e.path||e.pattern||"",i=n?u.cyan(n):"";switch(t){case"write_file":{r=n&&Gs.existsSync(Vs.resolve(process.cwd(),n))?`Updating ${i}`:`Creating ${i}`;break}case"edit_file":r=`Updating ${i}`;break;case"read_file":r=`Reading ${i}`;break;case"bash":r=`Running: ${u.cyan(e.command||"?")}`;break;case"web_search":r=`Searching: ${u.cyan(e.query||"?")}`;break;case"web_fetch":r=`Fetching: ${u.cyan(e.url||"?")}`;break;case"grep":r=`Searching '${e.pattern}' in ${i||"."}`;break;case"glob":r=`Finding files: ${e.pattern}`;break;case"list_dir":r=`Listing ${i||"."}`;break;default:r=`${t}`}console.log(u.yellow(`
|
|
16
|
+
\u{1F527} `)+r)}function gt(t,e,s,r){let n=r!=null?u.gray(` - Completed in ${(r/1e3).toFixed(1)}s`):"",i=s.length;if(!e){console.log(u.red(" \u2717 Failed")+n),s.trim()&&console.log(u.gray(` ${s.slice(0,200)}`));return}if(t==="bash"){if(console.log(u.blue(" \u2713 Command executed")+n),s.trim()){let o=s.split(`
|
|
17
|
+
`).map(a=>` ${a}`).join(`
|
|
18
|
+
`);console.log(u.white(o))}}else if(t==="read_file")console.log(u.blue(` \u2713 Successfully read ${qs(i)}`)+n);else if(t==="write_file")console.log(u.blue(` \u2713 Successfully wrote ${qs(i)}`)+n);else if(t==="edit_file")console.log(u.blue(" \u2713 Successfully edited")+n);else if(t==="grep"){let o=s.trim()?s.split(`
|
|
19
|
+
`).length:0;if(console.log(u.blue(` \u2713 ${o} matches found`)+n),s.trim()){let a=s.split(`
|
|
20
|
+
`).slice(0,10).map(c=>` ${u.gray(c)}`).join(`
|
|
21
|
+
`);console.log(a),o>10&&console.log(u.gray(` ... (${o} lines)`))}}else if(t==="glob"){let o=s.trim()?s.split(`
|
|
22
|
+
`).length:0;console.log(u.blue(` \u2713 ${o} files found`)+n)}else if(t==="list_dir"){let o=s.trim()?s.split(`
|
|
23
|
+
`).length:0;console.log(u.blue(` \u2713 ${o} entries`)+n)}else console.log(u.blue(" \u2713 Done")+n)}function qs(t){return t<1024?`${t} bytes`:t<1024*1024?`${(t/1024).toFixed(1)} KB`:`${(t/(1024*1024)).toFixed(1)} MB`}function Se(t){console.log(u.red(` \u274C ${t}`))}function Ks(t,e,s){let r=e?u.green("\u2713"):u.red("\u2717");if(t==="web_search"){let n=s.split(`
|
|
24
|
+
`).find(i=>i.startsWith("["))||"";console.log(` ${r} ${u.gray(n.slice(0,120))}`)}else if(t==="web_fetch"){let n=s.split(`
|
|
25
|
+
`)[0]?.slice(0,80)||"fetched";console.log(` ${r} ${u.gray(n)}`)}else console.log(` ${r}`)}function Js(t,e){console.log(u.cyan(`
|
|
26
|
+
\u2500\u2500 ${t} \u2500\u2500`));let s=e.split(`
|
|
27
|
+
`);for(let r=0;r<s.length;r++){let n=u.gray(String(r+1).padStart(4)+" \u2502 ");console.log(n+u.green("+ "+s[r]))}console.log(u.cyan(` \u2500\u2500 end \u2500\u2500
|
|
28
|
+
`))}function Xs(t,e,s,r){console.log("");let n=t.split(`
|
|
29
|
+
`),i=e.split(`
|
|
30
|
+
`),o=0;if(r){let a=r.indexOf(t);a>=0&&(o=r.substring(0,a).split(`
|
|
31
|
+
`).length)}if(r&&o>1){let a=r.split(`
|
|
32
|
+
`),c=Math.max(0,o-1-3);for(let l=c;l<o-1;l++){let h=u.gray(String(l+1).padStart(4)+" \u2502 ");console.log(h+u.gray(" "+a[l]))}}for(let a=0;a<n.length;a++){let c=o>0?o+a:a+1,l=u.gray(String(c).padStart(4)+" \u2502 ");console.log(l+u.red("- "+n[a]))}for(let a=0;a<i.length;a++){let c=o>0?o+a:a+1,l=u.gray(String(c).padStart(4)+" \u2502 ");console.log(l+u.green("+ "+i[a]))}if(r&&o>0){let a=r.split(`
|
|
33
|
+
`),c=o-1+n.length,l=Math.min(a.length,c+3);for(let h=c;h<l;h++){let p=u.gray(String(h+1).padStart(4)+" \u2502 ");console.log(p+u.gray(" "+a[h]))}}console.log("")}var le=x(require("fs")),yt=x(require("path")),Qs=x(require("readline"));var ui=process.env.SYNAPSE_API||"https://api.synapse.cloudc.top",er=yt.join(process.env.HOME||"~",".synapse"),tr=yt.join(er,"token");function Zs(t,e=!1){let s=Qs.createInterface({input:process.stdin,output:process.stderr});return new Promise(r=>{s.question(t,n=>{s.close(),r(n.trim())})})}async function sr(){console.log(u.cyan.bold(`
|
|
34
|
+
\u26A1 Synapse Login
|
|
35
|
+
`));let t=await Zs(" Username: "),e=await Zs(" Password: ");try{let s=await fetch(`${ui}/api/login`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:t,password:e})}),r=await s.json();(!s.ok||!r.token)&&(console.log(u.red(`
|
|
36
|
+
\u274C ${r.error||"Login failed"}`)),process.exit(1)),le.mkdirSync(er,{recursive:!0}),le.writeFileSync(tr,r.token,{mode:384}),console.log(u.green(`
|
|
37
|
+
\u2713 Logged in. Token saved to ~/.synapse/token`))}catch(s){console.log(u.red(`
|
|
38
|
+
\u274C Connection failed: ${s.message}`)),process.exit(1)}}function rr(){try{le.unlinkSync(tr),console.log(u.green(" \u2713 Logged out."))}catch{console.log(u.gray(" Already logged out."))}}var hi=process.env.SYNAPSE_CLI_WS||"wss://cli.synapse.cloudc.top",di=J.join(process.env.HOME||"~",".synapse","token"),je=process.argv[2];(async()=>{je==="login"&&(await sr(),process.exit(0)),je==="logout"&&(await rr(),process.exit(0)),(je==="--help"||je==="-h")&&(console.log(`
|
|
39
|
+
${u.cyan.bold("\u26A1 Synapse CLI")} \u2014 AI coding assistant
|
|
40
|
+
|
|
41
|
+
${u.bold("Usage:")}
|
|
42
|
+
synapse Start coding session in current directory
|
|
43
|
+
synapse login Login with username/password
|
|
44
|
+
synapse logout Remove stored credentials
|
|
45
|
+
|
|
46
|
+
${u.bold("Session commands:")}
|
|
47
|
+
/compact Compress conversation history
|
|
48
|
+
/context Show context usage (tokens, messages)
|
|
49
|
+
/quit End session
|
|
50
|
+
|
|
51
|
+
${u.bold("Permission prompts:")}
|
|
52
|
+
y Approve this operation
|
|
53
|
+
n Deny this operation
|
|
54
|
+
t Trust this tool type for the session
|
|
55
|
+
`),process.exit(0));let t=null,e=null,s=null;function r(){let f=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],d=0;process.stdout.write(u.gray(`
|
|
56
|
+
${f[0]} Thinking...`)),s=setInterval(()=>{d=(d+1)%f.length,process.stdout.write(`\r ${u.gray(f[d]+" Thinking...")}`)},80)}function n(){s&&(clearInterval(s),s=null,process.stdout.write("\r"+" ".repeat(30)+"\r"))}function i(){try{return k.readFileSync(di,"utf-8").trim()}catch{return null}}function o(){for(let f of["SYNAPSE.md","synapse.md"]){let d=J.join(process.cwd(),f);if(k.existsSync(d))return k.readFileSync(d,"utf-8")}}async function a(){Ys();let f=i();f||(Se("Not logged in. Run: synapse login"),process.exit(1));let d=`${hi}/ws?token=${encodeURIComponent(f)}`,S=new Ts(d);t=S,S.on("open",()=>{_({type:"auth",token:f,project:{path:process.cwd(),synapseMd:o()}})}),S.on("message",async T=>{let y=JSON.parse(T.toString());switch(y.type){case"session_ready":w();break;case"thinking":zs(y.content);break;case"reasoning_token":break;case"reasoning_end":break;case"content_token":n(),process.stdout.write(y.content);break;case"content_end":process.stdout.write(`
|
|
57
|
+
`);break;case"turn_end":n(),m();break;case"assistant_message":n(),Hs(y.content),m();break;case"tool_request":n(),y.tool==="web_search"||y.tool==="web_fetch"?mt(y.tool,y.args):await c(y);break;case"tool_result_from_cloud":Ks(y.tool,y.success,y.output),r();break;case"session_save":n(),h(y),m();break;case"session_load":n(),p(y);break;case"session_list_request":n(),g(),m();break;case"error":n(),Se(y.message),m();break}}),S.on("close",()=>{console.log(u.gray(`
|
|
58
|
+
Connection closed.`)),process.exit(0)}),S.on("error",T=>{Se(`Connection failed: ${T.message}`),process.exit(1)})}async function c(f){let d=f.description||`${f.tool}`;mt(f.tool,f.args,d);let S=await Ds(f.tool,f.args,d);if(S==="y"||S==="t"){let X=Date.now(),G=await _t(f.tool,f.args);gt(f.tool,G.success,G.output,Date.now()-X),_({type:"tool_result",call_id:f.call_id,...G}),r();return}if(f.tool==="write_file"&&f.args.content)Js(f.args.path,f.args.content);else if(f.tool==="edit_file"&&f.args.old_str&&f.args.new_str){let X=js(f.args.path);Xs(f.args.old_str,f.args.new_str,f.args.path,X)}if(e?.close(),e=null,await Ws(f.tool,f.args,d)==="n"){_({type:"tool_result",call_id:f.call_id,success:!1,output:"User denied"}),r();return}let y=Date.now(),B=await _t(f.tool,f.args);gt(f.tool,B.success,B.output,Date.now()-y),_({type:"tool_result",call_id:f.call_id,...B}),r()}let l=J.join(process.cwd(),".synapse","sessions");function h(f){k.mkdirSync(l,{recursive:!0});let d=f.name||new Date().toISOString().replace(/[:.]/g,"-").slice(0,19),S=J.join(l,`${d}.json`);if(k.existsSync(S)&&!f.force){Se(`Session '${d}' already exists. Use /save ${d} --force to overwrite.`);return}let T={name:d,saved_at:new Date().toISOString(),messages:f.messages,meta:f.meta};k.writeFileSync(S,JSON.stringify(T,null,2),"utf-8"),console.log(u.blue(` \u2713 Session saved: ${d}`)+u.gray(` (${f.messages.length} messages, ${(Buffer.byteLength(JSON.stringify(T))/1024).toFixed(1)} KB)`))}function p(f){let d=f.name;if(!d){g(),_({type:"session_data",messages:null,error:"No session name provided. Use /sessions to list, then /load <name>."}),m();return}let S=J.join(l,`${d}.json`);if(!k.existsSync(S)){_({type:"session_data",messages:null,error:`Session '${d}' not found.`}),m();return}try{let T=JSON.parse(k.readFileSync(S,"utf-8"));_({type:"session_data",name:d,messages:T.messages,meta:T.meta||{}}),r()}catch(T){_({type:"session_data",messages:null,error:`Failed to read session: ${T}`}),m()}}function g(){if(!k.existsSync(l)){console.log(u.gray(" No saved sessions."));return}let f=k.readdirSync(l).filter(d=>d.endsWith(".json")).sort();if(f.length===0){console.log(u.gray(" No saved sessions."));return}console.log(u.white(`
|
|
59
|
+
Saved sessions (${f.length}):`));for(let d of f)try{let S=JSON.parse(k.readFileSync(J.join(l,d),"utf-8")),T=d.replace(".json",""),y=S.messages?.length||0,B=S.saved_at?new Date(S.saved_at).toLocaleString():"?";console.log(u.cyan(` ${T}`)+u.gray(` \u2014 ${y} messages, saved ${B}`))}catch{console.log(u.cyan(` ${d.replace(".json","")}`)+u.gray(" \u2014 (unreadable)"))}console.log("")}function w(){m()}function m(){e&&(e.close(),e=null),e=nr.createInterface({input:process.stdin,output:process.stdout,terminal:!0}),e.question(u.cyan(`
|
|
60
|
+
> `),f=>{e?.close(),e=null;let d=f.trim();if(!d){m();return}if((d==="/quit"||d==="/exit")&&process.exit(0),d==="/help"){console.log(u.gray(`
|
|
61
|
+
/save [name] [--force] Save current session locally
|
|
62
|
+
/load <name> Load a saved session
|
|
63
|
+
/sessions List saved sessions
|
|
64
|
+
/compact Compress conversation history
|
|
65
|
+
/context Show context usage
|
|
66
|
+
/usage Show token usage
|
|
67
|
+
/tools List available tools
|
|
68
|
+
/help Show this help
|
|
69
|
+
/quit End session
|
|
70
|
+
`)),m();return}if(d==="/sessions"){g(),m();return}if(d.startsWith("/save")){_({type:"user_message",content:d});return}if(d.startsWith("/load")){let T=d.split(/\s+/)[1]||"";if(!T){g(),console.log(u.gray(" Usage: /load <name>")),m();return}p({type:"session_load",name:T});return}_({type:"user_message",content:d}),r()})}function _(f){t?.send(JSON.stringify(f))}a().catch(f=>{console.error(f),process.exit(1)})})();
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Permission manager — CLI-side authority on all permission decisions
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
import * as readline from "readline";
|
|
5
|
+
const PROJECT_ROOT = process.cwd();
|
|
6
|
+
const trusted = new Set();
|
|
7
|
+
function isInsideProject(filePath) {
|
|
8
|
+
const resolved = path.resolve(PROJECT_ROOT, filePath);
|
|
9
|
+
return resolved.startsWith(PROJECT_ROOT + path.sep) || resolved === PROJECT_ROOT;
|
|
10
|
+
}
|
|
11
|
+
const READ_ONLY_TOOLS = new Set(["read_file", "grep", "glob", "list_dir"]);
|
|
12
|
+
/**
|
|
13
|
+
* Auto-check: returns "y" if auto-approved, "t" if trusted, or "ask" if needs interactive prompt.
|
|
14
|
+
*/
|
|
15
|
+
export async function askPermission(tool, args, description) {
|
|
16
|
+
// Read-only tools: auto-approve only within project dir
|
|
17
|
+
if (READ_ONLY_TOOLS.has(tool)) {
|
|
18
|
+
const targetPath = args.path || args.pattern || ".";
|
|
19
|
+
if (isInsideProject(targetPath))
|
|
20
|
+
return "y";
|
|
21
|
+
}
|
|
22
|
+
// Already trusted for this session (bash can never be trusted)
|
|
23
|
+
if (tool !== "bash" && trusted.has(tool))
|
|
24
|
+
return "t";
|
|
25
|
+
return "ask";
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Interactive prompt: asks user y/n/t and waits for Enter.
|
|
29
|
+
*/
|
|
30
|
+
export async function askPermissionInteractive(tool, args, description) {
|
|
31
|
+
const hint = tool === "bash"
|
|
32
|
+
? "Allow this action? [y/n]: "
|
|
33
|
+
: "Allow this action? Use 't' to trust (always allow) this tool for the session. [y/n/t]: ";
|
|
34
|
+
const answer = await promptLine("\n" + hint);
|
|
35
|
+
const key = answer.trim().toLowerCase()[0] || "n";
|
|
36
|
+
if (key === "t" && tool !== "bash") {
|
|
37
|
+
trusted.add(tool);
|
|
38
|
+
return "t";
|
|
39
|
+
}
|
|
40
|
+
return key === "y" ? "y" : "n";
|
|
41
|
+
}
|
|
42
|
+
export function readFileForDiff(filePath) {
|
|
43
|
+
try {
|
|
44
|
+
const resolved = path.resolve(PROJECT_ROOT, filePath);
|
|
45
|
+
return fs.readFileSync(resolved, "utf-8");
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function promptLine(question) {
|
|
52
|
+
return new Promise((resolve) => {
|
|
53
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: true });
|
|
54
|
+
rl.question(question, (answer) => { rl.close(); resolve(answer); });
|
|
55
|
+
});
|
|
56
|
+
}
|
package/dist/protocol.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Local tool executor — runs tools on user's machine
|
|
2
|
+
// All "intelligence" is on the cloud side; this just executes
|
|
3
|
+
import { execSync } from "child_process";
|
|
4
|
+
import * as fs from "fs";
|
|
5
|
+
import * as path from "path";
|
|
6
|
+
const PROJECT_ROOT = process.cwd();
|
|
7
|
+
export async function executeTool(tool, args) {
|
|
8
|
+
try {
|
|
9
|
+
switch (tool) {
|
|
10
|
+
case "read_file": return readFile(args);
|
|
11
|
+
case "write_file": return writeFile(args);
|
|
12
|
+
case "edit_file": return editFile(args);
|
|
13
|
+
case "grep": return grep(args);
|
|
14
|
+
case "glob": return globFiles(args);
|
|
15
|
+
case "list_dir": return listDir(args);
|
|
16
|
+
case "bash": return bash(args);
|
|
17
|
+
default: return { success: false, output: `Unknown tool: ${tool}` };
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
catch (e) {
|
|
21
|
+
return { success: false, output: e.message };
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function resolve(p) {
|
|
25
|
+
return path.resolve(PROJECT_ROOT, p);
|
|
26
|
+
}
|
|
27
|
+
function readFile(args) {
|
|
28
|
+
const content = fs.readFileSync(resolve(args.path), "utf-8");
|
|
29
|
+
return { success: true, output: content };
|
|
30
|
+
}
|
|
31
|
+
function writeFile(args) {
|
|
32
|
+
const full = resolve(args.path);
|
|
33
|
+
fs.mkdirSync(path.dirname(full), { recursive: true });
|
|
34
|
+
fs.writeFileSync(full, args.content, "utf-8");
|
|
35
|
+
return { success: true, output: `Written ${args.path} (${args.content.length} chars)` };
|
|
36
|
+
}
|
|
37
|
+
function editFile(args) {
|
|
38
|
+
const full = resolve(args.path);
|
|
39
|
+
const content = fs.readFileSync(full, "utf-8");
|
|
40
|
+
if (!content.includes(args.old_str)) {
|
|
41
|
+
return { success: false, output: `old_str not found in ${args.path}` };
|
|
42
|
+
}
|
|
43
|
+
const count = content.split(args.old_str).length - 1;
|
|
44
|
+
if (count > 1) {
|
|
45
|
+
return { success: false, output: `old_str found ${count} times in ${args.path}, must be unique` };
|
|
46
|
+
}
|
|
47
|
+
fs.writeFileSync(full, content.replace(args.old_str, args.new_str), "utf-8");
|
|
48
|
+
return { success: true, output: `Edited ${args.path}` };
|
|
49
|
+
}
|
|
50
|
+
function grep(args) {
|
|
51
|
+
const target = args.path || ".";
|
|
52
|
+
let cmd = `grep -rn --include='${args.include || "*"}' '${args.pattern}' ${target} 2>/dev/null | head -50`;
|
|
53
|
+
const output = execSync(cmd, { cwd: PROJECT_ROOT, encoding: "utf-8", timeout: 10000 });
|
|
54
|
+
return { success: true, output: output || "(no matches)" };
|
|
55
|
+
}
|
|
56
|
+
function globFiles(args) {
|
|
57
|
+
const cmd = `find . -name '${args.pattern}' -not -path '*/node_modules/*' -not -path '*/.git/*' 2>/dev/null | head -100`;
|
|
58
|
+
const output = execSync(cmd, { cwd: PROJECT_ROOT, encoding: "utf-8", timeout: 10000 });
|
|
59
|
+
return { success: true, output: output || "(no files found)" };
|
|
60
|
+
}
|
|
61
|
+
function listDir(args) {
|
|
62
|
+
const target = resolve(args.path || ".");
|
|
63
|
+
const entries = fs.readdirSync(target, { withFileTypes: true });
|
|
64
|
+
const lines = entries
|
|
65
|
+
.filter((e) => !e.name.startsWith(".") && e.name !== "node_modules")
|
|
66
|
+
.map((e) => `${e.isDirectory() ? "📁" : "📄"} ${e.name}`)
|
|
67
|
+
.join("\n");
|
|
68
|
+
return { success: true, output: lines || "(empty)" };
|
|
69
|
+
}
|
|
70
|
+
function bash(args) {
|
|
71
|
+
// Block obviously destructive commands
|
|
72
|
+
const cmd = args.command.trim();
|
|
73
|
+
const blocked = [/\brm\s+-rf\s+[\/~]/, /\bmkfs\b/, /\bdd\s+if=/, /\b>\s*\/dev\/sd/, /\bchmod\s+-R\s+777\s+\//, /\bsudo\s+rm\b/];
|
|
74
|
+
if (blocked.some(p => p.test(cmd))) {
|
|
75
|
+
return { success: false, output: `Blocked: dangerous command detected` };
|
|
76
|
+
}
|
|
77
|
+
const output = execSync(cmd, {
|
|
78
|
+
cwd: PROJECT_ROOT,
|
|
79
|
+
encoding: "utf-8",
|
|
80
|
+
timeout: args.timeout || 30000,
|
|
81
|
+
maxBuffer: 1024 * 1024,
|
|
82
|
+
});
|
|
83
|
+
return { success: true, output };
|
|
84
|
+
}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
// Terminal UI — Kiro-style output
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
import * as path from "path";
|
|
5
|
+
function stripAnsi(s) {
|
|
6
|
+
return s.replace(/\x1b\[[0-9;]*m/g, "");
|
|
7
|
+
}
|
|
8
|
+
export function printWelcome() {
|
|
9
|
+
const w = process.stdout.columns || 60;
|
|
10
|
+
const bw = Math.min(w - 4, 62);
|
|
11
|
+
const dim = chalk.gray;
|
|
12
|
+
const hi = chalk.cyan;
|
|
13
|
+
const hiBold = chalk.cyanBright.bold;
|
|
14
|
+
const white = chalk.white;
|
|
15
|
+
const border = hi("│");
|
|
16
|
+
const pad = (s, len) => s + " ".repeat(Math.max(0, len - stripAnsi(s).length));
|
|
17
|
+
const line = (content) => ` ${border} ${pad(content, bw - 4)} ${border}`;
|
|
18
|
+
console.log("");
|
|
19
|
+
console.log(hi(" ███████╗██╗ ██╗███╗ ██╗ █████╗ ██████╗ ███████╗███████╗"));
|
|
20
|
+
console.log(hi(" ██╔════╝╚██╗ ██╔╝████╗ ██║██╔══██╗██╔══██╗██╔════╝██╔════╝"));
|
|
21
|
+
console.log(hiBold(" ███████╗ ╚████╔╝ ██╔██╗ ██║███████║██████╔╝███████╗█████╗ "));
|
|
22
|
+
console.log(hi(" ╚════██║ ╚██╔╝ ██║╚██╗██║██╔══██║██╔═══╝ ╚════██║██╔══╝ "));
|
|
23
|
+
console.log(hiBold(" ███████║ ██║ ██║ ╚████║██║ ██║██║ ███████║███████╗"));
|
|
24
|
+
console.log(hi(" ╚══════╝ ╚═╝ ╚═╝ ╚═══╝╚═╝ ╚═╝╚═╝ ╚══════╝╚══════╝"));
|
|
25
|
+
console.log("");
|
|
26
|
+
console.log(` ${hi("┌" + "─".repeat(bw - 2) + "┐")}`);
|
|
27
|
+
console.log(line(dim("AI-powered coding assistant") + " ".repeat(Math.max(0, bw - 38)) + dim("v0.1.2")));
|
|
28
|
+
console.log(line(""));
|
|
29
|
+
console.log(line(dim("model ") + white("Kimi K2.5") + dim(" context ") + white("256k")));
|
|
30
|
+
console.log(line(dim("location ") + white(process.cwd())));
|
|
31
|
+
console.log(line(""));
|
|
32
|
+
console.log(line(dim("/save save session /load restore session")));
|
|
33
|
+
console.log(line(dim("/compact compress history /context show usage")));
|
|
34
|
+
console.log(line(dim("/tools list tools /quit exit")));
|
|
35
|
+
console.log(line(""));
|
|
36
|
+
console.log(line(dim("Powered by Cloudflare · Built by Bowen Liu")));
|
|
37
|
+
console.log(` ${hi("└" + "─".repeat(bw - 2) + "┘")}`);
|
|
38
|
+
console.log("");
|
|
39
|
+
}
|
|
40
|
+
export function printAssistant(content) {
|
|
41
|
+
console.log(chalk.white(content));
|
|
42
|
+
}
|
|
43
|
+
export function printThinking(content) {
|
|
44
|
+
console.log(chalk.gray(` 💭 ${content}`));
|
|
45
|
+
}
|
|
46
|
+
export function printToolCall(tool, args, description) {
|
|
47
|
+
if (description) {
|
|
48
|
+
console.log(chalk.yellow(`\n 🔧 `) + description + chalk.gray(` (using tool: ${tool})`));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
// Kiro-style: "Creating file.py", "Updating file.py", "Running: cmd"
|
|
52
|
+
let label = "";
|
|
53
|
+
const filePath = args.path || args.pattern || "";
|
|
54
|
+
const fileDisplay = filePath ? chalk.cyan(filePath) : "";
|
|
55
|
+
switch (tool) {
|
|
56
|
+
case "write_file": {
|
|
57
|
+
const exists = filePath && fs.existsSync(path.resolve(process.cwd(), filePath));
|
|
58
|
+
label = exists ? `Updating ${fileDisplay}` : `Creating ${fileDisplay}`;
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
case "edit_file":
|
|
62
|
+
label = `Updating ${fileDisplay}`;
|
|
63
|
+
break;
|
|
64
|
+
case "read_file":
|
|
65
|
+
label = `Reading ${fileDisplay}`;
|
|
66
|
+
break;
|
|
67
|
+
case "bash":
|
|
68
|
+
label = `Running: ${chalk.cyan(args.command || "?")}`;
|
|
69
|
+
break;
|
|
70
|
+
case "web_search":
|
|
71
|
+
label = `Searching: ${chalk.cyan(args.query || "?")}`;
|
|
72
|
+
break;
|
|
73
|
+
case "web_fetch":
|
|
74
|
+
label = `Fetching: ${chalk.cyan(args.url || "?")}`;
|
|
75
|
+
break;
|
|
76
|
+
case "grep":
|
|
77
|
+
label = `Searching '${args.pattern}' in ${fileDisplay || "."}`;
|
|
78
|
+
break;
|
|
79
|
+
case "glob":
|
|
80
|
+
label = `Finding files: ${args.pattern}`;
|
|
81
|
+
break;
|
|
82
|
+
case "list_dir":
|
|
83
|
+
label = `Listing ${fileDisplay || "."}`;
|
|
84
|
+
break;
|
|
85
|
+
default:
|
|
86
|
+
label = `${tool}`;
|
|
87
|
+
}
|
|
88
|
+
console.log(chalk.yellow(`\n 🔧 `) + label);
|
|
89
|
+
}
|
|
90
|
+
export function printToolResult(tool, success, output, elapsedMs) {
|
|
91
|
+
const elapsed = elapsedMs != null ? chalk.gray(` - Completed in ${(elapsedMs / 1000).toFixed(1)}s`) : "";
|
|
92
|
+
const bytes = output.length;
|
|
93
|
+
if (!success) {
|
|
94
|
+
console.log(chalk.red(` ✗ Failed`) + elapsed);
|
|
95
|
+
if (output.trim())
|
|
96
|
+
console.log(chalk.gray(` ${output.slice(0, 200)}`));
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (tool === "bash") {
|
|
100
|
+
console.log(chalk.blue(` ✓ Command executed`) + elapsed);
|
|
101
|
+
if (output.trim()) {
|
|
102
|
+
const lines = output.split("\n").map(l => ` ${l}`).join("\n");
|
|
103
|
+
console.log(chalk.white(lines));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else if (tool === "read_file") {
|
|
107
|
+
console.log(chalk.blue(` ✓ Successfully read ${formatBytes(bytes)}`) + elapsed);
|
|
108
|
+
}
|
|
109
|
+
else if (tool === "write_file") {
|
|
110
|
+
console.log(chalk.blue(` ✓ Successfully wrote ${formatBytes(bytes)}`) + elapsed);
|
|
111
|
+
}
|
|
112
|
+
else if (tool === "edit_file") {
|
|
113
|
+
console.log(chalk.blue(` ✓ Successfully edited`) + elapsed);
|
|
114
|
+
}
|
|
115
|
+
else if (tool === "grep") {
|
|
116
|
+
const matchCount = output.trim() ? output.split("\n").length : 0;
|
|
117
|
+
console.log(chalk.blue(` ✓ ${matchCount} matches found`) + elapsed);
|
|
118
|
+
if (output.trim()) {
|
|
119
|
+
const lines = output.split("\n").slice(0, 10).map(l => ` ${chalk.gray(l)}`).join("\n");
|
|
120
|
+
console.log(lines);
|
|
121
|
+
if (matchCount > 10)
|
|
122
|
+
console.log(chalk.gray(` ... (${matchCount} lines)`));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else if (tool === "glob") {
|
|
126
|
+
const fileCount = output.trim() ? output.split("\n").length : 0;
|
|
127
|
+
console.log(chalk.blue(` ✓ ${fileCount} files found`) + elapsed);
|
|
128
|
+
}
|
|
129
|
+
else if (tool === "list_dir") {
|
|
130
|
+
const entryCount = output.trim() ? output.split("\n").length : 0;
|
|
131
|
+
console.log(chalk.blue(` ✓ ${entryCount} entries`) + elapsed);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
console.log(chalk.blue(` ✓ Done`) + elapsed);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function formatBytes(bytes) {
|
|
138
|
+
if (bytes < 1024)
|
|
139
|
+
return `${bytes} bytes`;
|
|
140
|
+
if (bytes < 1024 * 1024)
|
|
141
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
142
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
143
|
+
}
|
|
144
|
+
export function printError(msg) {
|
|
145
|
+
console.log(chalk.red(` ❌ ${msg}`));
|
|
146
|
+
}
|
|
147
|
+
export function printCloudToolResult(tool, success, output) {
|
|
148
|
+
const icon = success ? chalk.green("✓") : chalk.red("✗");
|
|
149
|
+
if (tool === "web_search") {
|
|
150
|
+
// Show first result title/url
|
|
151
|
+
const firstLine = output.split("\n").find(l => l.startsWith("[")) || "";
|
|
152
|
+
console.log(` ${icon} ${chalk.gray(firstLine.slice(0, 120))}`);
|
|
153
|
+
}
|
|
154
|
+
else if (tool === "web_fetch") {
|
|
155
|
+
// Show title or brief status
|
|
156
|
+
const title = output.split("\n")[0]?.slice(0, 80) || "fetched";
|
|
157
|
+
console.log(` ${icon} ${chalk.gray(title)}`);
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
console.log(` ${icon}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// Green + with line numbers for new file
|
|
164
|
+
export function printFileContent(filePath, content) {
|
|
165
|
+
console.log(chalk.cyan(`\n ── ${filePath} ──`));
|
|
166
|
+
const lines = content.split("\n");
|
|
167
|
+
for (let i = 0; i < lines.length; i++) {
|
|
168
|
+
const num = chalk.gray(String(i + 1).padStart(4) + " │ ");
|
|
169
|
+
console.log(num + chalk.green("+ " + lines[i]));
|
|
170
|
+
}
|
|
171
|
+
console.log(chalk.cyan(" ── end ──\n"));
|
|
172
|
+
}
|
|
173
|
+
// Red - / green + with context lines and line numbers
|
|
174
|
+
export function printDiff(oldStr, newStr, filePath, fullContent) {
|
|
175
|
+
console.log("");
|
|
176
|
+
const oldLines = oldStr.split("\n");
|
|
177
|
+
const newLines = newStr.split("\n");
|
|
178
|
+
let startLine = 0;
|
|
179
|
+
if (fullContent) {
|
|
180
|
+
const idx = fullContent.indexOf(oldStr);
|
|
181
|
+
if (idx >= 0) {
|
|
182
|
+
startLine = fullContent.substring(0, idx).split("\n").length;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// 3 lines before
|
|
186
|
+
if (fullContent && startLine > 1) {
|
|
187
|
+
const allLines = fullContent.split("\n");
|
|
188
|
+
const ctxStart = Math.max(0, startLine - 1 - 3);
|
|
189
|
+
for (let i = ctxStart; i < startLine - 1; i++) {
|
|
190
|
+
const num = chalk.gray(String(i + 1).padStart(4) + " │ ");
|
|
191
|
+
console.log(num + chalk.gray(" " + allLines[i]));
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
for (let i = 0; i < oldLines.length; i++) {
|
|
195
|
+
const lineNo = startLine > 0 ? startLine + i : i + 1;
|
|
196
|
+
const num = chalk.gray(String(lineNo).padStart(4) + " │ ");
|
|
197
|
+
console.log(num + chalk.red("- " + oldLines[i]));
|
|
198
|
+
}
|
|
199
|
+
for (let i = 0; i < newLines.length; i++) {
|
|
200
|
+
const lineNo = startLine > 0 ? startLine + i : i + 1;
|
|
201
|
+
const num = chalk.gray(String(lineNo).padStart(4) + " │ ");
|
|
202
|
+
console.log(num + chalk.green("+ " + newLines[i]));
|
|
203
|
+
}
|
|
204
|
+
// 3 lines after
|
|
205
|
+
if (fullContent && startLine > 0) {
|
|
206
|
+
const allLines = fullContent.split("\n");
|
|
207
|
+
const afterStart = startLine - 1 + oldLines.length;
|
|
208
|
+
const afterEnd = Math.min(allLines.length, afterStart + 3);
|
|
209
|
+
for (let i = afterStart; i < afterEnd; i++) {
|
|
210
|
+
const num = chalk.gray(String(i + 1).padStart(4) + " │ ");
|
|
211
|
+
console.log(num + chalk.gray(" " + allLines[i]));
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
console.log("");
|
|
215
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "synara",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "AI-powered coding assistant. Cloud brain, local hands.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"synapse": "./dist/index.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "node build.mjs",
|
|
13
|
+
"prepublishOnly": "npm run build"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"ai",
|
|
17
|
+
"coding",
|
|
18
|
+
"assistant",
|
|
19
|
+
"cli",
|
|
20
|
+
"cloudflare",
|
|
21
|
+
"synapse"
|
|
22
|
+
],
|
|
23
|
+
"author": "Bowen Liu",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=18"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/node": "^20.0.0",
|
|
30
|
+
"@types/ws": "^8.5.0",
|
|
31
|
+
"esbuild": "^0.28.0",
|
|
32
|
+
"typescript": "^5.7.0"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"chalk": "^5.4.0",
|
|
36
|
+
"ws": "^8.18.0"
|
|
37
|
+
}
|
|
38
|
+
}
|