@swifty.js/swifty 0.0.28 → 0.0.30

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 (37) hide show
  1. package/README.md +40 -38
  2. package/dist/{agent-3NON2EXE.js → agent-TCNIRVHD.js} +1 -1
  3. package/dist/anthropic-7RIVSEDF.js +4 -0
  4. package/dist/{checker-N5TIJEN5.js → checker-3LHDOATB.js} +1 -1
  5. package/dist/chunk-2IBMB3ZM.js +150 -0
  6. package/dist/chunk-AQ3A5CF4.js +5 -0
  7. package/dist/chunk-FA26MQ7K.js +257 -0
  8. package/dist/{chunk-JGSIQXEN.js → chunk-QFSCPD63.js} +1 -1
  9. package/dist/chunk-TKADLB2Q.js +4 -0
  10. package/dist/chunk-VA64DJNN.js +4 -0
  11. package/dist/lib/{agent-XYO2MXXK.js → agent-IRY7KR5D.js} +3 -3
  12. package/dist/lib/{anthropic-TGJGAP5R.js → anthropic-CL5IK7KN.js} +3 -3
  13. package/dist/lib/{checker-AXHPKVBY.js → checker-BS4MK3O6.js} +1 -1
  14. package/dist/lib/{chunk-2IVEVG5N.js → chunk-7QPDFSQE.js} +10 -17
  15. package/dist/lib/{chunk-P4F46PEF.js → chunk-I7OPU4K2.js} +48 -8
  16. package/dist/lib/{chunk-ALJAVRRX.js → chunk-IYPTOY3Y.js} +59 -19
  17. package/dist/lib/{chunk-DV6RV5WU.js → chunk-OOSNCCI7.js} +134 -258
  18. package/dist/lib/{chunk-FBSPZQGC.js → chunk-OQIQOU5S.js} +132 -73
  19. package/dist/lib/{chunk-IB5IQK2S.js → chunk-PIL7M52F.js} +2 -11
  20. package/dist/lib/{chunk-DJ6AILPN.js → chunk-RMB3J46W.js} +13 -16
  21. package/dist/lib/index.d.ts +387 -112
  22. package/dist/lib/index.js +1000 -1157
  23. package/dist/lib/{openai-5UCIIDPO.js → openai-LH4E7ZQS.js} +2 -2
  24. package/dist/lib/{tool-filter-R6HDDJHE.js → tool-filter-CS6W2GMU.js} +1 -1
  25. package/dist/main.js +186 -178
  26. package/dist/{openai-YLS2LUAI.js → openai-RZLCY55V.js} +15 -15
  27. package/dist/{server-GX72MJQF.js → server-IVIRQTO7.js} +17 -17
  28. package/dist/{tool-filter-VBP6WOGO.js → tool-filter-CG3KGQQW.js} +1 -1
  29. package/package.json +5 -4
  30. package/dist/anthropic-BJ5GN2VT.js +0 -4
  31. package/dist/chunk-D34FUVGU.js +0 -4
  32. package/dist/chunk-LZBOXJX2.js +0 -301
  33. package/dist/chunk-R63ASIIW.js +0 -407
  34. package/dist/chunk-WX3B64R4.js +0 -4
  35. package/dist/chunk-Y6SQB5FG.js +0 -4
  36. package/dist/glob.wasm +0 -0
  37. package/dist/lib/glob.wasm +0 -0
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire as __swiftyCreateRequire } from "node:module";
3
3
  const require = __swiftyCreateRequire(import.meta.url);
4
- function r(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}var p=new Set(["image/jpeg","image/png","image/gif","image/webp"]);function u(e){return p.has(e)}function c(e){return r(e)&&e.type==="text"&&typeof e.text=="string"?{type:"text",text:e.text}:null}function l(e){return!r(e)||e.type!=="image"||!r(e.source)?null:e.source.type==="url"&&typeof e.source.url=="string"?{type:"image",source:{type:"url",url:e.source.url}}:e.source.type==="base64"&&typeof e.source.media_type=="string"&&u(e.source.media_type)&&typeof e.source.data=="string"?{type:"image",source:{type:"base64",media_type:e.source.media_type,data:e.source.data}}:null}function a(e){if(e.type!=="document"||!r(e.source))return null;let t=null;if(e.source.type==="url"&&typeof e.source.url=="string")t={type:"url",url:e.source.url};else if(e.source.type==="base64"&&e.source.media_type==="application/pdf"&&typeof e.source.data=="string")t={type:"base64",media_type:"application/pdf",data:e.source.data};else if(e.source.type==="text"&&e.source.media_type==="text/plain"&&typeof e.source.data=="string")t={type:"text",media_type:"text/plain",data:e.source.data};else if(e.source.type==="content"){if(typeof e.source.content=="string")t={type:"content",content:e.source.content};else if(Array.isArray(e.source.content)){let o=[];for(let n of e.source.content){let i=c(n)??l(n);if(!i)return null;o.push(i)}t={type:"content",content:o}}}return t?{type:"document",source:t,...typeof e.title=="string"||e.title===null?{title:e.title}:{},...typeof e.context=="string"||e.context===null?{context:e.context}:{}}:null}function y(e){let t=c(e);if(t)return t;let o=l(e);if(o)return o;if(!r(e))return null;if(e.type==="tool_reference"&&typeof e.tool_name=="string")return{type:"tool_reference",tool_name:e.tool_name};if(e.type==="search_result"&&typeof e.source=="string"&&typeof e.title=="string"&&Array.isArray(e.content)){let n=[];for(let i of e.content){let s=c(i);if(!s)return null;n.push(s)}return{type:"search_result",source:e.source,title:e.title,content:n}}return a(e)}var m=new Set([".claude",".git",".swifty",".next",".venv",".mypy_cache",".tox","__pycache__","build","dist","node_modules","vendor","venv"]);export{y as a,m as b};
4
+ function r(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}var p=new Set(["image/jpeg","image/png","image/gif","image/webp"]);function u(e){return p.has(e)}function c(e){return r(e)&&e.type==="text"&&typeof e.text=="string"?{type:"text",text:e.text}:null}function l(e){return!r(e)||e.type!=="image"||!r(e.source)?null:e.source.type==="url"&&typeof e.source.url=="string"?{type:"image",source:{type:"url",url:e.source.url}}:e.source.type==="base64"&&typeof e.source.media_type=="string"&&u(e.source.media_type)&&typeof e.source.data=="string"?{type:"image",source:{type:"base64",media_type:e.source.media_type,data:e.source.data}}:null}function a(e){if(e.type!=="document"||!r(e.source))return null;let t=null;if(e.source.type==="url"&&typeof e.source.url=="string")t={type:"url",url:e.source.url};else if(e.source.type==="base64"&&e.source.media_type==="application/pdf"&&typeof e.source.data=="string")t={type:"base64",media_type:"application/pdf",data:e.source.data};else if(e.source.type==="text"&&e.source.media_type==="text/plain"&&typeof e.source.data=="string")t={type:"text",media_type:"text/plain",data:e.source.data};else if(e.source.type==="content"){if(typeof e.source.content=="string")t={type:"content",content:e.source.content};else if(Array.isArray(e.source.content)){let o=[];for(let n of e.source.content){let i=c(n)??l(n);if(!i)return null;o.push(i)}t={type:"content",content:o}}}return t?{type:"document",source:t,...typeof e.title=="string"||e.title===null?{title:e.title}:{},...typeof e.context=="string"||e.context===null?{context:e.context}:{}}:null}function y(e){let t=c(e);if(t)return t;let o=l(e);if(o)return o;if(!r(e))return null;if(e.type==="tool_reference"&&typeof e.tool_name=="string")return{type:"tool_reference",tool_name:e.tool_name};if(e.type==="search_result"&&typeof e.source=="string"&&typeof e.title=="string"&&Array.isArray(e.content)){let n=[];for(let i of e.content){let s=c(i);if(!s)return null;n.push(s)}return{type:"search_result",source:e.source,title:e.title,content:n}}return a(e)}var m=new Set([".agents",".git",".swifty",".next",".venv",".mypy_cache","__pycache__","dist","node_modules"]);export{y as a,m as b};
@@ -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{c as A}from"./chunk-QCKJLO6X.js";import{D as h,I as j,R as u,d as b,e as F}from"./chunk-OTVZGPHD.js";import{b as S}from"./chunk-E55KH72M.js";import{readFileSync as B,writeFileSync as G,mkdirSync as U,statSync as T}from"fs";import{homedir as J,tmpdir as X}from"os";import{join as g,resolve as l,dirname as C}from"path";import{realpathSync as M}from"fs";import{basename as O,dirname as z,isAbsolute as L,join as I,relative as N,resolve as W,sep as Y}from"path";function d(i){let e=W(i),t=[];for(;;)try{return I(M(e),...t)}catch(n){if(!(n instanceof Error)||!("code"in n)||n.code!=="ENOENT"&&n.code!=="ENOTDIR")throw n;let r=z(e);if(r===e)return W(i);t.unshift(O(e)),e=r}}function p(i,e){let t=N(i,e);return t===""||t!==".."&&!t.startsWith(`..${Y}`)&&!L(t)}var P=j({module:"permissions"}),q=[],H=["ls","pwd","echo","cat","head","tail","wc","date","whoami","uname","hostname","which","type","file","git status","git log","git diff","git branch","git show","git rev-parse","git remote","bun test","bun run","npm test","npm run","go test","go build","go vet","python -c","node -e"],K={Bash:"command",PowerShell:"command",ReadFile:"file_path",WriteFile:"file_path",EditFile:"file_path",Glob:"pattern",Grep:"pattern",InstallSkill:"source"},Q=[".swifty/permissions.yaml",".agents/skills/"];function R(i,e){if(i===S)return A(u(e,"server",""),u(e,"tool",""));let t=K[i];if(!t)return"";let n=e[t];return typeof n=="string"?n:""}var x=class{allowedRoots;denyWritePaths;projectDir;constructor(e){this.projectDir=l(e),this.allowedRoots=[this.projectDir,X()],this.denyWritePaths=Q.map(t=>g(this.projectDir,t))}addRoot(e){this.allowedRoots.push(l(e))}addDenyWrite(e){this.denyWritePaths.push(l(e))}checkDenyWrite(e){let t=l(this.projectDir,e),n=d(t);for(let r of this.denyWritePaths)if(p(r,t)||p(d(r),n))return{effect:"deny",reason:`Path ${e} is in deny-write list`};return null}check(e){let t=d(l(this.projectDir,e));for(let n of this.allowedRoots)if(p(d(n),t))return null;return{effect:"deny",reason:`Path ${e} is outside allowed directories`}}};function V(i,e){let t="^"+i.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*").replace(/\?/g,".")+"$";try{return new RegExp(t).test(e)}catch(n){return P.error({err:n},"permissions operation failed"),!1}}var Z=/^(\w+)\((.+)\)$/;function $(i){let e;try{e=B(i,"utf-8")}catch(s){return s.code!=="ENOENT"&&P.error({err:s},"permissions operation failed"),[]}let t=h.object({rule:h.string().optional(),effect:h.string().optional()}),n;try{let s=b.load(e);n=F(h.array(t),s)}catch(s){return P.error({err:s},"permissions operation failed"),[]}let r=[];for(let s of n){if(s.effect!=="allow"&&s.effect!=="deny"&&s.effect!=="ask")continue;let o=Z.exec((s.rule??"").trim());o&&r.push({tool:o[1],pattern:o[2],effect:s.effect})}return r}function m(i,e,t){let n=null;for(let r of i)if(!(r.tool!==e&&r.tool!=="*")&&V(r.pattern,t)){if(r.effect==="deny")return"deny";r.effect==="ask"?n="ask":n??="allow"}return n}var D=class{userPath;projectPath;cache=new Map;constructor(e){this.userPath=g(J(),".swifty","permissions.yaml"),this.projectPath=g(e,".swifty","permissions.yaml")}rulesFor(e){let t;try{t=T(e,{bigint:!0})}catch{return this.cache.delete(e),[]}let n=this.cache.get(e);if(n?.mtimeNs===t.mtimeNs&&n.size===t.size)return n.rules;let r=$(e);return this.cache.set(e,{mtimeNs:t.mtimeNs,size:t.size,rules:r}),r}snapshot(){return[this.userPath,this.projectPath].flatMap(e=>this.rulesFor(e))}evaluate(e,t){return m(this.snapshot(),e,t)}appendProjectRule(e){U(C(this.projectPath),{recursive:!0});let t=$(this.projectPath);if(t.some(s=>s.tool===e.tool&&s.pattern===e.pattern&&s.effect===e.effect))return;t.push(e);let r=t.map(s=>({rule:`${s.tool}(${s.pattern})`,effect:s.effect}));G(this.projectPath,b.dump(r),"utf-8")}};function ee(i){for(let e of q)if(e.re.test(i))return e.reason;return""}function te(i){let e=i.trim();return e.includes(">")||e.includes("<")||/[\r\n&]/.test(e)||e.includes("|")||e.includes(";")||e.includes("&&")||e.includes("$(")||e.includes("`")?!1:H.some(t=>e===t||e.startsWith(t+" ")||e.startsWith(t+" "))}function ne(i,e){switch(i){case"bypassPermissions":return"allow";case"plan":return e==="read"?"allow":"ask";case"acceptEdits":return e==="command"?"ask":"allow";default:return e==="read"?"allow":"ask"}}var _=class i{constructor(e,t="default"){this.workDir=e;this.mode=t,this.sandbox=new x(e),this.ruleEngine=new D(e)}workDir;mode;planFilePath="";sandboxEnabled=!1;sandboxAutoAllow=!1;sandbox;ruleEngine;forWorkDir(e){let t=new i(e,this.mode);return t.ruleEngine=this.ruleEngine,t.sandboxEnabled=this.sandboxEnabled,t.sandboxAutoAllow=this.sandboxAutoAllow,t}check(e,t,n){let r=R(e,n),s=null,o=()=>s??=this.ruleEngine.snapshot(),a=m(o(),e,r);if(a==="deny"||a==="ask")return{effect:a,reason:`Permission rule: ${a}`};if(this.mode==="plan"&&(e==="WriteFile"||e==="EditFile")){let f=u(n,"file_path","");if(this.planFilePath&&d(l(this.workDir,f))===d(l(this.workDir,this.planFilePath))&&!this.sandbox.checkDenyWrite(f))return{effect:"allow",reason:"Plan file write allowed in plan mode"}}if(t==="command"&&te(r))return{effect:"allow",reason:"Safe read-only command"};let k=t==="command"?ee(r):"";if(k)return{effect:"deny",reason:`Dangerous command blocked: ${k}`};if(this.sandboxEnabled&&this.sandboxAutoAllow&&e==="Bash"){let f=u(n,"command").split(/\s*(?:&&|\|\||[;|])\s*/).map(y=>y.trim()).filter(Boolean),c=!1;for(let y of f){let v=m(o(),e,y);if(v==="deny")return{effect:"deny",reason:"Permission rule: deny"};v==="ask"&&(c=!0)}return c?{effect:"ask",reason:"Permission rule: ask (sandbox does not override)"}:{effect:"allow",reason:"Sandbox auto-allow: OS sandbox active"}}let w=u(n,"file_path",u(n,"path",""));if((t==="read"||t==="write")&&w){if(t==="write"){let c=this.sandbox.checkDenyWrite(w);if(c)return c}let f=this.sandbox.check(w);if(f&&this.mode!=="bypassPermissions"){let c=this.ruleEngine.evaluate(e,r);return c?{effect:c,reason:`Permission rule: ${c}`}:{effect:"ask",reason:f.reason}}}let E=m(o(),e,r);return E?{effect:E,reason:`Permission rule: ${E}`}:{effect:ne(this.mode,t),reason:`Mode: ${this.mode}`}}allowExtraRoot(e){this.sandbox.addRoot(e)}allowAlways(e,t){let n=R(e,t),r=e==="ReadFile"||e==="WriteFile"||e==="EditFile",s;if(r&&n){let o=l(this.workDir,n),a=!1;try{a=T(o).isDirectory()}catch{}s=g(a?o:C(o),"*")}else s=n.trim().split(/\s+/).slice(0,2).join(" ")+"*";this.ruleEngine.appendProjectRule({tool:e,pattern:s,effect:"allow"})}describeToolAction(e,t){let n=R(e,t);if(n)return n;let r=[];for(let[s,o]of Object.entries(t)){let a=String(o);a.length>80&&(a=a.slice(0,80)+"..."),r.push(`${s}: ${a}`)}return r.join(", ")}};export{d as a,p as b,R as c,x as d,m as e,D as f,te as g,_ as h};
@@ -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 m,b as T}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===m&&!this.exposeToolSearch||s.name===T&&!this.exposeMcpCall)continue;let a=!!s.deferred&&!this.discovered.has(s.name);if(a&&!t)continue;let i=s.schema();e==="openai"?n.push({strict:i.strict??!1,type:"function",name:i.name,description:i.description,parameters:i.input_schema}):e==="openai-compat"?n.push({type:"function",function:{name:i.name,description:i.description,parameters:i.input_schema,strict:i.strict??!1}}):n.push({...i,type:"custom",...a?{defer_loading:!0}:{}})}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"]),f=new Set(["ExitPlanMode","Agent","AskUserQuestion","TaskStop"]),u=new Set(["ReadFile","Grep","Glob","Bash","PowerShell","EditFile","WriteFile","LoadSkill","SyntheticOutput","ToolSearch","EnterWorktree","ExitWorktree","McpCall"]);function g(r){return r.startsWith("mcp__")}function C(r,e,o,t,n=!1){let s=new Set(o??[]),a=new Set(e??[]),i=a.size>0&&!(a.size===1&&a.has("*")),p=new c;p.mcpLoadingMode=r.mcpLoadingMode;for(let d of r.listTools()){let l=d.name;if(g(l)){!s.has(l)&&(!i||a.has(l))&&p.register(d);continue}h.has(l)||n&&f.has(l)||t&&!u.has(l)||s.has(l)||i&&!a.has(l)||p.register(d)}return p}var S="agent:builtin:fork";function w(r){let e=new c;e.mcpLoadingMode=r.mcpLoadingMode;for(let o of r.listTools())if(o.name==="Agent"&&"querySource"in o){let t=Object.create(Object.getPrototypeOf(o),Object.getOwnPropertyDescriptors(o));t.querySource=S,e.register(t)}else e.register(o);return e}export{c as a,h as b,M as c,f as d,u as e,C as f,S as g,w as h};
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  Agent
3
- } from "./chunk-DV6RV5WU.js";
4
- import "./chunk-IB5IQK2S.js";
5
- import "./chunk-FBSPZQGC.js";
3
+ } from "./chunk-OOSNCCI7.js";
4
+ import "./chunk-PIL7M52F.js";
5
+ import "./chunk-OQIQOU5S.js";
6
6
  import "./chunk-KG4MJGKQ.js";
7
7
  import "./chunk-EY7HE52Q.js";
8
8
  import "./chunk-GHF2PSEW.js";
@@ -5,9 +5,9 @@ import {
5
5
  markLastUserTailForCache,
6
6
  markToolsForCache,
7
7
  needsToolSearchBeta
8
- } from "./chunk-ALJAVRRX.js";
9
- import "./chunk-IB5IQK2S.js";
10
- import "./chunk-FBSPZQGC.js";
8
+ } from "./chunk-IYPTOY3Y.js";
9
+ import "./chunk-PIL7M52F.js";
10
+ import "./chunk-OQIQOU5S.js";
11
11
  import "./chunk-KG4MJGKQ.js";
12
12
  import "./chunk-EY7HE52Q.js";
13
13
  import "./chunk-GHF2PSEW.js";
@@ -5,7 +5,7 @@ import {
5
5
  evaluateRules,
6
6
  extractContent,
7
7
  isSafeCommand
8
- } from "./chunk-DJ6AILPN.js";
8
+ } from "./chunk-RMB3J46W.js";
9
9
  import "./chunk-KG4MJGKQ.js";
10
10
  import "./chunk-EY7HE52Q.js";
11
11
  import "./chunk-GHF2PSEW.js";
@@ -45,33 +45,26 @@ var ToolRegistry = class {
45
45
  continue;
46
46
  }
47
47
  const s = tool.schema();
48
- if (isOpenAI) {
48
+ if (protocol === "openai") {
49
49
  schemas.push({
50
- strict: false,
51
- // Whether to enforce strict parameter validation. Default true.
50
+ strict: s.strict ?? false,
52
51
  type: "function",
53
52
  name: s.name,
54
53
  description: s.description,
55
- parameters: s.input_schema,
56
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
57
- // @ts-ignore
54
+ parameters: s.input_schema
55
+ });
56
+ } else if (protocol === "openai-compat") {
57
+ schemas.push({
58
+ type: "function",
58
59
  function: {
59
60
  name: s.name,
60
61
  description: s.description,
61
- parameters: s.input_schema
62
+ parameters: s.input_schema,
63
+ strict: s.strict ?? false
62
64
  }
63
65
  });
64
66
  } else {
65
- schemas.push(
66
- deferred ? {
67
- ...s,
68
- type: "custom",
69
- defer_loading: true
70
- } : {
71
- ...s,
72
- type: "custom"
73
- }
74
- );
67
+ schemas.push({ ...s, type: "custom", ...deferred ? { defer_loading: true } : {} });
75
68
  }
76
69
  }
77
70
  return schemas;
@@ -4,10 +4,14 @@ import {
4
4
  LLMError,
5
5
  NetworkError,
6
6
  RateLimitError,
7
+ clampThinkingLevel,
7
8
  ensureToolPairing,
8
9
  getMaxOutputTokens,
9
- resolveAPIKey
10
- } from "./chunk-FBSPZQGC.js";
10
+ getSupportedThinkingLevels,
11
+ getThinkingLevel,
12
+ resolveAPIKey,
13
+ toReasoningEffort
14
+ } from "./chunk-OQIQOU5S.js";
11
15
  import {
12
16
  asRecord,
13
17
  asString,
@@ -25,11 +29,13 @@ var OpenAIClient = class {
25
29
  model;
26
30
  systemPrompt;
27
31
  maxOutputTokens;
32
+ thinkingLevel;
33
+ config;
28
34
  constructor(config, systemPrompt) {
29
35
  const apiKey = resolveAPIKey(config);
30
36
  if (!apiKey) {
31
37
  throw new AuthenticationError(
32
- "OpenAI API key not found, set OPENAI_API_KEY in .swifty/config.y(a)ml, or via OPENAI_API_KEY env variable."
38
+ "OpenAI API key not found, set OPENAI_API_KEY in ~/.swifty/config.yaml, or via OPENAI_API_KEY env variable."
33
39
  );
34
40
  }
35
41
  this.client = new OpenAI({
@@ -39,6 +45,8 @@ var OpenAIClient = class {
39
45
  this.model = config.model;
40
46
  this.systemPrompt = systemPrompt;
41
47
  this.maxOutputTokens = getMaxOutputTokens(config);
48
+ this.config = { ...config };
49
+ this.thinkingLevel = getThinkingLevel(config);
42
50
  }
43
51
  async *stream(conversation, toolSchemas, abortSignal) {
44
52
  const messages = buildOpenAIInput(ensureToolPairing(conversation.getMessages()));
@@ -57,15 +65,19 @@ var OpenAIClient = class {
57
65
  name: s.name,
58
66
  description: s.description,
59
67
  parameters: schema,
60
- strict: false
68
+ strict: s.strict ?? false
61
69
  };
62
70
  });
71
+ const effort = toReasoningEffort(this.getThinkingLevel(), this.config);
63
72
  const params = {
64
73
  model: this.model,
65
74
  input,
66
75
  stream: true,
67
76
  max_output_tokens: this.maxOutputTokens,
68
- ...tools.length > 0 ? { tools } : {}
77
+ ...tools.length > 0 ? { tools } : {},
78
+ // Only explicit reasoning:false omits the field. Off sends none to defeat
79
+ // server-default reasoning; requesting a summary while off is unnecessary.
80
+ ...effort !== null ? { reasoning: { effort, ...effort !== "none" ? { summary: "auto" } : {} } } : {}
69
81
  };
70
82
  let inputTokens = 0;
71
83
  let outputTokens = 0;
@@ -190,6 +202,16 @@ var OpenAIClient = class {
190
202
  setMaxOutputTokens(maxTokens) {
191
203
  this.maxOutputTokens = maxTokens;
192
204
  }
205
+ setThinkingLevel(level) {
206
+ this.thinkingLevel = clampThinkingLevel(this.config, level);
207
+ return this.thinkingLevel;
208
+ }
209
+ getThinkingLevel() {
210
+ return this.thinkingLevel;
211
+ }
212
+ getSupportedThinkingLevels() {
213
+ return getSupportedThinkingLevels(this.config);
214
+ }
193
215
  };
194
216
  function imageDataUrl(block) {
195
217
  if (!isRecord(block) || block.type !== "image" || !isRecord(block.source)) {
@@ -386,17 +408,21 @@ var OpenAICompatClient = class {
386
408
  model;
387
409
  systemPrompt;
388
410
  maxOutputTokens;
411
+ thinkingLevel;
412
+ config;
389
413
  constructor(config, systemPrompt) {
390
414
  const apiKey = resolveAPIKey(config);
391
415
  if (!apiKey) {
392
416
  throw new AuthenticationError(
393
- "OpenAI API key not found. Set OPENAI_API_KEY in .swifty/config.y(a)ml, or via OPENAI_API_KEY env variable."
417
+ "OpenAI API key not found. Set OPENAI_API_KEY in ~/.swifty/config.yaml, or via OPENAI_API_KEY env variable."
394
418
  );
395
419
  }
396
420
  this.client = new OpenAI({ apiKey, baseURL: config.base_url });
397
421
  this.model = config.model;
398
422
  this.systemPrompt = systemPrompt;
399
423
  this.maxOutputTokens = getMaxOutputTokens(config);
424
+ this.config = { ...config };
425
+ this.thinkingLevel = getThinkingLevel(config);
400
426
  }
401
427
  setSystemPrompt(prompt) {
402
428
  this.systemPrompt = prompt;
@@ -404,6 +430,16 @@ var OpenAICompatClient = class {
404
430
  setMaxOutputTokens(maxTokens) {
405
431
  this.maxOutputTokens = maxTokens;
406
432
  }
433
+ setThinkingLevel(level) {
434
+ this.thinkingLevel = clampThinkingLevel(this.config, level);
435
+ return this.thinkingLevel;
436
+ }
437
+ getThinkingLevel() {
438
+ return this.thinkingLevel;
439
+ }
440
+ getSupportedThinkingLevels() {
441
+ return getSupportedThinkingLevels(this.config);
442
+ }
407
443
  async *stream(conversation, toolSchemas, abortSignal) {
408
444
  const messages = [
409
445
  {
@@ -420,16 +456,20 @@ var OpenAICompatClient = class {
420
456
  name: ts.name,
421
457
  description: ts.description,
422
458
  parameters: ts.input_schema,
423
- strict: false
459
+ strict: ts.strict ?? false
424
460
  }
425
461
  }));
462
+ const effort = toReasoningEffort(this.getThinkingLevel(), this.config);
426
463
  const params = {
427
464
  model: this.model,
428
465
  messages,
429
466
  stream: true,
430
467
  stream_options: { include_usage: true },
431
468
  max_tokens: this.maxOutputTokens,
432
- ...tools.length > 0 ? { tools } : {}
469
+ ...tools.length > 0 ? { tools } : {},
470
+ // Configured non-reasoning providers omit the field; off otherwise sends
471
+ // none explicitly so a server default cannot silently enable reasoning.
472
+ ...effort !== null ? { reasoning_effort: effort } : {}
433
473
  };
434
474
  let inputTokens = 0;
435
475
  let outputTokens = 0;
@@ -1,17 +1,23 @@
1
1
  import {
2
2
  normalizeToolResultContentBlock
3
- } from "./chunk-IB5IQK2S.js";
3
+ } from "./chunk-PIL7M52F.js";
4
4
  import {
5
5
  AuthenticationError,
6
6
  ContextTooLongError,
7
- DEFAULT_PROVIDER_THINKING,
8
7
  LLMError,
8
+ MIN_THINKING_ANSWER_TOKENS,
9
9
  NetworkError,
10
10
  RateLimitError,
11
+ clampThinkingLevel,
11
12
  ensureToolPairing,
12
13
  getMaxOutputTokens,
13
- resolveAPIKey
14
- } from "./chunk-FBSPZQGC.js";
14
+ getSupportedThinkingLevels,
15
+ getThinkingLevel,
16
+ resolveAPIKey,
17
+ thinkingBudgetForLevel,
18
+ toAnthropicThinkingEffort,
19
+ toReasoningEffort
20
+ } from "./chunk-OQIQOU5S.js";
15
21
  import {
16
22
  MCP_TOOL_PREFIX,
17
23
  isMcpToolLike
@@ -252,18 +258,16 @@ function buildAnthropicMessages(messages) {
252
258
  var AnthropicClient = class {
253
259
  client;
254
260
  model;
255
- /**
256
- * Whether supports/enable thinking, default false
257
- */
258
- thinking;
261
+ /** Effective logical level for budget or explicitly configured adaptive mode. */
262
+ thinkingLevel;
259
263
  systemPrompt;
260
264
  maxOutputTokens;
261
- /** Currently not used */
265
+ config;
262
266
  constructor(config, systemPrompt) {
263
267
  const apiKey = resolveAPIKey(config);
264
268
  if (!apiKey) {
265
269
  throw new AuthenticationError(
266
- "Anthropic API key not found, set ANTHROPIC_API_KEY in .swifty/config.y(a)ml, or via ANTHROPIC_API_KEY env variable."
270
+ "Anthropic API key not found, set ANTHROPIC_API_KEY in ~/.swifty/config.yaml, or via ANTHROPIC_API_KEY env variable."
267
271
  );
268
272
  }
269
273
  this.client = new Anthropic({
@@ -271,7 +275,8 @@ var AnthropicClient = class {
271
275
  baseURL: config.base_url
272
276
  });
273
277
  this.model = config.model;
274
- this.thinking = config.thinking ?? DEFAULT_PROVIDER_THINKING;
278
+ this.config = { ...config };
279
+ this.thinkingLevel = getThinkingLevel(config);
275
280
  this.systemPrompt = systemPrompt;
276
281
  this.maxOutputTokens = getMaxOutputTokens(config);
277
282
  }
@@ -279,24 +284,37 @@ var AnthropicClient = class {
279
284
  this.systemPrompt = prompt;
280
285
  }
281
286
  setMaxOutputTokens(maxTokens) {
282
- this.maxOutputTokens = maxTokens;
287
+ this.config = { ...this.config, max_output_tokens: maxTokens };
288
+ this.maxOutputTokens = getMaxOutputTokens(this.config);
289
+ this.setThinkingLevel(this.thinkingLevel);
290
+ }
291
+ setThinkingLevel(level) {
292
+ this.thinkingLevel = clampThinkingLevel(this.config, level);
293
+ return this.thinkingLevel;
294
+ }
295
+ getThinkingLevel() {
296
+ return this.thinkingLevel;
297
+ }
298
+ getSupportedThinkingLevels() {
299
+ return getSupportedThinkingLevels(this.config);
283
300
  }
284
301
  async *stream(conversation, toolSchemas, abortSignal) {
285
302
  const messages = buildAnthropicMessages(ensureToolPairing(conversation.getMessages()));
286
303
  const sendToolSearchBeta = needsToolSearchBeta(toolSchemas);
287
304
  const antToolSchemas = toolSchemas.map((s) => {
288
- const inputSchema = s.input_schema;
289
305
  const tool = {
290
306
  name: s.name,
291
307
  description: s.description,
292
- input_schema: {
293
- type: "object",
294
- properties: inputSchema.properties,
295
- required: inputSchema.required ?? []
296
- }
308
+ // Preserve constraints and definitions, not just properties/required.
309
+ input_schema: s.input_schema
297
310
  };
311
+ if (s.strict !== void 0) {
312
+ tool.strict = s.strict;
313
+ }
298
314
  if (s.defer_loading === true) {
299
315
  tool.defer_loading = true;
316
+ } else if (s.cache_control) {
317
+ tool.cache_control = s.cache_control;
300
318
  }
301
319
  return tool;
302
320
  });
@@ -319,7 +337,29 @@ var AnthropicClient = class {
319
337
  messages,
320
338
  ...antToolSchemas.length > 0 ? { tools: antToolSchemas } : {}
321
339
  };
322
- params.thinking = this.thinking && this.maxOutputTokens > 1024 ? { type: "enabled", budget_tokens: Math.min(16384, this.maxOutputTokens - 1) } : { type: "disabled" };
340
+ const level = this.getThinkingLevel();
341
+ if (this.config.reasoning !== false) {
342
+ if (level === "off") {
343
+ params.thinking = { type: "disabled" };
344
+ } else if (this.config.thinking_mode === "adaptive") {
345
+ const effort = toAnthropicThinkingEffort(level, this.config);
346
+ if (effort !== null) {
347
+ params.thinking = { type: "adaptive" };
348
+ params.output_config = { effort };
349
+ }
350
+ } else {
351
+ const effort = toReasoningEffort(level, this.config);
352
+ if (effort !== null && effort !== "none") {
353
+ params.thinking = {
354
+ type: "enabled",
355
+ budget_tokens: Math.min(
356
+ thinkingBudgetForLevel(effort),
357
+ this.maxOutputTokens - MIN_THINKING_ANSWER_TOKENS
358
+ )
359
+ };
360
+ }
361
+ }
362
+ }
323
363
  let inputTokens = 0;
324
364
  let outputTokens = 0;
325
365
  let cacheReadInputTokens = 0;