@paneui/core 0.0.6 → 0.0.8
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 +108 -96
- package/dist/client.js +119 -106
- package/dist/index.d.ts +2 -2
- package/dist/schemas.d.ts +4 -3
- package/dist/schemas.js +40 -31
- package/dist/stream.d.ts +4 -4
- package/dist/stream.js +3 -3
- package/dist/types.d.ts +53 -53
- package/package.json +1 -1
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
|
|
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
|
|
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
|
|
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
|
|
20
|
-
// INSIDE the
|
|
21
|
-
// transparently creates an anonymous
|
|
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
|
|
26
|
+
// views — the surface then accepts no page/agent events).
|
|
27
27
|
event_schema: z.unknown().optional(),
|
|
28
|
-
// Optional: when present, the
|
|
29
|
-
// this JSON Schema before the
|
|
30
|
-
// declared at `format: pane-
|
|
31
|
-
// via `window.pane.downloadBlob()`. Without this,
|
|
32
|
-
// `input_data` are silently unreachable for inline
|
|
33
|
-
// participant
|
|
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/
|
|
38
|
-
//
|
|
39
|
-
// and defaults to the
|
|
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
|
|
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: "
|
|
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
|
-
|
|
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
|
|
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/
|
|
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
|
|
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/
|
|
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
|
|
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/
|
|
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
|
-
|
|
115
|
+
surface_id: z.string().min(1).optional(),
|
|
107
116
|
});
|
|
108
|
-
// GET /v1/
|
|
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
|
-
|
|
125
|
+
template_id: z.string().min(1).optional(),
|
|
117
126
|
});
|
|
118
|
-
// POST /v1/
|
|
119
|
-
// existing
|
|
120
|
-
// minted at
|
|
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
|
-
/**
|
|
7
|
-
|
|
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
|
|
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
|
|
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/
|
|
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
|
|
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/
|
|
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
|
-
|
|
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
|
|
19
|
-
export type
|
|
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
|
|
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
|
|
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/
|
|
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/
|
|
43
|
+
/** Response from POST /v1/surfaces. */
|
|
44
44
|
export interface CreateSessionResponse {
|
|
45
|
-
|
|
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
|
|
56
|
-
* the
|
|
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/
|
|
60
|
-
export interface
|
|
61
|
-
|
|
59
|
+
/** Response from GET /v1/surfaces/:id. */
|
|
60
|
+
export interface SurfaceState {
|
|
61
|
+
surface_id: string;
|
|
62
62
|
status: string;
|
|
63
|
-
/** The
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
/** The tab title this
|
|
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/
|
|
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
|
|
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/
|
|
93
|
-
export interface
|
|
94
|
-
|
|
95
|
-
/** Tab title (required column; agent input or
|
|
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
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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
|
|
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/
|
|
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
|
|
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/
|
|
116
|
-
* one
|
|
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
|
-
|
|
119
|
+
surface_id: string;
|
|
120
120
|
items: ParticipantSummary[];
|
|
121
121
|
}
|
|
122
|
-
/** Response from GET /v1/
|
|
123
|
-
export interface
|
|
124
|
-
items:
|
|
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/
|
|
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
|
|
140
|
-
export interface
|
|
139
|
+
/** One immutable version of an template's content. */
|
|
140
|
+
export interface TemplateVersion {
|
|
141
141
|
id: string;
|
|
142
142
|
version: number;
|
|
143
|
-
type:
|
|
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
|
|
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:
|
|
160
|
+
versions: TemplateVersion[];
|
|
161
161
|
}
|
|
162
162
|
/**
|
|
163
|
-
* A full
|
|
164
|
-
* the public name; `
|
|
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
|
|
166
|
+
export type TemplateRecord = Artifact_;
|
|
167
167
|
/**
|
|
168
|
-
* A lean
|
|
169
|
-
* `source`
|
|
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
|
|
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/
|
|
180
|
+
/** Response from POST /v1/templates and POST /v1/templates/:id/versions. */
|
|
181
181
|
export interface CreateArtifactResponse {
|
|
182
|
-
|
|
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
|
|
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
|
-
|
|
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. */
|