kiosapi 0.1.16 → 0.1.17

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/dist/agent/run.js CHANGED
@@ -373,9 +373,10 @@ export function undoLastTurn(s) {
373
373
  * agent's final text (last answer or the `selesai` summary) — useful for chaining agents in a team.
374
374
  */
375
375
  export async function runTurn(s, userText) {
376
- // On the very first turn of a fresh session, auto-inject project metadata so the model
377
- // starts oriented without needing to call daftar_file(".") for basic orientation.
378
- // Injected: root directory tree + key manifest files (package.json, README, etc.).
376
+ // On the very first turn of a fresh session, append project metadata to the existing system
377
+ // message so the model starts oriented without needing daftar_file(".") for basic orientation.
378
+ // We APPEND (not push a new system message) because some providers reject requests that have
379
+ // more than one system-role message — a second {role:'system'} at index 1 causes HTTP 400.
379
380
  if (s.messages.filter((m) => m.role === 'user').length === 0) {
380
381
  const snippets = [];
381
382
  try {
@@ -393,10 +394,11 @@ export async function runTurn(s, userText) {
393
394
  }
394
395
  }
395
396
  if (snippets.length > 0) {
396
- s.messages.push({
397
- role: 'system',
398
- content: `## Konteks Proyek (auto-injected — jangan panggil daftar_file(".") lagi)\n${snippets.join('\n\n')}`,
399
- });
397
+ const sysMsg = s.messages[0];
398
+ if (sysMsg?.role === 'system') {
399
+ sysMsg.content +=
400
+ `\n\n## Konteks Proyek (auto-injected — jangan panggil daftar_file(".") lagi)\n${snippets.join('\n\n')}`;
401
+ }
400
402
  }
401
403
  }
402
404
  s.messages.push({ role: 'user', content: userText });
@@ -452,7 +454,13 @@ export async function runTurn(s, userText) {
452
454
  // (null content + no tool_calls) can appear from a truncated stream or a reasoning-only
453
455
  // step; pushing it corrupts the history and causes providers to reject subsequent calls.
454
456
  if (reply.content !== null || calls.length > 0) {
455
- s.messages.push({ role: 'assistant', content: reply.content, tool_calls: reply.tool_calls });
457
+ // When tool_calls are present, set content to null regardless of what text the model
458
+ // prefaced the call with. The text was already streamed to the user via onText; keeping
459
+ // it in history causes strict OpenAI-compat providers (DeepSeek, Workers AI, etc.) to
460
+ // return HTTP 400 on the next call because they require content: null when tool_calls
461
+ // is non-empty. Anthropic also works correctly with null here.
462
+ const storedContent = calls.length > 0 ? null : reply.content;
463
+ s.messages.push({ role: 'assistant', content: storedContent, tool_calls: reply.tool_calls });
456
464
  }
457
465
  if (reply.content)
458
466
  lastText = reply.content;
@@ -22,10 +22,8 @@ const TOOLS = {
22
22
  properties: {
23
23
  path: { type: 'string', description: 'Path folder (default ".")' },
24
24
  kedalaman: {
25
- type: 'integer',
26
- description: 'Kedalaman tree (1–5). Default: 3 untuk ".", 1 untuk subfolder.',
27
- minimum: 1,
28
- maximum: 5,
25
+ type: 'number',
26
+ description: 'Kedalaman tree 1–5. Default: 3 untuk ".", 1 untuk subfolder.',
29
27
  },
30
28
  },
31
29
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kiosapi",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "type": "module",
5
5
  "description": "CLI Kiosapi.id berbahasa Indonesia — bangun aplikasimu pakai API key Kiosapi (agen + multimodal).",
6
6
  "keywords": [