@paneui/core 0.0.6 → 0.0.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/schemas.js CHANGED
@@ -1,12 +1,12 @@
1
1
  // Zod schemas for the Pane relay request shapes. These let callers (the CLI,
2
- // other clients) validate user-supplied input — e.g. an inline JSON artifact
2
+ // other clients) validate user-supplied input — e.g. an inline JSON template
3
3
  // or callback config — before it hits the relay, producing clear errors.
4
4
  import { z } from "zod";
5
- // The artifact `type` discriminant. `html-inline` carries raw HTML in `source`;
5
+ // The template `type` discriminant. `html-inline` carries raw HTML in `source`;
6
6
  // `html-ref` carries a URL. The relay rejects `html-ref` in this release.
7
7
  export const artifactTypeSchema = z.enum(["html-inline", "html-ref"]);
8
8
  // Discriminated on `type`: both require a non-empty `source`. Kept for callers
9
- // that want to validate a bare artifact (no event schema attached).
9
+ // that want to validate a bare template (no event schema attached).
10
10
  export const artifactSchema = z.discriminatedUnion("type", [
11
11
  z.object({ type: z.literal("html-inline"), source: z.string().min(1) }),
12
12
  z.object({ type: z.literal("html-ref"), source: z.string().min(1) }),
@@ -16,32 +16,32 @@ export const callbackSchema = z.object({
16
16
  events: z.array(z.string().min(1)).min(1),
17
17
  secret: z.string().min(8),
18
18
  });
19
- // The inline artifact form for POST /v1/sessions — carries the event schema
20
- // INSIDE the artifact object (one-off, no registered artifact). The relay
21
- // transparently creates an anonymous artifact behind it.
19
+ // The inline template form for POST /v1/surfaces — carries the event schema
20
+ // INSIDE the template object (one-off, no registered template). The relay
21
+ // transparently creates an anonymous template behind it.
22
22
  const inlineArtifactSchema = z.object({
23
23
  source: z.string().min(1),
24
24
  type: artifactTypeSchema,
25
25
  // Optional: omit for a view-only one-off (a report/dashboard the human only
26
- // views — the session then accepts no page/agent events).
26
+ // views — the surface then accepts no page/agent events).
27
27
  event_schema: z.unknown().optional(),
28
- // Optional: when present, the session's `input_data` is validated against
29
- // this JSON Schema before the session row is created — and any blob refs
30
- // declared at `format: pane-blob-id` sites become reachable from the page
31
- // via `window.pane.downloadBlob()`. Without this, blob refs in
32
- // `input_data` are silently unreachable for inline sessions (the
33
- // participant blob-download bridge walks input_data against the artifact
28
+ // Optional: when present, the surface's `input_data` is validated against
29
+ // this JSON Schema before the surface row is created — and any attachment refs
30
+ // declared at `format: pane-attachment-id` sites become reachable from the page
31
+ // via `window.pane.downloadBlob()`. Without this, attachment refs in
32
+ // `input_data` are silently unreachable for inline surfaces (the
33
+ // participant attachment-download bridge walks input_data against the template
34
34
  // version's inputSchema; no schema means no walkable sites). See #208.
35
35
  input_schema: z.record(z.string(), z.unknown()).optional(),
36
36
  });
37
- // The reference form for POST /v1/sessions — instances an existing named
38
- // artifact. `id` accepts the artifact id or its slug; `version` is optional
39
- // and defaults to the artifact's latest version.
37
+ // The reference form for POST /v1/surfaces — instances an existing named
38
+ // template. `id` accepts the template id or its slug; `version` is optional
39
+ // and defaults to the template's latest version.
40
40
  const refArtifactSchema = z.object({
41
41
  id: z.string().min(1),
42
42
  version: z.number().int().positive().optional(),
43
43
  });
44
- // The session-create `artifact` field: exactly one of the two forms. A union
44
+ // The surface-create `template` field: exactly one of the two forms. A union
45
45
  // (not a discriminated union — the two forms share no discriminant key) with a
46
46
  // refine enforcing exactly-one-of `id` / `source`.
47
47
  const sessionArtifactSchema = z
@@ -51,22 +51,31 @@ const sessionArtifactSchema = z
51
51
  const hasSource = "source" in a && a.source !== undefined;
52
52
  return hasId !== hasSource;
53
53
  }, {
54
- message: "artifact must carry exactly one of `id` (reference an existing artifact) or `source` (inline a one-off artifact)",
54
+ message: "template must carry exactly one of `id` (reference an existing template) or `source` (inline a one-off template)",
55
55
  });
56
56
  export const createSessionSchema = z.object({
57
- artifact: sessionArtifactSchema,
57
+ template: sessionArtifactSchema,
58
58
  input_data: z.record(z.string(), z.unknown()).optional(),
59
59
  participants: z.object({ humans: z.number().int().positive() }).optional(),
60
60
  ttl: z.number().int().positive().optional(),
61
61
  metadata: z.record(z.string(), z.unknown()).optional(),
62
62
  callback: callbackSchema.optional(),
63
63
  // Tab title for the human's browser. Optional on the wire because the relay
64
- // also accepts the implicit fallback (an Artifact.name on the reference
64
+ // also accepts the implicit fallback (an Template.name on the reference
65
65
  // form). The relay enforces "required-or-fallback" + length/control-char
66
66
  // rules — Zod only confirms it's a string here.
67
67
  title: z.string().optional(),
68
+ // Phase G — natural-key dedup. When set, the relay collapses repeated
69
+ // creates with the same (template, owner, context_key) into one surface
70
+ // row. NULL = ad-hoc, no dedup. See HUMAN-SIDE-PROPOSAL.md §7.1.
71
+ context_key: z
72
+ .string()
73
+ .min(1)
74
+ .max(256)
75
+ .regex(/^[A-Za-z0-9_:.-]+$/, "context_key must be a short identifier")
76
+ .optional(),
68
77
  });
69
- // POST /v1/artifacts — create a named, reusable artifact plus its v1 content.
78
+ // POST /v1/templates — create a named, reusable template plus its v1 content.
70
79
  export const createArtifactSchema = z.object({
71
80
  name: z.string().min(1),
72
81
  slug: z.string().min(1).optional(),
@@ -74,19 +83,19 @@ export const createArtifactSchema = z.object({
74
83
  tags: z.array(z.string().min(1)).optional(),
75
84
  source: z.string().min(1),
76
85
  type: artifactTypeSchema,
77
- // Optional: omit for a view-only artifact (no event vocabulary).
86
+ // Optional: omit for a view-only template (no event vocabulary).
78
87
  event_schema: z.unknown().optional(),
79
88
  input_schema: z.record(z.string(), z.unknown()).optional(),
80
89
  });
81
- // POST /v1/artifacts/:id/versions — append a new version (content only).
90
+ // POST /v1/templates/:id/versions — append a new version (content only).
82
91
  export const createArtifactVersionSchema = z.object({
83
92
  source: z.string().min(1),
84
93
  type: artifactTypeSchema,
85
- // Optional: omit for a view-only artifact (no event vocabulary).
94
+ // Optional: omit for a view-only template (no event vocabulary).
86
95
  event_schema: z.unknown().optional(),
87
96
  input_schema: z.record(z.string(), z.unknown()).optional(),
88
97
  });
89
- // PATCH /v1/artifacts/:id — update head metadata only (never content).
98
+ // PATCH /v1/templates/:id — update head metadata only (never content).
90
99
  export const patchArtifactMetadataSchema = z.object({
91
100
  name: z.string().min(1).optional(),
92
101
  slug: z.string().min(1).optional(),
@@ -103,9 +112,9 @@ export const submitFeedbackSchema = z.object({
103
112
  .string()
104
113
  .transform((s) => s.trim())
105
114
  .pipe(z.string().min(1).max(4000)),
106
- session_id: z.string().min(1).optional(),
115
+ surface_id: z.string().min(1).optional(),
107
116
  });
108
- // GET /v1/sessions — list the calling agent's sessions. The relay also
117
+ // GET /v1/surfaces — list the calling agent's surfaces. The relay also
109
118
  // re-parses these on its side (defence in depth); this schema is for the CLI
110
119
  // to fail fast with a clear error before a round trip.
111
120
  export const listSessionsStatusSchema = z.enum(["open", "closed", "all"]);
@@ -113,11 +122,11 @@ export const listSessionsQuerySchema = z.object({
113
122
  status: listSessionsStatusSchema.optional(),
114
123
  limit: z.number().int().positive().max(200).optional(),
115
124
  cursor: z.string().min(1).optional(),
116
- artifact_id: z.string().min(1).optional(),
125
+ template_id: z.string().min(1).optional(),
117
126
  });
118
- // POST /v1/sessions/:id/participants — mint a fresh participant URL for an
119
- // existing session. v1 supports human participants only (the agent token is
120
- // minted at session-create and cannot be re-minted via this endpoint).
127
+ // POST /v1/surfaces/:id/participants — mint a fresh participant URL for an
128
+ // existing surface. v1 supports human participants only (the agent token is
129
+ // minted at surface-create and cannot be re-minted via this endpoint).
121
130
  export const mintParticipantSchema = z.object({
122
131
  kind: z.literal("human"),
123
132
  });
package/dist/stream.d.ts CHANGED
@@ -3,8 +3,8 @@ import type { PaneEvent } from "./types.js";
3
3
  export interface OpenStreamOptions {
4
4
  /** WebSocket base URL, e.g. wss://pane.example.com (no trailing slash). */
5
5
  wsBaseUrl: string;
6
- /** Session id. */
7
- sessionId: string;
6
+ /** Surface id. */
7
+ surfaceId: string;
8
8
  /** Agent (or participant) bearer token. */
9
9
  token: string;
10
10
  /** Opaque cursor: replay only events strictly after this id. */
@@ -32,7 +32,7 @@ export interface StreamHandlers {
32
32
  }
33
33
  /** A live handle to an open stream. */
34
34
  export interface StreamHandle {
35
- /** Send an event frame into the session. */
35
+ /** Send an event frame into the surface. */
36
36
  send(frame: {
37
37
  type: string;
38
38
  data?: unknown;
@@ -45,7 +45,7 @@ export interface StreamHandle {
45
45
  readonly socket: WebSocket;
46
46
  }
47
47
  /**
48
- * Open a WebSocket stream to a Pane session. Replays on connect, then streams
48
+ * Open a WebSocket stream to a Pane surface. Replays on connect, then streams
49
49
  * live. Returns a handle for sending frames and closing.
50
50
  */
51
51
  export declare function openStream(opts: OpenStreamOptions, handlers: StreamHandlers): StreamHandle;
package/dist/stream.js CHANGED
@@ -1,4 +1,4 @@
1
- // WebSocket client for WS /v1/sessions/:id/stream.
1
+ // WebSocket client for WS /v1/surfaces/:id/stream.
2
2
  //
3
3
  // The relay protocol (see the relay's src/ws/handler.ts):
4
4
  // - on connect, the relay replays every event since `?since=` (or from the
@@ -16,12 +16,12 @@
16
16
  import { WebSocket } from "ws";
17
17
  import { MAX_FRAME_SNIPPET_LENGTH } from "./limits.js";
18
18
  /**
19
- * Open a WebSocket stream to a Pane session. Replays on connect, then streams
19
+ * Open a WebSocket stream to a Pane surface. Replays on connect, then streams
20
20
  * live. Returns a handle for sending frames and closing.
21
21
  */
22
22
  export function openStream(opts, handlers) {
23
23
  const base = opts.wsBaseUrl.replace(/\/$/, "");
24
- const u = new URL(`${base}/v1/sessions/${encodeURIComponent(opts.sessionId)}/stream`);
24
+ const u = new URL(`${base}/v1/surfaces/${encodeURIComponent(opts.surfaceId)}/stream`);
25
25
  if (opts.since != null && opts.since !== "") {
26
26
  u.searchParams.set("since", opts.since);
27
27
  }
package/dist/types.d.ts CHANGED
@@ -4,7 +4,7 @@ export type AuthorKind = "human" | "agent" | "system";
4
4
  /** A single event envelope as emitted by the relay. */
5
5
  export interface PaneEvent {
6
6
  id: string;
7
- session_id: string;
7
+ surface_id: string;
8
8
  author: {
9
9
  kind: AuthorKind;
10
10
  id: string;
@@ -15,14 +15,14 @@ export interface PaneEvent {
15
15
  causation_id: string | null;
16
16
  idempotency_key: string | null;
17
17
  }
18
- /** The artifact content type. `html-ref` is rejected by the relay for now. */
19
- export type ArtifactType = "html-inline" | "html-ref";
18
+ /** The template content type. `html-ref` is rejected by the relay for now. */
19
+ export type TemplateType = "html-inline" | "html-ref";
20
20
  /**
21
- * An artifact: discriminated on `type`. `html-inline` carries raw HTML in
21
+ * An template: discriminated on `type`. `html-inline` carries raw HTML in
22
22
  * `source`; `html-ref` carries a URL the relay/shell fetches on the human's
23
23
  * behalf. The discriminant keeps the type↔source coupling explicit.
24
24
  */
25
- export type Artifact = {
25
+ export type Template = {
26
26
  type: "html-inline";
27
27
  source: string;
28
28
  } | {
@@ -36,13 +36,13 @@ export interface Callback {
36
36
  secret: string;
37
37
  }
38
38
  /**
39
- * Request body for POST /v1/sessions. Derived from `createSessionSchema` so the
39
+ * Request body for POST /v1/surfaces. Derived from `createSessionSchema` so the
40
40
  * runtime validator and the static type cannot drift.
41
41
  */
42
42
  export type CreateSessionRequest = z.infer<typeof createSessionSchema>;
43
- /** Response from POST /v1/sessions. */
43
+ /** Response from POST /v1/surfaces. */
44
44
  export interface CreateSessionResponse {
45
- session_id: string;
45
+ surface_id: string;
46
46
  tokens: {
47
47
  humans: string[];
48
48
  agent: string;
@@ -52,31 +52,31 @@ export interface CreateSessionResponse {
52
52
  agent_stream: string;
53
53
  };
54
54
  expires_at: string;
55
- /** The resolved tab title persisted on the session (the agent's value, or
56
- * the Artifact.name fallback). */
55
+ /** The resolved tab title persisted on the surface (the agent's value, or
56
+ * the Template.name fallback). */
57
57
  title: string;
58
58
  }
59
- /** Response from GET /v1/sessions/:id. */
60
- export interface SessionState {
61
- session_id: string;
59
+ /** Response from GET /v1/surfaces/:id. */
60
+ export interface SurfaceState {
61
+ surface_id: string;
62
62
  status: string;
63
- /** The artifact version this session is pinned to. */
64
- artifact_id: string;
65
- artifact_version_id: string;
66
- artifact_version: number;
67
- /** The tab title this session was created with (frozen for its lifetime). */
63
+ /** The template version this surface is pinned to. */
64
+ template_id: string;
65
+ template_version_id: string;
66
+ template_version: number;
67
+ /** The tab title this surface was created with (frozen for its lifetime). */
68
68
  title: string;
69
69
  metadata: Record<string, unknown> | null;
70
70
  input_data: Record<string, unknown> | null;
71
71
  created_at: string;
72
72
  expires_at: string;
73
73
  }
74
- /** Response from GET /v1/sessions/:id/events. */
74
+ /** Response from GET /v1/surfaces/:id/events. */
75
75
  export interface EventsPage {
76
76
  events: PaneEvent[];
77
77
  next_cursor: string | null;
78
78
  }
79
- /** A non-secret summary of one participant on a session — safe to list. */
79
+ /** A non-secret summary of one participant on a surface — safe to list. */
80
80
  export interface ParticipantSummary {
81
81
  /** The revoke handle (Participant.id). */
82
82
  participant_id: string;
@@ -89,43 +89,43 @@ export interface ParticipantSummary {
89
89
  /** ISO timestamp the participant was revoked; null while still active. */
90
90
  revoked_at: string | null;
91
91
  }
92
- /** A row in the GET /v1/sessions list response (no secrets, lean). */
93
- export interface SessionSummary {
94
- session_id: string;
95
- /** Tab title (required column; agent input or Artifact.name fallback). */
92
+ /** A row in the GET /v1/surfaces list response (no secrets, lean). */
93
+ export interface SurfaceSummary {
94
+ surface_id: string;
95
+ /** Tab title (required column; agent input or Template.name fallback). */
96
96
  title: string;
97
97
  /** Effective status — respects expiresAt projection (the column may say
98
98
  * "open" while `expires_at` is in the past; the projection reports "closed"). */
99
99
  status: "open" | "closed";
100
- /** Owning artifact's head id. Null for inline (anonymous) artifacts. */
101
- artifact_id: string | null;
102
- artifact_version_id: string;
103
- artifact_version: number;
100
+ /** Owning template's head id. Null for inline (anonymous) templates. */
101
+ template_id: string | null;
102
+ template_version_id: string;
103
+ template_version: number;
104
104
  /** Count of active (non-revoked) human participants. The full participant
105
- * array is intentionally NOT inlined here — agents with many sessions
105
+ * array is intentionally NOT inlined here — agents with many surfaces
106
106
  * would pay the bandwidth on every list call. Fetch
107
- * `GET /v1/sessions/:id/participants` when you need the rows. */
107
+ * `GET /v1/surfaces/:id/participants` when you need the rows. */
108
108
  active_human_participants: number;
109
109
  created_at: string;
110
110
  expires_at: string;
111
- /** Whether the session has a webhook callback configured (URL is NOT
111
+ /** Whether the surface has a webhook callback configured (URL is NOT
112
112
  * returned — it may carry a secret in the path). */
113
113
  has_callback: boolean;
114
114
  }
115
- /** Response from GET /v1/sessions/:id/participants — every participant on
116
- * one session (active and revoked). Bounded by MAX_PARTICIPANTS_PER_SESSION
115
+ /** Response from GET /v1/surfaces/:id/participants — every participant on
116
+ * one surface (active and revoked). Bounded by MAX_PARTICIPANTS_PER_SESSION
117
117
  * on the relay so no pagination is needed. */
118
118
  export interface ParticipantsList {
119
- session_id: string;
119
+ surface_id: string;
120
120
  items: ParticipantSummary[];
121
121
  }
122
- /** Response from GET /v1/sessions. */
123
- export interface SessionsPage {
124
- items: SessionSummary[];
122
+ /** Response from GET /v1/surfaces. */
123
+ export interface SurfacesPage {
124
+ items: SurfaceSummary[];
125
125
  /** Opaque cursor for the next page; null when no more rows. */
126
126
  next_cursor: string | null;
127
127
  }
128
- /** Response from POST /v1/sessions/:id/participants — one-shot, includes the
128
+ /** Response from POST /v1/surfaces/:id/participants — one-shot, includes the
129
129
  * plaintext token exactly once. The relay stores only the hash. */
130
130
  export interface MintParticipantResponse {
131
131
  participant_id: string;
@@ -136,17 +136,17 @@ export interface MintParticipantResponse {
136
136
  url: string;
137
137
  created_at: string;
138
138
  }
139
- /** One immutable version of an artifact's content. */
140
- export interface ArtifactVersion {
139
+ /** One immutable version of an template's content. */
140
+ export interface TemplateVersion {
141
141
  id: string;
142
142
  version: number;
143
- type: ArtifactType;
143
+ type: TemplateType;
144
144
  source: string;
145
145
  event_schema: unknown;
146
146
  input_schema: Record<string, unknown> | null;
147
147
  created_at: string;
148
148
  }
149
- /** A full artifact — head metadata plus its version list. */
149
+ /** A full template — head metadata plus its version list. */
150
150
  export interface Artifact_ {
151
151
  id: string;
152
152
  slug: string | null;
@@ -157,18 +157,18 @@ export interface Artifact_ {
157
157
  last_used_at: string | null;
158
158
  created_at: string;
159
159
  updated_at: string;
160
- versions: ArtifactVersion[];
160
+ versions: TemplateVersion[];
161
161
  }
162
162
  /**
163
- * A full artifact — head metadata plus its version list. (`ArtifactRecord` is
164
- * the public name; `Artifact` is kept as the older inline-artifact union.)
163
+ * A full template — head metadata plus its version list. (`TemplateRecord` is
164
+ * the public name; `Template` is kept as the older inline-template union.)
165
165
  */
166
- export type ArtifactRecord = Artifact_;
166
+ export type TemplateRecord = Artifact_;
167
167
  /**
168
- * A lean artifact summary for list/search responses — head metadata only, no
169
- * `source` blob. See GET /v1/artifacts.
168
+ * A lean template summary for list/search responses — head metadata only, no
169
+ * `source` attachment. See GET /v1/templates.
170
170
  */
171
- export interface ArtifactSummary {
171
+ export interface TemplateSummary {
172
172
  id: string;
173
173
  slug: string | null;
174
174
  name: string | null;
@@ -177,9 +177,9 @@ export interface ArtifactSummary {
177
177
  latest_version: number;
178
178
  last_used_at: string | null;
179
179
  }
180
- /** Response from POST /v1/artifacts and POST /v1/artifacts/:id/versions. */
180
+ /** Response from POST /v1/templates and POST /v1/templates/:id/versions. */
181
181
  export interface CreateArtifactResponse {
182
- artifact_id: string;
182
+ template_id: string;
183
183
  version: number;
184
184
  }
185
185
  /**
@@ -197,7 +197,7 @@ export interface KeyInfo {
197
197
  }
198
198
  /**
199
199
  * Response from GET /v1/taste, PUT /v1/taste — the calling agent's freeform
200
- * "taste notes" markdown blob (presentation preferences the agent has picked
200
+ * "taste notes" markdown attachment (presentation preferences the agent has picked
201
201
  * up from human feedback over time). `taste` and `updated_at` are null when
202
202
  * the agent has never written notes; `bytes` is the utf8 byte length and 0
203
203
  * when `taste` is null.
@@ -220,7 +220,7 @@ export interface FeedbackRecord {
220
220
  id: string;
221
221
  type: FeedbackType;
222
222
  message: string;
223
- session_id: string | null;
223
+ surface_id: string | null;
224
224
  created_at: string;
225
225
  }
226
226
  /** Response from GET /v1/feedback — page of the calling agent's own submissions. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paneui/core",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "Pane relay client: typed HTTP + WebSocket operations against a Pane relay. Framework-free.",
5
5
  "license": "MIT",
6
6
  "type": "module",