@psnext/slingcli 2.5.20260602-3 → 2.5.20260602-4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/sling.js CHANGED
@@ -128,6 +128,47 @@ function stripUpdateRequestFlags(argv) {
128
128
  return argv.filter((arg) => arg !== "-y" && arg !== "--yes");
129
129
  }
130
130
 
131
+ async function fetchLatestNpmVersion() {
132
+ try {
133
+ const res = await fetch("https://registry.npmjs.org/@psnext/slingcli/latest", {
134
+ signal: AbortSignal.timeout(10000),
135
+ headers: { accept: "application/json" },
136
+ });
137
+ if (!res.ok) return null;
138
+ const data = await res.json();
139
+ return typeof data?.version === "string" ? data.version : null;
140
+ } catch {
141
+ return null;
142
+ }
143
+ }
144
+
145
+ async function fetchRemoteAppConfig() {
146
+ try {
147
+ const res = await fetch(
148
+ "https://raw.githubusercontent.com/psnext/slingcli/main/sling-app-config.json",
149
+ {
150
+ signal: AbortSignal.timeout(5000),
151
+ headers: { accept: "application/json" },
152
+ },
153
+ );
154
+ if (!res.ok) return null;
155
+ const data = await res.json();
156
+ if (!data || typeof data !== "object") return null;
157
+
158
+ const minVersion = typeof data.minVersion === "string" ? data.minVersion : null;
159
+ const updateMessage = typeof data.updateMessage === "string" ? data.updateMessage : null;
160
+
161
+ if (!minVersion || !semver.valid(minVersion)) return null;
162
+
163
+ return {
164
+ minVersion,
165
+ updateMessage,
166
+ };
167
+ } catch {
168
+ return null;
169
+ }
170
+ }
171
+
131
172
  function stripSlingWrapperFlags(argv) {
132
173
  // Wrapper-only flags. They should not be forwarded to pi-coding-agent,
133
174
  // which does not recognize them.
@@ -246,27 +287,27 @@ async function checkForUpdate(args) {
246
287
 
247
288
  const autoYes = hasUpdateRequest(args);
248
289
 
249
- if (!autoYes && (!process.stdin.isTTY || !process.stdout.isTTY)) return;
250
-
251
- let latestVersion;
252
- try {
253
- const res = await fetch("https://registry.npmjs.org/@psnext/slingcli/latest", {
254
- signal: AbortSignal.timeout(10000),
255
- headers: { accept: "application/json" },
256
- });
257
- if (!res.ok) return;
258
- const data = await res.json();
259
- latestVersion = data.version;
260
- } catch {
261
- return;
262
- }
290
+ const [latestVersion, remoteConfig] = await Promise.all([
291
+ fetchLatestNpmVersion(),
292
+ fetchRemoteAppConfig(),
293
+ ]);
263
294
 
264
295
  if (!latestVersion || !semver.gt(latestVersion, SLING_VERSION)) return;
265
296
 
266
- console.log(`A new version ${latestVersion} is available (current ${SLING_VERSION}).`);
297
+ // Gate 2: force if current < minVersion (user is below the minimum required)
298
+ const shouldForceUpdate = remoteConfig && semver.lt(SLING_VERSION, remoteConfig.minVersion);
299
+
300
+ if (!shouldForceUpdate && !autoYes && (!process.stdin.isTTY || !process.stdout.isTTY)) return;
301
+
302
+ if (shouldForceUpdate) {
303
+ if (remoteConfig?.updateMessage) console.log(remoteConfig.updateMessage);
304
+ console.log(`Required version ${latestVersion} detected. Updating now...`);
305
+ } else {
306
+ console.log(`A new version ${latestVersion} is available (current ${SLING_VERSION}).`);
307
+ }
267
308
 
268
- let shouldUpdate = autoYes;
269
- if (!autoYes) {
309
+ let shouldUpdate = autoYes || shouldForceUpdate;
310
+ if (!shouldUpdate) {
270
311
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
271
312
  let answer;
272
313
  try {
@@ -286,6 +327,7 @@ async function checkForUpdate(args) {
286
327
  console.error("✗ Auto-update failed. Run manually:");
287
328
  console.error(" npm install -g @psnext/slingcli@latest");
288
329
  console.error(" (you may need sudo)");
330
+ if (shouldForceUpdate) process.exit(1);
289
331
  return;
290
332
  }
291
333
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@psnext/slingcli",
3
- "version": "2.5.20260602-3",
3
+ "version": "2.5.20260602-4",
4
4
  "description": "Connects Sling CLI to Publicis Sapient Slingshot enterprise LLM gateway. Bundles the pi coding-agent runtime.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -29,7 +29,7 @@
29
29
  "type": "git",
30
30
  "url": "git+https://pscode.lioncloud.net/psaiproducts/slingcli.git"
31
31
  },
32
- "slingVersion": "2.5.20260602-3",
32
+ "slingVersion": "2.5.20260602-4",
33
33
  "dependencies": {
34
34
  "@earendil-works/pi-tui": "file:../.sling-pack/earendil-works-pi-tui-0.78.0.tgz",
35
35
  "@earendil-works/pi-ai": "file:../.sling-pack/earendil-works-pi-ai-0.78.0.tgz",
@@ -444,7 +444,7 @@ Log file: ${qi}
444
444
  `;Ls.appendFileSync(qi,n)}catch{}}function Ve(t,e){if(!(!qi||!Ls||!Gl))try{let i=`[${new Date().toISOString()}] ${t}:
445
445
  ${JSON.stringify(e,null,2)}
446
446
 
447
- `;Ls.appendFileSync(qi,i)}catch{}}var Ws=null;function TM(t){if(!t)return;let e=t.trim();if(e)return e.replace(/\/+$/,"")}var we=class t{static{this.BASE_URL="base_url"}static{this.ANALYTICS_DOMAIN="analytics_domain"}static{this.CLIENT_ID="client_id"}static{this.PROJECT_ID="project_id"}static{this.WORKSPACE_ID="workspace_id"}static{this.defaultValues={[t.BASE_URL]:"https://sapientaiproducts.com",[t.ANALYTICS_DOMAIN]:"https://slingshot.sapientaiproducts.com",[t.CLIENT_ID]:"b97fbef7-cad9-4e56-9850-39e86c8fdf61",[t.PROJECT_ID]:"fa8121c4-e2fc-48f1-9478-8949c04e13cc",[t.WORKSPACE_ID]:"6e5756eb-d7e2-4d80-ad07-9d7a51600d85"}}static{this.LOGIN_PATH="/web/v1/studio-auth/login"}static{this.EXCHANGE_PATH="/api/v1/studio-auth/auth/desktop/exchange"}static{this.REFRESH_PATH="/api/v3/auth/refreshtoken"}static{this.REFRESH_CLIENT_NAME="machine"}static{this.API_BASE_PATH="/api/v1/llm"}static{this.SAGE_EVENTS_PATH="/api/v1/ai-portal/sage_events"}static{this.APP_TOKEN_PATH="/api/v3/auth/app-token"}static{this.CONFIG_SERVICE_PATH="/api/v2/configservice/client"}static{this.APP_TOKEN_REFRESH_BUFFER_MS=60*1e3}static{this.SLINGSHOT_APP_TOKEN_ENV="SLINGSHOT_APP_TOKEN_HEADER"}static{this.TOKEN_EXPIRY_BUFFER_MS=300*1e3}static{this.SAPI="/save/api/v1"}static{this.CLIENT_NAME="desktop"}static defaults(e){return this.defaultValues[e]}static getSettingsPath(){let e=Hl.resolve(process.cwd(),".sling","sling.settings.json");if(Gi.existsSync(e))return e;let n=Re();return Hl.resolve(n,"sling.settings.json")}static getSettings(){if(!Ws){let i=this.getSettingsPath();try{if(Gi.existsSync(i)){let s=Gi.readFileSync(i,"utf-8"),r=JSON.parse(s)||{};Ws={...this.defaultValues,...r}}else{let s=Hl.dirname(i);Gi.existsSync(s)||Gi.mkdirSync(s,{recursive:!0}),Gi.writeFileSync(i,JSON.stringify(this.defaultValues,null,2),"utf-8"),Ws={...this.defaultValues}}}catch(s){Ve("Error reading/writing sling.settings.json: ",s),Ws={...this.defaultValues}}}let e=TM(process.env.SLINGSHOT_API_DOMAIN),n=TM(process.env.SLINGSHOT_ANALYTICS_DOMAIN);return{...Ws,[t.BASE_URL]:e||Ws[t.BASE_URL],[t.ANALYTICS_DOMAIN]:n||Ws[t.ANALYTICS_DOMAIN]}}static updateSettings(e){let n=Re(),i=Hl.resolve(n,"sling.settings.json");try{let r={...this.getSettings()||{},...e},o=Hl.dirname(i);Gi.existsSync(o)||Gi.mkdirSync(o,{recursive:!0}),Gi.writeFileSync(i,JSON.stringify(r,null,2),"utf-8"),Ws=r}catch(s){Ve("Error updating sling.settings.json: ",s)}}static getLoginUrl(e){let n=this.getSettings(),i=new URLSearchParams({client:this.CLIENT_NAME,port:String(e.port),localState:e.localState});return e.clientId&&i.set("clientId",e.clientId),`${n[t.BASE_URL]}${this.LOGIN_PATH}?${i.toString()}`}static getExchangeUrl(){return`${this.getSettings()[t.BASE_URL]}${this.EXCHANGE_PATH}`}static getRefreshUrl(){let e=this.getSettings(),n=new URLSearchParams({client:this.REFRESH_CLIENT_NAME});return`${e[t.BASE_URL]}${this.REFRESH_PATH}?${n.toString()}`}static getApiBaseUrl(){return`${this.getSettings()[t.BASE_URL]}${this.API_BASE_PATH}`}static getSageEventsUrl(){return`${this.getSettings()[t.ANALYTICS_DOMAIN]}${this.SAGE_EVENTS_PATH}`}static getTokenExpiryBuffer(){return this.TOKEN_EXPIRY_BUFFER_MS}static getDefaultProjectId(){let e=this.getSettings();return process.env.SLINGSHOT_PROJECT_ID||e[t.PROJECT_ID]}static getDefaultWorkspaceId(){let e=this.getSettings();return process.env.SLINGSHOT_WORKSPACE_ID||e[t.WORKSPACE_ID]}static getDefaultClientId(){let e=this.getSettings();return process.env.CLIENT_ID||e[t.CLIENT_ID]}static getUserActivityUrl(){return`${this.getSettings()[t.BASE_URL]}${this.SAPI}/users/activity`}static getUserUrl(){return`${this.getSettings()[t.BASE_URL]}${this.SAPI}/users`}static getAppTokenUrl(){return`${this.getSettings()[t.BASE_URL]}${this.APP_TOKEN_PATH}`}static getConfigServiceUrl(e){let n=this.getSettings(),i=this.getDefaultClientId(),s=new URLSearchParams({keys:e});return`${n[t.BASE_URL]}${this.CONFIG_SERVICE_PATH}/${i}?${s.toString()}`}static getAppTokenRefreshBuffer(){return this.APP_TOKEN_REFRESH_BUFFER_MS}};function zl(t){try{let e=t.split(".");if(e.length!==3)return 0;let n=JSON.parse(atob(e[1]));return n.exp?n.exp*1e3:0}catch{return 0}}function Zp(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{let e=Math.random()*16|0;return(t==="x"?e:e&3|8).toString(16)})}function kM(){return`user_${Zp()}`}var rb="Xq7Wm2zR9pLkVbN4cD8fH3jT6yG1sA5",a8=BigInt(rb.length);function c8(t){if(t.length===0)return"";let e=0n;for(let i of t){let s=rb.indexOf(i);if(s===-1)throw new Error(`Cannot decode app_key: character "${i}" is not in the expected alphabet`);e=e*a8+BigInt(s)}let n=[];for(;e>0n;)n.unshift(Number(e&0xffn)),e>>=8n;for(let i of t)if(i===rb[0])n.unshift(0);else break;return new TextDecoder().decode(new Uint8Array(n))}var ob=new Map,eh=new Map;async function l8(t,e){let n=we.getConfigServiceUrl(t);Pe(`sling-config: fetching ${n}`);let i;try{i=await fetch(n,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${e}`}})}catch(o){let a=o instanceof Error?o.message:String(o);throw new Error(`Cannot reach config service: ${a}`)}if(!i.ok){let o=`${i.status} ${i.statusText}`;try{let a=await i.json();a.message?o=String(a.message):a.error&&(o=String(a.error))}catch{}throw new Error(`Config service request failed: ${o}`)}let r=(await i.json())?.data?.config;if(!r||typeof r!="object")throw new Error("Config service response missing data.config");return r}async function MM(t,e){let n=ob.get(t);if(n)return n;let i=eh.get(t);if(i)return i;if(!e)throw new Error("Cannot reach config service: no Slingshot user token provided");let s=l8(t,e).then(r=>(ob.set(t,r),r)).finally(()=>{eh.delete(t)});return eh.set(t,s),s}var sc=class{static async getSlingcliConfig(e){let n=await MM("slingcli",e),i=n.slingcli;if(!i||typeof i.app_id!="string"||typeof i.app_key!="string"||!i.app_id||!i.app_key)throw Ve("sling-config: missing slingcli block",n),new Error("Config service did not return slingcli.app_id / slingcli.app_key for this client");return{app_id:i.app_id,app_key:c8(i.app_key)}}static async getRemoteConfig(e,n){return MM(e,n)}static clearCache(){ob.clear(),eh=new Map}};import IM from"node:path";import Us from"node:fs";var u8="sling.app-creds.json";function ab(){return IM.resolve(Re(),u8)}function RM(){let t=ab();if(!Us.existsSync(t))return null;try{let e=Us.readFileSync(t,"utf-8"),n=JSON.parse(e);return typeof n.app_id!="string"||typeof n.app_key!="string"||!n.app_id||!n.app_key?(Ve("app-creds-store: invalid creds file, ignoring",n),null):{app_id:n.app_id,app_key:n.app_key}}catch(e){return Ve("app-creds-store: failed to read creds file",e),null}}function cb(t){let e=ab(),n=IM.dirname(e);try{Us.existsSync(n)||Us.mkdirSync(n,{recursive:!0});let i={...t,savedAt:Date.now()};Us.writeFileSync(e,JSON.stringify(i,null,2),{encoding:"utf-8",mode:384});try{Us.chmodSync(e,384)}catch{}Pe(`app-creds-store: persisted to ${e}`)}catch(i){Ve("app-creds-store: failed to persist creds",i)}}function PM(){let t=ab();try{Us.existsSync(t)&&(Us.unlinkSync(t),Pe(`app-creds-store: cleared ${t}`))}catch(e){Ve("app-creds-store: failed to clear creds file",e)}}var nh=class extends Error{constructor(n,i){super(i);this.status=n;this.name="AppTokenHttpError"}},Vl=null,Jl=null,th=null,rc=null;function _M(t){process.env[we.SLINGSHOT_APP_TOKEN_ENV]=`Bearer ${t}`}function d8(t){rc&&(clearTimeout(rc),rc=null);let e=t.expiresAt-Date.now();e<=0||(rc=setTimeout(()=>{rc=null,Ki().catch(n=>{Ve("app-token: scheduled refresh failed",n)})},e),rc.unref?.())}async function EM(t){let e=Buffer.from(`${t.app_id}:${t.app_key}`).toString("base64"),n=we.getAppTokenUrl();Pe(`app-token: minting from ${n}`);let i;try{i=await fetch(n,{method:"GET",headers:{Accept:"application/json",Authorization:`Basic ${e}`}})}catch(a){let c=a instanceof Error?a.message:String(a);throw new Error(`Cannot reach app-token service: ${c}`)}if(!i.ok){let a=`${i.status} ${i.statusText}`;try{let c=await i.text()||"";c&&(a=c)}catch{}throw new nh(i.status,`App token request failed: ${a}`)}let s=await i.json();if(!s.app_token||typeof s.expires_in!="number")throw new Error("App token response missing app_token or expires_in");let r=we.getAppTokenRefreshBuffer(),o=Date.now()+s.expires_in*1e3-r;return Pe(`app-token: minted, expires at ${new Date(o).toISOString()}`),{token:s.app_token,expiresAt:o}}async function p8(){let t=RM();if(t)return{creds:t,fromDisk:!0};if(!Jl)throw new Error("Cannot mint app token: no on-disk app credentials and no Slingshot user token available (please /login slingshot first)");let e=await sc.getSlingcliConfig(Jl);return cb(e),{creds:e,fromDisk:!1}}async function h8(){let{creds:t,fromDisk:e}=await p8();try{return await EM(t)}catch(n){let i=n instanceof nh&&(n.status===401||n.status===403);if(!e||!i)throw n;if(Ve("app-token: disk creds rejected (likely rotated), refetching from config service",{status:n.status}),PM(),!Jl)throw new Error("Cannot rotate app credentials: on-disk creds rejected and no Slingshot user token available (please /login slingshot)");let s=await sc.getSlingcliConfig(Jl);return cb(s),await EM(s)}}async function Ki(t){if(t&&(Jl=t),Vl&&Vl.expiresAt>Date.now())return _M(Vl.token),Vl.token;if(th)return(await th).token;let e=h8().then(i=>(Vl=i,_M(i.token),d8(i),i)).finally(()=>{th=null});return th=e,(await e).token}var Ql=null,lb=null;typeof process<"u"&&process.versions?.node&&(lb=import("node:http").then(t=>{Ql=t.createServer}));async function m8(){if(Ql||(lb&&await lb,Ql))return Ql;throw new Error("Slingshot OAuth requires Node.js")}async function ub(t){let e=await m8(),n,i,s,r=!1,o=new Promise((u,d)=>{i=u,s=d}),a=u=>{if(!r){r=!0;try{n.close()}catch{}u()}};n=e((u,d)=>{let p=new URL(u.url||"","http://127.0.0.1"),h=p.searchParams.get("code"),g=p.searchParams.get("state"),m=p.searchParams.get("clientId"),f=p.searchParams.get("error"),x=p.searchParams.get("error_description");if(f){d.writeHead(400,{"Content-Type":"text/html"}),d.end(`<html><body><h1>Login Failed</h1><p>${x||f}</p><p>You can close this window.</p></body></html>`),a(()=>s(new Error(`Login failed: ${x||f}`)));return}if(!h||!g){d.writeHead(400,{"Content-Type":"text/html"}),d.end("<html><body><h1>Login Failed</h1><p>Missing code or state in callback.</p><p>You can close this window.</p></body></html>"),a(()=>s(new Error("Missing code or state in callback")));return}d.writeHead(200,{"Content-Type":"text/html"}),d.end("<html><body><h1>Login Successful</h1><p>You can close this window and return to your terminal.</p><script>setTimeout(()=>window.close(),3000)</script></body></html>"),a(()=>i({code:h,state:g,clientId:m||""}))}),n.on("error",u=>{a(()=>s(u))});let c=setTimeout(()=>{a(()=>s(new Error("Login timeout - no callback received within 5 minutes")))},300*1e3);return n.on("close",()=>clearTimeout(c)),t&&t.addEventListener("abort",()=>{a(()=>s(new Error("Login cancelled")))}),{port:await new Promise((u,d)=>{n.once("error",d),n.listen(0,"127.0.0.1",()=>{let p=n.address();p&&typeof p=="object"?u(p.port):d(new Error("Failed to obtain loopback server port"))})}),result:o}}async function db(t,e){if(!t)throw new Error("Missing exchange code");if(!e)throw new Error("Missing clientId for exchange");let n=we.getExchangeUrl(),i;try{i=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",accept:"application/json"},body:JSON.stringify({code:t,clientId:e})})}catch(r){let o=r instanceof Error?r.message:String(r);throw new Error(`Cannot reach Studio Auth: ${o}`)}if(!i.ok){let r,o=`${i.status} ${i.statusText}`;try{let a=await i.json();r=a.error?.code,a.error?.message?o=a.error.message:a.message?o=a.message:r&&(o=r)}catch{}throw r==="INVALID_CALLBACK"?new Error("Login failed: exchange code is expired, already used, or bound to a different tenant. Please log in again."):new Error(`Code exchange failed: ${o}`)}let s=await i.json();if(!s.accessToken||!s.refreshToken)throw new Error("Exchange response missing accessToken or refreshToken");return s}function f8(){return g8(16).toString("hex")}function b8(t){let e=new URL(t),n=e.searchParams.get("code"),i=e.searchParams.get("state"),s=e.searchParams.get("clientId");if(!n||!i)throw new Error("Pasted URL is missing code or state");return{code:n,state:i,clientId:s||""}}async function pb(t){let e=process.env.SLINGSHOT_TOKEN;if(e){let u=zl(e);return Pe("Using Slingshot token from SLINGSHOT_TOKEN environment variable"),await Ki(e),{refresh:"",access:e,expires:u>0?u-we.getTokenExpiryBuffer():Date.now()+10800*1e3,projectId:process.env.SLINGSHOT_PROJECT_ID,workspaceId:process.env.SLINGSHOT_WORKSPACE_ID}}let{port:n,result:i}=await ub(t.signal),s=f8(),r=we.getDefaultClientId(),o=we.getLoginUrl({port:n,localState:s,clientId:r||void 0});t.onAuth({url:o});let a;if(t.onManualCodeInput){let u=t.onManualCodeInput().then(b8);a=await Promise.race([i,u])}else a=await i;if(a.state!==s)throw new Error("CSRF check failed - state does not match localState");if(!a.clientId)throw new Error("Login callback did not include clientId");let c=await db(a.code,a.clientId),l=zl(c.accessToken);return await Ki(c.accessToken),{refresh:c.refreshToken,access:c.accessToken,expires:l>0?l-we.getTokenExpiryBuffer():Date.now()+10800*1e3,projectId:void 0,workspaceId:void 0}}import{randomUUID as x8}from"node:crypto";async function ih(t){if(!t.refresh)throw new Error("No refresh token available. Please login again.");let e;try{e=await Ki()}catch(a){throw Ve("auth/refresh: app token unavailable for refresh call",a),new Error(`Cannot refresh Slingshot token: app token unavailable (${a instanceof Error?a.message:String(a)}). Please /login slingshot.`)}let n=x8(),i={accept:"application/json",rt:t.refresh,"trace-id":n,Authorization:`Bearer ${e}`},s;try{let a=we.getRefreshUrl();s=await fetch(a,{headers:i})}catch(a){let c=a instanceof Error?a.message:String(a);throw new Error(`Cannot reach Slingshot server: ${c}`)}if(!s.ok){let a=`${s.status} ${s.statusText}`;try{let c=await s.json();c.message?a=String(c.message):c.error&&(a=String(c.error))}catch{}throw new Error(`Token refresh failed: ${a}`)}let r=await s.json();if(!r.accessToken)throw new Error("No access token in refresh response");let o=zl(r.accessToken);try{await Ki(r.accessToken)}catch(a){throw Ve("auth/refresh: app token refresh failed",a),a}return{refresh:r.refreshToken||t.refresh,access:r.accessToken,expires:o>0?o-we.getTokenExpiryBuffer():Date.now()+10800*1e3,projectId:t.projectId,workspaceId:t.workspaceId}}var AM=[{id:"gpt-5.4-nano",name:"GPT-5.4 nano",reasoning:!0,thinkingLevelMap:{off:null,minimal:null,low:null,medium:null,high:null,xhigh:"xhigh"},input:["text","image"],cost:{input:.2,output:1.25,cacheRead:.02,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,api:"openai-completions",provider:"slingshot"},{id:"gpt-4.1",name:"GPT-4.1",reasoning:!1,input:["text","image"],cost:{input:2,output:8,cacheRead:.5,cacheWrite:0},contextWindow:1047576,maxTokens:32768,provider:"slingshot",api:"openai-completions"},{id:"gpt-5",name:"GPT-5",reasoning:!0,input:["text","image"],cost:{input:1.25,output:10,cacheRead:.125,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-completions"},{id:"gpt-5-mini",name:"GPT-5 Mini",reasoning:!0,input:["text","image"],cost:{input:.25,output:2,cacheRead:.025,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-completions"},{id:"gpt-5-nano",name:"GPT-5 Nano",reasoning:!0,input:["text","image"],cost:{input:.05,output:.4,cacheRead:.005,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-completions"},{id:"gpt-5.1",name:"GPT-5.1",reasoning:!0,input:["text","image"],cost:{input:1.25,output:10,cacheRead:.13,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-completions"},{id:"gpt-5.2",name:"GPT-5.2",reasoning:!0,input:["text","image"],cost:{input:1.75,output:14,cacheRead:.175,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-completions"},{id:"gpt-5.4-mini",name:"GPT-5.4 mini",reasoning:!0,thinkingLevelMap:{off:null,minimal:null,low:null,medium:null,high:null,xhigh:"xhigh"},input:["text","image"],cost:{input:.75,output:4.5,cacheRead:.075,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,api:"openai-completions",provider:"slingshot"},{id:"gpt-5.4",name:"GPT-5.4",reasoning:!0,thinkingLevelMap:{off:null,minimal:null,low:null,medium:null,high:null,xhigh:"xhigh"},input:["text","image"],cost:{input:2.5,output:15,cacheRead:.25,cacheWrite:0},contextWindow:272e3,maxTokens:128e3,api:"openai-completions",provider:"slingshot"},{id:"gpt-5.5",name:"GPT-5.5",reasoning:!0,thinkingLevelMap:{off:null,minimal:null,low:null,medium:null,high:null,xhigh:"xhigh"},input:["text","image"],cost:{input:5,output:30,cacheRead:.5,cacheWrite:0},contextWindow:272e3,maxTokens:128e3,api:"openai-completions",provider:"slingshot"},{id:"gpt-5.2-codex",name:"GPT-5.2 Codex",reasoning:!0,input:["text","image"],cost:{input:1.75,output:14,cacheRead:.175,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-codex-responses"},{id:"gpt-5.3-codex",name:"GPT-5.3 Codex",reasoning:!0,input:["text","image"],cost:{input:1.75,output:14,cacheRead:.175,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-codex-responses"},{id:"claude-opus-4@20250514",name:"Claude Opus 4",reasoning:!0,input:["text","image"],cost:{input:15,output:75,cacheRead:1.5,cacheWrite:18.75},contextWindow:2e5,maxTokens:32e3,provider:"slingshot",api:"openai-completions"},{id:"claude-sonnet-4@20250514",name:"Claude Sonnet 4",reasoning:!0,input:["text","image"],cost:{input:3,output:15,cacheRead:.3,cacheWrite:3.75},contextWindow:2e5,maxTokens:64e3,provider:"slingshot",api:"openai-completions"},{id:"claude-sonnet-4-5@20250929",name:"Claude Sonnet 4.5",reasoning:!0,input:["text","image"],cost:{input:3,output:15,cacheRead:.3,cacheWrite:3.75},contextWindow:2e5,maxTokens:64e3,provider:"slingshot",api:"openai-completions"},{id:"claude-sonnet-4-6",name:"Claude Sonnet 4.6",reasoning:!0,input:["text","image"],cost:{input:3,output:15,cacheRead:.3,cacheWrite:3.75},contextWindow:1e6,maxTokens:64e3,provider:"slingshot",api:"openai-completions"},{id:"claude-opus-4-6",name:"Claude Opus 4.6",reasoning:!0,input:["text","image"],cost:{input:5,output:25,cacheRead:.5,cacheWrite:6.25},contextWindow:1e6,maxTokens:128e3,provider:"slingshot",api:"openai-completions"},{id:"o3",name:"O3",reasoning:!0,input:["text","image"],cost:{input:2,output:8,cacheRead:.5,cacheWrite:0},contextWindow:2e5,maxTokens:1e5,provider:"slingshot",api:"openai-completions"},{id:"o3-mini",name:"o3-mini",reasoning:!0,input:["text"],cost:{input:1.1,output:4.4,cacheRead:.55,cacheWrite:0},contextWindow:2e5,maxTokens:1e5,provider:"slingshot",api:"openai-completions"},{id:"o4-mini",name:"o4-mini",reasoning:!0,input:["text"],cost:{input:1.1,output:4.4,cacheRead:.28,cacheWrite:0},contextWindow:2e5,maxTokens:1e5,provider:"slingshot",api:"openai-completions"},{id:"gemini-2.5-flash",name:"Gemini 2.5 Flash",reasoning:!0,input:["text","image"],cost:{input:.3,output:2.5,cacheRead:.075,cacheWrite:0},contextWindow:1048576,maxTokens:65536,provider:"slingshot",api:"openai-completions"}];var Er={name:"slingshot.cli",private:!0,type:"module",workspaces:["packages/*","packages/web-ui/example","packages/coding-agent/examples/extensions/with-deps","packages/coding-agent/examples/extensions/custom-provider-anthropic","packages/coding-agent/examples/extensions/custom-provider-gitlab-duo"],scripts:{clean:"npm run clean --workspaces",build:"cd packages/tui && npm run build && cd ../ai && npm run build && cd ../agent && npm run build && cd ../coding-agent && npm run build && cd ../web-ui && npm run build",dev:'concurrently --names "ai,agent,coding-agent,web-ui,tui" --prefix-colors "cyan,yellow,red,white,green,magenta" "cd packages/ai && npm run dev" "cd packages/agent && npm run dev" "cd packages/coding-agent && npm run dev" "cd packages/web-ui && npm run dev" "cd packages/tui && npm run dev"',"dev:tsc":'concurrently --names "ai,web-ui" --prefix-colors "cyan,green" "cd packages/ai && npm run dev:tsc" "cd packages/web-ui && npm run dev:tsc"',check:"","check:browser-smoke":"","profile:tui":"node scripts/profile-coding-agent-node.mjs --mode tui","profile:rpc":"node scripts/profile-coding-agent-node.mjs --mode rpc",test:"npm run test --workspaces --if-present","version:patch":"npm version patch -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install","version:minor":"npm version minor -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install","version:major":"npm version major -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install","version:set":"npm version -ws",prepublishOnly:"npm run clean && npm run build && npm run check",publish:"npm run prepublishOnly && npm publish -ws --access public","publish:dry":"npm run prepublishOnly && npm publish -ws --access public --dry-run","release:patch":"node scripts/release.mjs patch","release:minor":"node scripts/release.mjs minor","release:major":"node scripts/release.mjs major",prepare:"husky"},devDependencies:{"@anthropic-ai/sandbox-runtime":"0.0.26","@biomejs/biome":"2.3.5","@types/node":"22.19.19","@typescript/native-preview":"7.0.0-dev.20260120.1",concurrently:"^9.2.1",esbuild:"0.28.0",husky:"9.1.7",jiti:"2.7.0",shx:"0.4.0",tsx:"4.22.1",typescript:"5.9.3","@types/lodash.mergewith":"^4.6.9","fast-xml-parser":"^5.5.8",turbo:"^2.5.8",vitest:"^4.0.14"},engines:{node:">=20.0.0"},slingVersion:"2.5.20260602-3",overrides:{postcss:"8.5.14",next:{postcss:"8.5.14"},"ip-address":"^10.1.1","@modelcontextprotocol/sdk":"^1.29.0",ai:">=5.0.52","fast-xml-parser":"^5.5.8","@aws-sdk/xml-builder":{"fast-xml-parser":"^5.5.8"},"adaptivecards-templating":{"adaptive-expressions":{"fast-xml-parser":"^5.5.8"}},picomatch:"^4.0.4","path-to-regexp":"8.4.1",router:{"path-to-regexp":"8.4.1"},minimatch:"^10.2.3",tar:"7.5.11",react:"19.1.1","react-dom":"19.1.1","@types/react":"19","@types/react-dom":"19",tailwindcss:"4.1.12",lightningcss:"1.30.2",glob:{".":"11.1.0",minimatch:"10.2.3"},prismjs:"^1.30.0",qs:"^6.15.0","@hono/node-server":"1.19.14",protobufjs:"^8.2.0","@opentelemetry/otlp-transformer":{protobufjs:"^8.2.0"},langchain:{langsmith:">=0.7.0"},hono:"4.12.18",fsevents:"^2.3.3",swiper:"^12.1.2",lodash:"^4.18.0","lodash-es":"^4.18.1",axios:"^1.15.0","ibm-cloud-sdk-core":"^5.4.11",dompurify:">=3.4.0","react-markdown-mermaid":{mermaid:"10.9.6"}},dependencies:{"@modelcontextprotocol/sdk":"^1.29.0","@mozilla/readability":"^0.6.0","compound-engineering-pi":"^0.2.4","get-east-asian-width":"^1.4.0",linkedom:"^0.18.12",turndown:"^7.2.4",unpdf:"^1.6.2"}};var SRe=we.getRefreshUrl(),CRe=we.getApiBaseUrl(),TRe=we.getSageEventsUrl(),kRe=we.getTokenExpiryBuffer(),OM=we.getDefaultProjectId(),LM=we.getDefaultWorkspaceId(),WM=we.getDefaultClientId();async function sh(t,e,n){let i=kM(),s=await e.modelRegistry.getApiKeyForProvider(e.model?.provider||"slingshot");if(!s){Pe("ERROR: No API key found");return}let r=s.startsWith("Bearer ")?s:`Bearer ${s}`,o=process.env.SLINGSHOT_PROJECT_ID||OM,a=process.env.SLINGSHOT_WORKSPACE_ID||LM,c=process.env.CLIENT_ID||WM,l={"Content-Type":"application/json",accept:"application/json","access-token":r,"x-project-id":o,"x-workspace-id":a,"x-client-id":c,"sage-trace-id":i,"User-Agent":"pi-slingshot/1.0.0"},u=parseFloat(process.env.SLINGSHOT_TEMPERATURE||"0.2"),d=parseFloat(process.env.SLINGSHOT_TOP_P||"0.8"),p={source:Er.name||"sling",ai_model_info:{ai_provider_name:e.model?.provider||"slingshot",sage_modl_name:e.model?.id||"unknown",sage_modl_option:{temperature:String(u),max_token_size:String(e.model?.maxTokens||16834),top_p:String(d)}},rag_info:{type:null,account_name:"dummy",project_names:[],repository_names:[],programming_language:null},tab_data:{tab_count:"1"},tags:null,slingshot_version:Er.slingVersion||"2.3.2",chat_type:"agent",...n||{}};return{headers:l,sageCommonData:p}}async function rh(t,e,n,i){let s={eventName:t,sageCommonData:n,eventData:i};Pe(`Sending analytics event: ${t} : `+we.getSageEventsUrl());try{let r=await fetch(we.getSageEventsUrl(),{method:"POST",headers:e,body:JSON.stringify(s)});if(r.ok){let o=await r.json().catch(()=>{});if(o.error_code)throw new Error(`Analytics API error: ${o.error_code} - ${o.error_message||"No message"}`);Pe(`'SUCCESS: Event sent: ${t}`),Pe(`Response: ${JSON.stringify(o)}`),Pe("\u2500".repeat(66))}else{let o=await r.text().catch(()=>""),a={status:r.status,statusText:r.statusText,responseBody:o,requestHeaders:e};throw Pe(`ERROR: ${r.status} ${r.statusText}`),Ve("Error Details",a),Ve("Failed Request Body",s),new Error(`Analytics API error: ${r.status} ${r.statusText}`)}}catch(r){let o=r instanceof Error?r.message:String(r);console.warn("[Slingshot Analytics] Request that caused error:",o),Pe(`EXCEPTION: ${o}`),r instanceof Error&&r.stack&&Pe(`Stack trace: ${r.stack}`),Ve("Request that caused exception",s)}}import Yl from"chalk";function UM(t,e){return{render(n){let i=` \u26AC _______. __ __ .__ __. _______
447
+ `;Ls.appendFileSync(qi,i)}catch{}}var Ws=null;function TM(t){if(!t)return;let e=t.trim();if(e)return e.replace(/\/+$/,"")}var we=class t{static{this.BASE_URL="base_url"}static{this.ANALYTICS_DOMAIN="analytics_domain"}static{this.CLIENT_ID="client_id"}static{this.PROJECT_ID="project_id"}static{this.WORKSPACE_ID="workspace_id"}static{this.defaultValues={[t.BASE_URL]:"https://sapientaiproducts.com",[t.ANALYTICS_DOMAIN]:"https://slingshot.sapientaiproducts.com",[t.CLIENT_ID]:"b97fbef7-cad9-4e56-9850-39e86c8fdf61",[t.PROJECT_ID]:"fa8121c4-e2fc-48f1-9478-8949c04e13cc",[t.WORKSPACE_ID]:"6e5756eb-d7e2-4d80-ad07-9d7a51600d85"}}static{this.LOGIN_PATH="/web/v1/studio-auth/login"}static{this.EXCHANGE_PATH="/api/v1/studio-auth/auth/desktop/exchange"}static{this.REFRESH_PATH="/api/v3/auth/refreshtoken"}static{this.REFRESH_CLIENT_NAME="machine"}static{this.API_BASE_PATH="/api/v1/llm"}static{this.SAGE_EVENTS_PATH="/api/v1/ai-portal/sage_events"}static{this.APP_TOKEN_PATH="/api/v3/auth/app-token"}static{this.CONFIG_SERVICE_PATH="/api/v2/configservice/client"}static{this.APP_TOKEN_REFRESH_BUFFER_MS=60*1e3}static{this.SLINGSHOT_APP_TOKEN_ENV="SLINGSHOT_APP_TOKEN_HEADER"}static{this.TOKEN_EXPIRY_BUFFER_MS=300*1e3}static{this.SAPI="/save/api/v1"}static{this.CLIENT_NAME="desktop"}static defaults(e){return this.defaultValues[e]}static getSettingsPath(){let e=Hl.resolve(process.cwd(),".sling","sling.settings.json");if(Gi.existsSync(e))return e;let n=Re();return Hl.resolve(n,"sling.settings.json")}static getSettings(){if(!Ws){let i=this.getSettingsPath();try{if(Gi.existsSync(i)){let s=Gi.readFileSync(i,"utf-8"),r=JSON.parse(s)||{};Ws={...this.defaultValues,...r}}else{let s=Hl.dirname(i);Gi.existsSync(s)||Gi.mkdirSync(s,{recursive:!0}),Gi.writeFileSync(i,JSON.stringify(this.defaultValues,null,2),"utf-8"),Ws={...this.defaultValues}}}catch(s){Ve("Error reading/writing sling.settings.json: ",s),Ws={...this.defaultValues}}}let e=TM(process.env.SLINGSHOT_API_DOMAIN),n=TM(process.env.SLINGSHOT_ANALYTICS_DOMAIN);return{...Ws,[t.BASE_URL]:e||Ws[t.BASE_URL],[t.ANALYTICS_DOMAIN]:n||Ws[t.ANALYTICS_DOMAIN]}}static updateSettings(e){let n=Re(),i=Hl.resolve(n,"sling.settings.json");try{let r={...this.getSettings()||{},...e},o=Hl.dirname(i);Gi.existsSync(o)||Gi.mkdirSync(o,{recursive:!0}),Gi.writeFileSync(i,JSON.stringify(r,null,2),"utf-8"),Ws=r}catch(s){Ve("Error updating sling.settings.json: ",s)}}static getLoginUrl(e){let n=this.getSettings(),i=new URLSearchParams({client:this.CLIENT_NAME,port:String(e.port),localState:e.localState});return e.clientId&&i.set("clientId",e.clientId),`${n[t.BASE_URL]}${this.LOGIN_PATH}?${i.toString()}`}static getExchangeUrl(){return`${this.getSettings()[t.BASE_URL]}${this.EXCHANGE_PATH}`}static getRefreshUrl(){let e=this.getSettings(),n=new URLSearchParams({client:this.REFRESH_CLIENT_NAME});return`${e[t.BASE_URL]}${this.REFRESH_PATH}?${n.toString()}`}static getApiBaseUrl(){return`${this.getSettings()[t.BASE_URL]}${this.API_BASE_PATH}`}static getSageEventsUrl(){return`${this.getSettings()[t.ANALYTICS_DOMAIN]}${this.SAGE_EVENTS_PATH}`}static getTokenExpiryBuffer(){return this.TOKEN_EXPIRY_BUFFER_MS}static getDefaultProjectId(){let e=this.getSettings();return process.env.SLINGSHOT_PROJECT_ID||e[t.PROJECT_ID]}static getDefaultWorkspaceId(){let e=this.getSettings();return process.env.SLINGSHOT_WORKSPACE_ID||e[t.WORKSPACE_ID]}static getDefaultClientId(){let e=this.getSettings();return process.env.CLIENT_ID||e[t.CLIENT_ID]}static getUserActivityUrl(){return`${this.getSettings()[t.BASE_URL]}${this.SAPI}/users/activity`}static getUserUrl(){return`${this.getSettings()[t.BASE_URL]}${this.SAPI}/users`}static getAppTokenUrl(){return`${this.getSettings()[t.BASE_URL]}${this.APP_TOKEN_PATH}`}static getConfigServiceUrl(e){let n=this.getSettings(),i=this.getDefaultClientId(),s=new URLSearchParams({keys:e});return`${n[t.BASE_URL]}${this.CONFIG_SERVICE_PATH}/${i}?${s.toString()}`}static getAppTokenRefreshBuffer(){return this.APP_TOKEN_REFRESH_BUFFER_MS}};function zl(t){try{let e=t.split(".");if(e.length!==3)return 0;let n=JSON.parse(atob(e[1]));return n.exp?n.exp*1e3:0}catch{return 0}}function Zp(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{let e=Math.random()*16|0;return(t==="x"?e:e&3|8).toString(16)})}function kM(){return`user_${Zp()}`}var rb="Xq7Wm2zR9pLkVbN4cD8fH3jT6yG1sA5",a8=BigInt(rb.length);function c8(t){if(t.length===0)return"";let e=0n;for(let i of t){let s=rb.indexOf(i);if(s===-1)throw new Error(`Cannot decode app_key: character "${i}" is not in the expected alphabet`);e=e*a8+BigInt(s)}let n=[];for(;e>0n;)n.unshift(Number(e&0xffn)),e>>=8n;for(let i of t)if(i===rb[0])n.unshift(0);else break;return new TextDecoder().decode(new Uint8Array(n))}var ob=new Map,eh=new Map;async function l8(t,e){let n=we.getConfigServiceUrl(t);Pe(`sling-config: fetching ${n}`);let i;try{i=await fetch(n,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${e}`}})}catch(o){let a=o instanceof Error?o.message:String(o);throw new Error(`Cannot reach config service: ${a}`)}if(!i.ok){let o=`${i.status} ${i.statusText}`;try{let a=await i.json();a.message?o=String(a.message):a.error&&(o=String(a.error))}catch{}throw new Error(`Config service request failed: ${o}`)}let r=(await i.json())?.data?.config;if(!r||typeof r!="object")throw new Error("Config service response missing data.config");return r}async function MM(t,e){let n=ob.get(t);if(n)return n;let i=eh.get(t);if(i)return i;if(!e)throw new Error("Cannot reach config service: no Slingshot user token provided");let s=l8(t,e).then(r=>(ob.set(t,r),r)).finally(()=>{eh.delete(t)});return eh.set(t,s),s}var sc=class{static async getSlingcliConfig(e){let n=await MM("slingcli",e),i=n.slingcli;if(!i||typeof i.app_id!="string"||typeof i.app_key!="string"||!i.app_id||!i.app_key)throw Ve("sling-config: missing slingcli block",n),new Error("Config service did not return slingcli.app_id / slingcli.app_key for this client");return{app_id:i.app_id,app_key:c8(i.app_key)}}static async getRemoteConfig(e,n){return MM(e,n)}static clearCache(){ob.clear(),eh=new Map}};import IM from"node:path";import Us from"node:fs";var u8="sling.app-creds.json";function ab(){return IM.resolve(Re(),u8)}function RM(){let t=ab();if(!Us.existsSync(t))return null;try{let e=Us.readFileSync(t,"utf-8"),n=JSON.parse(e);return typeof n.app_id!="string"||typeof n.app_key!="string"||!n.app_id||!n.app_key?(Ve("app-creds-store: invalid creds file, ignoring",n),null):{app_id:n.app_id,app_key:n.app_key}}catch(e){return Ve("app-creds-store: failed to read creds file",e),null}}function cb(t){let e=ab(),n=IM.dirname(e);try{Us.existsSync(n)||Us.mkdirSync(n,{recursive:!0});let i={...t,savedAt:Date.now()};Us.writeFileSync(e,JSON.stringify(i,null,2),{encoding:"utf-8",mode:384});try{Us.chmodSync(e,384)}catch{}Pe(`app-creds-store: persisted to ${e}`)}catch(i){Ve("app-creds-store: failed to persist creds",i)}}function PM(){let t=ab();try{Us.existsSync(t)&&(Us.unlinkSync(t),Pe(`app-creds-store: cleared ${t}`))}catch(e){Ve("app-creds-store: failed to clear creds file",e)}}var nh=class extends Error{constructor(n,i){super(i);this.status=n;this.name="AppTokenHttpError"}},Vl=null,Jl=null,th=null,rc=null;function _M(t){process.env[we.SLINGSHOT_APP_TOKEN_ENV]=`Bearer ${t}`}function d8(t){rc&&(clearTimeout(rc),rc=null);let e=t.expiresAt-Date.now();e<=0||(rc=setTimeout(()=>{rc=null,Ki().catch(n=>{Ve("app-token: scheduled refresh failed",n)})},e),rc.unref?.())}async function EM(t){let e=Buffer.from(`${t.app_id}:${t.app_key}`).toString("base64"),n=we.getAppTokenUrl();Pe(`app-token: minting from ${n}`);let i;try{i=await fetch(n,{method:"GET",headers:{Accept:"application/json",Authorization:`Basic ${e}`}})}catch(a){let c=a instanceof Error?a.message:String(a);throw new Error(`Cannot reach app-token service: ${c}`)}if(!i.ok){let a=`${i.status} ${i.statusText}`;try{let c=await i.text()||"";c&&(a=c)}catch{}throw new nh(i.status,`App token request failed: ${a}`)}let s=await i.json();if(!s.app_token||typeof s.expires_in!="number")throw new Error("App token response missing app_token or expires_in");let r=we.getAppTokenRefreshBuffer(),o=Date.now()+s.expires_in*1e3-r;return Pe(`app-token: minted, expires at ${new Date(o).toISOString()}`),{token:s.app_token,expiresAt:o}}async function p8(){let t=RM();if(t)return{creds:t,fromDisk:!0};if(!Jl)throw new Error("Cannot mint app token: no on-disk app credentials and no Slingshot user token available (please /login slingshot first)");let e=await sc.getSlingcliConfig(Jl);return cb(e),{creds:e,fromDisk:!1}}async function h8(){let{creds:t,fromDisk:e}=await p8();try{return await EM(t)}catch(n){let i=n instanceof nh&&(n.status===401||n.status===403);if(!e||!i)throw n;if(Ve("app-token: disk creds rejected (likely rotated), refetching from config service",{status:n.status}),PM(),!Jl)throw new Error("Cannot rotate app credentials: on-disk creds rejected and no Slingshot user token available (please /login slingshot)");let s=await sc.getSlingcliConfig(Jl);return cb(s),await EM(s)}}async function Ki(t){if(t&&(Jl=t),Vl&&Vl.expiresAt>Date.now())return _M(Vl.token),Vl.token;if(th)return(await th).token;let e=h8().then(i=>(Vl=i,_M(i.token),d8(i),i)).finally(()=>{th=null});return th=e,(await e).token}var Ql=null,lb=null;typeof process<"u"&&process.versions?.node&&(lb=import("node:http").then(t=>{Ql=t.createServer}));async function m8(){if(Ql||(lb&&await lb,Ql))return Ql;throw new Error("Slingshot OAuth requires Node.js")}async function ub(t){let e=await m8(),n,i,s,r=!1,o=new Promise((u,d)=>{i=u,s=d}),a=u=>{if(!r){r=!0;try{n.close()}catch{}u()}};n=e((u,d)=>{let p=new URL(u.url||"","http://127.0.0.1"),h=p.searchParams.get("code"),g=p.searchParams.get("state"),m=p.searchParams.get("clientId"),f=p.searchParams.get("error"),x=p.searchParams.get("error_description");if(f){d.writeHead(400,{"Content-Type":"text/html"}),d.end(`<html><body><h1>Login Failed</h1><p>${x||f}</p><p>You can close this window.</p></body></html>`),a(()=>s(new Error(`Login failed: ${x||f}`)));return}if(!h||!g){d.writeHead(400,{"Content-Type":"text/html"}),d.end("<html><body><h1>Login Failed</h1><p>Missing code or state in callback.</p><p>You can close this window.</p></body></html>"),a(()=>s(new Error("Missing code or state in callback")));return}d.writeHead(200,{"Content-Type":"text/html"}),d.end("<html><body><h1>Login Successful</h1><p>You can close this window and return to your terminal.</p><script>setTimeout(()=>window.close(),3000)</script></body></html>"),a(()=>i({code:h,state:g,clientId:m||""}))}),n.on("error",u=>{a(()=>s(u))});let c=setTimeout(()=>{a(()=>s(new Error("Login timeout - no callback received within 5 minutes")))},300*1e3);return n.on("close",()=>clearTimeout(c)),t&&t.addEventListener("abort",()=>{a(()=>s(new Error("Login cancelled")))}),{port:await new Promise((u,d)=>{n.once("error",d),n.listen(0,"127.0.0.1",()=>{let p=n.address();p&&typeof p=="object"?u(p.port):d(new Error("Failed to obtain loopback server port"))})}),result:o}}async function db(t,e){if(!t)throw new Error("Missing exchange code");if(!e)throw new Error("Missing clientId for exchange");let n=we.getExchangeUrl(),i;try{i=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",accept:"application/json"},body:JSON.stringify({code:t,clientId:e})})}catch(r){let o=r instanceof Error?r.message:String(r);throw new Error(`Cannot reach Studio Auth: ${o}`)}if(!i.ok){let r,o=`${i.status} ${i.statusText}`;try{let a=await i.json();r=a.error?.code,a.error?.message?o=a.error.message:a.message?o=a.message:r&&(o=r)}catch{}throw r==="INVALID_CALLBACK"?new Error("Login failed: exchange code is expired, already used, or bound to a different tenant. Please log in again."):new Error(`Code exchange failed: ${o}`)}let s=await i.json();if(!s.accessToken||!s.refreshToken)throw new Error("Exchange response missing accessToken or refreshToken");return s}function f8(){return g8(16).toString("hex")}function b8(t){let e=new URL(t),n=e.searchParams.get("code"),i=e.searchParams.get("state"),s=e.searchParams.get("clientId");if(!n||!i)throw new Error("Pasted URL is missing code or state");return{code:n,state:i,clientId:s||""}}async function pb(t){let e=process.env.SLINGSHOT_TOKEN;if(e){let u=zl(e);return Pe("Using Slingshot token from SLINGSHOT_TOKEN environment variable"),await Ki(e),{refresh:"",access:e,expires:u>0?u-we.getTokenExpiryBuffer():Date.now()+10800*1e3,projectId:process.env.SLINGSHOT_PROJECT_ID,workspaceId:process.env.SLINGSHOT_WORKSPACE_ID}}let{port:n,result:i}=await ub(t.signal),s=f8(),r=we.getDefaultClientId(),o=we.getLoginUrl({port:n,localState:s,clientId:r||void 0});t.onAuth({url:o});let a;if(t.onManualCodeInput){let u=t.onManualCodeInput().then(b8);a=await Promise.race([i,u])}else a=await i;if(a.state!==s)throw new Error("CSRF check failed - state does not match localState");if(!a.clientId)throw new Error("Login callback did not include clientId");let c=await db(a.code,a.clientId),l=zl(c.accessToken);return await Ki(c.accessToken),{refresh:c.refreshToken,access:c.accessToken,expires:l>0?l-we.getTokenExpiryBuffer():Date.now()+10800*1e3,projectId:void 0,workspaceId:void 0}}import{randomUUID as x8}from"node:crypto";async function ih(t){if(!t.refresh)throw new Error("No refresh token available. Please login again.");let e;try{e=await Ki()}catch(a){throw Ve("auth/refresh: app token unavailable for refresh call",a),new Error(`Cannot refresh Slingshot token: app token unavailable (${a instanceof Error?a.message:String(a)}). Please /login slingshot.`)}let n=x8(),i={accept:"application/json",rt:t.refresh,"trace-id":n,Authorization:`Bearer ${e}`},s;try{let a=we.getRefreshUrl();s=await fetch(a,{headers:i})}catch(a){let c=a instanceof Error?a.message:String(a);throw new Error(`Cannot reach Slingshot server: ${c}`)}if(!s.ok){let a=`${s.status} ${s.statusText}`;try{let c=await s.json();c.message?a=String(c.message):c.error&&(a=String(c.error))}catch{}throw new Error(`Token refresh failed: ${a}`)}let r=await s.json();if(!r.accessToken)throw new Error("No access token in refresh response");let o=zl(r.accessToken);try{await Ki(r.accessToken)}catch(a){throw Ve("auth/refresh: app token refresh failed",a),a}return{refresh:r.refreshToken||t.refresh,access:r.accessToken,expires:o>0?o-we.getTokenExpiryBuffer():Date.now()+10800*1e3,projectId:t.projectId,workspaceId:t.workspaceId}}var AM=[{id:"gpt-5.4-nano",name:"GPT-5.4 nano",reasoning:!0,thinkingLevelMap:{off:null,minimal:null,low:null,medium:null,high:null,xhigh:"xhigh"},input:["text","image"],cost:{input:.2,output:1.25,cacheRead:.02,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,api:"openai-completions",provider:"slingshot"},{id:"gpt-4.1",name:"GPT-4.1",reasoning:!1,input:["text","image"],cost:{input:2,output:8,cacheRead:.5,cacheWrite:0},contextWindow:1047576,maxTokens:32768,provider:"slingshot",api:"openai-completions"},{id:"gpt-5",name:"GPT-5",reasoning:!0,input:["text","image"],cost:{input:1.25,output:10,cacheRead:.125,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-completions"},{id:"gpt-5-mini",name:"GPT-5 Mini",reasoning:!0,input:["text","image"],cost:{input:.25,output:2,cacheRead:.025,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-completions"},{id:"gpt-5-nano",name:"GPT-5 Nano",reasoning:!0,input:["text","image"],cost:{input:.05,output:.4,cacheRead:.005,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-completions"},{id:"gpt-5.1",name:"GPT-5.1",reasoning:!0,input:["text","image"],cost:{input:1.25,output:10,cacheRead:.13,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-completions"},{id:"gpt-5.2",name:"GPT-5.2",reasoning:!0,input:["text","image"],cost:{input:1.75,output:14,cacheRead:.175,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-completions"},{id:"gpt-5.4-mini",name:"GPT-5.4 mini",reasoning:!0,thinkingLevelMap:{off:null,minimal:null,low:null,medium:null,high:null,xhigh:"xhigh"},input:["text","image"],cost:{input:.75,output:4.5,cacheRead:.075,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,api:"openai-completions",provider:"slingshot"},{id:"gpt-5.4",name:"GPT-5.4",reasoning:!0,thinkingLevelMap:{off:null,minimal:null,low:null,medium:null,high:null,xhigh:"xhigh"},input:["text","image"],cost:{input:2.5,output:15,cacheRead:.25,cacheWrite:0},contextWindow:272e3,maxTokens:128e3,api:"openai-completions",provider:"slingshot"},{id:"gpt-5.5",name:"GPT-5.5",reasoning:!0,thinkingLevelMap:{off:null,minimal:null,low:null,medium:null,high:null,xhigh:"xhigh"},input:["text","image"],cost:{input:5,output:30,cacheRead:.5,cacheWrite:0},contextWindow:272e3,maxTokens:128e3,api:"openai-completions",provider:"slingshot"},{id:"gpt-5.2-codex",name:"GPT-5.2 Codex",reasoning:!0,input:["text","image"],cost:{input:1.75,output:14,cacheRead:.175,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-codex-responses"},{id:"gpt-5.3-codex",name:"GPT-5.3 Codex",reasoning:!0,input:["text","image"],cost:{input:1.75,output:14,cacheRead:.175,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-codex-responses"},{id:"claude-opus-4@20250514",name:"Claude Opus 4",reasoning:!0,input:["text","image"],cost:{input:15,output:75,cacheRead:1.5,cacheWrite:18.75},contextWindow:2e5,maxTokens:32e3,provider:"slingshot",api:"openai-completions"},{id:"claude-sonnet-4@20250514",name:"Claude Sonnet 4",reasoning:!0,input:["text","image"],cost:{input:3,output:15,cacheRead:.3,cacheWrite:3.75},contextWindow:2e5,maxTokens:64e3,provider:"slingshot",api:"openai-completions"},{id:"claude-sonnet-4-5@20250929",name:"Claude Sonnet 4.5",reasoning:!0,input:["text","image"],cost:{input:3,output:15,cacheRead:.3,cacheWrite:3.75},contextWindow:2e5,maxTokens:64e3,provider:"slingshot",api:"openai-completions"},{id:"claude-sonnet-4-6",name:"Claude Sonnet 4.6",reasoning:!0,input:["text","image"],cost:{input:3,output:15,cacheRead:.3,cacheWrite:3.75},contextWindow:1e6,maxTokens:64e3,provider:"slingshot",api:"openai-completions"},{id:"claude-opus-4-6",name:"Claude Opus 4.6",reasoning:!0,input:["text","image"],cost:{input:5,output:25,cacheRead:.5,cacheWrite:6.25},contextWindow:1e6,maxTokens:128e3,provider:"slingshot",api:"openai-completions"},{id:"o3",name:"O3",reasoning:!0,input:["text","image"],cost:{input:2,output:8,cacheRead:.5,cacheWrite:0},contextWindow:2e5,maxTokens:1e5,provider:"slingshot",api:"openai-completions"},{id:"o3-mini",name:"o3-mini",reasoning:!0,input:["text"],cost:{input:1.1,output:4.4,cacheRead:.55,cacheWrite:0},contextWindow:2e5,maxTokens:1e5,provider:"slingshot",api:"openai-completions"},{id:"o4-mini",name:"o4-mini",reasoning:!0,input:["text"],cost:{input:1.1,output:4.4,cacheRead:.28,cacheWrite:0},contextWindow:2e5,maxTokens:1e5,provider:"slingshot",api:"openai-completions"},{id:"gemini-2.5-flash",name:"Gemini 2.5 Flash",reasoning:!0,input:["text","image"],cost:{input:.3,output:2.5,cacheRead:.075,cacheWrite:0},contextWindow:1048576,maxTokens:65536,provider:"slingshot",api:"openai-completions"}];var Er={name:"slingshot.cli",private:!0,type:"module",workspaces:["packages/*","packages/web-ui/example","packages/coding-agent/examples/extensions/with-deps","packages/coding-agent/examples/extensions/custom-provider-anthropic","packages/coding-agent/examples/extensions/custom-provider-gitlab-duo"],scripts:{clean:"npm run clean --workspaces",build:"cd packages/tui && npm run build && cd ../ai && npm run build && cd ../agent && npm run build && cd ../coding-agent && npm run build && cd ../web-ui && npm run build",dev:'concurrently --names "ai,agent,coding-agent,web-ui,tui" --prefix-colors "cyan,yellow,red,white,green,magenta" "cd packages/ai && npm run dev" "cd packages/agent && npm run dev" "cd packages/coding-agent && npm run dev" "cd packages/web-ui && npm run dev" "cd packages/tui && npm run dev"',"dev:tsc":'concurrently --names "ai,web-ui" --prefix-colors "cyan,green" "cd packages/ai && npm run dev:tsc" "cd packages/web-ui && npm run dev:tsc"',check:"","check:browser-smoke":"","profile:tui":"node scripts/profile-coding-agent-node.mjs --mode tui","profile:rpc":"node scripts/profile-coding-agent-node.mjs --mode rpc",test:"npm run test --workspaces --if-present","version:patch":"npm version patch -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install","version:minor":"npm version minor -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install","version:major":"npm version major -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install","version:set":"npm version -ws",prepublishOnly:"npm run clean && npm run build && npm run check",publish:"npm run prepublishOnly && npm publish -ws --access public","publish:dry":"npm run prepublishOnly && npm publish -ws --access public --dry-run","release:patch":"node scripts/release.mjs patch","release:minor":"node scripts/release.mjs minor","release:major":"node scripts/release.mjs major",prepare:"husky"},devDependencies:{"@anthropic-ai/sandbox-runtime":"0.0.26","@biomejs/biome":"2.3.5","@types/node":"22.19.19","@typescript/native-preview":"7.0.0-dev.20260120.1",concurrently:"^9.2.1",esbuild:"0.28.0",husky:"9.1.7",jiti:"2.7.0",shx:"0.4.0",tsx:"4.22.1",typescript:"5.9.3","@types/lodash.mergewith":"^4.6.9","fast-xml-parser":"^5.5.8",turbo:"^2.5.8",vitest:"^4.0.14"},engines:{node:">=20.0.0"},slingVersion:"2.5.20260602-4",overrides:{postcss:"8.5.14",next:{postcss:"8.5.14"},"ip-address":"^10.1.1","@modelcontextprotocol/sdk":"^1.29.0",ai:">=5.0.52","fast-xml-parser":"^5.5.8","@aws-sdk/xml-builder":{"fast-xml-parser":"^5.5.8"},"adaptivecards-templating":{"adaptive-expressions":{"fast-xml-parser":"^5.5.8"}},picomatch:"^4.0.4","path-to-regexp":"8.4.1",router:{"path-to-regexp":"8.4.1"},minimatch:"^10.2.3",tar:"7.5.11",react:"19.1.1","react-dom":"19.1.1","@types/react":"19","@types/react-dom":"19",tailwindcss:"4.1.12",lightningcss:"1.30.2",glob:{".":"11.1.0",minimatch:"10.2.3"},prismjs:"^1.30.0",qs:"^6.15.0","@hono/node-server":"1.19.14",protobufjs:"^8.2.0","@opentelemetry/otlp-transformer":{protobufjs:"^8.2.0"},langchain:{langsmith:">=0.7.0"},hono:"4.12.18",fsevents:"^2.3.3",swiper:"^12.1.2",lodash:"^4.18.0","lodash-es":"^4.18.1",axios:"^1.15.0","ibm-cloud-sdk-core":"^5.4.11",dompurify:">=3.4.0","react-markdown-mermaid":{mermaid:"10.9.6"}},dependencies:{"@modelcontextprotocol/sdk":"^1.29.0","@mozilla/readability":"^0.6.0","compound-engineering-pi":"^0.2.4","get-east-asian-width":"^1.4.0",linkedom:"^0.18.12",turndown:"^7.2.4",unpdf:"^1.6.2"}};var SRe=we.getRefreshUrl(),CRe=we.getApiBaseUrl(),TRe=we.getSageEventsUrl(),kRe=we.getTokenExpiryBuffer(),OM=we.getDefaultProjectId(),LM=we.getDefaultWorkspaceId(),WM=we.getDefaultClientId();async function sh(t,e,n){let i=kM(),s=await e.modelRegistry.getApiKeyForProvider(e.model?.provider||"slingshot");if(!s){Pe("ERROR: No API key found");return}let r=s.startsWith("Bearer ")?s:`Bearer ${s}`,o=process.env.SLINGSHOT_PROJECT_ID||OM,a=process.env.SLINGSHOT_WORKSPACE_ID||LM,c=process.env.CLIENT_ID||WM,l={"Content-Type":"application/json",accept:"application/json","access-token":r,"x-project-id":o,"x-workspace-id":a,"x-client-id":c,"sage-trace-id":i,"User-Agent":"pi-slingshot/1.0.0"},u=parseFloat(process.env.SLINGSHOT_TEMPERATURE||"0.2"),d=parseFloat(process.env.SLINGSHOT_TOP_P||"0.8"),p={source:Er.name||"sling",ai_model_info:{ai_provider_name:e.model?.provider||"slingshot",sage_modl_name:e.model?.id||"unknown",sage_modl_option:{temperature:String(u),max_token_size:String(e.model?.maxTokens||16834),top_p:String(d)}},rag_info:{type:null,account_name:"dummy",project_names:[],repository_names:[],programming_language:null},tab_data:{tab_count:"1"},tags:null,slingshot_version:Er.slingVersion||"2.3.2",chat_type:"agent",...n||{}};return{headers:l,sageCommonData:p}}async function rh(t,e,n,i){let s={eventName:t,sageCommonData:n,eventData:i};Pe(`Sending analytics event: ${t} : `+we.getSageEventsUrl());try{let r=await fetch(we.getSageEventsUrl(),{method:"POST",headers:e,body:JSON.stringify(s)});if(r.ok){let o=await r.json().catch(()=>{});if(o.error_code)throw new Error(`Analytics API error: ${o.error_code} - ${o.error_message||"No message"}`);Pe(`'SUCCESS: Event sent: ${t}`),Pe(`Response: ${JSON.stringify(o)}`),Pe("\u2500".repeat(66))}else{let o=await r.text().catch(()=>""),a={status:r.status,statusText:r.statusText,responseBody:o,requestHeaders:e};throw Pe(`ERROR: ${r.status} ${r.statusText}`),Ve("Error Details",a),Ve("Failed Request Body",s),new Error(`Analytics API error: ${r.status} ${r.statusText}`)}}catch(r){let o=r instanceof Error?r.message:String(r);console.warn("[Slingshot Analytics] Request that caused error:",o),Pe(`EXCEPTION: ${o}`),r instanceof Error&&r.stack&&Pe(`Stack trace: ${r.stack}`),Ve("Request that caused exception",s)}}import Yl from"chalk";function UM(t,e){return{render(n){let i=` \u26AC _______. __ __ .__ __. _______
448
448
  \u274D \xB7 \u274D / || | | | | \\ | | / _____|
449
449
  \u2726 \u26AC \u2726 | (----\`| | | | | \\| | | | __
450
450
  \u26AC \xB7 \u26AC \u26AC \xB7 \u26AC \\ \\ | | | | | . \` | | | |_ |