@ambasada/village 0.8.6 → 0.8.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/client.d.ts CHANGED
@@ -1,11 +1,17 @@
1
1
  import { Ambasada, type AmbasadaOptions } from "@ambasada/sdk/platform";
2
2
  import { type IncomingRequest } from "./receipt.js";
3
3
  import type { AgentConfigInput, BuyOptions, BuyResult, ChatRequest, ChatResponse, CheckoutInput, CheckoutReceiptClaims, CheckoutDelivery, CheckoutDeliveryInput, CheckoutSession, ImageRequest, ImageResult, LedgerPage, Listing, ListingInput, MarketOffering, PaidCall, PaymentLink, PaymentLinkInput, ToolListing, ToolResult, TranscriptEntry, ChatLine, ChatProposal, ChatTurn, TransferOptions, Wallet, WebhookDelivery, WebhookEvent } from "./types.js";
4
+ /** How long a utility call may take here: the API's own limit plus a margin, so the SDK never gives up on a call the API finishes and charges. */
5
+ export declare const CLIENT_TIMEOUT_MS: {
6
+ readonly llm: number;
7
+ readonly image: number;
8
+ readonly tool: number;
9
+ };
4
10
  /** The Hack A Ton API. The platform API (`@ambasada/sdk`) is https://api.ambasada.dev. */
5
11
  export declare const DEFAULT_VILLAGE_API_URL = "https://hackaton.ambasada.id";
6
12
  export declare const DEFAULT_MODEL = "deepseek-v4.1-flash";
7
13
  export interface VillageOptions extends AmbasadaOptions {
8
- /** Team key (`sk_live_…`, from the village app → Developers). Default: `AMBASADA_API_KEY`. */
14
+ /** Team key (`sk_live_…`, from the village app → Team → Settings). Default: `AMBASADA_API_KEY`. */
9
15
  apiKey?: string;
10
16
  /**
11
17
  * Default: `AMBASADA_VILLAGE_API_URL`, else `AMBASADA_API_URL` when it is not the platform host (0.7
@@ -74,7 +80,9 @@ export declare class Village extends Ambasada {
74
80
  }>;
75
81
  /**
76
82
  * Tells the village what a paid checkout delivered (`text` ≤ 4000 chars, an https `url`, or both): the person sees it
77
- * with the purchase in their app and can rate it. Again for the same session replaces it. CONFLICT before it is paid.
83
+ * with the purchase in their app (one push, the first time) and can rate it. The same delivery again changes nothing;
84
+ * a new text replaces it. `{ status: "working" }` / `{ status: "failed", error }` while the work runs or when it gave
85
+ * up (never over a delivery). CONFLICT before it is paid.
78
86
  */
79
87
  deliverCheckout(id: string, delivery: CheckoutDeliveryInput): Promise<CheckoutDelivery>;
80
88
  /** A reusable payment link for static pages (`<button data-village-pay="pl_…">` with pay.js). */
@@ -101,6 +109,7 @@ export declare class Village extends Ambasada {
101
109
  }>;
102
110
  /** Sends a `webhook.test` event now and returns the delivery. */
103
111
  testWebhook(): Promise<WebhookDelivery>;
112
+ /** Sends a failed or pending delivery again now (same `webhook-id`). CONFLICT for one already delivered: it never goes out twice. */
104
113
  retryWebhookDelivery(id: string): Promise<WebhookDelivery>;
105
114
  /** Buys one call of `company/offering` through the Gateway. Money moves only if the seller answers 2xx with valid output. */
106
115
  buy<Output = any>(offering: string, input: unknown, options?: BuyOptions): Promise<BuyResult<Output>>;
package/dist/index.js CHANGED
@@ -4,22 +4,6 @@ var __export = (target, all) => {
4
4
  __defProp(target, name, { get: all[name], enumerable: true });
5
5
  };
6
6
 
7
- // src/client.ts
8
- import { Ambasada, AmbasadaError as AmbasadaError3 } from "@ambasada/sdk/platform";
9
-
10
- // src/errors.ts
11
- import { AmbasadaError, isAmbasadaError } from "@ambasada/sdk/platform";
12
- var VillageError = AmbasadaError;
13
- var isVillageError = isAmbasadaError;
14
- var ReceiptInvalidError = class extends AmbasadaError {
15
- reason;
16
- constructor(reason, message) {
17
- super("RECEIPT_INVALID", `payment required: ${message}`, 402, { reason });
18
- this.name = "ReceiptInvalidError";
19
- this.reason = reason;
20
- }
21
- };
22
-
23
7
  // ../protocol/src/index.ts
24
8
  var src_exports = {};
25
9
  __export(src_exports, {
@@ -57,7 +41,9 @@ __export(src_exports, {
57
41
  SHELL_TOKEN_TTL_S: () => SHELL_TOKEN_TTL_S,
58
42
  SLOW_ENTRY_MS: () => SLOW_ENTRY_MS,
59
43
  SYSTEM_ACCOUNT: () => SYSTEM_ACCOUNT,
60
- VillageError: () => VillageError2,
44
+ UTILITY_CLIENT_MARGIN_MS: () => UTILITY_CLIENT_MARGIN_MS,
45
+ UTILITY_TIMEOUT_MS: () => UTILITY_TIMEOUT_MS,
46
+ VillageError: () => VillageError,
61
47
  WEBHOOK_HEADERS: () => WEBHOOK_HEADERS,
62
48
  WebhookError: () => WebhookError,
63
49
  appNotifyBody: () => appNotifyBody,
@@ -189,7 +175,7 @@ var ERROR_STATUS = {
189
175
  // Deploy-freeze and unattended windows: agents keep running, but config and steer are closed (DESIGN.md §5)
190
176
  FROZEN: 403
191
177
  };
192
- var VillageError2 = class extends Error {
178
+ var VillageError = class extends Error {
193
179
  code;
194
180
  status;
195
181
  details;
@@ -1505,12 +1491,30 @@ var HEADERS = {
1505
1491
  };
1506
1492
  var MAX_DEPTH = 4;
1507
1493
  var OFFERING_TIMEOUT_MS = { min: 100, max: 3e4 };
1494
+ var UTILITY_TIMEOUT_MS = { llm: 12e4, image: 18e4, tool: 6e4 };
1495
+ var UTILITY_CLIENT_MARGIN_MS = 1e4;
1508
1496
  function offeringTimeoutProblem(value) {
1509
1497
  if (value === void 0) return null;
1510
1498
  const n = Number(value);
1511
1499
  return Number.isInteger(n) && n >= OFFERING_TIMEOUT_MS.min && n <= OFFERING_TIMEOUT_MS.max ? null : `timeout_ms must be between ${OFFERING_TIMEOUT_MS.min} and ${OFFERING_TIMEOUT_MS.max} (got ${JSON.stringify(value)})`;
1512
1500
  }
1513
1501
 
1502
+ // src/client.ts
1503
+ import { Ambasada, AmbasadaError as AmbasadaError3 } from "@ambasada/sdk/platform";
1504
+
1505
+ // src/errors.ts
1506
+ import { AmbasadaError, isAmbasadaError } from "@ambasada/sdk/platform";
1507
+ var VillageError2 = AmbasadaError;
1508
+ var isVillageError = isAmbasadaError;
1509
+ var ReceiptInvalidError = class extends AmbasadaError {
1510
+ reason;
1511
+ constructor(reason, message) {
1512
+ super("RECEIPT_INVALID", `payment required: ${message}`, 402, { reason });
1513
+ this.name = "ReceiptInvalidError";
1514
+ this.reason = reason;
1515
+ }
1516
+ };
1517
+
1514
1518
  // src/receipt.ts
1515
1519
  import { AmbasadaError as AmbasadaError2, getHeader } from "@ambasada/sdk/platform";
1516
1520
  var RECEIPT_HEADER2 = "x-village-receipt";
@@ -1627,6 +1631,11 @@ async function verifyWebhookPayload(secret, headers, body, options = {}) {
1627
1631
  }
1628
1632
 
1629
1633
  // src/client.ts
1634
+ var CLIENT_TIMEOUT_MS = {
1635
+ llm: UTILITY_TIMEOUT_MS.llm + UTILITY_CLIENT_MARGIN_MS,
1636
+ image: UTILITY_TIMEOUT_MS.image + UTILITY_CLIENT_MARGIN_MS,
1637
+ tool: UTILITY_TIMEOUT_MS.tool + UTILITY_CLIENT_MARGIN_MS
1638
+ };
1630
1639
  var DEFAULT_VILLAGE_API_URL = "https://hackaton.ambasada.id";
1631
1640
  var DEFAULT_MODEL = "deepseek-v4.1-flash";
1632
1641
  function randomKey() {
@@ -1755,7 +1764,9 @@ var Village = class extends Ambasada {
1755
1764
  }
1756
1765
  /**
1757
1766
  * Tells the village what a paid checkout delivered (`text` ≤ 4000 chars, an https `url`, or both): the person sees it
1758
- * with the purchase in their app and can rate it. Again for the same session replaces it. CONFLICT before it is paid.
1767
+ * with the purchase in their app (one push, the first time) and can rate it. The same delivery again changes nothing;
1768
+ * a new text replaces it. `{ status: "working" }` / `{ status: "failed", error }` while the work runs or when it gave
1769
+ * up (never over a delivery). CONFLICT before it is paid.
1759
1770
  */
1760
1771
  deliverCheckout(id, delivery) {
1761
1772
  return this.call("POST", `/v1/checkout/sessions/${encodeURIComponent(id)}/delivery`, { body: delivery });
@@ -1789,6 +1800,7 @@ var Village = class extends Ambasada {
1789
1800
  testWebhook() {
1790
1801
  return this.call("POST", "/v1/webhook/test");
1791
1802
  }
1803
+ /** Sends a failed or pending delivery again now (same `webhook-id`). CONFLICT for one already delivered: it never goes out twice. */
1792
1804
  retryWebhookDelivery(id) {
1793
1805
  return this.call("POST", `/v1/webhook/deliveries/${encodeURIComponent(id)}/retry`);
1794
1806
  }
@@ -1845,12 +1857,13 @@ var Village = class extends Ambasada {
1845
1857
  return res.choices[0]?.message.content ?? "";
1846
1858
  },
1847
1859
  {
1848
- chat: (req) => this.call("POST", "/v1/llm/chat", { body: { ...req, model: req.model ?? DEFAULT_MODEL } })
1860
+ // The API waits up to 120 s for the model (one that reasons first can take a minute): not the client's 45 s.
1861
+ chat: (req) => this.call("POST", "/v1/llm/chat", { body: { ...req, model: req.model ?? DEFAULT_MODEL }, timeoutMs: CLIENT_TIMEOUT_MS.llm })
1849
1862
  }
1850
1863
  );
1851
1864
  images = {
1852
1865
  /** Generates an image; the URL is re-hosted in the village files store. Default model: nano_banana. */
1853
- generate: (req) => this.call("POST", "/v1/images", { body: { ...req, model: req.model ?? "nano_banana" } })
1866
+ generate: (req) => this.call("POST", "/v1/images", { body: { ...req, model: req.model ?? "nano_banana" }, timeoutMs: CLIENT_TIMEOUT_MS.image })
1854
1867
  };
1855
1868
  tools = {
1856
1869
  /** The curated LLMOK tool catalog with TON prices. */
@@ -1863,6 +1876,8 @@ var Village = class extends Ambasada {
1863
1876
  const res = await this.send("POST", `/v1/tools/${encodeURIComponent(id)}`, {
1864
1877
  body: input ?? {},
1865
1878
  retry: true,
1879
+ // Image tools take as long as images; a routed search may try several providers within the API's 60 s.
1880
+ timeoutMs: id.startsWith("image.") ? CLIENT_TIMEOUT_MS.image : CLIENT_TIMEOUT_MS.tool,
1866
1881
  headers: { "idempotency-key": options.idempotencyKey ?? randomKey() }
1867
1882
  });
1868
1883
  const json = res.json;
@@ -1951,7 +1966,7 @@ export {
1951
1966
  RECEIPT_HEADER2 as RECEIPT_HEADER,
1952
1967
  ReceiptInvalidError,
1953
1968
  Village,
1954
- VillageError,
1969
+ VillageError2 as VillageError,
1955
1970
  WEBHOOK_HEADERS2 as WEBHOOK_HEADERS,
1956
1971
  WebhookInvalidError2 as WebhookInvalidError,
1957
1972
  createVillage,
package/dist/types.d.ts CHANGED
@@ -55,15 +55,26 @@ export interface CheckoutInput {
55
55
  /** Seconds, 300–86400 (default 3600). */
56
56
  expires_in?: number;
57
57
  }
58
- /** What a paid checkout delivered (`POST /v1/checkout/sessions/:id/delivery`): text, an https URL, or both. */
58
+ /**
59
+ * What a paid checkout delivered (`POST /v1/checkout/sessions/:id/delivery`): text, an https URL, or both. While the
60
+ * work runs (the templates' Jobs Durable Object), `status: "working"` (with `error`: why the last attempt failed, while
61
+ * it retries); `status: "failed"` with `error` when it gives up. `ambasada village deliveries` shows all three.
62
+ */
59
63
  export interface CheckoutDeliveryInput {
60
64
  text?: string;
61
65
  url?: string;
66
+ /** Default `delivered` (with text and/or url). */
67
+ status?: "working" | "delivered" | "failed";
68
+ /** Why an attempt failed (working: retrying) or why it gave up (failed); at most 300 characters are kept. */
69
+ error?: string;
62
70
  }
63
71
  export interface CheckoutDelivery {
64
72
  session: string;
73
+ /** `delivered` when the API predates delivery statuses. */
74
+ status?: "working" | "delivered" | "failed";
65
75
  text: string | null;
66
76
  url: string | null;
77
+ error?: string | null;
67
78
  at: string;
68
79
  }
69
80
  export interface CheckoutSession {
@@ -166,6 +177,8 @@ export interface ChatRequest {
166
177
  messages: ChatMessage[];
167
178
  temperature?: number;
168
179
  max_tokens?: number;
180
+ /** How much the model thinks before it answers; the village sends "low" when you leave it out. More thinking takes longer and more of `max_tokens`. */
181
+ reasoning_effort?: "low" | "medium" | "high" | (string & {});
169
182
  /** `json_schema`: JSON in the schema's shape (live, and the mock's sample of it under `ambasada dev`); `json_object`: any JSON. */
170
183
  response_format?: {
171
184
  type: "text" | "json_object";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ambasada/village",
3
- "version": "0.8.6",
3
+ "version": "0.8.7",
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,7 +27,7 @@
27
27
  "node": ">=22"
28
28
  },
29
29
  "dependencies": {
30
- "@ambasada/sdk": "^0.8.6"
30
+ "@ambasada/sdk": "^0.8.7"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/node": "^22.20.5",
@@ -35,7 +35,7 @@
35
35
  "typescript": "~5.9.3",
36
36
  "vitest": "^4.1.12",
37
37
  "@ambasada/protocol": "0.1.0",
38
- "@ambasada/cli": "0.8.6"
38
+ "@ambasada/cli": "0.8.7"
39
39
  },
40
40
  "author": "CENTYSO (https://centyso.com)",
41
41
  "homepage": "https://ambasada.id",