@ambasada/village 0.8.9 → 0.8.11
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/cli.mjs +265 -84
- package/dist/client.d.ts +24 -2
- package/dist/errors.d.ts +10 -0
- package/dist/index.js +105 -33
- package/dist/types.d.ts +15 -5
- package/package.json +4 -4
package/dist/client.d.ts
CHANGED
|
@@ -53,11 +53,23 @@ export declare class Village extends Ambasada {
|
|
|
53
53
|
/**
|
|
54
54
|
* Wraps a paid offering as a fetch handler: verifies the receipt (402 if missing or bad), runs
|
|
55
55
|
* `handler(input, call, req)` and answers JSON. A thrown `AmbasadaError` keeps its status (the
|
|
56
|
-
* Gateway then refunds the buyer).
|
|
56
|
+
* Gateway then refunds the buyer). The buyer pays only for what you deliver, so a handler that returns an error
|
|
57
|
+
* object (`{ error: { code, message } }`) or nothing (`undefined`, `null`, `""`) is answered as an error too, never
|
|
58
|
+
* 200 (dry run 7 #8: "busy, try again" answers were charged). If you can't deliver the paid thing (a tool you
|
|
59
|
+
* need is rate-limited, CAP_TOOLS_RATE, or down, TOOL_UNAVAILABLE), throw, or rethrow what you caught: the buyer
|
|
60
|
+
* is refunded and told when to try again.
|
|
57
61
|
*
|
|
58
62
|
* export default village.sell("translate", async ({ text, to }) => ({ text: await village.llm(`…`) }));
|
|
59
63
|
*/
|
|
60
64
|
sell<Input = any, Output = unknown>(offering: string, handler: SellHandler<Input, Output>): (req: Request) => Promise<Response>;
|
|
65
|
+
/**
|
|
66
|
+
* A warning worth seeing in `ambasada logs` even though the request succeeded, e.g. an answer degraded because a
|
|
67
|
+
* tool was rate-limited: `console.warn("[village]", …)`. The templates send a request's `[village]` lines along with
|
|
68
|
+
* any answer, and ambasada.dev keeps them as warnings (at most 50 an hour; never counted as errors).
|
|
69
|
+
*
|
|
70
|
+
* village.warn("wikipedia.search: CAP_TOOLS_RATE, answering from the model alone");
|
|
71
|
+
*/
|
|
72
|
+
warn(...message: unknown[]): void;
|
|
61
73
|
/**
|
|
62
74
|
* An async offering's answer to a paid call (`async: true` in offerings.ts): the work goes on as job `id` (in the
|
|
63
75
|
* template, a Jobs Durable Object named after it), and the Gateway asks `GET <endpoint>/jobs/<id>` until it is done.
|
|
@@ -157,6 +169,7 @@ export declare class Village extends Ambasada {
|
|
|
157
169
|
/** Generates an image; the URL is re-hosted in the village files store. Default model: nano_banana. */
|
|
158
170
|
generate: (req: ImageRequest) => Promise<ImageResult>;
|
|
159
171
|
};
|
|
172
|
+
private generateImage;
|
|
160
173
|
readonly tools: {
|
|
161
174
|
/** The curated LLMOK tool catalog with TON prices. */
|
|
162
175
|
list: () => Promise<ToolListing[]>;
|
|
@@ -165,6 +178,7 @@ export declare class Village extends Ambasada {
|
|
|
165
178
|
idempotencyKey?: string;
|
|
166
179
|
}) => Promise<ToolResult<Output>>;
|
|
167
180
|
};
|
|
181
|
+
private callTool;
|
|
168
182
|
readonly listings: {
|
|
169
183
|
/** Creates or updates an offering (price changes are versioned). */
|
|
170
184
|
put: (name: string, def: ListingInput) => Promise<Listing>;
|
|
@@ -213,9 +227,17 @@ export declare class Village extends Ambasada {
|
|
|
213
227
|
decide: (id: string, decision: "approve" | "decline", reason?: string, options?: {
|
|
214
228
|
wait?: boolean;
|
|
215
229
|
}) => Promise<ChatDecision>;
|
|
216
|
-
|
|
230
|
+
/**
|
|
231
|
+
* The agent's transcript after `since`, oldest first: the first `limit` entries, or with `newest` the last `limit`.
|
|
232
|
+
* `more`: entries after this page (read on from `next_since`); `earlier`: with `newest`, the ones before it.
|
|
233
|
+
*/
|
|
234
|
+
transcript: (since?: number, limit?: number, options?: {
|
|
235
|
+
newest?: boolean;
|
|
236
|
+
}) => Promise<{
|
|
217
237
|
entries: TranscriptEntry[];
|
|
218
238
|
next_since: number;
|
|
239
|
+
more?: number;
|
|
240
|
+
earlier?: number;
|
|
219
241
|
}>;
|
|
220
242
|
state: () => Promise<Record<string, unknown>>;
|
|
221
243
|
};
|
package/dist/errors.d.ts
CHANGED
|
@@ -12,6 +12,16 @@ export type VillageError = AmbasadaError;
|
|
|
12
12
|
/** `isAmbasadaError` under its 0.7 name. */
|
|
13
13
|
export declare const isVillageError: typeof isAmbasadaError;
|
|
14
14
|
export type ReceiptFailure = "malformed" | "unknown_key" | "bad_signature" | "expired" | "not_yet_valid" | "wrong_issuer" | "wrong_seller" | "wrong_offering" | "wrong_kind" | "wrong_session" | "body_mismatch" | "replayed" | "missing";
|
|
15
|
+
/** The stack above `fn` (the SDK method the product called): where the product made the call. */
|
|
16
|
+
export declare function callSite(fn: (...args: never[]) => unknown): string | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* A failed utility call says which one it was and where the product made it (village dry run 6 #9: a provider error in
|
|
19
|
+
* a job pointed at `errorFromResponse (worker.js:87121:12)`, inside the SDK, and not at the call). The message ends with
|
|
20
|
+
* `(during tools.call web.search)` (job attempts and `ambasada logs` show it), `during` names the call, and the stack
|
|
21
|
+
* starts at the product's calling frame, which `ambasada logs` maps to its source (`at api/frost.ts:12`). An error
|
|
22
|
+
* already named keeps its name; `restack` gives it this call site (llm() through llm.chat).
|
|
23
|
+
*/
|
|
24
|
+
export declare function duringCall(error: unknown, what: string, site: string | undefined, restack?: boolean): unknown;
|
|
15
25
|
/** The request is not paid: no receipt, a forged or expired one, or one for another seller / offering / body. */
|
|
16
26
|
export declare class ReceiptInvalidError extends AmbasadaError {
|
|
17
27
|
readonly reason: ReceiptFailure;
|
package/dist/index.js
CHANGED
|
@@ -148,6 +148,8 @@ var ERROR_STATUS = {
|
|
|
148
148
|
// inbox texts: 20 an hour, 1 unsolicited per counterparty an hour (EXCHANGE.md §8)
|
|
149
149
|
CAP_CHAT_RATE: 429,
|
|
150
150
|
// turns of the CEO chat per company (docs/AGENT-CHAT.md)
|
|
151
|
+
CAP_TOOLS_RATE: 429,
|
|
152
|
+
// tool calls per company per minute (the provider's pool has no limit of its own)
|
|
151
153
|
// Additions needed by the gateway and bank
|
|
152
154
|
UPSTREAM_ERROR: 502,
|
|
153
155
|
PRICE_ABOVE_MAX: 409,
|
|
@@ -174,6 +176,8 @@ var ERROR_STATUS = {
|
|
|
174
176
|
// provider refused the model/tool/key (a configuration problem on our side). Never the caller's fault.
|
|
175
177
|
PROVIDER_BUDGET: 503,
|
|
176
178
|
PROVIDER_DENIED: 502,
|
|
179
|
+
// A tool or model whose supplier failed 3 times in a row: refused for 5 minutes without calling it (never charged)
|
|
180
|
+
TOOL_UNAVAILABLE: 503,
|
|
177
181
|
// Deploy-freeze and unattended windows: agents keep running, but config and steer are closed (DESIGN.md §5)
|
|
178
182
|
FROZEN: 403
|
|
179
183
|
};
|
|
@@ -1518,6 +1522,24 @@ import { Ambasada, AmbasadaError as AmbasadaError3 } from "@ambasada/sdk/platfor
|
|
|
1518
1522
|
import { AmbasadaError, isAmbasadaError } from "@ambasada/sdk/platform";
|
|
1519
1523
|
var VillageError2 = AmbasadaError;
|
|
1520
1524
|
var isVillageError = isAmbasadaError;
|
|
1525
|
+
function callSite(fn) {
|
|
1526
|
+
const site = {};
|
|
1527
|
+
Error.captureStackTrace?.(site, fn);
|
|
1528
|
+
return site.stack;
|
|
1529
|
+
}
|
|
1530
|
+
function duringCall(error, what, site, restack = false) {
|
|
1531
|
+
if (!(error instanceof Error)) return error;
|
|
1532
|
+
const e = error;
|
|
1533
|
+
if (e.during && !restack) return e;
|
|
1534
|
+
if (!e.during) {
|
|
1535
|
+
e.during = what;
|
|
1536
|
+
e.message = `${e.message} (during ${what})`;
|
|
1537
|
+
}
|
|
1538
|
+
const frames = (site ?? "").split("\n").filter((line) => line.trim().startsWith("at "));
|
|
1539
|
+
if (frames.length) e.stack = `${e.name}: ${e.message}
|
|
1540
|
+
${frames.join("\n")}`;
|
|
1541
|
+
return e;
|
|
1542
|
+
}
|
|
1521
1543
|
var ReceiptInvalidError = class extends AmbasadaError {
|
|
1522
1544
|
reason;
|
|
1523
1545
|
constructor(reason, message) {
|
|
@@ -1727,7 +1749,11 @@ var Village = class extends Ambasada {
|
|
|
1727
1749
|
/**
|
|
1728
1750
|
* Wraps a paid offering as a fetch handler: verifies the receipt (402 if missing or bad), runs
|
|
1729
1751
|
* `handler(input, call, req)` and answers JSON. A thrown `AmbasadaError` keeps its status (the
|
|
1730
|
-
* Gateway then refunds the buyer).
|
|
1752
|
+
* Gateway then refunds the buyer). The buyer pays only for what you deliver, so a handler that returns an error
|
|
1753
|
+
* object (`{ error: { code, message } }`) or nothing (`undefined`, `null`, `""`) is answered as an error too, never
|
|
1754
|
+
* 200 (dry run 7 #8: "busy, try again" answers were charged). If you can't deliver the paid thing (a tool you
|
|
1755
|
+
* need is rate-limited, CAP_TOOLS_RATE, or down, TOOL_UNAVAILABLE), throw, or rethrow what you caught: the buyer
|
|
1756
|
+
* is refunded and told when to try again.
|
|
1731
1757
|
*
|
|
1732
1758
|
* export default village.sell("translate", async ({ text, to }) => ({ text: await village.llm(`…`) }));
|
|
1733
1759
|
*/
|
|
@@ -1743,7 +1769,16 @@ var Village = class extends Ambasada {
|
|
|
1743
1769
|
}
|
|
1744
1770
|
try {
|
|
1745
1771
|
const out = await handler(call.input, call, req);
|
|
1746
|
-
|
|
1772
|
+
if (out instanceof Response) return out;
|
|
1773
|
+
if (out === void 0 || out === null || out === "") {
|
|
1774
|
+
return new AmbasadaError3("UPSTREAM_ERROR", `the ${offering2} handler returned nothing; the buyer is refunded (return what was paid for, or throw)`, 502).toResponse();
|
|
1775
|
+
}
|
|
1776
|
+
const error = out.error;
|
|
1777
|
+
if (typeof error === "object" && error !== null && typeof error.code === "string") {
|
|
1778
|
+
const { code, message, ...details } = error;
|
|
1779
|
+
return new AmbasadaError3(code, typeof message === "string" ? message : code, void 0, details).toResponse();
|
|
1780
|
+
}
|
|
1781
|
+
return Response.json(out);
|
|
1747
1782
|
} catch (error) {
|
|
1748
1783
|
if (error instanceof AmbasadaError3) return error.toResponse();
|
|
1749
1784
|
console.error(error);
|
|
@@ -1751,6 +1786,16 @@ var Village = class extends Ambasada {
|
|
|
1751
1786
|
}
|
|
1752
1787
|
};
|
|
1753
1788
|
}
|
|
1789
|
+
/**
|
|
1790
|
+
* A warning worth seeing in `ambasada logs` even though the request succeeded, e.g. an answer degraded because a
|
|
1791
|
+
* tool was rate-limited: `console.warn("[village]", …)`. The templates send a request's `[village]` lines along with
|
|
1792
|
+
* any answer, and ambasada.dev keeps them as warnings (at most 50 an hour; never counted as errors).
|
|
1793
|
+
*
|
|
1794
|
+
* village.warn("wikipedia.search: CAP_TOOLS_RATE, answering from the model alone");
|
|
1795
|
+
*/
|
|
1796
|
+
warn(...message) {
|
|
1797
|
+
console.warn("[village]", ...message);
|
|
1798
|
+
}
|
|
1754
1799
|
/**
|
|
1755
1800
|
* An async offering's answer to a paid call (`async: true` in offerings.ts): the work goes on as job `id` (in the
|
|
1756
1801
|
* template, a Jobs Durable Object named after it), and the Gateway asks `GET <endpoint>/jobs/<id>` until it is done.
|
|
@@ -1772,8 +1817,10 @@ var Village = class extends Ambasada {
|
|
|
1772
1817
|
return async (req) => {
|
|
1773
1818
|
const id = decodeURIComponent(new URL(req.url).pathname.split("/").filter(Boolean).at(-1) ?? "");
|
|
1774
1819
|
try {
|
|
1820
|
+
const token = receiptHeader(req.headers);
|
|
1821
|
+
if (!token) throw new ReceiptInvalidError("missing", "missing x-village-receipt (the village Gateway polls this route)");
|
|
1775
1822
|
const seller = await this.company();
|
|
1776
|
-
const claims = await verifyCallReceipt(
|
|
1823
|
+
const claims = await verifyCallReceipt(token, new Uint8Array(), { keys: this.keySource(), seller, offering: `${seller}/${offering2}` });
|
|
1777
1824
|
if (claims.job !== id) throw new ReceiptInvalidError("wrong_kind", "this receipt is for another job");
|
|
1778
1825
|
} catch (error) {
|
|
1779
1826
|
if (error instanceof AmbasadaError3) return error.toResponse();
|
|
@@ -1902,22 +1949,40 @@ var Village = class extends Ambasada {
|
|
|
1902
1949
|
* `village.llm("prompt")` → the answer text; `village.llm.chat(req)` → the full OpenAI-style response.
|
|
1903
1950
|
* Default model: deepseek-v4.1-flash.
|
|
1904
1951
|
*/
|
|
1905
|
-
llm =
|
|
1906
|
-
|
|
1907
|
-
const
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
}
|
|
1912
|
-
{
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1952
|
+
llm = (() => {
|
|
1953
|
+
const chat = (req) => {
|
|
1954
|
+
const site = callSite(chat);
|
|
1955
|
+
return this.call("POST", "/v1/llm/chat", { body: { ...req, model: req.model ?? DEFAULT_MODEL }, timeoutMs: CLIENT_TIMEOUT_MS.llm }).catch((e) => {
|
|
1956
|
+
throw duringCall(e, "llm.chat", site);
|
|
1957
|
+
});
|
|
1958
|
+
};
|
|
1959
|
+
const llm = async (prompt, options = {}) => {
|
|
1960
|
+
const site = callSite(llm);
|
|
1961
|
+
try {
|
|
1962
|
+
const { system, ...rest } = options;
|
|
1963
|
+
const messages = system ? [{ role: "system", content: system }] : [];
|
|
1964
|
+
const res = await chat({ ...rest, messages: [...messages, { role: "user", content: prompt }] });
|
|
1965
|
+
const choice = res.choices[0];
|
|
1966
|
+
if (!choice?.message.content?.trim() && choice?.finish_reason === "length") {
|
|
1967
|
+
const hint = typeof res.village_hint === "string" ? res.village_hint : `the model ran out of max_tokens before it answered (nothing was charged): raise max_tokens (8192+ with reasoning on), ask for less, or turn reasoning off (reasoning_effort: "none")`;
|
|
1968
|
+
throw new AmbasadaError3("UPSTREAM_ERROR", `llm: ${hint}`, 502, { finish_reason: "length" });
|
|
1969
|
+
}
|
|
1970
|
+
return choice?.message.content ?? "";
|
|
1971
|
+
} catch (e) {
|
|
1972
|
+
throw duringCall(e, "llm.chat", site, true);
|
|
1973
|
+
}
|
|
1974
|
+
};
|
|
1975
|
+
return Object.assign(llm, { chat });
|
|
1976
|
+
})();
|
|
1917
1977
|
images = {
|
|
1918
1978
|
/** Generates an image; the URL is re-hosted in the village files store. Default model: nano_banana. */
|
|
1919
|
-
generate: (req) => this.
|
|
1979
|
+
generate: (req) => this.generateImage(req, callSite(this.images.generate))
|
|
1920
1980
|
};
|
|
1981
|
+
generateImage(req, site) {
|
|
1982
|
+
return this.call("POST", "/v1/images", { body: { ...req, model: req.model ?? "nano_banana" }, timeoutMs: CLIENT_TIMEOUT_MS.image }).catch((e) => {
|
|
1983
|
+
throw duringCall(e, `images.generate ${req.model ?? "nano_banana"}`, site);
|
|
1984
|
+
});
|
|
1985
|
+
}
|
|
1921
1986
|
tools = {
|
|
1922
1987
|
/** The curated LLMOK tool catalog with TON prices. */
|
|
1923
1988
|
list: async () => {
|
|
@@ -1925,23 +1990,26 @@ var Village = class extends Ambasada {
|
|
|
1925
1990
|
return Array.isArray(res) ? res : res.tools;
|
|
1926
1991
|
},
|
|
1927
1992
|
/** Runs one tool; debits your wallet only on success. Replays with the same idempotency key are free. */
|
|
1928
|
-
call:
|
|
1929
|
-
const res = await this.send("POST", `/v1/tools/${encodeURIComponent(id)}`, {
|
|
1930
|
-
body: input ?? {},
|
|
1931
|
-
retry: true,
|
|
1932
|
-
// Image tools take as long as images; a routed search may try several providers within the API's 60 s.
|
|
1933
|
-
timeoutMs: id.startsWith("image.") ? CLIENT_TIMEOUT_MS.image : CLIENT_TIMEOUT_MS.tool,
|
|
1934
|
-
headers: { "idempotency-key": options.idempotencyKey ?? randomKey() }
|
|
1935
|
-
});
|
|
1936
|
-
const json = res.json;
|
|
1937
|
-
return {
|
|
1938
|
-
output: json.output,
|
|
1939
|
-
callId: json.call_id ?? res.headers.get("x-village-call-id"),
|
|
1940
|
-
amount: json.cost ?? num(res.headers.get("x-village-amount")),
|
|
1941
|
-
replayed: res.headers.get("idempotent-replayed") === "true"
|
|
1942
|
-
};
|
|
1943
|
-
}
|
|
1993
|
+
call: (id, input, options = {}) => this.callTool(id, input, options, callSite(this.tools.call))
|
|
1944
1994
|
};
|
|
1995
|
+
async callTool(id, input, options, site) {
|
|
1996
|
+
const res = await this.send("POST", `/v1/tools/${encodeURIComponent(id)}`, {
|
|
1997
|
+
body: input ?? {},
|
|
1998
|
+
retry: true,
|
|
1999
|
+
// Image tools take as long as images; a routed search may try several providers within the API's 60 s.
|
|
2000
|
+
timeoutMs: id.startsWith("image.") ? CLIENT_TIMEOUT_MS.image : CLIENT_TIMEOUT_MS.tool,
|
|
2001
|
+
headers: { "idempotency-key": options.idempotencyKey ?? randomKey() }
|
|
2002
|
+
}).catch((e) => {
|
|
2003
|
+
throw duringCall(e, `tools.call ${id}`, site);
|
|
2004
|
+
});
|
|
2005
|
+
const json = res.json;
|
|
2006
|
+
return {
|
|
2007
|
+
output: json.output,
|
|
2008
|
+
callId: json.call_id ?? res.headers.get("x-village-call-id"),
|
|
2009
|
+
amount: json.cost ?? num(res.headers.get("x-village-amount")),
|
|
2010
|
+
replayed: res.headers.get("idempotent-replayed") === "true"
|
|
2011
|
+
};
|
|
2012
|
+
}
|
|
1945
2013
|
// ── listings, wallet, ledger ──────────────────────────────────────────────
|
|
1946
2014
|
listings = {
|
|
1947
2015
|
/** Creates or updates an offering (price changes are versioned). */
|
|
@@ -1996,7 +2064,11 @@ var Village = class extends Ambasada {
|
|
|
1996
2064
|
body: { decision, ...reason ? { reason } : {}, ...options.wait ? { wait: true } : {} },
|
|
1997
2065
|
...options.wait ? { timeoutMs: CHAT_WAIT_MS + 15e3 } : {}
|
|
1998
2066
|
}),
|
|
1999
|
-
|
|
2067
|
+
/**
|
|
2068
|
+
* The agent's transcript after `since`, oldest first: the first `limit` entries, or with `newest` the last `limit`.
|
|
2069
|
+
* `more`: entries after this page (read on from `next_since`); `earlier`: with `newest`, the ones before it.
|
|
2070
|
+
*/
|
|
2071
|
+
transcript: (since = 0, limit = 200, options = {}) => this.call("GET", "/v1/agent/transcript", { query: { since, limit, ...options.newest ? { newest: 1 } : {} } }),
|
|
2000
2072
|
state: () => this.call("GET", "/v1/agent/state")
|
|
2001
2073
|
};
|
|
2002
2074
|
};
|
package/dist/types.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export interface ReceiptClaims {
|
|
|
17
17
|
/** TON you may still spend downstream on behalf of this call. */
|
|
18
18
|
budget?: number;
|
|
19
19
|
deal_id?: string;
|
|
20
|
-
/** An async offering's call: when the buyer's max_wait_s runs out (unix seconds); `startJob(…, { deadline: call.deadline
|
|
20
|
+
/** An async offering's call: when the buyer's max_wait_s runs out (unix seconds); pass it as it is: `startJob(…, { deadline: call.deadline })` (the templates' jobs take seconds or ms). */
|
|
21
21
|
deadline?: number;
|
|
22
22
|
body_sha256: string;
|
|
23
23
|
iat: number;
|
|
@@ -159,7 +159,7 @@ export interface BuyOptions {
|
|
|
159
159
|
}
|
|
160
160
|
/** What an async offering's `GET <endpoint>/jobs/<id>` says (village.jobStatus): the Gateway settles on done or failed. */
|
|
161
161
|
export type JobAnswer =
|
|
162
|
-
/** `attempts`: the failed ones so far (the template's `jobAnswer(job)`); the buyer sees "working (attempt
|
|
162
|
+
/** `attempts`: the failed ones so far (the template's `jobAnswer(job)`); the buyer sees "working (attempt 1 failed: …; retrying)". */
|
|
163
163
|
{
|
|
164
164
|
status: "working";
|
|
165
165
|
attempts?: {
|
|
@@ -192,7 +192,7 @@ export interface BuyResult<Output = any> {
|
|
|
192
192
|
job?: string;
|
|
193
193
|
}
|
|
194
194
|
/** What the village sells (apps/api/config/pricing.json); any other model is refused. */
|
|
195
|
-
export type ChatModel = "deepseek-v4.1-flash" | (string & {});
|
|
195
|
+
export type ChatModel = "deepseek-v4.1-flash" | "glm-5.3-flash" | (string & {});
|
|
196
196
|
export interface ChatMessage {
|
|
197
197
|
role: "system" | "user" | "assistant" | "tool";
|
|
198
198
|
content: string;
|
|
@@ -204,8 +204,11 @@ export interface ChatRequest {
|
|
|
204
204
|
messages: ChatMessage[];
|
|
205
205
|
temperature?: number;
|
|
206
206
|
max_tokens?: number;
|
|
207
|
-
/**
|
|
208
|
-
|
|
207
|
+
/**
|
|
208
|
+
* deepseek-v4.1-flash reasons only when you send `"on"` (the village sends `"none"` otherwise): it thinks 1–3.5k
|
|
209
|
+
* tokens first, inside `max_tokens`, which is then at least 8192. glm-5.3-flash always reasons.
|
|
210
|
+
*/
|
|
211
|
+
reasoning_effort?: "none" | "on" | (string & {});
|
|
209
212
|
/** `json_schema`: JSON in the schema's shape (live, and the mock's sample of it under `ambasada dev`); `json_object`: any JSON. */
|
|
210
213
|
response_format?: {
|
|
211
214
|
type: "text" | "json_object";
|
|
@@ -232,7 +235,12 @@ export interface ChatResponse {
|
|
|
232
235
|
prompt_tokens: number;
|
|
233
236
|
completion_tokens: number;
|
|
234
237
|
total_tokens: number;
|
|
238
|
+
completion_tokens_details?: {
|
|
239
|
+
reasoning_tokens?: number;
|
|
240
|
+
};
|
|
235
241
|
};
|
|
242
|
+
/** On an empty answer cut by `max_tokens` (`finish_reason: "length"`): what to change. */
|
|
243
|
+
village_hint?: string;
|
|
236
244
|
[key: string]: unknown;
|
|
237
245
|
}
|
|
238
246
|
export interface ImageRequest {
|
|
@@ -336,6 +344,8 @@ export interface AgentSettings {
|
|
|
336
344
|
};
|
|
337
345
|
/** Agent tools offered to the model (default: all). */
|
|
338
346
|
tools?: string[];
|
|
347
|
+
/** A wake changes one offering's price at most this often, in minutes (default 120; 0: any time). */
|
|
348
|
+
price_cooldown_minutes?: number;
|
|
339
349
|
/**
|
|
340
350
|
* The whole company's spend limits, TON: the product's own LLM and image calls count too, not only the agent's
|
|
341
351
|
* purchases. Over `auto_per_payment` (and `auto_per_day`) an agent payment needs the team's approval.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ambasada/village",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.11",
|
|
4
4
|
"description": "The Hack A Ton add-on for Ambasada apps: TON checkout, receipts, offerings, LLM, the agent, the market; CLI commands and the local bank.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -27,15 +27,15 @@
|
|
|
27
27
|
"node": ">=22"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@ambasada/sdk": "^0.8.
|
|
30
|
+
"@ambasada/sdk": "^0.8.11"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@types/node": "^22.20.5",
|
|
34
34
|
"esbuild": "^0.28.2",
|
|
35
35
|
"typescript": "~5.9.3",
|
|
36
36
|
"vitest": "^4.1.12",
|
|
37
|
-
"@ambasada/
|
|
38
|
-
"@ambasada/
|
|
37
|
+
"@ambasada/cli": "0.8.11",
|
|
38
|
+
"@ambasada/protocol": "0.1.0"
|
|
39
39
|
},
|
|
40
40
|
"author": "CENTYSO (https://centyso.com)",
|
|
41
41
|
"homepage": "https://ambasada.id",
|