@prismer/sdk 1.8.2 → 1.9.6

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.
@@ -0,0 +1,10 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ export {
9
+ __require
10
+ };
package/dist/cli.js CHANGED
@@ -1,3 +1,4 @@
1
+ #!/usr/bin/env node
1
2
  "use strict";
2
3
  var __create = Object.create;
3
4
  var __defProp = Object.defineProperty;
@@ -1772,6 +1773,23 @@ var AccountClient = class {
1772
1773
  async refreshToken() {
1773
1774
  return this._r("POST", "/api/im/token/refresh");
1774
1775
  }
1776
+ /**
1777
+ * List agents owned by the current human user (v1.9.3).
1778
+ * Mobile clients call this on launch to populate the Profile/agent runtime card.
1779
+ * Returns `[]` for non-human / api-key-proxy callers without a cloudUserId.
1780
+ */
1781
+ async listAgents() {
1782
+ return this._r("GET", "/api/im/me/agents");
1783
+ }
1784
+ /**
1785
+ * Self-service account deletion (v1.9.3).
1786
+ * Soft-deletes the IMUser, cascades owned conversations + open tasks,
1787
+ * revokes pc_api_keys, and blacklists the request token.
1788
+ * The caller can only delete themselves — there is no target id parameter.
1789
+ */
1790
+ async deleteAccount() {
1791
+ return this._r("DELETE", "/api/im/me");
1792
+ }
1775
1793
  };
1776
1794
  var DirectClient = class {
1777
1795
  constructor(_r) {
@@ -2094,6 +2112,9 @@ var TasksClient = class {
2094
2112
  /** List tasks with optional filters */
2095
2113
  async list(options) {
2096
2114
  const query = {};
2115
+ query.view = options?.view ?? "board";
2116
+ if (options?.kind) query.kind = options.kind;
2117
+ if (!options?.kind && query.view === "board") query.kind = "work_item,goal";
2097
2118
  if (options?.status) query.status = options.status;
2098
2119
  if (options?.capability) query.capability = options.capability;
2099
2120
  if (options?.assigneeId) query.assigneeId = options.assigneeId;
@@ -2101,12 +2122,38 @@ var TasksClient = class {
2101
2122
  if (options?.scheduleType) query.scheduleType = options.scheduleType;
2102
2123
  if (options?.limit != null) query.limit = String(options.limit);
2103
2124
  if (options?.cursor) query.cursor = options.cursor;
2125
+ if (options?.workspaceId) query.workspaceId = options.workspaceId;
2126
+ if (options?.conversationId) query.conversationId = options.conversationId;
2104
2127
  return this._r("GET", "/api/im/tasks", void 0, query);
2105
2128
  }
2106
2129
  /** Get task details with logs */
2107
2130
  async get(taskId) {
2108
2131
  return this._r("GET", `/api/im/tasks/${taskId}`);
2109
2132
  }
2133
+ /**
2134
+ * Wave-9 (v1.9.4) — fetch the canonical task result.
2135
+ *
2136
+ * Replaces the legacy "list IMAssets where kind=task-result + sourceTaskId"
2137
+ * pattern. Returns the locked shape defined by `IMTaskResult`; in
2138
+ * particular `assetIds` is always an array (possibly empty) so callers
2139
+ * can iterate without a null-check.
2140
+ *
2141
+ * Access: creator, assignee, or marketplace visibility on the task.
2142
+ */
2143
+ async getResult(taskId) {
2144
+ return this._r("GET", `/api/im/tasks/${taskId}/result`);
2145
+ }
2146
+ /**
2147
+ * Wave-9 (v1.9.4) — fetch the canonical run result.
2148
+ *
2149
+ * Same shape as `getResult` but reads from IMTaskRun.output instead of
2150
+ * IMTask.result. Use this for chat-mention dispatches whose result lives
2151
+ * on a run row rather than a board task. The `taskId` field of the
2152
+ * returned object is the run.id.
2153
+ */
2154
+ async getRunResult(runId) {
2155
+ return this._r("GET", `/api/im/runs/${runId}/result`);
2156
+ }
2110
2157
  /** Update a task */
2111
2158
  async update(taskId, options) {
2112
2159
  return this._r("PATCH", `/api/im/tasks/${taskId}`, options);
@@ -2185,6 +2232,18 @@ var MemoryClient = class {
2185
2232
  async getKnowledgeLinks() {
2186
2233
  return this._r("GET", "/api/im/memory/links");
2187
2234
  }
2235
+ /**
2236
+ * Get a CC-style always-load digest of all memory files (v1.9.3).
2237
+ * The digest is a Markdown bundle suitable for prepending to LLM context.
2238
+ * Server clamps `maxLines` to 10–1000 and `maxBytes` to 500–30000.
2239
+ */
2240
+ async digest(options) {
2241
+ const query = {};
2242
+ if (options?.scope) query.scope = options.scope;
2243
+ if (options?.maxLines != null) query.maxLines = String(options.maxLines);
2244
+ if (options?.maxBytes != null) query.maxBytes = String(options.maxBytes);
2245
+ return this._r("GET", "/api/im/memory/digest", void 0, query);
2246
+ }
2188
2247
  };
2189
2248
  var KnowledgeLinkClient = class {
2190
2249
  constructor(_r) {
@@ -2722,6 +2781,226 @@ var EvolutionClient = class {
2722
2781
  function safeSlug(input) {
2723
2782
  return input.replace(/[\/\\]/g, "").replace(/\.\./g, "").replace(/\0/g, "");
2724
2783
  }
2784
+ var WorkspacesClient = class {
2785
+ constructor(_r) {
2786
+ this._r = _r;
2787
+ }
2788
+ /** List active workspaces owned by the caller. */
2789
+ async list() {
2790
+ return this._r("GET", "/api/im/workspaces");
2791
+ }
2792
+ /**
2793
+ * Create a workspace. In 1.9.x most callers don't need this — registration
2794
+ * auto-creates a default workspace. The first workspace per owner is
2795
+ * always default; subsequent ones must omit `isDefault` (server returns 409).
2796
+ */
2797
+ async create(options) {
2798
+ return this._r("POST", "/api/im/workspaces", options);
2799
+ }
2800
+ /** Daemon delta-sync workspaces since an ISO timestamp. */
2801
+ async sync(since) {
2802
+ const query = {};
2803
+ if (since) query.since = since;
2804
+ return this._r("GET", "/api/im/workspaces/sync", void 0, query);
2805
+ }
2806
+ /** Get a single workspace by id (caller must own). */
2807
+ async get(workspaceId) {
2808
+ return this._r("GET", `/api/im/workspaces/${workspaceId}`);
2809
+ }
2810
+ /** Update workspace name and/or metadata. `slug` and `isDefault` are immutable in 1.9.x. */
2811
+ async update(workspaceId, options) {
2812
+ return this._r("PATCH", `/api/im/workspaces/${workspaceId}`, options);
2813
+ }
2814
+ /**
2815
+ * Archive (delete) a workspace. Server returns 405 in 1.9.x — workspace
2816
+ * deletion equals account close, which goes through `account.deleteAccount()`.
2817
+ * Provided for forward-compat; will become real in 1.10+.
2818
+ */
2819
+ async archive(workspaceId) {
2820
+ return this._r("DELETE", `/api/im/workspaces/${workspaceId}`);
2821
+ }
2822
+ };
2823
+ var WorkspaceFilesClient = class {
2824
+ constructor(_r) {
2825
+ this._r = _r;
2826
+ }
2827
+ /** List the active file tree for a workspace, or look up a single file by path. */
2828
+ async list(workspaceId, options) {
2829
+ const query = {};
2830
+ if (options?.path) query.path = options.path;
2831
+ return this._r("GET", `/api/im/workspaces/${workspaceId}/files`, void 0, query);
2832
+ }
2833
+ /**
2834
+ * Bind `path → assetId`. Idempotent if `(path, assetId)` matches the existing
2835
+ * active binding. Asset must already exist in the same workspace.
2836
+ */
2837
+ async create(workspaceId, options) {
2838
+ return this._r("POST", `/api/im/workspaces/${workspaceId}/files`, options);
2839
+ }
2840
+ /** Soft-delete the active binding at `path`. */
2841
+ async delete(workspaceId, path4) {
2842
+ return this._r("DELETE", `/api/im/workspaces/${workspaceId}/files`, void 0, { path: path4 });
2843
+ }
2844
+ /** Daemon delta-sync workspace files since an ISO timestamp. */
2845
+ async sync(workspaceId, since) {
2846
+ const query = {};
2847
+ if (since) query.since = since;
2848
+ return this._r("GET", `/api/im/workspaces/${workspaceId}/files/sync`, void 0, query);
2849
+ }
2850
+ /** Get the version chain for a file (walks `parentVersionId`). */
2851
+ async history(workspaceId, fileId) {
2852
+ return this._r("GET", `/api/im/workspaces/${workspaceId}/files/${fileId}/history`);
2853
+ }
2854
+ };
2855
+ var AssetsClient = class {
2856
+ constructor(_r, _baseUrl, _fetchFn, _getAuthHeaders) {
2857
+ this._r = _r;
2858
+ this._baseUrl = _baseUrl;
2859
+ this._fetchFn = _fetchFn;
2860
+ this._getAuthHeaders = _getAuthHeaders;
2861
+ }
2862
+ /** List assets in a workspace (filterable by task and kind). */
2863
+ async list(options) {
2864
+ const query = {};
2865
+ if (options.workspaceId) query.workspaceId = options.workspaceId;
2866
+ if (options.taskId) query.taskId = options.taskId;
2867
+ if (options.kind) query.kind = options.kind;
2868
+ if (options.limit != null) query.limit = String(options.limit);
2869
+ return this._r("GET", "/api/im/assets", void 0, query);
2870
+ }
2871
+ /**
2872
+ * Look up an asset by content hash within a workspace. Useful for dedupe
2873
+ * checks ("do I already have this file?") before uploading.
2874
+ */
2875
+ async byHash(hash, workspaceId) {
2876
+ return this._r("GET", `/api/im/assets/by-hash/${encodeURIComponent(hash)}`, void 0, { wsId: workspaceId });
2877
+ }
2878
+ /**
2879
+ * Get full asset metadata + a freshly-signed URL (5 min TTL, S3 backend only).
2880
+ * For `kind === 'photo-memory-segment'` this also includes a `photoRefs`
2881
+ * reverse-lookup of memory references.
2882
+ */
2883
+ async detail(assetId) {
2884
+ return this._r("GET", `/api/im/assets/${assetId}/detail`);
2885
+ }
2886
+ /**
2887
+ * Soft-delete an asset (the underlying S3 object is retained). Idempotent.
2888
+ */
2889
+ async delete(assetId) {
2890
+ return this._r("DELETE", `/api/im/assets/${assetId}`);
2891
+ }
2892
+ /**
2893
+ * Build a download URL for an asset. Filesystem backend streams bytes
2894
+ * directly; S3 backend returns a 302 to a 5-minute presigned URL.
2895
+ * Use `download()` for a one-shot fetch returning bytes.
2896
+ */
2897
+ url(assetId) {
2898
+ return `${this._baseUrl}/api/im/assets/${assetId}`;
2899
+ }
2900
+ /**
2901
+ * Download an asset's bytes. Authentication is forwarded; for S3 backend
2902
+ * the server returns a 302 which `fetch` follows automatically.
2903
+ */
2904
+ async download(assetId) {
2905
+ const resp = await this._fetchFn(this.url(assetId), {
2906
+ method: "GET",
2907
+ headers: this._getAuthHeaders()
2908
+ });
2909
+ if (!resp.ok) {
2910
+ throw new Error(`Asset download failed (${resp.status}): ${await resp.text()}`);
2911
+ }
2912
+ const ab = await resp.arrayBuffer();
2913
+ const sizeHeader = resp.headers.get("content-length");
2914
+ return {
2915
+ bytes: new Uint8Array(ab),
2916
+ mime: resp.headers.get("content-type"),
2917
+ sizeBytes: sizeHeader ? Number(sizeHeader) : null
2918
+ };
2919
+ }
2920
+ /**
2921
+ * Upload bytes as an asset (multipart). 100 MB hard cap; >50 MB returns
2922
+ * 413 with `USE_PRESIGNED` — use S3 presign flow for those (not yet wrapped).
2923
+ */
2924
+ async upload(input, options) {
2925
+ let bytes;
2926
+ let fileName;
2927
+ if (typeof input === "string") {
2928
+ const fs4 = await import("fs");
2929
+ const path4 = await import("path");
2930
+ const buf = await fs4.promises.readFile(input);
2931
+ bytes = new Uint8Array(buf);
2932
+ fileName = options.fileName || path4.basename(input);
2933
+ } else if (typeof Blob !== "undefined" && input instanceof Blob) {
2934
+ const ab2 = await input.arrayBuffer();
2935
+ bytes = new Uint8Array(ab2);
2936
+ fileName = options.fileName || (input instanceof File ? input.name : "");
2937
+ if (!fileName) throw new Error("fileName is required when uploading Blob without name");
2938
+ } else if (input instanceof Uint8Array) {
2939
+ bytes = input;
2940
+ fileName = options.fileName || "";
2941
+ if (!fileName) throw new Error("fileName is required when uploading Buffer or Uint8Array");
2942
+ } else {
2943
+ throw new Error("Unsupported input type");
2944
+ }
2945
+ const mimeType = options.mimeType || guessMimeType(fileName);
2946
+ const sizeBytes = bytes.byteLength;
2947
+ if (sizeBytes > 100 * 1024 * 1024) {
2948
+ throw new Error("Asset exceeds 100 MB cap");
2949
+ }
2950
+ const formData = new FormData();
2951
+ const ab = new ArrayBuffer(bytes.byteLength);
2952
+ new Uint8Array(ab).set(bytes);
2953
+ formData.append("file", new Blob([ab], { type: mimeType }), fileName);
2954
+ formData.append("workspaceId", options.workspaceId);
2955
+ if (options.kind) formData.append("kind", options.kind);
2956
+ if (options.sourceAgentImUserId) formData.append("sourceAgentImUserId", options.sourceAgentImUserId);
2957
+ if (options.sourceTaskId) formData.append("sourceTaskId", options.sourceTaskId);
2958
+ if (options.metadata) formData.append("metadata", JSON.stringify(options.metadata));
2959
+ const resp = await this._fetchFn(`${this._baseUrl}/api/im/assets`, {
2960
+ method: "POST",
2961
+ body: formData,
2962
+ headers: this._getAuthHeaders()
2963
+ });
2964
+ options.onProgress?.(sizeBytes, sizeBytes);
2965
+ const data = await resp.json().catch(() => ({}));
2966
+ if (!resp.ok) {
2967
+ return {
2968
+ ok: false,
2969
+ error: data?.error || { code: "HTTP_ERROR", message: `Upload failed (${resp.status})` }
2970
+ };
2971
+ }
2972
+ return data;
2973
+ }
2974
+ };
2975
+ var RuntimeInstallationsClient = class {
2976
+ constructor(_r) {
2977
+ this._r = _r;
2978
+ }
2979
+ /** List runtime installations in a workspace. */
2980
+ async list(workspaceId, options) {
2981
+ const query = { workspaceId };
2982
+ if (options?.limit != null) query.limit = String(options.limit);
2983
+ return this._r("GET", "/api/workspace/runtime-installations", void 0, query);
2984
+ }
2985
+ /**
2986
+ * Create a new runtime installation. Mints a durable runtime API key,
2987
+ * RPCs the sandbox controller, and persists an `IMContainer` row.
2988
+ * The daemon receives `PRISMER_API_KEY`, `PRISMER_DAEMON_ID`,
2989
+ * `PRISMER_BASE_URL`, `PRISMER_WORKSPACE_ID`, and
2990
+ * `PRISMER_RUNTIME_KIND=workspace-daemon` env vars.
2991
+ */
2992
+ async create(options) {
2993
+ return this._r("POST", "/api/workspace/runtime-installations", options);
2994
+ }
2995
+ /**
2996
+ * Install an agent onto a runtime daemon. Resolves or creates the agent
2997
+ * profile, calls the controller's `installAgent` RPC, and stamps
2998
+ * `IMAgentCard.metadata.daemonId` + `runtimeInstallationId`.
2999
+ */
3000
+ async installAgent(runtimeInstallationId, options) {
3001
+ return this._r("POST", `/api/workspace/runtime-installations/${runtimeInstallationId}/agents`, options);
3002
+ }
3003
+ };
2725
3004
  function guessMimeType(fileName) {
2726
3005
  const ext = fileName.split(".").pop()?.toLowerCase() || "";
2727
3006
  const map = {
@@ -2928,8 +3207,9 @@ var FilesClient = class {
2928
3207
  }
2929
3208
  };
2930
3209
  var IMRealtimeClient = class {
2931
- constructor(_wsBase) {
3210
+ constructor(_wsBase, _fetchFn = fetch) {
2932
3211
  this._wsBase = _wsBase;
3212
+ this._fetchFn = _fetchFn;
2933
3213
  }
2934
3214
  /** Get the WebSocket URL */
2935
3215
  wsUrl(token) {
@@ -2940,6 +3220,14 @@ var IMRealtimeClient = class {
2940
3220
  sseUrl(token) {
2941
3221
  return token ? `${this._wsBase}/sse?token=${token}` : `${this._wsBase}/sse`;
2942
3222
  }
3223
+ /**
3224
+ * Get the URL for the v1.8.2 task SSE stream
3225
+ * (`GET /api/im/tasks/events?token=...`).
3226
+ * Supports `Last-Event-ID` for replay.
3227
+ */
3228
+ taskEventsUrl(token) {
3229
+ return `${this._wsBase}/api/im/tasks/events?token=${encodeURIComponent(token)}`;
3230
+ }
2943
3231
  /** Create a WebSocket client. Call .connect() to establish connection. */
2944
3232
  connectWS(config) {
2945
3233
  return new RealtimeWSClient(this._wsBase, config);
@@ -2948,6 +3236,101 @@ var IMRealtimeClient = class {
2948
3236
  connectSSE(config) {
2949
3237
  return new RealtimeSSEClient(this._wsBase, config);
2950
3238
  }
3239
+ /**
3240
+ * Subscribe to the task events SSE stream (v1.8.2/v1.9.3).
3241
+ *
3242
+ * Resolves with a `disconnect()` function for cleanup. Emits envelopes of
3243
+ * shape `{ id?, type, payload }` for each parsed `event:` block. Ignores
3244
+ * comment lines (`:` heartbeats).
3245
+ *
3246
+ * @example
3247
+ * const sub = await client.im.realtime.subscribeTaskEvents(apiKey, (evt) => {
3248
+ * if (evt.type === 'task.completed') console.log('done:', evt.payload);
3249
+ * });
3250
+ * // ... later:
3251
+ * sub.disconnect();
3252
+ */
3253
+ async subscribeTaskEvents(token, onEvent, options) {
3254
+ const controller = new AbortController();
3255
+ const onAbort = () => controller.abort();
3256
+ options?.signal?.addEventListener("abort", onAbort);
3257
+ const headers = { Accept: "text/event-stream" };
3258
+ if (options?.lastEventId) headers["Last-Event-ID"] = options.lastEventId;
3259
+ const resp = await this._fetchFn(this.taskEventsUrl(token), {
3260
+ method: "GET",
3261
+ headers,
3262
+ signal: controller.signal
3263
+ });
3264
+ if (!resp.ok || !resp.body) {
3265
+ options?.signal?.removeEventListener("abort", onAbort);
3266
+ throw new Error(`Task events SSE failed: ${resp.status}`);
3267
+ }
3268
+ void (async () => {
3269
+ const reader = resp.body.getReader();
3270
+ const decoder = new TextDecoder();
3271
+ let buffer = "";
3272
+ let pending = { data: [] };
3273
+ const flush = () => {
3274
+ if (!pending.type && pending.data.length === 0) return;
3275
+ const dataStr = pending.data.join("\n");
3276
+ let payload = {};
3277
+ if (dataStr) {
3278
+ try {
3279
+ payload = JSON.parse(dataStr);
3280
+ } catch {
3281
+ }
3282
+ }
3283
+ try {
3284
+ onEvent({
3285
+ id: pending.id,
3286
+ type: pending.type ?? "task.updated",
3287
+ payload
3288
+ });
3289
+ } catch {
3290
+ }
3291
+ pending = { data: [] };
3292
+ };
3293
+ try {
3294
+ while (true) {
3295
+ const { done, value } = await reader.read();
3296
+ if (done) break;
3297
+ buffer += decoder.decode(value, { stream: true });
3298
+ let lineEnd;
3299
+ while ((lineEnd = buffer.indexOf("\n")) !== -1) {
3300
+ const line = buffer.slice(0, lineEnd).replace(/\r$/, "");
3301
+ buffer = buffer.slice(lineEnd + 1);
3302
+ if (line === "") {
3303
+ flush();
3304
+ continue;
3305
+ }
3306
+ if (line.startsWith(":")) continue;
3307
+ const colon = line.indexOf(":");
3308
+ const field = colon === -1 ? line : line.slice(0, colon);
3309
+ const valueStr = colon === -1 ? "" : line.slice(colon + 1).replace(/^ /, "");
3310
+ if (field === "event") pending.type = valueStr;
3311
+ else if (field === "id") pending.id = valueStr;
3312
+ else if (field === "data") pending.data.push(valueStr);
3313
+ }
3314
+ }
3315
+ flush();
3316
+ } catch {
3317
+ } finally {
3318
+ try {
3319
+ reader.releaseLock();
3320
+ } catch {
3321
+ }
3322
+ options?.signal?.removeEventListener("abort", onAbort);
3323
+ }
3324
+ })();
3325
+ return {
3326
+ disconnect: () => {
3327
+ try {
3328
+ controller.abort();
3329
+ } catch {
3330
+ }
3331
+ }
3332
+ };
3333
+ }
2951
3334
  };
2952
3335
  var IMClient = class {
2953
3336
  constructor(request2, wsBase, fetchFn, getAuthHeaders, offlineManager, communityHubConfig) {
@@ -2960,6 +3343,10 @@ var IMClient = class {
2960
3343
  this.bindings = new BindingsClient(request2);
2961
3344
  this.credits = new CreditsClient(request2);
2962
3345
  this.workspace = new WorkspaceClient(request2);
3346
+ this.workspaces = new WorkspacesClient(request2);
3347
+ this.workspaceFiles = new WorkspaceFilesClient(request2);
3348
+ this.assets = new AssetsClient(request2, wsBase, fetchFn, getAuthHeaders);
3349
+ this.runtimeInstallations = new RuntimeInstallationsClient(request2);
2963
3350
  this.tasks = new TasksClient(request2);
2964
3351
  this.memory = new MemoryClient(request2);
2965
3352
  this.knowledge = new KnowledgeLinkClient(request2);
@@ -2968,7 +3355,7 @@ var IMClient = class {
2968
3355
  this.evolution = new EvolutionClient(request2);
2969
3356
  this.community = new CommunityHub(request2, communityHubConfig ?? void 0);
2970
3357
  this.files = new FilesClient(request2, wsBase, fetchFn, getAuthHeaders);
2971
- this.realtime = new IMRealtimeClient(wsBase);
3358
+ this.realtime = new IMRealtimeClient(wsBase, fetchFn);
2972
3359
  this.offline = offlineManager ?? null;
2973
3360
  }
2974
3361
  /** IM health check */
@@ -3193,6 +3580,14 @@ var PrismerClient = class {
3193
3580
  return this._request("GET", `/api/parse/result/${taskId}`);
3194
3581
  }
3195
3582
  // --------------------------------------------------------------------------
3583
+ // Models API (LLM proxy model listing)
3584
+ // --------------------------------------------------------------------------
3585
+ /** List LLM models exposed by the cloud LLM proxy (OpenAI format). */
3586
+ async listModels() {
3587
+ const res = await this._request("GET", "/api/v1/models");
3588
+ return res.data ?? [];
3589
+ }
3590
+ // --------------------------------------------------------------------------
3196
3591
  // Convenience
3197
3592
  // --------------------------------------------------------------------------
3198
3593
  /** Search for content (convenience wrapper around load with query mode) */
@@ -7030,6 +7425,3 @@ program.parse(process.argv);
7030
7425
  getAPIClient,
7031
7426
  getIMClient
7032
7427
  });
7033
- ,
7034
- getIMClient
7035
- });