@swifty.js/swifty 0.0.26 → 0.0.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +14 -6
  2. package/dist/agent-3NON2EXE.js +4 -0
  3. package/dist/anthropic-BJ5GN2VT.js +4 -0
  4. package/dist/checker-N5TIJEN5.js +4 -0
  5. package/dist/{chunk-H7VXSMJR.js → chunk-C3WGLVVZ.js} +10 -10
  6. package/dist/chunk-D34FUVGU.js +4 -0
  7. package/dist/chunk-FPQ2LBL4.js +10 -0
  8. package/dist/chunk-JGSIQXEN.js +4 -0
  9. package/dist/{chunk-5KXBVL2A.js → chunk-K5ZK27BX.js} +1 -1
  10. package/dist/chunk-LZBOXJX2.js +301 -0
  11. package/dist/chunk-OTVZGPHD.js +121 -0
  12. package/dist/chunk-QCKJLO6X.js +4 -0
  13. package/dist/chunk-R63ASIIW.js +407 -0
  14. package/dist/chunk-WX3B64R4.js +4 -0
  15. package/dist/chunk-Y6SQB5FG.js +4 -0
  16. package/dist/{devtools-3OAJUZGE.js → devtools-OJ75EP3T.js} +1 -1
  17. package/dist/glob.wasm +0 -0
  18. package/dist/lib/agent-XYO2MXXK.js +11 -0
  19. package/dist/lib/{anthropic-RYPJDHQM.js → anthropic-TGJGAP5R.js} +4 -5
  20. package/dist/lib/{checker-6BW4222R.js → checker-AXHPKVBY.js} +2 -2
  21. package/dist/lib/{chunk-HK2Z6WP4.js → chunk-2IVEVG5N.js} +5 -1
  22. package/dist/lib/{chunk-2AUSNVIB.js → chunk-ALJAVRRX.js} +28 -34
  23. package/dist/lib/{chunk-GNI7YX6F.js → chunk-DJ6AILPN.js} +70 -24
  24. package/dist/lib/chunk-DV6RV5WU.js +2345 -0
  25. package/dist/lib/{chunk-3LU4APFB.js → chunk-FBSPZQGC.js} +126 -73
  26. package/dist/lib/chunk-IB5IQK2S.js +136 -0
  27. package/dist/lib/{chunk-PZ42NAFA.js → chunk-KG4MJGKQ.js} +19 -21
  28. package/dist/lib/{chunk-XFSN4LMA.js → chunk-P4F46PEF.js} +43 -14
  29. package/dist/lib/glob.wasm +0 -0
  30. package/dist/lib/index.d.ts +145 -123
  31. package/dist/lib/index.js +2186 -1726
  32. package/dist/lib/{openai-VX5VBXZ4.js → openai-5UCIIDPO.js} +2 -3
  33. package/dist/lib/{tool-filter-VF7TZRE5.js → tool-filter-R6HDDJHE.js} +1 -1
  34. package/dist/main.js +226 -196
  35. package/dist/{node-OES65R33.js → node-4LTSRXL2.js} +1 -1
  36. package/dist/{openai-6MXNADYN.js → openai-YLS2LUAI.js} +14 -14
  37. package/dist/server-GX72MJQF.js +244 -0
  38. package/dist/{tool-filter-NO7I3HFD.js → tool-filter-VBP6WOGO.js} +1 -1
  39. package/package.json +36 -32
  40. package/dist/agent-GAABBZRW.js +0 -4
  41. package/dist/anthropic-7QRAPLOY.js +0 -4
  42. package/dist/checker-3RWAYF2U.js +0 -4
  43. package/dist/chunk-7MHXMDYC.js +0 -35
  44. package/dist/chunk-A2VR3BC4.js +0 -4
  45. package/dist/chunk-FZPTNGTU.js +0 -4
  46. package/dist/chunk-MWZIARZE.js +0 -130
  47. package/dist/chunk-NR62AA5K.js +0 -4
  48. package/dist/chunk-QN27QEFS.js +0 -4
  49. package/dist/chunk-RMMK4PO5.js +0 -389
  50. package/dist/chunk-SIWLMWHH.js +0 -93
  51. package/dist/chunk-VC6OXOMP.js +0 -238
  52. package/dist/chunk-W37Y53LX.js +0 -4
  53. package/dist/chunk-XBHVVB5A.js +0 -10
  54. package/dist/lib/agent-U7MIUCKT.js +0 -9
  55. package/dist/lib/chunk-2QILP24G.js +0 -1120
  56. package/dist/lib/chunk-OO2CLOEE.js +0 -88
  57. package/dist/lib/chunk-RKJYTYQM.js +0 -1285
  58. package/dist/server-P2VE5HLJ.js +0 -244
@@ -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{D as n,I as S,b as g,c as _,d as b}from"./chunk-OTVZGPHD.js";import{existsSync as D,readFileSync as $}from"fs";import{homedir as L}from"os";import{join as h}from"path";function m(e){return!!e._zod}function l(e,o){return m(e)?g(e,o):e.safeParse(o)}async function pe(e,o){return m(e)?await _(e,o):await e.safeParseAsync(o)}function ue(e){if(!e)return;let o;if(m(e)?o=e._zod?.def?.shape:o=e.shape,!!o){if(typeof o=="function")try{return o()}catch{return}return o}}function de(e){if(m(e)){let i=e._zod?.def;if(i){if(i.value!==void 0)return i.value;if(Array.isArray(i.values)&&i.values.length>0)return i.values[0]}}let t=e._def;if(t){if(t.value!==void 0)return t.value;if(Array.isArray(t.values)&&t.values.length>0)return t.values[0]}let r=e.value;if(r!==void 0)return r}var w=S({module:"config"}),j={anthropic:"ANTHROPIC_API_KEY",openai:"OPENAI_API_KEY","openai-compat":"OPENAI_API_KEY"};function V(e){return y.has(e)}var y=new Set(Object.keys(j)),p=class extends Error{constructor(o){super(o),this.name="ConfigError"}},T=n.object({name:n.string(),protocol:n.enum(["anthropic","openai","openai-compat"]),base_url:n.string(),model:n.string(),api_key:n.string().optional(),thinking:n.boolean().optional(),context_window:n.coerce.number().optional(),max_output_tokens:n.coerce.number().optional()}),K=!0,k=1e6,P=128e3;function A(e){return{...e,thinking:e.thinking??K,context_window:Y(e),max_output_tokens:F(e)}}function Y(e){return Number.isSafeInteger(e.context_window)&&(e.context_window??0)>0?e.context_window??k:k}function F(e){return Number.isSafeInteger(e.max_output_tokens)&&(e.max_output_tokens??0)>0?e.max_output_tokens??P:P}function Se(e){if(e.api_key)return e.api_key;let o=V(e.protocol)?j[e.protocol]:"";return o?process.env[o]??"":""}var O=n.object({name:n.string(),command:n.string().optional(),args:n.array(n.string()).optional(),url:n.string().optional(),transport:n.string().optional(),headers:n.record(n.string(),n.string()).optional(),env:n.record(n.string(),n.string()).optional()}),M=n.object({id:n.string().optional(),event:n.string(),condition:n.string().optional(),action:n.object({type:n.string(),command:n.string().optional(),url:n.string().optional(),method:n.string().optional(),prompt:n.string().optional()}),reject:n.boolean().optional(),once:n.boolean().optional(),async:n.boolean().optional(),on_error:n.string().optional()}),z=n.object({enabled:n.boolean().optional(),auto_allow:n.boolean().optional(),network_enabled:n.boolean().optional()}),H=n.looseObject({providers:n.array(T),permission_mode:n.string().optional(),mcp_servers:n.array(O).default([]),hooks:n.array(M).default([]),sandbox:z.optional(),enable_coordinator_mode:n.boolean().optional(),enable_fork:n.boolean().optional()});function we(e){return e.enable_fork!==!1}function B(e){return typeof e=="object"&&e!==null}function C(e){let o=$(e,"utf-8"),t=b.load(o);if(!B(t))return w.error({path:e},"invalid yaml"),{providers:[],mcp_servers:[],hooks:[]};let r=l(H,t);if(r.success){let f=r.data;return{...f,providers:f.providers.map(A)}}w.error({error:r.error},"config error");let a=[],i,c=[],s=[],d,v=!1,x=!0;if("providers"in t){let f=l(n.array(T),t.providers);f.success&&(a=f.data.map(A))}if("permission_mode"in t&&typeof t.permission_mode=="string"&&(i=t.permission_mode),"mcp_servers"in t){let f=l(n.array(O),t.mcp_servers);f.success&&(c=f.data)}if("hooks"in t){let f=l(n.array(M),t.hooks);f.success&&(s=f.data)}if("sandbox"in t){let f=l(z,t.sandbox);f.success&&(d=f.data)}return"enable_coordinator_mode"in t&&(v=!!t.enable_coordinator_mode),"enable_fork"in t&&(x=!!t.enable_fork),{providers:a,permission_mode:i,mcp_servers:c,hooks:s,sandbox:d,enable_coordinator_mode:v,enable_fork:x}}function W(e,o){if(o.providers.length>0&&(e.providers=o.providers),o.permission_mode&&(e.permission_mode=o.permission_mode),o.mcp_servers.length>0){let t=new Map;for(let r=0;r<e.mcp_servers.length;r++){let a=e.mcp_servers[r];t.set(a.name,r)}for(let r of o.mcp_servers){let a=t.get(r.name);a!==void 0?e.mcp_servers[a]=r:(e.mcp_servers.push(r),t.set(r.name,e.mcp_servers.length-1))}}return e.hooks=[...e.hooks,...o.hooks],o.sandbox&&(e.sandbox={...e.sandbox,...o.sandbox}),o.enable_coordinator_mode&&(e.enable_coordinator_mode=!0),o.enable_fork!==void 0&&(e.enable_fork=o.enable_fork),e}function E(e){if(e.providers.length===0)throw new p("At least one provider MUST be configured.");let o=["name","protocol","base_url","model"];for(let t=0;t<e.providers.length;t++){let r=e.providers[t],a={name:r.name,protocol:r.protocol,base_url:r.base_url,model:r.model},i=o.filter(c=>!a[c].trim());if(i.length>0)throw new p(`Provider #${String(t+1)}: missing fields: ${i.join(", ")}`);if(!y.has(r.protocol))throw new p(`Provider #${String(t+1)}: invalid protocol '${r.protocol}', MUST be one of: ${Array.from(y).join(", ")}`)}}function ke(e,o={}){if(e){let c=C(e);return(!o.allowEmptyProviders||c.providers.length>0)&&E(c),c}let t=process.cwd(),r=L(),a=[h(r,".swifty","config.yaml"),h(t,".swifty","config.yaml"),h(t,".swifty","config.local.yaml")],i=null;for(let c of a){if(!D(c))continue;let s=C(c);i?i=W(i,s):i=s}if(!i){if(o.allowEmptyProviders)return{providers:[],mcp_servers:[],hooks:[]};throw new p("No config file found, expected .swifty/config.y(a)ml under project or $HOME/.swifty/config.y(a)ml.")}return(!o.allowEmptyProviders||i.providers.length>0)&&E(i),i}var u=class extends Error{constructor(o){super(o),this.name="LLMError"}},I=class extends u{constructor(o){super(o),this.name="AuthenticationError"}},R=class extends u{retryAfter;constructor(o,t){super(o),this.name="RateLimitError",this.retryAfter=t}},N=class extends u{constructor(o){super(o),this.name="NetworkError"}},U=class extends u{constructor(o){super(o),this.name="ContextTooLongError"}};var Z="Tool execution was interrupted. The tool may or may not have completed; verify before relying on its effects.",Ce="The user rejected this tool use. Nothing was changed (for file edits, the new content was NOT written).";function Ee(e){let o=[];for(let t=0;t<e.length;t++){let r=e[t];if(r.role==="assistant"&&r.toolUses?.length){o.push(r);let a=new Set(r.toolUses.map(s=>s.toolUseId)),i=[],c=[];for(;t+1<e.length;){let s=e[t+1];if(s.role!=="user"||!s.toolResults?.length||s.toolUses?.length)break;t++,c.push(s);for(let d of s.toolResults)a.delete(d.toolUseId)&&i.push(d)}for(let s of a)i.push({toolUseId:s,content:Z,isError:!0});o.push({...c[0]??{role:"user",content:""},toolResults:i});for(let s of c.slice(1))(s.content.length>0||s.thinkingBlocks?.length)&&o.push({...s,toolResults:[]});continue}if((r.toolResults?.length??0)>0){if(r.content.length===0&&!r.toolUses?.length&&!r.thinkingBlocks?.length)continue;o.push({...r,toolResults:[]})}else o.push(r)}return o}export{l as a,pe as b,ue as c,de as d,T as e,K as f,k as g,P as h,Y as i,F as j,Se as k,we as l,ke as m,u as n,I as o,R as p,N as q,U as r,Ce as s,Ee as t};
@@ -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 as T,b as f}from"./chunk-E55KH72M.js";var c=class{tools=new Map;discovered=new Set;mcpLoadingMode="eager";exposeToolSearch=!1;exposeMcpCall=!1;register(e){this.tools.set(e.name,e)}get(e){return this.tools.get(e)}listTools(){return[...this.tools.values()]}getAllSchemas(e="anthropic"){let o=e==="openai"||e==="openai-compat",t=this.mcpLoadingMode==="native"&&!o,n=[];for(let s of this.tools.values()){if(s.name===T&&!this.exposeToolSearch||s.name===f&&!this.exposeMcpCall)continue;let a=!!s.deferred&&!this.discovered.has(s.name);if(a&&!t)continue;let r=s.schema();o?n.push({strict:!1,type:"function",name:r.name,description:r.description,parameters:r.input_schema,function:{name:r.name,description:r.description,parameters:r.input_schema}}):n.push(a?{...r,type:"custom",defer_loading:!0}:{...r,type:"custom"})}return n}getDeferredToolNames(){let e=[];for(let o of this.tools.values())o.deferred&&!this.discovered.has(o.name)&&e.push(o.name);return e.sort()}getDeferredTools(){return[...this.tools.values()].filter(e=>e.deferred&&!this.discovered.has(e.name))}searchDeferred(e,o=5){let t=e.toLowerCase(),n=[];for(let s of this.tools.values())if(!(!s.deferred||this.discovered.has(s.name))&&(s.name.toLowerCase().includes(t)||s.description.toLowerCase().includes(t))&&(n.push(s),n.length>=o))break;return n}findDeferredByNames(e){let o=new Map;for(let[t,n]of this.tools)o.set(t.toLowerCase(),n);return e.map(t=>o.get(t.toLowerCase())).filter(t=>t?.deferred??!1)}markDiscovered(e){this.discovered.add(e)}isDiscovered(e){return this.discovered.has(e)}};var h=new Set(["ExitPlanMode","Agent","AskUserQuestion","TaskStop"]),M=new Set(["TeamCreate","TeamDelete"]),m=new Set(["ExitPlanMode","Agent","AskUserQuestion","TaskStop"]),u=new Set(["ReadFile","Grep","Glob","Bash","PowerShell","EditFile","WriteFile","LoadSkill","SyntheticOutput","ToolSearch","EnterWorktree","ExitWorktree","McpCall"]);function g(i){return i.startsWith("mcp__")}function w(i,e,o,t,n=!1){let s=new Set(o??[]),a=new Set(e??[]),r=a.size>0&&!(a.size===1&&a.has("*")),p=new c;p.mcpLoadingMode=i.mcpLoadingMode;for(let d of i.listTools()){let l=d.name;if(g(l)){!s.has(l)&&(!r||a.has(l))&&p.register(d);continue}h.has(l)||n&&m.has(l)||t&&!u.has(l)||s.has(l)||r&&!a.has(l)||p.register(d)}return p}var A="agent:builtin:fork";function k(i){let e=new c;e.mcpLoadingMode=i.mcpLoadingMode;for(let o of i.listTools())if(o.name==="Agent"&&"querySource"in o){let t=Object.create(Object.getPrototypeOf(o),Object.getOwnPropertyDescriptors(o));t.querySource=A,e.register(t)}else e.register(o);return e}export{c as a,h as b,M as c,m as d,u as e,w as f,A as g,k as h};
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire as __swiftyCreateRequire } from "node:module";
3
3
  const require = __swiftyCreateRequire(import.meta.url);
4
- import{c as t}from"./chunk-XBHVVB5A.js";import"./chunk-X3UA5OZL.js";var n=globalThis;n.WebSocket||=t;n.window||=globalThis;n.self||=globalThis;n.window.__REACT_DEVTOOLS_COMPONENT_FILTERS__=[{type:1,value:7,isEnabled:!0},{type:2,value:"InternalApp",isEnabled:!0,isValid:!0},{type:2,value:"InternalAppContext",isEnabled:!0,isValid:!0},{type:2,value:"InternalStdoutContext",isEnabled:!0,isValid:!0},{type:2,value:"InternalStderrContext",isEnabled:!0,isValid:!0},{type:2,value:"InternalStdinContext",isEnabled:!0,isValid:!0},{type:2,value:"InternalFocusContext",isEnabled:!0,isValid:!0}];import a from"react-devtools-core";var l=async()=>new Promise(o=>{let e=new t("ws://localhost:8097"),i=setTimeout(()=>{e.terminate(),o(!1)},2e3);i.unref(),e.on("open",()=>{clearTimeout(i),e.terminate(),o(!0)}),e.on("error",()=>{clearTimeout(i),e.terminate(),o(!1)})});await l()?(a.initialize(),a.connectToDevTools()):console.warn(`DEV is set to true, but the React DevTools server is not running. Start it with:
4
+ import{c as t}from"./chunk-FPQ2LBL4.js";import"./chunk-X3UA5OZL.js";var n=globalThis;n.WebSocket||=t;n.window||=globalThis;n.self||=globalThis;n.window.__REACT_DEVTOOLS_COMPONENT_FILTERS__=[{type:1,value:7,isEnabled:!0},{type:2,value:"InternalApp",isEnabled:!0,isValid:!0},{type:2,value:"InternalAppContext",isEnabled:!0,isValid:!0},{type:2,value:"InternalStdoutContext",isEnabled:!0,isValid:!0},{type:2,value:"InternalStderrContext",isEnabled:!0,isValid:!0},{type:2,value:"InternalStdinContext",isEnabled:!0,isValid:!0},{type:2,value:"InternalFocusContext",isEnabled:!0,isValid:!0}];import a from"react-devtools-core";var l=async()=>new Promise(o=>{let e=new t("ws://localhost:8097"),i=setTimeout(()=>{e.terminate(),o(!1)},2e3);i.unref(),e.on("open",()=>{clearTimeout(i),e.terminate(),o(!0)}),e.on("error",()=>{clearTimeout(i),e.terminate(),o(!1)})});await l()?(a.initialize(),a.connectToDevTools()):console.warn(`DEV is set to true, but the React DevTools server is not running. Start it with:
5
5
 
6
6
  $ npx react-devtools
7
7
  `);
package/dist/glob.wasm CHANGED
Binary file
@@ -0,0 +1,11 @@
1
+ import {
2
+ Agent
3
+ } from "./chunk-DV6RV5WU.js";
4
+ import "./chunk-IB5IQK2S.js";
5
+ import "./chunk-FBSPZQGC.js";
6
+ import "./chunk-KG4MJGKQ.js";
7
+ import "./chunk-EY7HE52Q.js";
8
+ import "./chunk-GHF2PSEW.js";
9
+ export {
10
+ Agent
11
+ };
@@ -5,11 +5,10 @@ import {
5
5
  markLastUserTailForCache,
6
6
  markToolsForCache,
7
7
  needsToolSearchBeta
8
- } from "./chunk-2AUSNVIB.js";
9
- import "./chunk-2QILP24G.js";
10
- import "./chunk-3LU4APFB.js";
11
- import "./chunk-OO2CLOEE.js";
12
- import "./chunk-PZ42NAFA.js";
8
+ } from "./chunk-ALJAVRRX.js";
9
+ import "./chunk-IB5IQK2S.js";
10
+ import "./chunk-FBSPZQGC.js";
11
+ import "./chunk-KG4MJGKQ.js";
13
12
  import "./chunk-EY7HE52Q.js";
14
13
  import "./chunk-GHF2PSEW.js";
15
14
  export {
@@ -5,8 +5,8 @@ import {
5
5
  evaluateRules,
6
6
  extractContent,
7
7
  isSafeCommand
8
- } from "./chunk-GNI7YX6F.js";
9
- import "./chunk-PZ42NAFA.js";
8
+ } from "./chunk-DJ6AILPN.js";
9
+ import "./chunk-KG4MJGKQ.js";
10
10
  import "./chunk-EY7HE52Q.js";
11
11
  import "./chunk-GHF2PSEW.js";
12
12
  export {
@@ -167,10 +167,13 @@ function filterToolsForAgent(registry, allowedTools, disallowedTools, isAsync, i
167
167
  const allowed = new Set(allowedTools ?? []);
168
168
  const hasWhitelist = allowed.size > 0 && !(allowed.size === 1 && allowed.has("*"));
169
169
  const filtered = new ToolRegistry();
170
+ filtered.mcpLoadingMode = registry.mcpLoadingMode;
170
171
  for (const tool of registry.listTools()) {
171
172
  const name = tool.name;
172
173
  if (isMCPTool(name)) {
173
- filtered.register(tool);
174
+ if (!disallowed.has(name) && (!hasWhitelist || allowed.has(name))) {
175
+ filtered.register(tool);
176
+ }
174
177
  continue;
175
178
  }
176
179
  if (SUBAGENT_DISALLOWED_TOOLS.has(name)) {
@@ -195,6 +198,7 @@ function filterToolsForAgent(registry, allowedTools, disallowedTools, isAsync, i
195
198
  var FORK_QUERY_SOURCE = "agent:builtin:fork";
196
199
  function cloneRegistryForFork(registry) {
197
200
  const forked = new ToolRegistry();
201
+ forked.mcpLoadingMode = registry.mcpLoadingMode;
198
202
  for (const tool of registry.listTools()) {
199
203
  if (tool.name === "Agent" && "querySource" in tool) {
200
204
  const clone = Object.create(
@@ -1,30 +1,29 @@
1
1
  import {
2
- computeCompactThreshold
3
- } from "./chunk-2QILP24G.js";
4
- import {
5
- getContextWindow,
6
- getMaxOutputTokens,
7
- resolveAPIKey
8
- } from "./chunk-3LU4APFB.js";
2
+ normalizeToolResultContentBlock
3
+ } from "./chunk-IB5IQK2S.js";
9
4
  import {
10
5
  AuthenticationError,
11
6
  ContextTooLongError,
7
+ DEFAULT_PROVIDER_THINKING,
12
8
  LLMError,
13
9
  NetworkError,
14
10
  RateLimitError,
15
- ensureToolPairing
16
- } from "./chunk-OO2CLOEE.js";
11
+ ensureToolPairing,
12
+ getMaxOutputTokens,
13
+ resolveAPIKey
14
+ } from "./chunk-FBSPZQGC.js";
17
15
  import {
18
16
  MCP_TOOL_PREFIX,
19
17
  isMcpToolLike
20
- } from "./chunk-PZ42NAFA.js";
18
+ } from "./chunk-KG4MJGKQ.js";
21
19
  import {
22
20
  asErrorString,
23
21
  asRecord,
24
22
  asString,
25
23
  contentToText,
26
24
  createChildLogger,
27
- isRecord
25
+ isRecord,
26
+ strArg
28
27
  } from "./chunk-EY7HE52Q.js";
29
28
 
30
29
  // src/llm/anthropic.ts
@@ -152,14 +151,17 @@ async function fetchModelContextWindow(config) {
152
151
  clearTimeout(timer);
153
152
  }
154
153
  }
155
- function supportsAdaptiveThinking() {
156
- return true;
157
- }
158
154
  function userBlocksFor(content) {
159
155
  if (typeof content === "string") {
160
156
  return [{ type: "text", text: content }];
161
157
  }
162
- return content;
158
+ return content.map((raw) => {
159
+ const block = normalizeToolResultContentBlock(raw);
160
+ if (!block || block.type === "tool_reference") {
161
+ throw new Error(`Unsupported user content block: ${strArg(raw, "type", "unknown")}`);
162
+ }
163
+ return block;
164
+ });
163
165
  }
164
166
  function buildAnthropicMessages(messages) {
165
167
  const result = [];
@@ -208,6 +210,9 @@ function buildAnthropicMessages(messages) {
208
210
  content: tr.contentBlocks?.length ? tr.contentBlocks : tr.content
209
211
  });
210
212
  }
213
+ if (m.content.length > 0) {
214
+ blocks.push(...userBlocksFor(m.content));
215
+ }
211
216
  result.push({ role: "user", content: blocks });
212
217
  } else {
213
218
  if (result.length === 0) {
@@ -254,7 +259,6 @@ var AnthropicClient = class {
254
259
  systemPrompt;
255
260
  maxOutputTokens;
256
261
  /** Currently not used */
257
- contextWindow;
258
262
  constructor(config, systemPrompt) {
259
263
  const apiKey = resolveAPIKey(config);
260
264
  if (!apiKey) {
@@ -267,10 +271,9 @@ var AnthropicClient = class {
267
271
  baseURL: config.base_url
268
272
  });
269
273
  this.model = config.model;
270
- this.thinking = config.thinking ?? true;
274
+ this.thinking = config.thinking ?? DEFAULT_PROVIDER_THINKING;
271
275
  this.systemPrompt = systemPrompt;
272
276
  this.maxOutputTokens = getMaxOutputTokens(config);
273
- this.contextWindow = getContextWindow(config);
274
277
  }
275
278
  setSystemPrompt(prompt) {
276
279
  this.systemPrompt = prompt;
@@ -316,19 +319,7 @@ var AnthropicClient = class {
316
319
  messages,
317
320
  ...antToolSchemas.length > 0 ? { tools: antToolSchemas } : {}
318
321
  };
319
- if (this.thinking) {
320
- if (supportsAdaptiveThinking()) {
321
- params.thinking = {
322
- type: "enabled",
323
- budget_tokens: computeCompactThreshold(this.contextWindow, this.maxOutputTokens)
324
- };
325
- }
326
- } else {
327
- params.thinking = {
328
- type: "enabled",
329
- budget_tokens: computeCompactThreshold(this.contextWindow, this.maxOutputTokens)
330
- };
331
- }
322
+ params.thinking = this.thinking && this.maxOutputTokens > 1024 ? { type: "enabled", budget_tokens: Math.min(16384, this.maxOutputTokens - 1) } : { type: "disabled" };
332
323
  let inputTokens = 0;
333
324
  let outputTokens = 0;
334
325
  let cacheReadInputTokens = 0;
@@ -377,7 +368,7 @@ var AnthropicClient = class {
377
368
  text: delta.thinking
378
369
  };
379
370
  } else if (delta.type === "signature_delta") {
380
- thinkingSignature = delta.signature;
371
+ thinkingSignature += delta.signature;
381
372
  } else if (delta.type === "text_delta") {
382
373
  yield {
383
374
  type: "text_delta",
@@ -497,6 +488,7 @@ function markLastUserTailForCache(messages) {
497
488
  Reflect.set(last, "cache_control", {
498
489
  type: "ephemeral"
499
490
  });
491
+ return;
500
492
  }
501
493
  }
502
494
  function classifyAnthropicError(err) {
@@ -508,14 +500,16 @@ function classifyAnthropicError(err) {
508
500
  return new AuthenticationError(`Invalid API key: ${err.message}`);
509
501
  }
510
502
  if (err.status === 429 /* RateLimitError */) {
511
- const retryAfter = asRecord(err.headers)["retry-after"];
503
+ const headers = err.headers;
504
+ const retryAfter = headers instanceof Headers ? headers.get("retry-after") : void 0;
512
505
  let message = "Rate Limited";
513
506
  if (retryAfter) {
514
507
  const s = Number.parseInt(asString(retryAfter));
515
508
  if (Number.isNaN(s)) {
516
509
  message += ", please wait.";
510
+ } else {
511
+ message += `, retry after ${asString(s)}s.`;
517
512
  }
518
- message += `, retry after ${asString(s)}s.`;
519
513
  } else {
520
514
  message += ", please wait.";
521
515
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  mcpCallPermissionContent
3
- } from "./chunk-PZ42NAFA.js";
3
+ } from "./chunk-KG4MJGKQ.js";
4
4
  import {
5
5
  createChildLogger,
6
6
  strArg
@@ -12,9 +12,38 @@ import {
12
12
  // src/permissions/checker.ts
13
13
  import { readFileSync, writeFileSync, mkdirSync, statSync } from "fs";
14
14
  import { homedir, tmpdir } from "os";
15
- import { join, resolve, dirname } from "path";
15
+ import { join as join2, resolve as resolve2, dirname as dirname2 } from "path";
16
16
  import yaml from "js-yaml";
17
17
  import z, { parse } from "zod";
18
+
19
+ // src/utils/paths.ts
20
+ import { realpathSync } from "fs";
21
+ import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "path";
22
+ function canonicalPath(path) {
23
+ let current = resolve(path);
24
+ const missing = [];
25
+ for (; ; ) {
26
+ try {
27
+ return join(realpathSync(current), ...missing);
28
+ } catch (error) {
29
+ if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT" && error.code !== "ENOTDIR") {
30
+ throw error;
31
+ }
32
+ const parent = dirname(current);
33
+ if (parent === current) {
34
+ return resolve(path);
35
+ }
36
+ missing.unshift(basename(current));
37
+ current = parent;
38
+ }
39
+ }
40
+ }
41
+ function isPathWithin(root, path) {
42
+ const child = relative(root, path);
43
+ return child === "" || child !== ".." && !child.startsWith(`..${sep}`) && !isAbsolute(child);
44
+ }
45
+
46
+ // src/permissions/checker.ts
18
47
  var log = createChildLogger({ module: "permissions" });
19
48
  var DANGEROUS_PATTERNS = [];
20
49
  var SAFE_PREFIXES = [
@@ -56,7 +85,8 @@ var CONTENT_FIELDS = {
56
85
  WriteFile: "file_path",
57
86
  EditFile: "file_path",
58
87
  Glob: "pattern",
59
- Grep: "pattern"
88
+ Grep: "pattern",
89
+ InstallSkill: "source"
60
90
  };
61
91
  var DEFAULT_DENY_WRITE = [
62
92
  ".swifty/config.yaml",
@@ -79,25 +109,26 @@ var PathSandbox = class {
79
109
  denyWritePaths;
80
110
  projectDir;
81
111
  constructor(projectDir) {
82
- this.projectDir = resolve(projectDir);
112
+ this.projectDir = resolve2(projectDir);
83
113
  this.allowedRoots = [this.projectDir, tmpdir()];
84
- this.denyWritePaths = DEFAULT_DENY_WRITE.map((p) => join(this.projectDir, p));
114
+ this.denyWritePaths = DEFAULT_DENY_WRITE.map((p) => join2(this.projectDir, p));
85
115
  }
86
116
  addRoot(root) {
87
- this.allowedRoots.push(resolve(root));
117
+ this.allowedRoots.push(resolve2(root));
88
118
  }
89
119
  // Add custom deny-write paths
90
120
  addDenyWrite(path) {
91
- this.denyWritePaths.push(resolve(path));
121
+ this.denyWritePaths.push(resolve2(path));
92
122
  }
93
123
  /**
94
124
  * Check whether a path is in the deny-write list.
95
125
  * denyWrite has the highest priority — even if the path is within an allowed root, writes are still denied.
96
126
  */
97
127
  checkDenyWrite(filePath) {
98
- const absolute = resolve(filePath);
128
+ const absolute = resolve2(this.projectDir, filePath);
129
+ const canonical = canonicalPath(absolute);
99
130
  for (const denied of this.denyWritePaths) {
100
- if (absolute.startsWith(denied)) {
131
+ if (isPathWithin(denied, absolute) || isPathWithin(canonicalPath(denied), canonical)) {
101
132
  return {
102
133
  effect: "deny",
103
134
  reason: `Path ${filePath} is in deny-write list`
@@ -107,9 +138,9 @@ var PathSandbox = class {
107
138
  return null;
108
139
  }
109
140
  check(filePath) {
110
- const absolute = resolve(filePath);
141
+ const absolute = canonicalPath(resolve2(this.projectDir, filePath));
111
142
  for (const root of this.allowedRoots) {
112
- if (absolute.startsWith(root)) {
143
+ if (isPathWithin(canonicalPath(root), absolute)) {
113
144
  return null;
114
145
  }
115
146
  }
@@ -190,9 +221,9 @@ var RuleEngine = class {
190
221
  localPath;
191
222
  cache = /* @__PURE__ */ new Map();
192
223
  constructor(workDir) {
193
- this.userPath = join(homedir(), ".swifty", "permissions.yaml");
194
- this.projectPath = join(workDir, ".swifty", "permissions.yaml");
195
- this.localPath = join(workDir, ".swifty", "permissions.local.yaml");
224
+ this.userPath = join2(homedir(), ".swifty", "permissions.yaml");
225
+ this.projectPath = join2(workDir, ".swifty", "permissions.yaml");
226
+ this.localPath = join2(workDir, ".swifty", "permissions.local.yaml");
196
227
  }
197
228
  // Read a single rules file; skips disk I/O and parsing on cache hit.
198
229
  rulesFor(path) {
@@ -229,7 +260,7 @@ var RuleEngine = class {
229
260
  // Persists a rule to the project-local YAML file in the `Tool(pattern)`
230
261
  // format so "allow always" survives a restart.
231
262
  appendLocalRule(rule) {
232
- mkdirSync(dirname(this.localPath), { recursive: true });
263
+ mkdirSync(dirname2(this.localPath), { recursive: true });
233
264
  const rules = loadRulesFile(this.localPath);
234
265
  const exists = rules.some(
235
266
  (r) => r.tool === rule.tool && r.pattern === rule.pattern && r.effect === rule.effect
@@ -255,7 +286,7 @@ function detectDangerous(command) {
255
286
  }
256
287
  function isSafeCommand(command) {
257
288
  const trimmed = command.trim();
258
- if (trimmed.includes(">") || trimmed.includes("|") || trimmed.includes(";") || trimmed.includes("&&") || trimmed.includes("$(") || trimmed.includes("`")) {
289
+ if (trimmed.includes(">") || trimmed.includes("<") || /[\r\n&]/.test(trimmed) || trimmed.includes("|") || trimmed.includes(";") || trimmed.includes("&&") || trimmed.includes("$(") || trimmed.includes("`")) {
259
290
  return false;
260
291
  }
261
292
  return SAFE_PREFIXES.some(
@@ -275,7 +306,14 @@ function modeDecide(mode, category) {
275
306
  return category === "read" ? "allow" : "ask";
276
307
  }
277
308
  }
278
- var PermissionChecker = class {
309
+ var PermissionChecker = class _PermissionChecker {
310
+ constructor(workDir, mode = "default") {
311
+ this.workDir = workDir;
312
+ this.mode = mode;
313
+ this.sandbox = new PathSandbox(workDir);
314
+ this.ruleEngine = new RuleEngine(workDir);
315
+ }
316
+ workDir;
279
317
  mode;
280
318
  planFilePath = "";
281
319
  // Sandbox mode: when enabled, command-category tools run through OS sandbox isolation, with optional auto-allow
@@ -283,18 +321,24 @@ var PermissionChecker = class {
283
321
  sandboxAutoAllow = false;
284
322
  sandbox;
285
323
  ruleEngine;
286
- constructor(workDir, mode = "default") {
287
- this.mode = mode;
288
- this.sandbox = new PathSandbox(workDir);
289
- this.ruleEngine = new RuleEngine(workDir);
324
+ forWorkDir(workDir) {
325
+ const checker = new _PermissionChecker(workDir, this.mode);
326
+ checker.ruleEngine = this.ruleEngine;
327
+ checker.sandboxEnabled = this.sandboxEnabled;
328
+ checker.sandboxAutoAllow = this.sandboxAutoAllow;
329
+ return checker;
290
330
  }
291
331
  check(toolName, category, args) {
292
332
  const content = extractContent(toolName, args);
293
333
  let snapshot = null;
294
334
  const rules = () => snapshot ??= this.ruleEngine.snapshot();
335
+ const explicitEffect = evaluateRules(rules(), toolName, content);
336
+ if (explicitEffect === "deny" || explicitEffect === "ask") {
337
+ return { effect: explicitEffect, reason: `Permission rule: ${explicitEffect}` };
338
+ }
295
339
  if (this.mode === "plan" && (toolName === "WriteFile" || toolName === "EditFile")) {
296
340
  const path = strArg(args, "file_path", "");
297
- if (path.includes(".swifty/plans/")) {
341
+ if (this.planFilePath && canonicalPath(resolve2(this.workDir, path)) === canonicalPath(resolve2(this.workDir, this.planFilePath)) && !this.sandbox.checkDenyWrite(path)) {
298
342
  return {
299
343
  effect: "allow",
300
344
  reason: "Plan file write allowed in plan mode"
@@ -377,13 +421,13 @@ var PermissionChecker = class {
377
421
  const isFilePath = toolName === "ReadFile" || toolName === "WriteFile" || toolName === "EditFile";
378
422
  let pattern;
379
423
  if (isFilePath && content) {
380
- const abs = resolve(content);
424
+ const abs = resolve2(this.workDir, content);
381
425
  let isDir = false;
382
426
  try {
383
427
  isDir = statSync(abs).isDirectory();
384
428
  } catch {
385
429
  }
386
- pattern = join(isDir ? abs : dirname(abs), "*");
430
+ pattern = join2(isDir ? abs : dirname2(abs), "*");
387
431
  } else {
388
432
  const words = content.trim().split(/\s+/).slice(0, 2);
389
433
  pattern = words.join(" ") + "*";
@@ -417,6 +461,8 @@ var PermissionChecker = class {
417
461
  };
418
462
 
419
463
  export {
464
+ canonicalPath,
465
+ isPathWithin,
420
466
  extractContent,
421
467
  PathSandbox,
422
468
  evaluateRules,