pi-provider-litellm 1.2.7 → 1.2.9

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.
@@ -1,5 +1,5 @@
1
1
  import { type ToolDefinition } from "@earendil-works/pi-coding-agent";
2
2
  import type { LiteLLMMcpTool } from "./types.js";
3
- export declare function discoverMcpTools(baseUrl: string, apiKey: string): Promise<LiteLLMMcpTool[]>;
4
- export declare function executeMcpTool(baseUrl: string, apiKey: string, serverId: string, toolName: string, args: Record<string, unknown>): Promise<string>;
5
- export declare function createMcpToolDefinitions(baseUrl: string, getApiKey: () => Promise<string>): Promise<ToolDefinition[]>;
3
+ export declare function discoverMcpTools(baseUrl: string, apiKey: string, headers?: Record<string, string>): Promise<LiteLLMMcpTool[]>;
4
+ export declare function executeMcpTool(baseUrl: string, apiKey: string, serverId: string, toolName: string, args: Record<string, unknown>, headers?: Record<string, string>): Promise<string>;
5
+ export declare function createMcpToolDefinitions(baseUrl: string, getApiKey: () => Promise<string>, headers?: Record<string, string>): Promise<ToolDefinition[]>;
package/dist/mcp-tools.js CHANGED
@@ -3,6 +3,9 @@ import { defineTool } from "@earendil-works/pi-coding-agent";
3
3
  import { normalizeBaseUrl } from "./discover.js";
4
4
  const LIST_TIMEOUT_MS = 10_000;
5
5
  const CALL_TIMEOUT_MS = 30_000;
6
+ const MCP_RETRY_DELAY_MS = 350;
7
+ const MCP_RETRY_ATTEMPTS = 1;
8
+ const RETRYABLE_HTTP_STATUS = new Set([408, 425, 429, 500, 502, 503, 504]);
6
9
  function withTimeout(timeoutMs) {
7
10
  const controller = new AbortController();
8
11
  const timer = setTimeout(() => controller.abort(new Error(`Timed out after ${timeoutMs}ms`)), timeoutMs);
@@ -14,6 +17,23 @@ function withTimeout(timeoutMs) {
14
17
  function asRecord(value) {
15
18
  return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
16
19
  }
20
+ function sleep(ms) {
21
+ return new Promise((resolve) => setTimeout(resolve, ms));
22
+ }
23
+ function formatMcpToolError(toolName, serverId, error) {
24
+ return `Error calling ${toolName} on ${serverId}: ${error instanceof Error ? error.message : String(error)}`;
25
+ }
26
+ function isRetryableTransportError(error) {
27
+ if (!(error instanceof Error))
28
+ return false;
29
+ if (error.name === "AbortError" || error.name === "TimeoutError")
30
+ return true;
31
+ if (error.message.startsWith("Timed out after "))
32
+ return true;
33
+ if (error.name !== "TypeError")
34
+ return false;
35
+ return /fetch failed|failed to fetch|network|terminated|ECONNRESET|ECONNREFUSED|ETIMEDOUT|EAI_AGAIN|ENOTFOUND|socket/i.test(error.message);
36
+ }
17
37
  function stringValue(value) {
18
38
  return typeof value === "string" && value.trim() ? value.trim() : undefined;
19
39
  }
@@ -37,11 +57,12 @@ function normalizeMcpTool(value) {
37
57
  input_schema: inputSchema,
38
58
  };
39
59
  }
40
- export async function discoverMcpTools(baseUrl, apiKey) {
60
+ export async function discoverMcpTools(baseUrl, apiKey, headers) {
41
61
  const { signal, cancel } = withTimeout(LIST_TIMEOUT_MS);
42
62
  try {
43
63
  const response = await fetch(`${normalizeBaseUrl(baseUrl)}/mcp-rest/tools/list`, {
44
64
  headers: {
65
+ ...headers,
45
66
  Authorization: `Bearer ${apiKey}`,
46
67
  "Content-Type": "application/json",
47
68
  },
@@ -61,25 +82,59 @@ export async function discoverMcpTools(baseUrl, apiKey) {
61
82
  cancel();
62
83
  }
63
84
  }
64
- export async function executeMcpTool(baseUrl, apiKey, serverId, toolName, args) {
85
+ export async function executeMcpTool(baseUrl, apiKey, serverId, toolName, args, headers) {
86
+ for (let attempt = 0; attempt <= MCP_RETRY_ATTEMPTS; attempt++) {
87
+ const result = await executeMcpToolOnce(baseUrl, apiKey, serverId, toolName, args, headers);
88
+ if (attempt < MCP_RETRY_ATTEMPTS && result.retryable) {
89
+ await sleep(MCP_RETRY_DELAY_MS);
90
+ continue;
91
+ }
92
+ return result.text;
93
+ }
94
+ return `Error calling ${toolName} on ${serverId}: retry attempts exhausted`;
95
+ }
96
+ async function executeMcpToolOnce(baseUrl, apiKey, serverId, toolName, args, headers) {
65
97
  const { signal, cancel } = withTimeout(CALL_TIMEOUT_MS);
66
98
  try {
67
- const response = await fetch(`${normalizeBaseUrl(baseUrl)}/mcp-rest/tools/call`, {
68
- method: "POST",
69
- headers: {
70
- Authorization: `Bearer ${apiKey}`,
71
- "Content-Type": "application/json",
72
- },
73
- body: JSON.stringify({ server_id: serverId, name: toolName, arguments: args }),
74
- signal,
75
- });
76
- if (!response.ok)
77
- return `Error calling ${toolName} on ${serverId}: HTTP ${response.status}`;
78
- const body = (await response.json());
79
- return JSON.stringify("result" in body ? body.result : body, null, 2);
99
+ let response;
100
+ try {
101
+ response = await fetch(`${normalizeBaseUrl(baseUrl)}/mcp-rest/tools/call`, {
102
+ method: "POST",
103
+ headers: {
104
+ ...headers,
105
+ Authorization: `Bearer ${apiKey}`,
106
+ "Content-Type": "application/json",
107
+ },
108
+ body: JSON.stringify({ server_id: serverId, name: toolName, arguments: args }),
109
+ signal,
110
+ });
111
+ }
112
+ catch (error) {
113
+ return {
114
+ text: formatMcpToolError(toolName, serverId, error),
115
+ retryable: isRetryableTransportError(error),
116
+ };
117
+ }
118
+ if (!response.ok) {
119
+ return {
120
+ text: `Error calling ${toolName} on ${serverId}: HTTP ${response.status}`,
121
+ retryable: RETRYABLE_HTTP_STATUS.has(response.status),
122
+ };
123
+ }
124
+ try {
125
+ const body = (await response.json());
126
+ const bodyRecord = asRecord(body);
127
+ return {
128
+ text: JSON.stringify(bodyRecord && "result" in bodyRecord ? bodyRecord.result : body, null, 2),
129
+ retryable: false,
130
+ };
131
+ }
132
+ catch (error) {
133
+ return { text: formatMcpToolError(toolName, serverId, error), retryable: false };
134
+ }
80
135
  }
81
136
  catch (error) {
82
- return `Error calling ${toolName} on ${serverId}: ${error instanceof Error ? error.message : String(error)}`;
137
+ return { text: formatMcpToolError(toolName, serverId, error), retryable: false };
83
138
  }
84
139
  finally {
85
140
  cancel();
@@ -92,37 +147,6 @@ function sanitizeName(name) {
92
147
  .replace(/^_+|_+$/g, "");
93
148
  return sanitized || "tool";
94
149
  }
95
- function isMappableSchema(value) {
96
- if (!value || typeof value !== "object")
97
- return false;
98
- const schema = value;
99
- if ("$ref" in schema || "anyOf" in schema || "oneOf" in schema || "allOf" in schema)
100
- return false;
101
- if (["string", "number", "integer", "boolean"].includes(String(schema.type)))
102
- return true;
103
- if (schema.type === "array") {
104
- const items = schema.items;
105
- return items?.type === "string";
106
- }
107
- return false;
108
- }
109
- function mapPropertySchema(name, schema) {
110
- const description = typeof schema.description === "string" ? schema.description : name;
111
- switch (schema.type) {
112
- case "string":
113
- return Type.String({ description });
114
- case "number":
115
- return Type.Number({ description });
116
- case "integer":
117
- return Type.Integer({ description });
118
- case "boolean":
119
- return Type.Boolean({ description });
120
- case "array":
121
- return Type.Array(Type.String(), { description });
122
- default:
123
- return Type.Unknown({ description });
124
- }
125
- }
126
150
  function buildParameters(inputSchema) {
127
151
  const properties = inputSchema.properties;
128
152
  if (!properties || typeof properties !== "object") {
@@ -130,24 +154,11 @@ function buildParameters(inputSchema) {
130
154
  args: Type.Record(Type.String(), Type.Unknown(), { description: "Tool arguments as key-value pairs" }),
131
155
  });
132
156
  }
133
- const required = Array.isArray(inputSchema.required)
134
- ? inputSchema.required.filter((key) => typeof key === "string")
135
- : [];
136
- const mapped = {};
137
- for (const [key, property] of Object.entries(properties)) {
138
- if (!isMappableSchema(property)) {
139
- return Type.Object({
140
- args: Type.Record(Type.String(), Type.Unknown(), { description: "Tool arguments as key-value pairs" }),
141
- });
142
- }
143
- const field = mapPropertySchema(key, property);
144
- mapped[key] = required.includes(key) ? field : Type.Optional(field);
145
- }
146
- return Type.Object(mapped);
157
+ return Type.Unsafe(inputSchema);
147
158
  }
148
- export async function createMcpToolDefinitions(baseUrl, getApiKey) {
159
+ export async function createMcpToolDefinitions(baseUrl, getApiKey, headers) {
149
160
  const discoveryApiKey = await getApiKey();
150
- const tools = await discoverMcpTools(baseUrl, discoveryApiKey);
161
+ const tools = await discoverMcpTools(baseUrl, discoveryApiKey, headers);
151
162
  return tools.map((mcpTool) => {
152
163
  const safeServer = sanitizeName(mcpTool.server_name);
153
164
  const safeTool = sanitizeName(mcpTool.name);
@@ -157,6 +168,7 @@ export async function createMcpToolDefinitions(baseUrl, getApiKey) {
157
168
  label: `${mcpTool.server_name}: ${mcpTool.name}`,
158
169
  description: `${mcpTool.description} (via ${mcpTool.server_name} MCP server)`,
159
170
  promptSnippet: `${mcpTool.description} via ${mcpTool.server_name} MCP server`,
171
+ executionMode: "parallel",
160
172
  parameters,
161
173
  async execute(_toolCallId, params) {
162
174
  const apiKey = await getApiKey();
@@ -164,7 +176,7 @@ export async function createMcpToolDefinitions(baseUrl, getApiKey) {
164
176
  const args = Object.keys(rawParams).length === 1 && rawParams.args && typeof rawParams.args === "object"
165
177
  ? rawParams.args
166
178
  : rawParams;
167
- const text = await executeMcpTool(baseUrl, apiKey, mcpTool.server_id ?? mcpTool.server_name, mcpTool.name, args);
179
+ const text = await executeMcpTool(baseUrl, apiKey, mcpTool.server_id ?? mcpTool.server_name, mcpTool.name, args, headers);
168
180
  return {
169
181
  content: [{ type: "text", text }],
170
182
  details: { server: mcpTool.server_name, serverId: mcpTool.server_id, tool: mcpTool.name },
package/dist/skills.d.ts CHANGED
@@ -1,13 +1,14 @@
1
1
  import { type ToolDefinition } from "@earendil-works/pi-coding-agent";
2
2
  import type { LiteLLMSkill } from "./types.js";
3
- export declare function listSkills(baseUrl: string, apiKey: string): Promise<LiteLLMSkill[]>;
3
+ export declare function listSkills(baseUrl: string, apiKey: string, headers?: Record<string, string>): Promise<LiteLLMSkill[]>;
4
4
  export declare function createSkill(baseUrl: string, apiKey: string, input: {
5
5
  name: string;
6
- description: string;
7
- code: string;
6
+ description?: string;
7
+ source?: Record<string, unknown>;
8
+ code?: string;
8
9
  inputSchema?: Record<string, unknown>;
9
- }): Promise<unknown>;
10
- export declare function deleteSkill(baseUrl: string, apiKey: string, skillId: string): Promise<void>;
10
+ }, headers?: Record<string, string>): Promise<unknown>;
11
+ export declare function deleteSkill(baseUrl: string, apiKey: string, skillId: string, headers?: Record<string, string>): Promise<void>;
11
12
  export declare function createSkillsPromptSection(skills: LiteLLMSkill[]): string | undefined;
12
- export declare function createSkillToolDefinitions(baseUrl: string, getApiKey: () => Promise<string>): ToolDefinition[];
13
+ export declare function createSkillToolDefinitions(baseUrl: string, getApiKey: () => Promise<string>, headers?: Record<string, string>): ToolDefinition[];
13
14
  export declare function resetSkillsCache(): void;
package/dist/skills.js CHANGED
@@ -8,6 +8,8 @@ function getSkillsFromBody(body) {
8
8
  return body;
9
9
  if (body && typeof body === "object") {
10
10
  const record = body;
11
+ if (Array.isArray(record.plugins))
12
+ return record.plugins;
11
13
  if (Array.isArray(record.data))
12
14
  return record.data;
13
15
  if (Array.isArray(record.skills))
@@ -15,7 +17,7 @@ function getSkillsFromBody(body) {
15
17
  }
16
18
  return [];
17
19
  }
18
- export async function listSkills(baseUrl, apiKey) {
20
+ export async function listSkills(baseUrl, apiKey, headers) {
19
21
  const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
20
22
  if (skillsCache &&
21
23
  skillsCache.baseUrl === normalizedBaseUrl &&
@@ -23,47 +25,110 @@ export async function listSkills(baseUrl, apiKey) {
23
25
  Date.now() - skillsCache.fetchedAt < SKILLS_CACHE_TTL_MS) {
24
26
  return skillsCache.skills;
25
27
  }
26
- try {
27
- const response = await fetch(`${normalizedBaseUrl}/v1/skills`, {
28
- headers: { Authorization: `Bearer ${apiKey}`, Accept: "application/json" },
29
- signal: AbortSignal.timeout(10_000),
30
- });
31
- if (!response.ok)
28
+ const fetchSkills = async (path) => {
29
+ try {
30
+ const response = await fetch(`${normalizedBaseUrl}${path}`, {
31
+ headers: { ...headers, Authorization: `Bearer ${apiKey}`, Accept: "application/json" },
32
+ signal: AbortSignal.timeout(10_000),
33
+ });
34
+ return response.ok ? getSkillsFromBody(await response.json()) : [];
35
+ }
36
+ catch {
32
37
  return [];
33
- const skills = getSkillsFromBody(await response.json());
34
- skillsCache = { baseUrl: normalizedBaseUrl, apiKey, fetchedAt: Date.now(), skills };
35
- return skills;
36
- }
37
- catch {
38
- return [];
39
- }
38
+ }
39
+ };
40
+ const [skillHub, legacy] = await Promise.all([
41
+ fetchSkills("/claude-code/marketplace.json"),
42
+ fetchSkills("/v1/skills"),
43
+ ]);
44
+ const skillHubNames = new Set(skillHub.map((skill) => skill.name));
45
+ const skills = [...skillHub, ...legacy.filter((skill) => !skillHubNames.has(skill.name))];
46
+ skillsCache = { baseUrl: normalizedBaseUrl, apiKey, fetchedAt: Date.now(), skills };
47
+ return skills;
40
48
  }
41
- export async function createSkill(baseUrl, apiKey, input) {
42
- const response = await fetch(`${normalizeBaseUrl(baseUrl)}/v1/skills`, {
49
+ export async function createSkill(baseUrl, apiKey, input, headers) {
50
+ if (!input.source && !input.code)
51
+ throw new Error("code is required when source is omitted");
52
+ const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
53
+ let usedSkillHub = input.source !== undefined;
54
+ const skillHubPayload = input.source
55
+ ? {
56
+ name: input.name,
57
+ description: input.description,
58
+ source: input.source,
59
+ }
60
+ : {
61
+ name: input.name,
62
+ description: input.description,
63
+ code: input.code,
64
+ input_schema: input.inputSchema ?? { type: "object", properties: {} },
65
+ };
66
+ let response = await fetch(`${normalizedBaseUrl}${input.source ? "/claude-code/plugins" : "/v1/skills"}`, {
43
67
  method: "POST",
44
68
  headers: {
69
+ ...headers,
45
70
  Authorization: `Bearer ${apiKey}`,
46
71
  "Content-Type": "application/json",
47
72
  },
48
- body: JSON.stringify({
49
- name: input.name,
50
- description: input.description,
51
- code: input.code,
52
- input_schema: input.inputSchema ?? { type: "object", properties: {} },
53
- }),
73
+ body: JSON.stringify(skillHubPayload),
54
74
  signal: AbortSignal.timeout(10_000),
55
75
  });
76
+ if (input.source && response.status === 404) {
77
+ usedSkillHub = false;
78
+ response = await fetch(`${normalizedBaseUrl}/v1/skills`, {
79
+ method: "POST",
80
+ headers: {
81
+ ...headers,
82
+ Authorization: `Bearer ${apiKey}`,
83
+ "Content-Type": "application/json",
84
+ },
85
+ body: JSON.stringify({
86
+ name: input.name,
87
+ description: input.description,
88
+ code: input.code,
89
+ input_schema: input.inputSchema ?? { type: "object", properties: {} },
90
+ }),
91
+ signal: AbortSignal.timeout(10_000),
92
+ });
93
+ }
56
94
  if (!response.ok)
57
95
  throw new Error(`LiteLLM skill create failed: HTTP ${response.status}`);
58
96
  skillsCache = undefined;
97
+ if (usedSkillHub) {
98
+ const enableResponse = await fetch(`${normalizedBaseUrl}/claude-code/plugins/${encodeURIComponent(input.name)}/enable`, {
99
+ method: "POST",
100
+ headers: { ...headers, Authorization: `Bearer ${apiKey}` },
101
+ signal: AbortSignal.timeout(10_000),
102
+ });
103
+ if (!enableResponse.ok)
104
+ throw new Error(`LiteLLM skill enable failed: HTTP ${enableResponse.status}`);
105
+ }
59
106
  return response.json().catch(() => ({}));
60
107
  }
61
- export async function deleteSkill(baseUrl, apiKey, skillId) {
62
- const response = await fetch(`${normalizeBaseUrl(baseUrl)}/v1/skills/${encodeURIComponent(skillId)}`, {
108
+ export async function deleteSkill(baseUrl, apiKey, skillId, headers) {
109
+ const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
110
+ let skillHubError;
111
+ const skillHubResponse = await fetch(`${normalizedBaseUrl}/claude-code/plugins/${encodeURIComponent(skillId)}`, {
63
112
  method: "DELETE",
64
- headers: { Authorization: `Bearer ${apiKey}` },
113
+ headers: { ...headers, Authorization: `Bearer ${apiKey}`, Accept: "application/json" },
65
114
  signal: AbortSignal.timeout(10_000),
115
+ }).catch((error) => {
116
+ skillHubError = error;
117
+ return undefined;
66
118
  });
119
+ let response = skillHubResponse;
120
+ if (!response || response.status === 404 || response.status >= 500) {
121
+ response = await fetch(`${normalizedBaseUrl}/v1/skills/${encodeURIComponent(skillId)}`, {
122
+ method: "DELETE",
123
+ headers: { ...headers, Authorization: `Bearer ${apiKey}` },
124
+ signal: AbortSignal.timeout(10_000),
125
+ });
126
+ }
127
+ if (response.status === 404 && skillHubResponse?.status !== 404) {
128
+ if (skillHubError instanceof Error)
129
+ throw skillHubError;
130
+ throw new Error(`LiteLLM skill delete failed: HTTP ${skillHubResponse?.status}`);
131
+ }
67
132
  if (!response.ok && response.status !== 404)
68
133
  throw new Error(`LiteLLM skill delete failed: HTTP ${response.status}`);
69
134
  skillsCache = undefined;
@@ -92,14 +157,22 @@ function formatSkills(skills) {
92
157
  }
93
158
  const CreateSkillParams = Type.Object({
94
159
  name: Type.String({ description: "Skill name" }),
95
- description: Type.String({ description: "Skill description" }),
96
- code: Type.String({ description: "Skill implementation or prompt code" }),
160
+ description: Type.Optional(Type.String({ description: "Skill description" })),
161
+ sourceJson: Type.Optional(Type.String({ description: "Optional Skill Hub source metadata JSON object" })),
162
+ code: Type.Optional(Type.String({ description: "Legacy Skills Gateway implementation or prompt code" })),
97
163
  inputSchemaJson: Type.Optional(Type.String({ description: "Optional JSON Schema string for skill inputs" })),
98
164
  });
99
165
  const DeleteSkillParams = Type.Object({
100
166
  skillId: Type.String({ description: "LiteLLM skill id" }),
101
167
  });
102
- export function createSkillToolDefinitions(baseUrl, getApiKey) {
168
+ function parseJsonObject(value, fieldName) {
169
+ const parsed = JSON.parse(value);
170
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
171
+ throw new Error(`${fieldName} must be a JSON object`);
172
+ }
173
+ return parsed;
174
+ }
175
+ export function createSkillToolDefinitions(baseUrl, getApiKey, headers) {
103
176
  return [
104
177
  defineTool({
105
178
  name: "litellm_skill_list",
@@ -109,7 +182,7 @@ export function createSkillToolDefinitions(baseUrl, getApiKey) {
109
182
  parameters: Type.Object({}),
110
183
  async execute() {
111
184
  const apiKey = await getApiKey();
112
- const skills = await listSkills(baseUrl, apiKey);
185
+ const skills = await listSkills(baseUrl, apiKey, headers);
113
186
  return { content: [{ type: "text", text: formatSkills(skills) }], details: { count: skills.length } };
114
187
  },
115
188
  }),
@@ -120,10 +193,17 @@ export function createSkillToolDefinitions(baseUrl, getApiKey) {
120
193
  parameters: CreateSkillParams,
121
194
  async execute(_toolCallId, params) {
122
195
  const apiKey = await getApiKey();
196
+ const source = params.sourceJson ? parseJsonObject(params.sourceJson, "sourceJson") : undefined;
123
197
  const inputSchema = params.inputSchemaJson
124
- ? JSON.parse(params.inputSchemaJson)
198
+ ? parseJsonObject(params.inputSchemaJson, "inputSchemaJson")
125
199
  : undefined;
126
- const result = await createSkill(baseUrl, apiKey, { ...params, inputSchema });
200
+ const result = await createSkill(baseUrl, apiKey, {
201
+ name: params.name,
202
+ description: params.description,
203
+ source,
204
+ code: params.code,
205
+ inputSchema,
206
+ }, headers);
127
207
  return { content: [{ type: "text", text: "LiteLLM skill created." }], details: { result } };
128
208
  },
129
209
  }),
@@ -134,7 +214,7 @@ export function createSkillToolDefinitions(baseUrl, getApiKey) {
134
214
  parameters: DeleteSkillParams,
135
215
  async execute(_toolCallId, params) {
136
216
  const apiKey = await getApiKey();
137
- await deleteSkill(baseUrl, apiKey, params.skillId);
217
+ await deleteSkill(baseUrl, apiKey, params.skillId, headers);
138
218
  return { content: [{ type: "text", text: `LiteLLM skill deleted: ${params.skillId}` }], details: {} };
139
219
  },
140
220
  }),
package/dist/types.d.ts CHANGED
@@ -3,6 +3,7 @@ export type DiscoverySource = "model_info" | "models_list" | "health";
3
3
  export interface CacheFile {
4
4
  baseUrl: string;
5
5
  apiKeyFingerprint: string;
6
+ headersFingerprint?: string;
6
7
  fetchedAt: number;
7
8
  source: DiscoverySource;
8
9
  models: ProviderModelConfig[];
@@ -14,6 +15,7 @@ export interface DiscoveryResult {
14
15
  export interface DiscoveryOptions {
15
16
  timeoutMs?: number;
16
17
  signal?: AbortSignal;
18
+ headers?: Record<string, string>;
17
19
  }
18
20
  export interface ModelInfoEntry {
19
21
  model_name?: string;
@@ -75,6 +77,14 @@ export interface LiteLLMSkill {
75
77
  name: string;
76
78
  description?: string;
77
79
  enabled?: boolean;
80
+ source?: Record<string, unknown>;
81
+ version?: string;
82
+ keywords?: string[];
83
+ domain?: string;
84
+ namespace?: string;
85
+ category?: string;
86
+ author?: string;
87
+ homepage?: string;
78
88
  input_schema?: Record<string, unknown>;
79
89
  code?: string;
80
90
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-provider-litellm",
3
- "version": "1.2.7",
3
+ "version": "1.2.9",
4
4
  "description": "LiteLLM proxy provider extension for Pi",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -40,7 +40,7 @@
40
40
  "image": "https://raw.githubusercontent.com/balcsida/pi-provider-litellm/refs/heads/main/assets/pi_litellm_gallery.png"
41
41
  },
42
42
  "scripts": {
43
- "clean": "shx rm -rf dist",
43
+ "clean": "rm -rf dist",
44
44
  "build": "tsgo -p tsconfig.build.json",
45
45
  "dev": "tsgo -p tsconfig.build.json --watch --preserveWatchOutput",
46
46
  "typecheck": "tsgo --noEmit",
@@ -64,14 +64,12 @@
64
64
  "protobufjs": "8.2.1"
65
65
  },
66
66
  "devDependencies": {
67
- "@earendil-works/pi-ai": "^0.79.1",
68
- "@earendil-works/pi-coding-agent": "^0.79.1",
67
+ "@earendil-works/pi-ai": "^0.80.2",
68
+ "@earendil-works/pi-coding-agent": "^0.80.2",
69
69
  "@biomejs/biome": "^2.4.15",
70
- "@types/node": "^25.9.1",
71
- "@typescript/native-preview": "7.0.0-dev.20260610.1",
72
- "shx": "^0.4.0",
70
+ "@types/node": "^26.0.0",
71
+ "@typescript/native-preview": "7.0.0-dev.20260707.2",
73
72
  "tsx": "^4.21.0",
74
- "typescript": "^6.0.3",
75
73
  "vitest": "^4.1.7"
76
74
  }
77
75
  }