@ycodium-ai/agent-pi 0.2.3598 → 0.2.3614

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -21,8 +21,8 @@ in `/v1`, without `/chat/completions` or `/responses`. For Anthropic Messages,
21
21
  supply the service root or a base URL ending in `/v1`; the runtime resolves the
22
22
  request route to `/v1/messages`. URLs must not contain embedded credentials,
23
23
  query parameters or a fragment. The model ID must be accepted by that service. The instance exposes
24
- that one configured model; its readiness check does not make a model request or
25
- verify API credentials. The first request checks access to the service.
24
+ the configured model plus the instance's custom models, all on the same endpoint and key;
25
+ its readiness check does not make a model request or verify API credentials. The first request checks access to the service.
26
26
 
27
27
  ## Install
28
28
 
@@ -48,7 +48,8 @@ is shown as invalid and must be explicitly replaced. Advanced configurations
48
48
  can also supply `YCODIUM_PI_API_BASE_URL`.
49
49
 
50
50
  The plugin starts `pi --mode rpc` through Ycodium's managed process API. It
51
- provides temporary model and MCP configuration, and enables Pi's built-in MCP and tool-search
51
+ provides temporary model and MCP configuration (every listed model under one `ycodium`
52
+ provider), and enables Pi's built-in MCP and tool-search
52
53
  extensions. MCP tools are discovered on demand rather than all advertised in the first request.
53
54
  Native session files live in a directory specific
54
55
  to the instance under `~/.pi/ycodium/`, unless a session directory is configured
@@ -60,9 +61,11 @@ history and require a new thread. Missing saved history is reported as an error;
60
61
  does not silently replace it with an empty conversation.
61
62
 
62
63
  Pi runs with full process permissions. It provides no sandbox or native per-tool
63
- approval flow. Context compaction and steering use native RPC operations. This
64
+ approval flow. Context compaction and steering use native RPC operations. Choosing another listed model
65
+ sends `set_model` before the next prompt in the same process; steering keeps the current model.
66
+ Models are declared without reasoning support, so no thinking-level option is exposed. This
64
67
  integration does not offer OAuth, an auxiliary text-generation assistant,
65
- mid-session model switching, inline image attachments, or a guarantee that an
68
+ inline image attachments, or a guarantee that an
66
69
  interrupted tool's external side effects have stopped. MCP transports are stdio
67
70
  and HTTP; legacy SSE is unsupported.
68
71
 
package/assets/ui.js CHANGED
@@ -1,4 +1,4 @@
1
- var C=window.__ycodiumPluginHost.modules?.["@ycodium-ai/plugin-api/provider-settings"];if(!C)throw new Error("This plugin needs a newer Ycodium app. Update the app.");var{PROVIDER_SETTINGS_VIEW_CAPABILITY:_,accountDirectoryCandidates:G,accountDirectorySlug:W,accountProbeHasSignedInAccount:q,allocateAccountDirectory:J,providerInstanceAccountPaths:Q}=C;var j=window.__ycodiumPluginHost.react;var{Activity:Z,Children:ee,Component:te,Fragment:oe,Profiler:ne,PureComponent:re,StrictMode:ie,Suspense:ae,__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE:se,__COMPILER_RUNTIME:ce,act:pe,cache:le,cacheSignal:ue,captureOwnerStack:de,cloneElement:me,createContext:b,createElement:w,createRef:ge,forwardRef:fe,isValidElement:Pe,lazy:ye,memo:we,startTransition:ve,unstable_useCacheRefresh:he,use:Se,useActionState:Ie,useCallback:xe,useContext:E,useDebugValue:Te,useDeferredValue:Ce,useEffect:A,useEffectEvent:_e,useId:R,useImperativeHandle:be,useInsertionEffect:Ee,useLayoutEffect:Ae,useMemo:Re,useOptimistic:Ne,useReducer:Ue,useRef:ke,useState:Oe,useSyncExternalStore:Le,useTransition:Be,version:De}=j;var N=b(null),U=N.Provider;function l(){let t=E(N);if(t===null)throw new Error("Pi UI has not been registered.");return t}var v=["openai-completions","openai-responses","anthropic-messages"],k="openai-completions";function u(t){return v.some(e=>e===t)}var h="connection",f="YCODIUM_PI_API_KEY";function S(t){try{let e=new URL(t.trim());return(e.protocol==="http:"||e.protocol==="https:")&&!e.username&&!e.password&&!e.search&&!e.hash}catch{return!1}}function O(t){let{apiProtocol:e,apiBaseUrl:i,model:p}=t.config,n=t.environment.find(a=>a.name===f);return(e===void 0||u(e))&&typeof i=="string"&&S(i)&&typeof p=="string"&&p.trim().length>0&&n!==void 0&&(n.valueRedacted===!0||n.value.trim().length>0)}function L(t,e){let i=t.trim();return!i&&e?{}:{environment:[{name:f,value:i,sensitive:!0}]}}function I(t){return w(l().ui.DraftInput,t)}function d(t){return(e=>w(l().ui[t],{...e,className:`ycodium-pi-ui ${typeof e.className=="string"?e.className:""}`}))}var B=d("Select"),D=d("SelectTrigger"),H=d("SelectPopup"),K=d("SelectItem"),V=d("SelectValue");function $(){let t=l().i18n.usePluginTranslation();return{t:(e,i)=>t(e,i)}}var{jsx:r,jsxs:c,Fragment:qe}=window.__ycodiumPluginHost.jsxRuntime;function M({instance:t,readOnly:e,onReport:i,onChange:p}){let{t:n}=$(),a=R(),P=O(t),x=P?n("connectionNotVerified"):void 0;A(()=>i({complete:P,hidesSignIn:!0,signInAfterAdd:!1,notice:x}),[P,x,i]);let T=t.environment.find(o=>o.name===f),m=T?.valueRedacted===!0,y=t.config.apiProtocol,s=y===void 0?k:u(y)?y:null;return c("div",{className:"ycodium-pi-ui grid min-w-0 gap-4",children:[c("div",{className:"grid min-w-0 gap-1",children:[r("span",{id:`${a}-protocol-label`,className:"text-control-4 font-medium",children:n("form.apiProtocol.title")}),c(B,{value:s,disabled:e,onValueChange:o=>{!e&&u(o)&&p({config:{apiProtocol:o}})},children:[r(D,{"aria-labelledby":`${a}-protocol-label`,"aria-describedby":`${a}-protocol-description`,"aria-invalid":s===null,children:r(V,{children:n(s===null?"connection.protocolUnknown":`connection.protocols.${s}`)})}),r(H,{children:v.map(o=>r(K,{value:o,children:n(`connection.protocols.${o}`)},o))})]}),r("span",{id:`${a}-protocol-description`,className:s===null?"text-ui-sm text-destructive-foreground":"text-ui-sm text-muted-foreground",children:n(s===null?"connection.invalidProtocol":"form.apiProtocol.description")})]}),["apiBaseUrl","model"].map(o=>c("label",{className:"grid min-w-0 gap-1",children:[r("span",{className:"text-control-4 font-medium",children:n(`form.${o}.title`)}),r(I,{value:typeof t.config[o]=="string"?t.config[o]:"",onCommit:g=>{e||p({config:{[o]:g.trim()}})},validate:g=>(o==="apiBaseUrl"?S(g):g.trim().length>0)?null:n(o==="apiBaseUrl"?"connection.invalidUrl":"connection.modelRequired"),disabled:e,autoComplete:"off",spellCheck:!1,"aria-label":n(`form.${o}.title`),"aria-describedby":`${a}-${o}-description`}),r("span",{id:`${a}-${o}-description`,className:"text-ui-sm text-muted-foreground",children:n(o==="apiBaseUrl"&&s!==null?`connection.baseUrlGuidance.${s}`:`form.${o}.description`)})]},o)),c("label",{className:"grid min-w-0 gap-1",children:[r("span",{className:"text-control-4 font-medium",children:n("connection.key")}),r(I,{type:"password",autoComplete:"off",spellCheck:!1,disabled:e,"aria-label":n("connection.key"),value:m?"":T?.value??"",placeholder:m?n("connection.stored"):void 0,validate:o=>m||o.trim()?null:n("connection.keyRequired"),onCommit:o=>{e||p(L(o,m))}})]})]})}var Y=`/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */
1
+ var C=window.__ycodiumPluginHost.modules?.["@ycodium-ai/plugin-api/provider-settings"];if(!C)throw new Error("This plugin needs a newer Ycodium app. Update the app.");var{PROVIDER_SETTINGS_VIEW_CAPABILITY:_,accountDirectoryCandidates:G,accountDirectorySlug:W,accountProbeHasSignedInAccount:q,allocateAccountDirectory:J,providerInstanceAccountPaths:Q}=C;var j=window.__ycodiumPluginHost.react;var{Activity:Z,Children:ee,Component:te,Fragment:oe,Profiler:ne,PureComponent:re,StrictMode:ie,Suspense:ae,__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE:se,__COMPILER_RUNTIME:ce,act:le,cache:pe,cacheSignal:ue,captureOwnerStack:de,cloneElement:me,createContext:b,createElement:w,createRef:ge,forwardRef:fe,isValidElement:Pe,lazy:ye,memo:we,startTransition:ve,unstable_useCacheRefresh:he,use:Se,useActionState:Ie,useCallback:xe,useContext:E,useDebugValue:Te,useDeferredValue:Ce,useEffect:A,useEffectEvent:_e,useId:R,useImperativeHandle:be,useInsertionEffect:Ee,useLayoutEffect:Ae,useMemo:Re,useOptimistic:Ne,useReducer:Ue,useRef:ke,useState:Oe,useSyncExternalStore:Le,useTransition:Be,version:De}=j;var N=b(null),U=N.Provider;function p(){let t=E(N);if(t===null)throw new Error("Pi UI has not been registered.");return t}var v=["openai-completions","openai-responses","anthropic-messages"],k="openai-completions";function u(t){return v.some(e=>e===t)}var h="connection",f="YCODIUM_PI_API_KEY";function S(t){try{let e=new URL(t.trim());return(e.protocol==="http:"||e.protocol==="https:")&&!e.username&&!e.password&&!e.search&&!e.hash}catch{return!1}}function O(t){let{apiProtocol:e,apiBaseUrl:i,model:l}=t.config,n=t.environment.find(a=>a.name===f);return(e===void 0||u(e))&&typeof i=="string"&&S(i)&&typeof l=="string"&&l.trim().length>0&&n!==void 0&&(n.valueRedacted===!0||n.value.trim().length>0)}function L(t,e){let i=t.trim();return!i&&e?{}:{environment:[{name:f,value:i,sensitive:!0}]}}function I(t){return w(p().ui.DraftInput,t)}function d(t){return(e=>w(p().ui[t],{...e,className:`ycodium-pi-ui ${typeof e.className=="string"?e.className:""}`}))}var B=d("Select"),D=d("SelectTrigger"),H=d("SelectPopup"),K=d("SelectItem"),V=d("SelectValue");function $(){let t=p().i18n.usePluginTranslation();return{t:(e,i)=>t(e,i)}}var{jsx:r,jsxs:c,Fragment:qe}=window.__ycodiumPluginHost.jsxRuntime;function M({instance:t,readOnly:e,onReport:i,onChange:l}){let{t:n}=$(),a=R(),P=O(t),x=P?n("connectionNotVerified"):void 0;A(()=>i({complete:P,hidesSignIn:!0,signInAfterAdd:!1,notice:x}),[P,x,i]);let T=t.environment.find(o=>o.name===f),m=T?.valueRedacted===!0,y=t.config.apiProtocol,s=y===void 0?k:u(y)?y:null;return c("div",{className:"ycodium-pi-ui grid min-w-0 gap-4",children:[c("div",{className:"grid min-w-0 gap-1",children:[r("span",{id:`${a}-protocol-label`,className:"text-control-4 font-medium",children:n("form.apiProtocol.title")}),c(B,{value:s,disabled:e,onValueChange:o=>{!e&&u(o)&&l({config:{apiProtocol:o}})},children:[r(D,{"aria-labelledby":`${a}-protocol-label`,"aria-describedby":s===null?`${a}-protocol-description`:void 0,"aria-invalid":s===null,children:r(V,{children:n(s===null?"connection.protocolUnknown":`connection.protocols.${s}`)})}),r(H,{children:v.map(o=>r(K,{value:o,children:n(`connection.protocols.${o}`)},o))})]}),s===null?r("span",{id:`${a}-protocol-description`,className:"text-ui-sm text-destructive-foreground",children:n("connection.invalidProtocol")}):null]}),["apiBaseUrl","model"].map(o=>c("label",{className:"grid min-w-0 gap-1",children:[r("span",{className:"text-control-4 font-medium",children:n(`form.${o}.title`)}),r(I,{value:typeof t.config[o]=="string"?t.config[o]:"",onCommit:g=>{e||l({config:{[o]:g.trim()}})},validate:g=>(o==="apiBaseUrl"?S(g):g.trim().length>0)?null:n(o==="apiBaseUrl"?"connection.invalidUrl":"connection.modelRequired"),disabled:e,autoComplete:"off",spellCheck:!1,"aria-label":n(`form.${o}.title`),"aria-describedby":`${a}-${o}-description`}),r("span",{id:`${a}-${o}-description`,className:"text-ui-sm text-muted-foreground",children:n(o==="apiBaseUrl"&&s!==null?`connection.baseUrlGuidance.${s}`:`form.${o}.description`)})]},o)),c("label",{className:"grid min-w-0 gap-1",children:[r("span",{className:"text-control-4 font-medium",children:n("connection.key")}),r(I,{type:"password",autoComplete:"off",spellCheck:!1,disabled:e,"aria-label":n("connection.key"),value:m?"":T?.value??"",placeholder:m?n("connection.stored"):void 0,validate:o=>m||o.trim()?null:n("connection.keyRequired"),onCommit:o=>{e||l(L(o,m))}})]})]})}var Y=`/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */
2
2
  @layer properties, theme, base, components, utilities;
3
3
  @layer properties;
4
4
  @layer utilities {
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ import { definePlugin } from "@ycodium-ai/plugin-api";
5
5
  import * as NodeCrypto from "node:crypto";
6
6
  import * as NodeOS from "node:os";
7
7
  import * as NodePath from "node:path";
8
+ import { matchCatalogModel } from "@ycodium-ai/plugin-api/executor";
8
9
 
9
10
  // src/protocol.ts
10
11
  var PI_API_PROTOCOLS = [
@@ -37,11 +38,16 @@ function parseConfig(value, instanceId) {
37
38
  );
38
39
  const configuredHome = string(config.homePath).trim();
39
40
  const homePath = configuredHome.startsWith("~/") || configuredHome.startsWith("~\\") ? NodePath.join(NodeOS.homedir(), configuredHome.slice(2)) : configuredHome;
41
+ const model = string(config.model).trim();
42
+ const custom = (Array.isArray(config.customModels) ? config.customModels : []).map(
43
+ (entry) => string(typeof entry === "string" ? entry : record(entry).slug).trim()
44
+ );
40
45
  return {
41
46
  binaryPath: string(config.binaryPath).trim() || "pi",
42
47
  apiBaseUrl: string(config.apiBaseUrl).trim() || environment.YCODIUM_PI_API_BASE_URL?.trim() || "",
43
48
  apiProtocol: readPiApiProtocol(config.apiProtocol),
44
- model: string(config.model).trim(),
49
+ model,
50
+ models: [...new Set([model, ...custom].filter(Boolean))],
45
51
  environment,
46
52
  homePath: homePath ? NodePath.resolve(homePath) : NodePath.join(NodeOS.homedir(), ".pi", "ycodium", identifier(instanceId))
47
53
  };
@@ -65,6 +71,18 @@ function validateConnection(config) {
65
71
  if (!config.model) throw new Error("Pi model ID is required.");
66
72
  if (!config.environment[PI_API_KEY_ENV]?.trim()) throw new Error("Pi API key is required.");
67
73
  }
74
+ function requestedModel(config, selection) {
75
+ const raw = string(record(selection).model).trim();
76
+ if (!raw) return void 0;
77
+ const id = matchCatalogModel(raw, config.models) ?? matchCatalogModel(raw.replace(/^ycodium\//, ""), config.models);
78
+ if (id) return id;
79
+ throw Object.assign(
80
+ new Error(
81
+ `Pi instance does not list model "${raw}". Choose one of: ${config.models.join(", ")}. Provider setting changes apply after the session restarts.`
82
+ ),
83
+ { code: "provider-rejected" }
84
+ );
85
+ }
68
86
  function redact(config, value) {
69
87
  let text = value instanceof Error ? value.message : String(value);
70
88
  for (const secret of Object.values(config.environment).filter(Boolean).sort((a, b) => b.length - a.length))
@@ -97,7 +115,7 @@ var PI_CARD = {
97
115
  verifiedSkills: false,
98
116
  everydayHarness: false,
99
117
  capabilities: {
100
- sessionModelSwitch: "unsupported",
118
+ sessionModelSwitch: "in-session",
101
119
  runtimeModeSwitch: "next-turn",
102
120
  contextCompaction: "native",
103
121
  turnSteering: true
@@ -114,8 +132,7 @@ var PI_CARD = {
114
132
  enum: PI_API_PROTOCOLS,
115
133
  default: DEFAULT_PI_API_PROTOCOL,
116
134
  "x-ycodium-form": {
117
- titleKey: "form.apiProtocol.title",
118
- descriptionKey: "form.apiProtocol.description"
135
+ titleKey: "form.apiProtocol.title"
119
136
  }
120
137
  },
121
138
  ...Object.fromEntries(
@@ -147,7 +164,8 @@ import {
147
164
  describeExecutorSpawnFailure,
148
165
  ExecutorSpawnAbortedError,
149
166
  ExecutorSpawnRefusedError,
150
- isExecutorSpawnFailure
167
+ isExecutorSpawnFailure,
168
+ raceAbort
151
169
  } from "@ycodium-ai/plugin-api/executor";
152
170
  import { runProcessOperation } from "@ycodium-ai/plugin-api/process-operation";
153
171
 
@@ -349,7 +367,7 @@ async function createLaunch(config, input, cursor) {
349
367
  baseUrl,
350
368
  api: apiProtocol,
351
369
  apiKey: `\${${PI_API_KEY_ENV}}`,
352
- models: [{ id: config.model }]
370
+ models: config.models.map((id) => ({ id }))
353
371
  }
354
372
  }
355
373
  }),
@@ -381,7 +399,7 @@ async function createLaunch(config, input, cursor) {
381
399
  "rpc",
382
400
  "--no-approve",
383
401
  "--model",
384
- `ycodium/${config.model}`,
402
+ `ycodium/${requestedModel(config, input?.modelSelection) ?? config.model}`,
385
403
  "--no-extensions",
386
404
  "--no-skills"
387
405
  ];
@@ -862,13 +880,6 @@ function createPiInstance(value, host) {
862
880
  const disposed = new AbortController();
863
881
  const now = () => (/* @__PURE__ */ new Date()).toISOString();
864
882
  const nativeMode = PI_NATIVE_MODE_REPORT;
865
- const validateModel = (selection) => {
866
- const model = string(record(selection).model).trim();
867
- if (model && model !== config.model && model !== `ycodium/${config.model}`)
868
- throw Object.assign(new Error("Pi can only run the model configured for this instance."), {
869
- code: "provider-rejected"
870
- });
871
- };
872
883
  const safeError = (cause) => {
873
884
  if (cause instanceof ExecutorSpawnRefusedError || cause instanceof ExecutorSpawnAbortedError)
874
885
  return cause;
@@ -992,6 +1003,8 @@ function createPiInstance(value, host) {
992
1003
  const abortTurn = async (booked, signal) => {
993
1004
  const turn = booked.turn, conn = booked.connection;
994
1005
  if (!turn || turn.completed || !conn) return;
1006
+ if (booked.dispatching) await raceAbort(booked.dispatching, signal);
1007
+ if (turn.completed) return;
995
1008
  await conn.rpc.request("clear_queue", {}, signal, 1e4);
996
1009
  await conn.rpc.request("abort", {}, signal, 1e4);
997
1010
  await waitForSettled(booked, turn, signal);
@@ -1019,7 +1032,7 @@ function createPiInstance(value, host) {
1019
1032
  const startOne = async (input, signal) => {
1020
1033
  ensureActive();
1021
1034
  validateConnection(config);
1022
- validateModel(input.modelSelection);
1035
+ const model = requestedModel(config, input.modelSelection) ?? config.model;
1023
1036
  signal?.throwIfAborted();
1024
1037
  const nativeModeId = piNativeModeFor(input.runtimeMode, input.nativeModeId);
1025
1038
  const existing = threads.get(input.threadId);
@@ -1037,7 +1050,7 @@ function createPiInstance(value, host) {
1037
1050
  runtimeMode: input.runtimeMode,
1038
1051
  nativeModeId,
1039
1052
  status: "starting",
1040
- model: config.model,
1053
+ model,
1041
1054
  createdAt: now(),
1042
1055
  updatedAt: now(),
1043
1056
  resumeCursor: cursor,
@@ -1199,10 +1212,13 @@ function createPiInstance(value, host) {
1199
1212
  startSession: start,
1200
1213
  sendTurn: async (input, signal) => {
1201
1214
  signal?.throwIfAborted();
1202
- validateModel(input.modelSelection);
1215
+ const requested = requestedModel(config, input.modelSelection);
1203
1216
  const booked = requireThread(input.threadId), conn = connection(booked);
1204
1217
  if (booked.stopping) throw new Error("Pi is stopping the current turn.");
1205
1218
  if (input.expectedTurnId !== void 0) {
1219
+ if (booked.dispatching) await raceAbort(booked.dispatching, signal);
1220
+ signal?.throwIfAborted();
1221
+ if (booked.stopping || booked.closing) throw new Error("Pi is stopping the current turn.");
1206
1222
  if (!booked.turn || booked.turn.id !== input.expectedTurnId || booked.turn.completed)
1207
1223
  throw Object.assign(new Error("The target Pi turn has ended."), {
1208
1224
  code: "provider-rejected"
@@ -1221,7 +1237,8 @@ function createPiInstance(value, host) {
1221
1237
  }
1222
1238
  if (booked.turn) throw new Error("Pi already has an active turn.");
1223
1239
  const cursor = record(booked.session.resumeCursor);
1224
- const turn = new PiTurn(booked.emit, config.model, string(cursor.sessionId), () => {
1240
+ const model = requested ?? booked.session.model ?? config.model;
1241
+ const turn = new PiTurn(booked.emit, model, string(cursor.sessionId), () => {
1225
1242
  if (booked.turn === turn) booked.turn = void 0;
1226
1243
  booked.session.status = "idle";
1227
1244
  booked.session.updatedAt = now();
@@ -1229,11 +1246,26 @@ function createPiInstance(value, host) {
1229
1246
  booked.turn = turn;
1230
1247
  booked.session.status = "running";
1231
1248
  turn.start();
1249
+ const issued = Promise.withResolvers();
1250
+ const dispatch = (async () => {
1251
+ try {
1252
+ if (model !== booked.session.model) {
1253
+ await conn.rpc.request("set_model", { provider: "ycodium", modelId: model }, signal);
1254
+ booked.session.model = model;
1255
+ }
1256
+ if (booked.stopping || booked.closing) return turn.finish("interrupted");
1257
+ const prompting = conn.rpc.request("prompt", { message: input.input ?? "" }, signal);
1258
+ issued.resolve();
1259
+ const response = record(await prompting);
1260
+ if (response.disposition === "handled") turn.finish("completed");
1261
+ } finally {
1262
+ issued.resolve();
1263
+ }
1264
+ })();
1265
+ const dispatched = issued.promise;
1266
+ booked.dispatching = dispatched;
1232
1267
  try {
1233
- const response = record(
1234
- await conn.rpc.request("prompt", { message: input.input ?? "" }, signal)
1235
- );
1236
- if (response.disposition === "handled") turn.finish("completed");
1268
+ await dispatch;
1237
1269
  return {
1238
1270
  threadId: input.threadId,
1239
1271
  turnId: turn.id,
@@ -1243,6 +1275,8 @@ function createPiInstance(value, host) {
1243
1275
  turn.finish("failed", redact(config, cause));
1244
1276
  if (!(cause instanceof PiResponseError)) await close(booked);
1245
1277
  throw safeError(cause);
1278
+ } finally {
1279
+ if (booked.dispatching === dispatched) booked.dispatching = void 0;
1246
1280
  }
1247
1281
  },
1248
1282
  interruptTurn: async (threadId, turnId, signal) => {
@@ -1375,7 +1409,7 @@ function createPiInstance(value, host) {
1375
1409
  // src/index.ts
1376
1410
  var index_default = definePlugin({
1377
1411
  id: "agent-pi",
1378
- apiVersion: 48,
1412
+ apiVersion: 49,
1379
1413
  executors: [
1380
1414
  { card: PI_CARD, createInstance: async (config, host) => createPiInstance(config, host) }
1381
1415
  ],
package/locales/en.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "setupNote": "Choose Chat Completions, OpenAI Responses or Anthropic Messages, then configure the API base URL, API key and model ID. Pi runs tools with the permissions of its process; it does not provide a sandbox or per-tool approvals.",
2
+ "setupNote": "Pi runs tools with the permissions of its process; it does not provide a sandbox or per-tool approvals.",
3
3
  "connectionNotVerified": "API credentials and model access will be checked on the first request.",
4
4
  "connection": {
5
5
  "protocolUnknown": "Choose a supported protocol",
@@ -22,8 +22,7 @@
22
22
  },
23
23
  "form": {
24
24
  "apiProtocol": {
25
- "title": "API protocol",
26
- "description": "Choose the request format supported by your API service."
25
+ "title": "API protocol"
27
26
  },
28
27
  "apiBaseUrl": {
29
28
  "title": "API base URL",
@@ -1,5 +1,5 @@
1
1
  {
2
- "setupNote": "选择 Chat Completions、OpenAI Responses 或 Anthropic Messages,再配置 API 地址、API Key 和模型名称。Pi 按进程权限执行工具,不提供沙箱或逐工具审批。",
2
+ "setupNote": "Pi 按进程权限执行工具,不提供沙箱或逐工具审批。",
3
3
  "connectionNotVerified": "首次请求时将验证 API 凭据和模型访问权限。",
4
4
  "connection": {
5
5
  "protocolUnknown": "请选择支持的协议",
@@ -22,14 +22,16 @@
22
22
  },
23
23
  "form": {
24
24
  "apiProtocol": {
25
- "title": "API 协议",
26
- "description": "选择 API 服务支持的请求格式。"
25
+ "title": "API 协议"
27
26
  },
28
27
  "apiBaseUrl": {
29
28
  "title": "API 地址",
30
29
  "description": "所选 API 协议的基础地址,不包含最终请求端点。"
31
30
  },
32
- "model": { "title": "模型名称", "description": "API 服务接受的准确模型 ID。" },
31
+ "model": {
32
+ "title": "模型名称",
33
+ "description": "API 服务接受的准确模型 ID。"
34
+ },
33
35
  "binaryPath": {
34
36
  "title": "Pi 程序",
35
37
  "description": "可选的 Pi 1.4.0 或更高版本程序路径。留空则从 PATH 查找 pi。"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ycodium-ai/agent-pi",
3
- "version": "0.2.3598",
3
+ "version": "0.2.3614",
4
4
  "description": "Pi executor over the native RPC protocol.",
5
5
  "keywords": [
6
6
  "ycodium",
@@ -30,7 +30,7 @@
30
30
  "tailwindcss": "^4.0.0",
31
31
  "typescript": "~6.0.3",
32
32
  "vite-plus": "0.2.2",
33
- "@ycodium-ai/plugin-api": "0.2.3598",
33
+ "@ycodium-ai/plugin-api": "0.2.3614",
34
34
  "ycodium-executor-testing": "0.0.0",
35
35
  "@ycodium/contracts": "0.0.33"
36
36
  },