@swifty.js/swifty 0.0.2-alpha → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -119
- package/dist/agent-MICFDGUF.js +4 -0
- package/dist/anthropic-JDAGNAPR.js +4 -0
- package/dist/checker-PF3FEOF2.js +4 -0
- package/dist/chunk-4KVSJNS6.js +90 -0
- package/dist/chunk-6ARDOHBL.js +4 -0
- package/dist/chunk-7MHXMDYC.js +35 -0
- package/dist/chunk-F6HLYUZ4.js +355 -0
- package/dist/chunk-FZPTNGTU.js +4 -0
- package/dist/chunk-LPLPMGWW.js +336 -0
- package/dist/chunk-RD3MICOU.js +4 -0
- package/dist/glob_addon.node +0 -0
- package/dist/main.js +233 -233
- package/dist/{openai-BUFKIEZO.js → openai-I4WTRNNT.js} +11 -11
- package/dist/{server-4FIOX5PK.js → server-OGPKL2U2.js} +22 -21
- package/package.json +1 -1
- package/dist/anthropic-RNEEF6RX.js +0 -4
- package/dist/chunk-SLGPWJQF.js +0 -121
- package/dist/chunk-YUOKPBUW.js +0 -526
package/README.md
CHANGED
|
@@ -181,122 +181,3 @@ Inside the TUI, these commands are available:
|
|
|
181
181
|
| Ctrl+O | Toggle full vs. truncated tool output |
|
|
182
182
|
| Ctrl+T | Toggle Teams dialog overlay |
|
|
183
183
|
| Shift+Tab | Cycle permission modes |
|
|
184
|
-
|
|
185
|
-
## Development
|
|
186
|
-
|
|
187
|
-
Requires Node.js 20+ and pnpm 10+.
|
|
188
|
-
|
|
189
|
-
### Scripts
|
|
190
|
-
|
|
191
|
-
```bash
|
|
192
|
-
pnpm dev # Run in development mode via tsx
|
|
193
|
-
pnpm build # Build production bundle with tsup (runs prebuild first)
|
|
194
|
-
pnpm test # Run tests with Vitest
|
|
195
|
-
pnpm test:watch # Run tests in watch mode
|
|
196
|
-
pnpm lint # Lint source with ESLint
|
|
197
|
-
pnpm lint:fix # Lint and auto-fix
|
|
198
|
-
pnpm format # Format with oxfmt
|
|
199
|
-
pnpm typecheck # Type-check with tsc --noEmit
|
|
200
|
-
|
|
201
|
-
pnpm dev:docs # Run documentation site (Rspress)
|
|
202
|
-
pnpm build:docs # Build documentation
|
|
203
|
-
pnpm preview:docs # Preview built documentation
|
|
204
|
-
|
|
205
|
-
pnpm fe:dev # Run remote frontend in dev mode (Rsbuild)
|
|
206
|
-
pnpm fe:build # Build remote frontend
|
|
207
|
-
pnpm fe:preview # Preview built frontend
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
### Build Output
|
|
211
|
-
|
|
212
|
-
The tsup build produces a single ESM bundle at dist/main.js with a #!/usr/bin/env node shebang. The prebuild step compiles the glob-wasm module and the glob-addon native binary. These are copied into dist/ along with built-in skills:
|
|
213
|
-
|
|
214
|
-
- dist/main.js: CLI entry point
|
|
215
|
-
- dist/release.wasm: WASM glob matcher
|
|
216
|
-
- dist/glob_addon.node: Native C++ addon for glob (platform-specific)
|
|
217
|
-
- dist/builtin/: Built-in skill markdown files
|
|
218
|
-
|
|
219
|
-
### Testing
|
|
220
|
-
|
|
221
|
-
Tests live in tests/ and use Vitest with V8 coverage. The test timeout is set to 30 seconds.
|
|
222
|
-
|
|
223
|
-
```bash
|
|
224
|
-
pnpm test
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
## Dependencies and Tech Stack
|
|
228
|
-
|
|
229
|
-
### Runtime
|
|
230
|
-
|
|
231
|
-
| Package | Purpose |
|
|
232
|
-
| ------------------------- | -------------------------------------------- |
|
|
233
|
-
| @anthropic-ai/sdk | Anthropic Claude API client |
|
|
234
|
-
| openai | OpenAI API client |
|
|
235
|
-
| @modelcontextprotocol/sdk | MCP protocol support |
|
|
236
|
-
| ink + react | Terminal UI framework |
|
|
237
|
-
| zod | Schema validation (config, session, hooks) |
|
|
238
|
-
| js-yaml | YAML config parsing |
|
|
239
|
-
| koa + ws | Remote mode HTTP server and WebSocket bridge |
|
|
240
|
-
| pino | Structured logging |
|
|
241
|
-
| marked + dompurify | Markdown rendering and sanitization |
|
|
242
|
-
| fuse.js | Fuzzy search for tool/command lookup |
|
|
243
|
-
| chalk | Terminal color output |
|
|
244
|
-
|
|
245
|
-
### Build Toolchain
|
|
246
|
-
|
|
247
|
-
| Tool | Purpose |
|
|
248
|
-
| -------------------------- | ------------------------------------- |
|
|
249
|
-
| tsup | Bundle to single ESM file for Node.js |
|
|
250
|
-
| tsx | Development runner |
|
|
251
|
-
| typescript | Type checking |
|
|
252
|
-
| vitest | Testing |
|
|
253
|
-
| eslint + typescript-eslint | Linting |
|
|
254
|
-
| oxfmt | Code formatting |
|
|
255
|
-
| rspress | Documentation site |
|
|
256
|
-
| rsbuild | Remote frontend bundler |
|
|
257
|
-
| biome | Remote frontend linter/formatter |
|
|
258
|
-
| tailwindcss | Remote frontend styling |
|
|
259
|
-
|
|
260
|
-
## Project Structure
|
|
261
|
-
|
|
262
|
-
```
|
|
263
|
-
apps/swifty/
|
|
264
|
-
src/
|
|
265
|
-
main.tsx CLI entry point (TUI, remote, print, teammate routing)
|
|
266
|
-
agent/ Agent loop (ReAct pattern, streaming executor)
|
|
267
|
-
compact/ Context window compaction
|
|
268
|
-
commands/ Slash command registry and loader
|
|
269
|
-
config/ YAML config loading and validation
|
|
270
|
-
conversation/ Message management and conversation state
|
|
271
|
-
file-history/ File snapshot checkpoints for rewind
|
|
272
|
-
hooks/ Event-driven hook engine
|
|
273
|
-
llm/ LLM clients (Anthropic, OpenAI, OpenAI-compatible)
|
|
274
|
-
logger/ Structured logging (pino)
|
|
275
|
-
mcp/ MCP client, manager, and tool wrapper
|
|
276
|
-
memory/ Long-term memory extraction, consolidation, recall
|
|
277
|
-
permissions/ Permission checker with dangerous pattern detection
|
|
278
|
-
plan-file/ Plan mode file management
|
|
279
|
-
print-mode/ Non-interactive print mode (-p flag)
|
|
280
|
-
prompt/ System prompt builder and environment detection
|
|
281
|
-
remote/
|
|
282
|
-
server.ts Koa + WebSocket remote server
|
|
283
|
-
fe/ React frontend for remote mode (Rsbuild)
|
|
284
|
-
sandbox/ Sandbox implementations (bwrap, seatbelt)
|
|
285
|
-
session/ Session persistence and resume
|
|
286
|
-
skills/ Skill catalog, executor, load/install tools
|
|
287
|
-
subagent/ Subagent spawning and task management
|
|
288
|
-
teams/ Team coordination, file mailboxes, progress tracking
|
|
289
|
-
teammate.ts Teammate process entry point
|
|
290
|
-
todo/ Task list management tools
|
|
291
|
-
tool-result/ Tool output budgeting and reconstruction
|
|
292
|
-
tools/ Built-in tools (ReadFile, Bash, Glob, Grep, etc.)
|
|
293
|
-
tui/ Terminal UI components (Ink/React)
|
|
294
|
-
utils/ Shared utilities
|
|
295
|
-
worktree/ Git worktree management
|
|
296
|
-
tests/ Vitest test suite (25 test files)
|
|
297
|
-
docs/ Rspress documentation (15 chapters)
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
## License
|
|
301
|
-
|
|
302
|
-
ISC
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire as __swiftyCreateRequire } from "node:module";
|
|
3
|
+
const require = __swiftyCreateRequire(import.meta.url);
|
|
4
|
+
import{q as a}from"./chunk-F6HLYUZ4.js";import"./chunk-FZPTNGTU.js";import"./chunk-4KVSJNS6.js";import"./chunk-MQ5XOYLD.js";import"./chunk-X3UA5OZL.js";export{a as Agent};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire as __swiftyCreateRequire } from "node:module";
|
|
3
|
+
const require = __swiftyCreateRequire(import.meta.url);
|
|
4
|
+
import{g as P}from"./chunk-H7VXSMJR.js";import{f as B,h as W,i as R}from"./chunk-RD3MICOU.js";import{b as O,c as j,d as M,e as U,f as $,g as K}from"./chunk-FZPTNGTU.js";import"./chunk-7MHXMDYC.js";import{H as w,J as v,K as S,L as I,M as k,N,e as L,l as E}from"./chunk-4KVSJNS6.js";import"./chunk-MQ5XOYLD.js";import"./chunk-X3UA5OZL.js";var x=L({module:"llm"});var H=3e3,Y=w.object({max_input_tokens:w.coerce.number()});async function ot(n){if(n.protocol!=="anthropic")return 0;let t=R(n),o=`${n.base_url.replace(/\/+$/,"")}/v1/models/${encodeURIComponent(n.model)}`,r=new AbortController,a=setTimeout(()=>{r.abort()},H);try{let l=await fetch(o,{method:"GET",headers:{"anthropic-version":"2023-06-01",...t?{"x-api-key":t}:{}},signal:r.signal});if(!l.ok)return 0;let g=await l.json(),{success:h,error:f,data:d}=await E(Y,g);if(!h)return console.error(f.message),0;let y=d.max_input_tokens;return Math.max(y,0)}catch(l){return console.error(l),0}finally{clearTimeout(a)}}function q(){return!0}function D(n){let t=[];for(let e of n)if(e.role==="assistant"){let o=[];if(e.thinkingBlocks)for(let r of e.thinkingBlocks)o.push({type:"thinking",thinking:r.thinking,signature:r.signature});if(e.content&&o.push({type:"text",text:e.content}),e.toolUses)for(let r of e.toolUses)o.push({type:"tool_use",id:r.toolUseId,name:r.toolName,input:r.arguments});o.length===0&&o.push({type:"text",text:""}),t.push({role:"assistant",content:o})}else if(e.toolResults&&e.toolResults.length>0){let o=[];for(let r of e.toolResults)o.push({type:"tool_result",tool_use_id:r.toolUseId,is_error:r.isError,content:r.content});t.push({role:"user",content:o})}else{if(t.length===0){t.push({role:"user",content:[{type:"text",text:e.content}]});continue}let o=!1,r=t[t.length-1],a=r.content;r.role==="user"&&(typeof a=="string"||Array.isArray(a)&&a.length>0&&a[0].type==="text")&&(o=!0),o?(typeof a=="string"&&(a=r.content=a.trim().length>0?[{type:"text",text:a}]:[]),a.push({type:"text",text:e.content})):t.push({role:"user",content:[{type:"text",text:e.content}]})}return t}var G=class{client;model;thinking;systemPrompt;maxOutputTokens;contextWindow;constructor(t,e){let o=R(t);if(!o)throw new M("Anthropic API key not found, set ANTHROPIC_API_KEY in .swifty/config.y(a)ml, or via ANTHROPIC_API_KEY env variable.");this.client=new P({apiKey:o,baseURL:t.base_url}),this.model=t.model,this.thinking=t.thinking??!0,this.systemPrompt=e,this.maxOutputTokens=W(t),this.contextWindow=B(t)}setSystemPrompt(t){this.systemPrompt=t}setMaxOutputTokens(t){this.maxOutputTokens=t}async*stream(t,e,o){let r=D(O(t.getMessages())),a=e.map(c=>{let p=c.input_schema;return{name:c.name,description:c.description,input_schema:{type:"object",properties:p.properties,required:p.required??[]}}});a.length>0&&(a[a.length-1].cache_control={type:"ephemeral"}),F(r);let l={model:this.model,max_tokens:this.maxOutputTokens,stream:!0,system:[{type:"text",text:this.systemPrompt,cache_control:{type:"ephemeral"}}],messages:r,...a.length>0?{tools:a}:{}};this.thinking?q()&&(l.thinking={type:"enabled",budget_tokens:this.maxOutputTokens-1}):l.thinking={type:"enabled",budget_tokens:this.maxOutputTokens-1};let g=0,h=0,f=0,d=0,y="end_turn",b="",T="",A=!1,C=0;try{let c=this.client.messages.stream(l,{...o?{signal:o}:{}}),p="",_="",u="";for await(let i of c)switch(i.type){case"content_block_start":{let s=i.content_block;s.type==="thinking"?(A=!0,b="",T=""):s.type==="tool_use"&&(_=s.id,p=s.name,u="",yield{type:"tool_call_start",toolName:p,toolId:_});break}case"content_block_delta":{let s=i.delta;s.type==="thinking_delta"?(b+=s.thinking,yield{type:"thinking_delta",text:s.thinking}):s.type==="signature_delta"?(x.debug({signature:s.signature},"thinking signature received"),T=s.signature):s.type==="text_delta"?yield{type:"text_delta",text:s.text}:s.type==="input_json_delta"&&(u+=s.partial_json,yield{type:"tool_call_delta",text:s.partial_json});break}case"content_block_stop":{if(A&&(yield{type:"thinking_complete",thinking:b,signature:T},A=!1),p){let s={};if(u)try{let m=JSON.parse(u);s=S(m)?I(m):{[v]:u}}catch(m){x.error({err:m},"llm operation failed"),s={[v]:u}}yield{type:"tool_call_complete",toolId:_,toolName:p,arguments:s},p="",_="",u=""}break}case"message_delta":{i.delta.stop_reason&&(y=i.delta.stop_reason),i.usage.output_tokens&&(h=i.usage.output_tokens,i.usage.input_tokens&&(g=i.usage.input_tokens),i.usage.cache_read_input_tokens&&(f=i.usage.cache_read_input_tokens),i.usage.cache_creation_input_tokens&&(d=i.usage.cache_creation_input_tokens));break}case"message_start":{C=performance.now(),g=i.message.usage.input_tokens,h=i.message.usage.output_tokens,f=i.message.usage.cache_read_input_tokens??0,d=i.message.usage.cache_creation_input_tokens??0;break}case"message_stop":{let m=performance.now()-C;x.debug({elapsedMs:m},"message stream complete");break}}yield{type:"stream_end",stopReason:y,usage:{inputTokens:g,outputTokens:h,cacheReadInputTokens:f,cacheCreationInputTokens:d}}}catch(c){throw x.error({err:c},"llm operation failed"),J(c)}}};function F(n){for(let t=n.length-1;t>=0;t--){if(n[t].role!=="user")continue;let e=n[t].content;if(typeof e=="string"&&e.length===0||Array.isArray(e)&&e.length===0)return;typeof e=="string"&&(e=n[t].content=[{type:"text",text:e}]);let o=e[e.length-1];Reflect.set(o,"cache_control",{type:"ephemeral"})}}function J(n){if(n instanceof P.APIError){if(n.status===413||/prompts?\s+too\s+long/i.test(n.message))return new K(`Prompt too long: ${n.message}`);if(n.status===401)return new M(`Invalid API key: ${n.message}`);if(n.status===429){let t=I(n.headers)["retry-after"],e="Rate Limited";if(t){let o=Number.parseInt(k(t));Number.isNaN(o)&&(e+=", please wait."),e+=`, retry after ${k(o)}s.`}else e+=", please wait.";return new U(e,t?k(t):void 0)}return new j(`Anthropic API error (${k(n.status)}): ${n.message}`)}return new $(`Network error: ${N(n)}`)}export{G as AnthropicClient,D as buildAnthropicMessages,ot as fetchModelContextWindow};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire as __swiftyCreateRequire } from "node:module";
|
|
3
|
+
const require = __swiftyCreateRequire(import.meta.url);
|
|
4
|
+
import{a,b,c,d}from"./chunk-6ARDOHBL.js";import"./chunk-7MHXMDYC.js";import"./chunk-4KVSJNS6.js";import"./chunk-MQ5XOYLD.js";import"./chunk-X3UA5OZL.js";export{b as PathSandbox,d as PermissionChecker,c as RuleEngine,a as extractContent};
|