@shareai-lab/kode-sdk 2.7.2 → 2.7.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.
@@ -3,7 +3,7 @@
3
3
  * Shared utilities for provider implementations.
4
4
  */
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.AUDIO_UNSUPPORTED_TEXT = exports.IMAGE_UNSUPPORTED_TEXT = exports.FILE_UNSUPPORTED_TEXT = void 0;
6
+ exports.OPENAI_SUPPORTED_AUDIO_FORMATS = exports.VIDEO_UNSUPPORTED_TEXT = exports.AUDIO_UNSUPPORTED_TEXT = exports.IMAGE_UNSUPPORTED_TEXT = exports.FILE_UNSUPPORTED_TEXT = void 0;
7
7
  exports.resolveProxyUrl = resolveProxyUrl;
8
8
  exports.getProxyDispatcher = getProxyDispatcher;
9
9
  exports.withProxy = withProxy;
@@ -23,6 +23,10 @@ exports.splitThinkText = splitThinkText;
23
23
  exports.extractReasoningDetails = extractReasoningDetails;
24
24
  exports.buildGeminiImagePart = buildGeminiImagePart;
25
25
  exports.buildGeminiFilePart = buildGeminiFilePart;
26
+ exports.buildGeminiAudioPart = buildGeminiAudioPart;
27
+ exports.buildGeminiVideoPart = buildGeminiVideoPart;
28
+ exports.extractOpenAIAudioFormat = extractOpenAIAudioFormat;
29
+ exports.buildOpenAIAudioPart = buildOpenAIAudioPart;
26
30
  exports.sanitizeGeminiSchema = sanitizeGeminiSchema;
27
31
  exports.hasAnthropicFileBlocks = hasAnthropicFileBlocks;
28
32
  exports.mergeAnthropicBetaHeader = mergeAnthropicBetaHeader;
@@ -78,8 +82,8 @@ function normalizeBaseUrl(url) {
78
82
  }
79
83
  function normalizeOpenAIBaseUrl(url) {
80
84
  let normalized = url.replace(/\/+$/, '');
81
- // Auto-append /v1 if not present (for OpenAI-compatible APIs)
82
- if (!normalized.endsWith('/v1')) {
85
+ // Auto-append /v1 if no version path detected (e.g., /v1, /v2, /v4)
86
+ if (!/\/v\d+$/.test(normalized)) {
83
87
  normalized += '/v1';
84
88
  }
85
89
  return normalized;
@@ -150,6 +154,7 @@ function safeJsonStringify(value) {
150
154
  exports.FILE_UNSUPPORTED_TEXT = '[file unsupported] This model does not support PDF input. Please extract text or images first.';
151
155
  exports.IMAGE_UNSUPPORTED_TEXT = '[image unsupported] This model does not support image URLs; please provide base64 data if supported.';
152
156
  exports.AUDIO_UNSUPPORTED_TEXT = '[audio unsupported] This model does not support audio input; please provide a text transcript instead.';
157
+ exports.VIDEO_UNSUPPORTED_TEXT = '[video unsupported] This model does not support video input; please provide text description or extracted frames instead.';
153
158
  // =============================================================================
154
159
  // Reasoning/Thinking Utilities
155
160
  // =============================================================================
@@ -270,6 +275,81 @@ function buildGeminiFilePart(block) {
270
275
  }
271
276
  return null;
272
277
  }
278
+ function buildGeminiAudioPart(block) {
279
+ const mimeType = block.mime_type || 'audio/wav';
280
+ if (block.file_id) {
281
+ return { file_data: { mime_type: mimeType, file_uri: block.file_id } };
282
+ }
283
+ if (block.url) {
284
+ if (block.url.startsWith('gs://')) {
285
+ return { file_data: { mime_type: mimeType, file_uri: block.url } };
286
+ }
287
+ // Gemini supports https URLs for audio via file_data
288
+ return { file_data: { mime_type: mimeType, file_uri: block.url } };
289
+ }
290
+ if (block.base64) {
291
+ return { inline_data: { mime_type: mimeType, data: block.base64 } };
292
+ }
293
+ return null;
294
+ }
295
+ function buildGeminiVideoPart(block) {
296
+ const mimeType = block.mime_type || 'video/mp4';
297
+ if (block.file_id) {
298
+ return { file_data: { mime_type: mimeType, file_uri: block.file_id } };
299
+ }
300
+ if (block.url) {
301
+ if (block.url.startsWith('gs://')) {
302
+ return { file_data: { mime_type: mimeType, file_uri: block.url } };
303
+ }
304
+ // Gemini supports https URLs for video via file_data
305
+ return { file_data: { mime_type: mimeType, file_uri: block.url } };
306
+ }
307
+ if (block.base64) {
308
+ return { inline_data: { mime_type: mimeType, data: block.base64 } };
309
+ }
310
+ return null;
311
+ }
312
+ // =============================================================================
313
+ // OpenAI Audio Helpers
314
+ // =============================================================================
315
+ /** Supported OpenAI audio formats */
316
+ exports.OPENAI_SUPPORTED_AUDIO_FORMATS = ['wav', 'mp3'];
317
+ /**
318
+ * Extract and validate OpenAI audio format from MIME type.
319
+ * OpenAI Chat Completions API only supports wav and mp3.
320
+ * @returns The audio format if supported, null otherwise
321
+ */
322
+ function extractOpenAIAudioFormat(mimeType) {
323
+ if (!mimeType)
324
+ return null;
325
+ const lower = mimeType.toLowerCase();
326
+ if (lower === 'audio/wav' || lower === 'audio/x-wav' || lower === 'audio/wave') {
327
+ return 'wav';
328
+ }
329
+ if (lower === 'audio/mpeg' || lower === 'audio/mp3') {
330
+ return 'mp3';
331
+ }
332
+ return null;
333
+ }
334
+ /**
335
+ * Build OpenAI input_audio content part from AudioContentBlock.
336
+ * OpenAI only supports base64 encoded audio (no URLs).
337
+ * @returns The OpenAI input_audio part or null if not supported
338
+ */
339
+ function buildOpenAIAudioPart(block) {
340
+ const format = extractOpenAIAudioFormat(block.mime_type);
341
+ if (!format)
342
+ return null;
343
+ if (!block.base64)
344
+ return null;
345
+ return {
346
+ type: 'input_audio',
347
+ input_audio: {
348
+ data: block.base64,
349
+ format,
350
+ },
351
+ };
352
+ }
273
353
  function sanitizeGeminiSchema(schema) {
274
354
  if (schema === null || schema === undefined)
275
355
  return schema;
@@ -3,11 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SandboxFactory = void 0;
4
4
  const sandbox_1 = require("./sandbox");
5
5
  const e2b_sandbox_1 = require("./e2b/e2b-sandbox");
6
+ const opensandbox_1 = require("./opensandbox");
6
7
  class SandboxFactory {
7
8
  constructor() {
8
9
  this.factories = new Map();
9
10
  this.factories.set('local', (config) => new sandbox_1.LocalSandbox(config));
10
11
  this.factories.set('e2b', (config) => new e2b_sandbox_1.E2BSandbox(config));
12
+ this.factories.set('opensandbox', (config) => new opensandbox_1.OpenSandbox(config));
11
13
  }
12
14
  register(kind, factory) {
13
15
  this.factories.set(kind, factory);
@@ -24,6 +26,9 @@ class SandboxFactory {
24
26
  if (config.kind === 'e2b' && sandbox instanceof e2b_sandbox_1.E2BSandbox) {
25
27
  await sandbox.init();
26
28
  }
29
+ if (config.kind === 'opensandbox' && sandbox instanceof opensandbox_1.OpenSandbox) {
30
+ await sandbox.init();
31
+ }
27
32
  return sandbox;
28
33
  }
29
34
  }
@@ -1,4 +1,4 @@
1
- export type SandboxKind = 'local' | 'docker' | 'k8s' | 'remote' | 'vfs' | 'e2b';
1
+ export type SandboxKind = 'local' | 'docker' | 'k8s' | 'remote' | 'vfs' | 'e2b' | 'opensandbox';
2
2
  export interface SandboxFS {
3
3
  resolve(path: string): string;
4
4
  isInside(path: string): boolean;
@@ -582,7 +582,8 @@ class JSONStore {
582
582
  const fs = require('fs').promises;
583
583
  try {
584
584
  await fs.access(this.getAgentDir(agentId));
585
- return true;
585
+ const info = await this.loadInfo(agentId);
586
+ return !!(info && info.metadata);
586
587
  }
587
588
  catch {
588
589
  return false;
@@ -51,11 +51,11 @@ function createSkillsTool(skillsManager) {
51
51
  const { action, skill_name } = args;
52
52
  // 注释掉 list 操作的代码
53
53
  // if (action === 'list') {
54
- // // 列出所有skills
54
+ // // 列出所有skills(使用文件夹名称作为标识符)
55
55
  // const skills = await skillsManager.getSkillsMetadata();
56
56
  //
57
57
  // const skillsList = skills.map(s => ({
58
- // name: s.name,
58
+ // name: s.name, // 文件夹名称
59
59
  // description: s.description,
60
60
  // }));
61
61
  //
@@ -87,7 +87,7 @@ export declare const patterns: {
87
87
  /**
88
88
  * 字符串数组
89
89
  */
90
- stringArray: (description?: string) => z.ZodArray<z.ZodString, "many">;
90
+ stringArray: (description?: string) => z.ZodArray<z.ZodString>;
91
91
  /**
92
92
  * 可选字符串
93
93
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shareai-lab/kode-sdk",
3
- "version": "2.7.2",
3
+ "version": "2.7.4",
4
4
  "description": "Event-driven, long-running AI Agent development framework with enterprise-grade persistence and context management",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -22,6 +22,7 @@
22
22
  "example:room": "ts-node examples/03-room-collab.ts",
23
23
  "example:scheduler": "ts-node examples/04-scheduler-watch.ts",
24
24
  "example:nextjs": "ts-node examples/nextjs-api-route.ts",
25
+ "example:opensandbox": "ts-node examples/opensandbox-usage.ts",
25
26
  "example:openrouter": "ts-node examples/05-openrouter-complete.ts",
26
27
  "example:openrouter-stream": "ts-node examples/06-openrouter-stream.ts",
27
28
  "example:openrouter-agent": "ts-node examples/07-openrouter-agent.ts",
@@ -42,16 +43,18 @@
42
43
  "author": "",
43
44
  "license": "MIT",
44
45
  "dependencies": {
46
+ "@alibaba-group/opensandbox": "~0.1.4",
45
47
  "@modelcontextprotocol/sdk": "~1.22.0",
46
48
  "ajv": "^8.17.1",
47
49
  "better-sqlite3": "^12.6.2",
48
50
  "dotenv": "^16.4.5",
49
51
  "e2b": "^2.10.3",
50
52
  "fast-glob": "^3.3.2",
53
+ "minimatch": "^10.2.4",
51
54
  "pg": "^8.17.2",
52
55
  "undici": "^7.18.2",
53
- "zod": "~3.23.8",
54
- "zod-to-json-schema": "~3.23.0"
56
+ "zod": "^4.3.5",
57
+ "zod-to-json-schema": "^3.24.6"
55
58
  },
56
59
  "devDependencies": {
57
60
  "@shareai-lab/kode-sdk": "file:.",