@paneui/core 0.0.2 → 0.0.4

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,4 +1,4 @@
1
- import type { ArtifactRecord, ArtifactSummary, ArtifactType, ArtifactVersion, CreateArtifactResponse, CreateSessionRequest, CreateSessionResponse, EventsPage, KeyInfo, PaneEvent, SessionState } from "./types.js";
1
+ import type { ArtifactRecord, ArtifactSummary, ArtifactType, ArtifactVersion, CreateArtifactResponse, CreateSessionRequest, CreateSessionResponse, EventsPage, FeedbackPage, FeedbackSubmission, FeedbackType, KeyInfo, PaneEvent, SessionState, TasteInfo } from "./types.js";
2
2
  export interface ClientOptions {
3
3
  /** Relay base URL, e.g. https://pane.example.com. Trailing slash is trimmed. */
4
4
  url: string;
@@ -6,6 +6,15 @@ export interface ClientOptions {
6
6
  apiKey: string;
7
7
  /** Optional fetch override (defaults to global fetch). */
8
8
  fetch?: typeof fetch;
9
+ /**
10
+ * Optional client version string sent as `x-pane-cli-version` on every
11
+ * request. The CLI passes its own `VERSION` constant here so a relay can
12
+ * detect version skew and respond with a `cli_upgrade_required` error
13
+ * (HTTP 426) when the CLI is below the relay's minimum supported version.
14
+ * Library callers (non-CLI) can leave this unset — the header is omitted
15
+ * and the relay treats the request as version-unknown.
16
+ */
17
+ cliVersion?: string;
9
18
  }
10
19
  /** Low-level relay response: ok flag, HTTP status, parsed JSON body. */
11
20
  export interface RelayResponse {
@@ -72,6 +81,7 @@ export declare class PaneClient {
72
81
  private readonly base;
73
82
  private readonly apiKey;
74
83
  private readonly fetchImpl;
84
+ private readonly cliVersion;
75
85
  constructor(opts: ClientOptions);
76
86
  /** Relay base URL (trailing slash trimmed). */
77
87
  get baseUrl(): string;
@@ -153,9 +163,56 @@ export declare class PaneClient {
153
163
  * self-destruct. Returns 204 with no body on success.
154
164
  */
155
165
  revokeKey(id: string): Promise<void>;
166
+ /**
167
+ * GET /v1/taste — the calling agent's freeform "taste notes" markdown blob:
168
+ * presentation preferences the agent has picked up from human feedback over
169
+ * time. Returns `{ taste: null, updated_at: null, bytes: 0 }` when the
170
+ * agent has never written notes. Read this before generating an artifact so
171
+ * the agent applies prior feedback.
172
+ */
173
+ getTaste(): Promise<TasteInfo>;
174
+ /**
175
+ * PUT /v1/taste — whole-blob replace of the calling agent's taste notes.
176
+ * Empty/whitespace-only values are rejected by the relay; callers asking to
177
+ * clear must use {@link clearTaste}. The relay caps the payload at the
178
+ * server's `MAX_TASTE_BYTES` (utf8 bytes).
179
+ */
180
+ setTaste(taste: string): Promise<TasteInfo>;
181
+ /**
182
+ * DELETE /v1/taste — clear the calling agent's taste notes (idempotent on
183
+ * the relay; clearing already-empty notes still succeeds). Returns 204 with
184
+ * no body.
185
+ */
186
+ clearTaste(): Promise<void>;
187
+ /**
188
+ * POST /v1/feedback — submit a one-shot bug report, feature request, or
189
+ * note to the relay operator. Returns the new row's id, type, and
190
+ * created_at; the message is not echoed.
191
+ */
192
+ submitFeedback(req: {
193
+ type: FeedbackType;
194
+ message: string;
195
+ sessionId?: string;
196
+ }): Promise<FeedbackSubmission>;
197
+ /**
198
+ * GET /v1/feedback — the calling agent's own submissions, newest first.
199
+ * `before` is an opaque cursor from a previous page's `next_before`.
200
+ */
201
+ listFeedback(opts?: {
202
+ limit?: number;
203
+ before?: string;
204
+ }): Promise<FeedbackPage>;
156
205
  /**
157
206
  * DELETE /v1/sessions/:id — close/delete a session. Idempotent on the relay
158
207
  * side (an already-closed session still returns 204 with no body).
159
208
  */
160
209
  deleteSession(id: string): Promise<void>;
210
+ /**
211
+ * DELETE /v1/artifacts/:id — remove an artifact and (server-side) all its
212
+ * versions. Strict cascade: the relay refuses with 409 conflict if any
213
+ * session in any state still references one of the artifact's versions —
214
+ * surface that as a typed PaneApiError so the CLI can render a hint
215
+ * instead of swallowing it.
216
+ */
217
+ deleteArtifact(idOrSlug: string): Promise<void>;
161
218
  }
package/dist/client.js CHANGED
@@ -31,10 +31,12 @@ export class PaneClient {
31
31
  base;
32
32
  apiKey;
33
33
  fetchImpl;
34
+ cliVersion;
34
35
  constructor(opts) {
35
36
  this.base = opts.url.replace(/\/$/, "");
36
37
  this.apiKey = opts.apiKey;
37
38
  this.fetchImpl = opts.fetch ?? fetch;
39
+ this.cliVersion = opts.cliVersion;
38
40
  }
39
41
  /** Relay base URL (trailing slash trimmed). */
40
42
  get baseUrl() {
@@ -60,6 +62,10 @@ export class PaneClient {
60
62
  headers: {
61
63
  authorization: "Bearer " + this.apiKey,
62
64
  ...(body ? { "content-type": "application/json" } : {}),
65
+ // x-pane-cli-version drives the relay's version-skew check. Header
66
+ // is omitted entirely when no version was supplied so the relay
67
+ // can distinguish "old CLI" from "non-CLI caller".
68
+ ...(this.cliVersion ? { "x-pane-cli-version": this.cliVersion } : {}),
63
69
  },
64
70
  body: body ? JSON.stringify(body) : undefined,
65
71
  });
@@ -269,6 +275,72 @@ export class PaneClient {
269
275
  if (!r.ok)
270
276
  this.fail(r);
271
277
  }
278
+ /**
279
+ * GET /v1/taste — the calling agent's freeform "taste notes" markdown blob:
280
+ * presentation preferences the agent has picked up from human feedback over
281
+ * time. Returns `{ taste: null, updated_at: null, bytes: 0 }` when the
282
+ * agent has never written notes. Read this before generating an artifact so
283
+ * the agent applies prior feedback.
284
+ */
285
+ async getTaste() {
286
+ const r = await this.call("GET", "/v1/taste");
287
+ if (!r.ok)
288
+ this.fail(r);
289
+ return this.asObject(r);
290
+ }
291
+ /**
292
+ * PUT /v1/taste — whole-blob replace of the calling agent's taste notes.
293
+ * Empty/whitespace-only values are rejected by the relay; callers asking to
294
+ * clear must use {@link clearTaste}. The relay caps the payload at the
295
+ * server's `MAX_TASTE_BYTES` (utf8 bytes).
296
+ */
297
+ async setTaste(taste) {
298
+ const r = await this.call("PUT", "/v1/taste", { taste });
299
+ if (!r.ok)
300
+ this.fail(r);
301
+ return this.asObject(r);
302
+ }
303
+ /**
304
+ * DELETE /v1/taste — clear the calling agent's taste notes (idempotent on
305
+ * the relay; clearing already-empty notes still succeeds). Returns 204 with
306
+ * no body.
307
+ */
308
+ async clearTaste() {
309
+ const r = await this.call("DELETE", "/v1/taste");
310
+ if (!r.ok)
311
+ this.fail(r);
312
+ }
313
+ /**
314
+ * POST /v1/feedback — submit a one-shot bug report, feature request, or
315
+ * note to the relay operator. Returns the new row's id, type, and
316
+ * created_at; the message is not echoed.
317
+ */
318
+ async submitFeedback(req) {
319
+ const r = await this.call("POST", "/v1/feedback", {
320
+ type: req.type,
321
+ message: req.message,
322
+ session_id: req.sessionId,
323
+ });
324
+ if (!r.ok)
325
+ this.fail(r);
326
+ return this.asObject(r);
327
+ }
328
+ /**
329
+ * GET /v1/feedback — the calling agent's own submissions, newest first.
330
+ * `before` is an opaque cursor from a previous page's `next_before`.
331
+ */
332
+ async listFeedback(opts = {}) {
333
+ const q = new URLSearchParams();
334
+ if (opts.limit != null)
335
+ q.set("limit", String(opts.limit));
336
+ if (opts.before != null && opts.before !== "")
337
+ q.set("before", opts.before);
338
+ const qs = q.toString();
339
+ const r = await this.call("GET", `/v1/feedback${qs ? "?" + qs : ""}`);
340
+ if (!r.ok)
341
+ this.fail(r);
342
+ return this.asObject(r);
343
+ }
272
344
  /**
273
345
  * DELETE /v1/sessions/:id — close/delete a session. Idempotent on the relay
274
346
  * side (an already-closed session still returns 204 with no body).
@@ -278,4 +350,16 @@ export class PaneClient {
278
350
  if (!r.ok)
279
351
  this.fail(r);
280
352
  }
353
+ /**
354
+ * DELETE /v1/artifacts/:id — remove an artifact and (server-side) all its
355
+ * versions. Strict cascade: the relay refuses with 409 conflict if any
356
+ * session in any state still references one of the artifact's versions —
357
+ * surface that as a typed PaneApiError so the CLI can render a hint
358
+ * instead of swallowing it.
359
+ */
360
+ async deleteArtifact(idOrSlug) {
361
+ const r = await this.call("DELETE", `/v1/artifacts/${encodeURIComponent(idOrSlug)}`);
362
+ if (!r.ok)
363
+ this.fail(r);
364
+ }
281
365
  }
package/dist/index.d.ts CHANGED
@@ -4,7 +4,7 @@ export { openStream } from "./stream.js";
4
4
  export type { OpenStreamOptions, StreamHandlers, StreamHandle, } from "./stream.js";
5
5
  export { registerAgent } from "./register.js";
6
6
  export type { RegisterAgentOptions, RegisterAgentResult } from "./register.js";
7
- export { artifactSchema, callbackSchema, createSessionSchema, artifactTypeSchema, createArtifactSchema, createArtifactVersionSchema, patchArtifactMetadataSchema, } from "./schemas.js";
7
+ export { artifactSchema, callbackSchema, createSessionSchema, artifactTypeSchema, createArtifactSchema, createArtifactVersionSchema, patchArtifactMetadataSchema, feedbackTypeSchema, submitFeedbackSchema, } from "./schemas.js";
8
8
  export type { CreateSessionInput } from "./schemas.js";
9
9
  export { MAX_EVENT_TYPE_LENGTH, MAX_IDEMPOTENCY_KEY_LENGTH, MAX_RESPONSE_SNIPPET_LENGTH, MAX_FRAME_SNIPPET_LENGTH, } from "./limits.js";
10
- export type { AuthorKind, PaneEvent, Artifact, ArtifactType, ArtifactVersion, ArtifactRecord, ArtifactSummary, CreateArtifactResponse, KeyInfo, Callback, CreateSessionRequest, CreateSessionResponse, SessionState, EventsPage, RelayError, } from "./types.js";
10
+ export type { AuthorKind, PaneEvent, Artifact, ArtifactType, ArtifactVersion, ArtifactRecord, ArtifactSummary, CreateArtifactResponse, KeyInfo, TasteInfo, FeedbackType, FeedbackSubmission, FeedbackRecord, FeedbackPage, Callback, CreateSessionRequest, CreateSessionResponse, SessionState, EventsPage, RelayError, } from "./types.js";
package/dist/index.js CHANGED
@@ -3,5 +3,5 @@
3
3
  export { PaneClient, PaneApiError } from "./client.js";
4
4
  export { openStream } from "./stream.js";
5
5
  export { registerAgent } from "./register.js";
6
- export { artifactSchema, callbackSchema, createSessionSchema, artifactTypeSchema, createArtifactSchema, createArtifactVersionSchema, patchArtifactMetadataSchema, } from "./schemas.js";
6
+ export { artifactSchema, callbackSchema, createSessionSchema, artifactTypeSchema, createArtifactSchema, createArtifactVersionSchema, patchArtifactMetadataSchema, feedbackTypeSchema, submitFeedbackSchema, } from "./schemas.js";
7
7
  export { MAX_EVENT_TYPE_LENGTH, MAX_IDEMPOTENCY_KEY_LENGTH, MAX_RESPONSE_SNIPPET_LENGTH, MAX_FRAME_SNIPPET_LENGTH, } from "./limits.js";
@@ -11,6 +11,13 @@ export interface RegisterAgentOptions {
11
11
  secret?: string;
12
12
  /** Optional fetch override (defaults to global fetch). */
13
13
  fetch?: typeof fetch;
14
+ /**
15
+ * Optional client version string. Sent as `x-pane-cli-version` so the
16
+ * relay's version-skew check can flag a too-old CLI even on the
17
+ * un-authenticated register endpoint. See `PaneClient`'s `cliVersion`
18
+ * option for the parent contract.
19
+ */
20
+ cliVersion?: string;
14
21
  }
15
22
  export interface RegisterAgentResult {
16
23
  agent_id: string;
package/dist/register.js CHANGED
@@ -26,6 +26,9 @@ export async function registerAgent(opts) {
26
26
  if (opts.secret !== undefined && opts.secret !== "") {
27
27
  headers["authorization"] = `Bearer ${opts.secret}`;
28
28
  }
29
+ if (opts.cliVersion !== undefined && opts.cliVersion !== "") {
30
+ headers["x-pane-cli-version"] = opts.cliVersion;
31
+ }
29
32
  let res;
30
33
  try {
31
34
  res = await fetchImpl(base + "/v1/register", {
package/dist/schemas.d.ts CHANGED
@@ -193,5 +193,19 @@ export declare const patchArtifactMetadataSchema: z.ZodObject<{
193
193
  description?: string | undefined;
194
194
  tags?: string[] | undefined;
195
195
  }>;
196
+ export declare const feedbackTypeSchema: z.ZodEnum<["bug", "feature", "note"]>;
197
+ export declare const submitFeedbackSchema: z.ZodObject<{
198
+ type: z.ZodEnum<["bug", "feature", "note"]>;
199
+ message: z.ZodPipeline<z.ZodEffects<z.ZodString, string, string>, z.ZodString>;
200
+ session_id: z.ZodOptional<z.ZodString>;
201
+ }, "strip", z.ZodTypeAny, {
202
+ type: "bug" | "feature" | "note";
203
+ message: string;
204
+ session_id?: string | undefined;
205
+ }, {
206
+ type: "bug" | "feature" | "note";
207
+ message: string;
208
+ session_id?: string | undefined;
209
+ }>;
196
210
  /** @deprecated use `CreateSessionRequest` from ./types.js (same type). */
197
211
  export type CreateSessionInput = z.infer<typeof createSessionSchema>;
package/dist/schemas.js CHANGED
@@ -80,3 +80,15 @@ export const patchArtifactMetadataSchema = z.object({
80
80
  description: z.string().optional(),
81
81
  tags: z.array(z.string().min(1)).optional(),
82
82
  });
83
+ // POST /v1/feedback — an agent submits a bug report, feature request, or note
84
+ // to the relay operator. Message is trimmed before length check so whitespace
85
+ // padding cannot bypass the 1..4000 cap.
86
+ export const feedbackTypeSchema = z.enum(["bug", "feature", "note"]);
87
+ export const submitFeedbackSchema = z.object({
88
+ type: feedbackTypeSchema,
89
+ message: z
90
+ .string()
91
+ .transform((s) => s.trim())
92
+ .pipe(z.string().min(1).max(4000)),
93
+ session_id: z.string().min(1).optional(),
94
+ });
package/dist/types.d.ts CHANGED
@@ -130,6 +130,39 @@ export interface KeyInfo {
130
130
  last_used_at: string | null;
131
131
  revoked_at: string | null;
132
132
  }
133
+ /**
134
+ * Response from GET /v1/taste, PUT /v1/taste — the calling agent's freeform
135
+ * "taste notes" markdown blob (presentation preferences the agent has picked
136
+ * up from human feedback over time). `taste` and `updated_at` are null when
137
+ * the agent has never written notes; `bytes` is the utf8 byte length and 0
138
+ * when `taste` is null.
139
+ */
140
+ export interface TasteInfo {
141
+ taste: string | null;
142
+ updated_at: string | null;
143
+ bytes: number;
144
+ }
145
+ /** A feedback `type` discriminant accepted by POST /v1/feedback. */
146
+ export type FeedbackType = "bug" | "feature" | "note";
147
+ /** Response from POST /v1/feedback — id, type, created_at only (no message echo). */
148
+ export interface FeedbackSubmission {
149
+ id: string;
150
+ type: FeedbackType;
151
+ created_at: string;
152
+ }
153
+ /** A row from GET /v1/feedback — full record including message. */
154
+ export interface FeedbackRecord {
155
+ id: string;
156
+ type: FeedbackType;
157
+ message: string;
158
+ session_id: string | null;
159
+ created_at: string;
160
+ }
161
+ /** Response from GET /v1/feedback — page of the calling agent's own submissions. */
162
+ export interface FeedbackPage {
163
+ items: FeedbackRecord[];
164
+ next_before?: string;
165
+ }
133
166
  /** A relay error envelope. */
134
167
  export interface RelayError {
135
168
  code: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paneui/core",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Pane relay client: typed HTTP + WebSocket operations against a Pane relay. Framework-free.",
5
5
  "license": "MIT",
6
6
  "type": "module",