kiosapi 0.1.5 → 0.1.7
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 +1 -1
- package/dist/api.js +44 -17
- package/dist/commands.js +3 -4
- package/package.json +1 -1
package/dist/agent/run.js
CHANGED
|
@@ -124,7 +124,7 @@ export async function runTurn(s, userText) {
|
|
|
124
124
|
const calls = reply.tool_calls ?? [];
|
|
125
125
|
if (calls.length === 0) {
|
|
126
126
|
if (step === 0) {
|
|
127
|
-
console.log(dim('(Model tidak memakai tool —
|
|
127
|
+
console.log(dim('(Model tidak memakai tool — pilih model ber-🔧 untuk agen, mis. /model deepseek/deepseek-v4-flash.)'));
|
|
128
128
|
}
|
|
129
129
|
return lastText; // final text answer
|
|
130
130
|
}
|
package/dist/api.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { loadConfig } from './config.js';
|
|
2
|
-
import { dim } from './ui.js';
|
|
2
|
+
import { dim, sleep } from './ui.js';
|
|
3
3
|
/** Turn an upstream HTTP status into an actionable Indonesian message. */
|
|
4
4
|
function humanizeError(status) {
|
|
5
5
|
if (status === 401)
|
|
@@ -61,22 +61,45 @@ export async function resolveModel(flag) {
|
|
|
61
61
|
process.stderr.write(`${dim(`(model otomatis: ${pick.id} — atur tetap dengan: kiosapi setel model <id>)`)}\n`);
|
|
62
62
|
return pick.id;
|
|
63
63
|
}
|
|
64
|
-
/**
|
|
64
|
+
/** Prefer the gateway's own (localized) error message; fall back to a status-based one. */
|
|
65
|
+
async function gatewayError(res) {
|
|
66
|
+
try {
|
|
67
|
+
const body = (await res.json());
|
|
68
|
+
if (body?.error?.message)
|
|
69
|
+
return body.error.message;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// non-JSON body
|
|
73
|
+
}
|
|
74
|
+
return humanizeError(res.status);
|
|
75
|
+
}
|
|
76
|
+
const RETRY_BACKOFF_MS = [5000, 10000, 20000];
|
|
77
|
+
/**
|
|
78
|
+
* Authenticated request to the gateway. Retries 429 (rate limit) with a silent backoff — agent/`tim`
|
|
79
|
+
* runs burst many requests and easily hit the per-minute cap, so a brief wait + retry keeps them
|
|
80
|
+
* going instead of failing. On other errors, surfaces the gateway's own message.
|
|
81
|
+
*/
|
|
65
82
|
async function authedFetch(path, init) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
83
|
+
for (let attempt = 0;; attempt++) {
|
|
84
|
+
const { baseUrl, apiKey } = loadConfig();
|
|
85
|
+
if (!apiKey)
|
|
86
|
+
throw new Error('Belum masuk. Jalankan: kiosapi masuk');
|
|
87
|
+
const res = await fetch(`${baseUrl}${path}`, {
|
|
88
|
+
...init,
|
|
89
|
+
headers: {
|
|
90
|
+
Authorization: `Bearer ${apiKey}`,
|
|
91
|
+
'Content-Type': 'application/json',
|
|
92
|
+
...init?.headers,
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
if (res.ok)
|
|
96
|
+
return res;
|
|
97
|
+
if (res.status === 429 && attempt < RETRY_BACKOFF_MS.length) {
|
|
98
|
+
await sleep(RETRY_BACKOFF_MS[attempt] ?? 20000);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
throw new Error(await gatewayError(res));
|
|
102
|
+
}
|
|
80
103
|
}
|
|
81
104
|
/** GET /v1/saldo — own balance summary. */
|
|
82
105
|
export async function fetchSaldo() {
|
|
@@ -156,7 +179,11 @@ export async function chatComplete(model, messages, tools, onText) {
|
|
|
156
179
|
}
|
|
157
180
|
const tool_calls = [...calls.values()]
|
|
158
181
|
.filter((c) => c.name)
|
|
159
|
-
.map((c) => ({
|
|
182
|
+
.map((c) => ({
|
|
183
|
+
id: c.id,
|
|
184
|
+
type: 'function',
|
|
185
|
+
function: { name: c.name, arguments: c.args },
|
|
186
|
+
}));
|
|
160
187
|
return { content: content || null, tool_calls: tool_calls.length > 0 ? tool_calls : undefined };
|
|
161
188
|
}
|
|
162
189
|
/** Parse an OpenAI SSE stream, yielding content deltas. */
|
package/dist/commands.js
CHANGED
|
@@ -136,7 +136,7 @@ export async function cmdModel(args) {
|
|
|
136
136
|
/** Warn (best-effort) if the chosen model likely can't drive the agent's tools. */
|
|
137
137
|
export async function warnIfNoTools(model) {
|
|
138
138
|
if (!(await modelSupportsTools(model))) {
|
|
139
|
-
console.error(yellow(`⚠ Model "${model}"
|
|
139
|
+
console.error(yellow(`⚠ Model "${model}" tak mendukung tool calling via Kiosapi — agen tak bekerja. Pilih model 🔧 (lihat: kiosapi model --tools), mis. deepseek/deepseek-v4-flash.`));
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
/** tanya — one-shot streaming question (also reads piped stdin as context). */
|
|
@@ -436,10 +436,9 @@ export async function cmdTim(args) {
|
|
|
436
436
|
/** saldo — show own balance, bonus tokens, and month-to-date spend. */
|
|
437
437
|
export async function cmdSaldo() {
|
|
438
438
|
const s = await fetchSaldo();
|
|
439
|
-
console.log(`${bold('Saldo')}
|
|
440
|
-
console.log(`Bonus token : ${idn(s.bonus_tokens)}`);
|
|
439
|
+
console.log(`${bold('Saldo')} : ${green(rupiah(s.balance_rupiah))}`);
|
|
441
440
|
const cap = s.monthly_cap_rupiah != null ? ` / batas ${rupiah(s.monthly_cap_rupiah)}` : '';
|
|
442
|
-
console.log(`Bulan ini
|
|
441
|
+
console.log(`Bulan ini : ${rupiah(s.month_spend_rupiah)}${dim(cap)}`);
|
|
443
442
|
}
|
|
444
443
|
/** pakai — usage summary over the last N days (default 30). */
|
|
445
444
|
export async function cmdPakai(args) {
|