@ptkl/sdk 1.17.1 → 1.18.1

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.
@@ -1628,18 +1628,51 @@ var ProtokolSDK010 = (function (exports, axios) {
1628
1628
  return await this.client.get(`/luma/appservice/v1/forge/${ref}/services`);
1629
1629
  }
1630
1630
  // --- Variables ---
1631
+ /**
1632
+ * Build the variables path for a target app.
1633
+ *
1634
+ * Omitting `ref` selects the pathless self route, where the server resolves the
1635
+ * app from the caller's own token. That is why the self forms work in every
1636
+ * context an app token does, including Node, where `resolveCurrentAppUuid()`
1637
+ * has nothing to read.
1638
+ */
1639
+ variablesPath(ref) {
1640
+ return ref
1641
+ ? `/luma/appservice/v1/forge/${encodeURIComponent(ref)}/variables`
1642
+ : `/luma/appservice/v1/forge/variables`;
1643
+ }
1644
+ /**
1645
+ * Read variables for the current environment (`X-Project-Env`, defaults to dev).
1646
+ *
1647
+ * With no argument this returns the CALLING APP's own variables and needs no
1648
+ * permission at all. With a `ref` it reads that app's variables and needs
1649
+ * `manage forge`.
1650
+ *
1651
+ * @param ref App uuid, name or tag. Omit for the current app.
1652
+ *
1653
+ * @example
1654
+ * const mine = await platform.forge().getVariables()
1655
+ * const other = await platform.forge().getVariables('storefront')
1656
+ */
1631
1657
  async getVariables(ref) {
1632
- return await this.client.get(`/luma/appservice/v1/forge/${ref}/variables`);
1658
+ return await this.client.get(this.variablesPath(ref));
1633
1659
  }
1634
- async updateVariables(ref, variables) {
1635
- return await this.client.patch(`/luma/appservice/v1/forge/${ref}/variables`, variables);
1660
+ async updateVariables(a, b) {
1661
+ const [ref, variables] = typeof a === 'string'
1662
+ ? [a, b]
1663
+ : [undefined, a];
1664
+ return await this.client.patch(this.variablesPath(ref), variables);
1636
1665
  }
1637
- async addVariable(ref, key, value) {
1666
+ async addVariable(a, b, c) {
1638
1667
  var _a;
1639
- const resp = await this.client.get(`/luma/appservice/v1/forge/${ref}/variables`);
1640
- const current = (_a = resp.data) !== null && _a !== void 0 ? _a : {};
1641
- current[key] = value;
1642
- return await this.client.patch(`/luma/appservice/v1/forge/${ref}/variables`, current);
1668
+ // Arity, not `c !== undefined` — otherwise addVariable('ref', 'KEY', undefined)
1669
+ // is read as the two-argument self form and writes a variable named "ref".
1670
+ const [ref, key, value] = arguments.length >= 3
1671
+ ? [a, b, c]
1672
+ : [undefined, a, b];
1673
+ const path = this.variablesPath(ref);
1674
+ const resp = await this.client.get(path);
1675
+ return await this.client.patch(path, { ...((_a = resp.data) !== null && _a !== void 0 ? _a : {}), [key]: value });
1643
1676
  }
1644
1677
  // --- Service execution (forge-runtime) ---
1645
1678
  /**
@@ -1799,22 +1832,29 @@ var ProtokolSDK010 = (function (exports, axios) {
1799
1832
  // Stateless completion — no conversation is created and nothing is
1800
1833
  // persisted. The caller owns the message list.
1801
1834
  //
1802
- // Always responds with an SSE stream (message_start, thinking_delta,
1803
- // content_delta, message_complete, error). Tool calls are surfaced in
1835
+ // Returns the raw SSE body as a string: events separated by blank lines,
1836
+ // each `event: <name>` + `data: <json>`. Tool calls arrive in
1804
1837
  // message_complete for client-side execution; post the results back as
1805
1838
  // messages with role 'tool' and the matching tool_call_id.
1806
1839
  //
1840
+ // NOT typed as a stream, deliberately. This SDK is executed inside
1841
+ // isolated-vm sandboxes (the eval server runs the bundle in-isolate and
1842
+ // proxies HTTP through an adapter), and every value crossing that boundary
1843
+ // is structure-cloned. A Node Readable carries internal callbacks and dies
1844
+ // there with "could not be cloned" — an error that points nowhere near the
1845
+ // method that caused it. Buffering keeps this binding usable everywhere.
1846
+ //
1847
+ // A consumer that genuinely needs incremental delivery should drive the
1848
+ // endpoint directly rather than through the SDK, as the kortex CLI does.
1849
+ //
1807
1850
  // Constraints enforced server-side: agent_uuid is required, the last
1808
1851
  // message must have role 'user', 'context' or 'tool', and no message
1809
1852
  // content may exceed 32000 bytes.
1810
- //
1811
- // Typed as a Node stream because that is what axios `responseType:
1812
- // 'stream'` yields under Node, which is where this binding is used.
1813
- // Browser callers should drive the endpoint with fetch directly rather
1814
- // than through axios.
1815
1853
  async chat(data) {
1816
1854
  return await this.client.post(`${BASE$1}/chat`, data, {
1817
- responseType: 'stream',
1855
+ responseType: 'text',
1856
+ // Keep the SSE body intact — the default transform attempts JSON.parse.
1857
+ transformResponse: [(body) => body],
1818
1858
  timeout: 120000,
1819
1859
  });
1820
1860
  }
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ptkl/sdk",
3
- "version": "1.17.1",
3
+ "version": "1.18.1",
4
4
  "scripts": {
5
5
  "build": "rollup -c",
6
6
  "build:monaco": "npm run build && node scripts/generate-monaco-types.cjs",
@@ -1,12 +1,61 @@
1
1
  import PlatformBaseClient from "./platformBaseClient";
2
+ import type { ForgeVariables } from "../types/forge";
2
3
  export default class Forge extends PlatformBaseClient {
3
4
  bundleUpload(buffer: Buffer): Promise<any>;
4
5
  getWorkspaceApps(): Promise<any>;
5
6
  removeVersion(ref: string, version: string): Promise<any>;
6
7
  list(): Promise<any>;
7
8
  listServices(ref: string): Promise<any>;
8
- getVariables(ref: string): Promise<any>;
9
- updateVariables(ref: string, variables: Record<string, any>): Promise<any>;
9
+ /**
10
+ * Build the variables path for a target app.
11
+ *
12
+ * Omitting `ref` selects the pathless self route, where the server resolves the
13
+ * app from the caller's own token. That is why the self forms work in every
14
+ * context an app token does, including Node, where `resolveCurrentAppUuid()`
15
+ * has nothing to read.
16
+ */
17
+ private variablesPath;
18
+ /**
19
+ * Read variables for the current environment (`X-Project-Env`, defaults to dev).
20
+ *
21
+ * With no argument this returns the CALLING APP's own variables and needs no
22
+ * permission at all. With a `ref` it reads that app's variables and needs
23
+ * `manage forge`.
24
+ *
25
+ * @param ref App uuid, name or tag. Omit for the current app.
26
+ *
27
+ * @example
28
+ * const mine = await platform.forge().getVariables()
29
+ * const other = await platform.forge().getVariables('storefront')
30
+ */
31
+ getVariables(ref?: string): Promise<any>;
32
+ /**
33
+ * Replace the variable set for the current environment.
34
+ *
35
+ * This REPLACES the whole set for that environment — keys absent from
36
+ * `variables` are removed. The other environment is left untouched.
37
+ *
38
+ * The self form needs `manage_variables forge`, which only ever writes the
39
+ * calling app. Targeting another app by `ref` needs `manage forge`.
40
+ *
41
+ * @example
42
+ * await platform.forge().updateVariables({ WEBHOOK_URL: '...' })
43
+ * await platform.forge().updateVariables('storefront', { WEBHOOK_URL: '...' })
44
+ */
45
+ updateVariables(variables: ForgeVariables): Promise<any>;
46
+ updateVariables(ref: string, variables: ForgeVariables): Promise<any>;
47
+ /**
48
+ * Set a single variable, preserving the rest.
49
+ *
50
+ * A read-modify-write over a replace-everything PATCH, so concurrent writers
51
+ * can lose each other's updates. Prefer `updateVariables` when setting more
52
+ * than one key.
53
+ *
54
+ * @example
55
+ * await platform.forge().addVariable('WEBHOOK_URL', '...')
56
+ * await platform.forge().addVariable('storefront', 'WEBHOOK_URL', '...')
57
+ */
58
+ addVariable(key: string, value: any): Promise<any>;
10
59
  addVariable(ref: string, key: string, value: any): Promise<any>;
11
60
  /**
12
61
  * Run a Forge service: `runService(target, body?, { query?, headers? })`.
@@ -17,6 +17,7 @@ export { default as Sandbox } from './sandbox';
17
17
  export { default as System } from './system';
18
18
  export { default as Workflow } from './workflow';
19
19
  export { default as Forge } from './forge';
20
+ export type { ForgeVariables } from '../types/forge';
20
21
  export { default as Kortex } from './kortex';
21
22
  export { default as Project } from './project';
22
23
  export { default as Config } from './config';
@@ -35,7 +35,7 @@ export default class Kortex extends PlatformBaseClient {
35
35
  streamMessage(conversationUUID: string, data: SendMessagePayload): Promise<AxiosResponse<ReadableStream>>;
36
36
  listMessages(conversationUUID: string, params?: PaginationParams): Promise<AxiosResponse<PagedResponse<Message>>>;
37
37
  injectMessage(conversationUUID: string, data: InjectMessagePayload): Promise<AxiosResponse<Message>>;
38
- chat(data: KortexChatPayload): Promise<AxiosResponse<NodeJS.ReadableStream>>;
38
+ chat(data: KortexChatPayload): Promise<AxiosResponse<string>>;
39
39
  ocr(data: OCRPayload): Promise<AxiosResponse<OCRResult>>;
40
40
  createUserAccess(data: UserAccessCreatePayload): Promise<AxiosResponse<UserAccess>>;
41
41
  listUserAccess(params?: PaginationParams): Promise<AxiosResponse<PagedResponse<UserAccess>>>;
@@ -20594,18 +20594,51 @@ class Forge extends PlatformBaseClient {
20594
20594
  return await this.client.get(`/luma/appservice/v1/forge/${ref}/services`);
20595
20595
  }
20596
20596
  // --- Variables ---
20597
+ /**
20598
+ * Build the variables path for a target app.
20599
+ *
20600
+ * Omitting `ref` selects the pathless self route, where the server resolves the
20601
+ * app from the caller's own token. That is why the self forms work in every
20602
+ * context an app token does, including Node, where `resolveCurrentAppUuid()`
20603
+ * has nothing to read.
20604
+ */
20605
+ variablesPath(ref) {
20606
+ return ref
20607
+ ? `/luma/appservice/v1/forge/${encodeURIComponent(ref)}/variables`
20608
+ : `/luma/appservice/v1/forge/variables`;
20609
+ }
20610
+ /**
20611
+ * Read variables for the current environment (`X-Project-Env`, defaults to dev).
20612
+ *
20613
+ * With no argument this returns the CALLING APP's own variables and needs no
20614
+ * permission at all. With a `ref` it reads that app's variables and needs
20615
+ * `manage forge`.
20616
+ *
20617
+ * @param ref App uuid, name or tag. Omit for the current app.
20618
+ *
20619
+ * @example
20620
+ * const mine = await platform.forge().getVariables()
20621
+ * const other = await platform.forge().getVariables('storefront')
20622
+ */
20597
20623
  async getVariables(ref) {
20598
- return await this.client.get(`/luma/appservice/v1/forge/${ref}/variables`);
20624
+ return await this.client.get(this.variablesPath(ref));
20599
20625
  }
20600
- async updateVariables(ref, variables) {
20601
- return await this.client.patch(`/luma/appservice/v1/forge/${ref}/variables`, variables);
20626
+ async updateVariables(a, b) {
20627
+ const [ref, variables] = typeof a === 'string'
20628
+ ? [a, b]
20629
+ : [undefined, a];
20630
+ return await this.client.patch(this.variablesPath(ref), variables);
20602
20631
  }
20603
- async addVariable(ref, key, value) {
20632
+ async addVariable(a, b, c) {
20604
20633
  var _a;
20605
- const resp = await this.client.get(`/luma/appservice/v1/forge/${ref}/variables`);
20606
- const current = (_a = resp.data) !== null && _a !== void 0 ? _a : {};
20607
- current[key] = value;
20608
- return await this.client.patch(`/luma/appservice/v1/forge/${ref}/variables`, current);
20634
+ // Arity, not `c !== undefined` — otherwise addVariable('ref', 'KEY', undefined)
20635
+ // is read as the two-argument self form and writes a variable named "ref".
20636
+ const [ref, key, value] = arguments.length >= 3
20637
+ ? [a, b, c]
20638
+ : [undefined, a, b];
20639
+ const path = this.variablesPath(ref);
20640
+ const resp = await this.client.get(path);
20641
+ return await this.client.patch(path, { ...((_a = resp.data) !== null && _a !== void 0 ? _a : {}), [key]: value });
20609
20642
  }
20610
20643
  // --- Service execution (forge-runtime) ---
20611
20644
  /**
@@ -20765,22 +20798,29 @@ class Kortex extends PlatformBaseClient {
20765
20798
  // Stateless completion — no conversation is created and nothing is
20766
20799
  // persisted. The caller owns the message list.
20767
20800
  //
20768
- // Always responds with an SSE stream (message_start, thinking_delta,
20769
- // content_delta, message_complete, error). Tool calls are surfaced in
20801
+ // Returns the raw SSE body as a string: events separated by blank lines,
20802
+ // each `event: <name>` + `data: <json>`. Tool calls arrive in
20770
20803
  // message_complete for client-side execution; post the results back as
20771
20804
  // messages with role 'tool' and the matching tool_call_id.
20772
20805
  //
20806
+ // NOT typed as a stream, deliberately. This SDK is executed inside
20807
+ // isolated-vm sandboxes (the eval server runs the bundle in-isolate and
20808
+ // proxies HTTP through an adapter), and every value crossing that boundary
20809
+ // is structure-cloned. A Node Readable carries internal callbacks and dies
20810
+ // there with "could not be cloned" — an error that points nowhere near the
20811
+ // method that caused it. Buffering keeps this binding usable everywhere.
20812
+ //
20813
+ // A consumer that genuinely needs incremental delivery should drive the
20814
+ // endpoint directly rather than through the SDK, as the kortex CLI does.
20815
+ //
20773
20816
  // Constraints enforced server-side: agent_uuid is required, the last
20774
20817
  // message must have role 'user', 'context' or 'tool', and no message
20775
20818
  // content may exceed 32000 bytes.
20776
- //
20777
- // Typed as a Node stream because that is what axios `responseType:
20778
- // 'stream'` yields under Node, which is where this binding is used.
20779
- // Browser callers should drive the endpoint with fetch directly rather
20780
- // than through axios.
20781
20819
  async chat(data) {
20782
20820
  return await this.client.post(`${BASE$1}/chat`, data, {
20783
- responseType: 'stream',
20821
+ responseType: 'text',
20822
+ // Keep the SSE body intact — the default transform attempts JSON.parse.
20823
+ transformResponse: [(body) => body],
20784
20824
  timeout: 120000,
20785
20825
  });
20786
20826
  }
@@ -1627,18 +1627,51 @@ class Forge extends PlatformBaseClient {
1627
1627
  return await this.client.get(`/luma/appservice/v1/forge/${ref}/services`);
1628
1628
  }
1629
1629
  // --- Variables ---
1630
+ /**
1631
+ * Build the variables path for a target app.
1632
+ *
1633
+ * Omitting `ref` selects the pathless self route, where the server resolves the
1634
+ * app from the caller's own token. That is why the self forms work in every
1635
+ * context an app token does, including Node, where `resolveCurrentAppUuid()`
1636
+ * has nothing to read.
1637
+ */
1638
+ variablesPath(ref) {
1639
+ return ref
1640
+ ? `/luma/appservice/v1/forge/${encodeURIComponent(ref)}/variables`
1641
+ : `/luma/appservice/v1/forge/variables`;
1642
+ }
1643
+ /**
1644
+ * Read variables for the current environment (`X-Project-Env`, defaults to dev).
1645
+ *
1646
+ * With no argument this returns the CALLING APP's own variables and needs no
1647
+ * permission at all. With a `ref` it reads that app's variables and needs
1648
+ * `manage forge`.
1649
+ *
1650
+ * @param ref App uuid, name or tag. Omit for the current app.
1651
+ *
1652
+ * @example
1653
+ * const mine = await platform.forge().getVariables()
1654
+ * const other = await platform.forge().getVariables('storefront')
1655
+ */
1630
1656
  async getVariables(ref) {
1631
- return await this.client.get(`/luma/appservice/v1/forge/${ref}/variables`);
1657
+ return await this.client.get(this.variablesPath(ref));
1632
1658
  }
1633
- async updateVariables(ref, variables) {
1634
- return await this.client.patch(`/luma/appservice/v1/forge/${ref}/variables`, variables);
1659
+ async updateVariables(a, b) {
1660
+ const [ref, variables] = typeof a === 'string'
1661
+ ? [a, b]
1662
+ : [undefined, a];
1663
+ return await this.client.patch(this.variablesPath(ref), variables);
1635
1664
  }
1636
- async addVariable(ref, key, value) {
1665
+ async addVariable(a, b, c) {
1637
1666
  var _a;
1638
- const resp = await this.client.get(`/luma/appservice/v1/forge/${ref}/variables`);
1639
- const current = (_a = resp.data) !== null && _a !== void 0 ? _a : {};
1640
- current[key] = value;
1641
- return await this.client.patch(`/luma/appservice/v1/forge/${ref}/variables`, current);
1667
+ // Arity, not `c !== undefined` — otherwise addVariable('ref', 'KEY', undefined)
1668
+ // is read as the two-argument self form and writes a variable named "ref".
1669
+ const [ref, key, value] = arguments.length >= 3
1670
+ ? [a, b, c]
1671
+ : [undefined, a, b];
1672
+ const path = this.variablesPath(ref);
1673
+ const resp = await this.client.get(path);
1674
+ return await this.client.patch(path, { ...((_a = resp.data) !== null && _a !== void 0 ? _a : {}), [key]: value });
1642
1675
  }
1643
1676
  // --- Service execution (forge-runtime) ---
1644
1677
  /**
@@ -1798,22 +1831,29 @@ class Kortex extends PlatformBaseClient {
1798
1831
  // Stateless completion — no conversation is created and nothing is
1799
1832
  // persisted. The caller owns the message list.
1800
1833
  //
1801
- // Always responds with an SSE stream (message_start, thinking_delta,
1802
- // content_delta, message_complete, error). Tool calls are surfaced in
1834
+ // Returns the raw SSE body as a string: events separated by blank lines,
1835
+ // each `event: <name>` + `data: <json>`. Tool calls arrive in
1803
1836
  // message_complete for client-side execution; post the results back as
1804
1837
  // messages with role 'tool' and the matching tool_call_id.
1805
1838
  //
1839
+ // NOT typed as a stream, deliberately. This SDK is executed inside
1840
+ // isolated-vm sandboxes (the eval server runs the bundle in-isolate and
1841
+ // proxies HTTP through an adapter), and every value crossing that boundary
1842
+ // is structure-cloned. A Node Readable carries internal callbacks and dies
1843
+ // there with "could not be cloned" — an error that points nowhere near the
1844
+ // method that caused it. Buffering keeps this binding usable everywhere.
1845
+ //
1846
+ // A consumer that genuinely needs incremental delivery should drive the
1847
+ // endpoint directly rather than through the SDK, as the kortex CLI does.
1848
+ //
1806
1849
  // Constraints enforced server-side: agent_uuid is required, the last
1807
1850
  // message must have role 'user', 'context' or 'tool', and no message
1808
1851
  // content may exceed 32000 bytes.
1809
- //
1810
- // Typed as a Node stream because that is what axios `responseType:
1811
- // 'stream'` yields under Node, which is where this binding is used.
1812
- // Browser callers should drive the endpoint with fetch directly rather
1813
- // than through axios.
1814
1852
  async chat(data) {
1815
1853
  return await this.client.post(`${BASE$1}/chat`, data, {
1816
- responseType: 'stream',
1854
+ responseType: 'text',
1855
+ // Keep the SSE body intact — the default transform attempts JSON.parse.
1856
+ transformResponse: [(body) => body],
1817
1857
  timeout: 120000,
1818
1858
  });
1819
1859
  }
@@ -251,10 +251,20 @@ type FieldConstraints = {
251
251
  unique?: boolean;
252
252
  placeholder?: string;
253
253
  default?: string;
254
+ /** Bounds the *length* of a string value (input/text, password, ...). */
254
255
  length?: {
255
256
  min?: number | null;
256
257
  max?: number | null;
257
258
  };
259
+ /**
260
+ * Bounds the *value* of a numeric field (input/number). Inclusive on both
261
+ * ends. Prefer this over `length` for numbers — `length` is only still read
262
+ * as a fallback for fields authored before `range` existed.
263
+ */
264
+ range?: {
265
+ min?: number | null;
266
+ max?: number | null;
267
+ };
258
268
  not_allowed_words?: string;
259
269
  regex?: string;
260
270
  date?: {
@@ -0,0 +1,11 @@
1
+ /**
2
+ * A Forge app's variables for a single environment: a flat, JSON-serialisable
3
+ * key/value map.
4
+ *
5
+ * Each app holds two independent sets, `dev` and `live`. Which one an API call
6
+ * reads or writes is selected by the `X-Project-Env` header, not by this type.
7
+ *
8
+ * @example
9
+ * const vars: ForgeVariables = { WEBHOOK_URL: 'https://example.com/hook', MAX_RETRIES: 3 }
10
+ */
11
+ export type ForgeVariables = Record<string, any>;
@@ -1,4 +1,18 @@
1
1
  export type ThunderReadOptions = {
2
+ /**
3
+ * Maximum age, in seconds, of a cached response you are willing to accept.
4
+ *
5
+ * - omitted — serve whatever is cached, regardless of age (Thunder's
6
+ * historical behaviour, and still the cheapest read)
7
+ * - `0` — skip the cache and read from the database
8
+ * - `> 0` — serve a cached response only if it is younger than this many
9
+ * seconds, otherwise refresh from the database
10
+ *
11
+ * Not clamped: `1` and `86400` are both honoured.
12
+ *
13
+ * Note this differs from the component read option of the same name, where
14
+ * an omitted value behaves like `0` and the value is clamped to 5-300s.
15
+ */
2
16
  cacheTTL?: number;
3
17
  only?: string[];
4
18
  };
@@ -221,10 +221,20 @@ type FieldConstraints = {
221
221
  unique?: boolean;
222
222
  placeholder?: string;
223
223
  default?: string;
224
+ /** Bounds the *length* of a string value (input/text, password, ...). */
224
225
  length?: {
225
226
  min?: number | null;
226
227
  max?: number | null;
227
228
  };
229
+ /**
230
+ * Bounds the *value* of a numeric field (input/number). Inclusive on both
231
+ * ends. Prefer this over `length` for numbers — `length` is only still read
232
+ * as a fallback for fields authored before `range` existed.
233
+ */
234
+ range?: {
235
+ min?: number | null;
236
+ max?: number | null;
237
+ };
228
238
  not_allowed_words?: string;
229
239
  regex?: string;
230
240
  date?: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ptkl/sdk",
3
- "version": "1.17.1",
3
+ "version": "1.18.1",
4
4
  "scripts": {
5
5
  "build": "rollup -c",
6
6
  "build:monaco": "npm run build && node scripts/generate-monaco-types.cjs",