@marketrix.ai/widget 4.0.135 → 4.0.137
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/src/components/views/ChatView.d.ts +5 -1
- package/dist/src/context/ChatContext.d.ts +23 -8
- package/dist/src/hooks/useWidget.d.ts +1 -1
- package/dist/src/sdk/contracts/activityLogMetadata.d.ts +3 -10
- package/dist/src/sdk/contracts/activityLogVocabulary.d.ts +3 -11
- package/dist/src/sdk/contracts/common.d.ts +6 -27
- package/dist/src/sdk/contracts/entities.d.ts +28 -7
- package/dist/src/sdk/contracts/widget.d.ts +8 -2
- package/dist/src/services/StorageService.d.ts +10 -1
- package/dist/src/services/StreamClient.d.ts +4 -1
- package/dist/widget.mjs +64 -64
- package/package.json +1 -1
|
@@ -6,7 +6,11 @@
|
|
|
6
6
|
* shell's toolbar button fills with a share toggle, and the composer textarea ref. `MODES` pairs the
|
|
7
7
|
* mode chips' display order with the tenant setting enabling each, so the composer offers only what
|
|
8
8
|
* the workspace turned on. `ChatView` owns the draft text; `handleSendMessage` posts the turn and
|
|
9
|
-
* `handleModeChange` announces a mode switch in the transcript before flipping state.
|
|
9
|
+
* `handleModeChange` announces a mode switch in the transcript before flipping state. A POST failure
|
|
10
|
+
* restores the composed text to the (now-cleared) composer — `messageDispatch`'s resolved `false` —
|
|
11
|
+
* unless the visitor already started typing a new message in the meantime, so a resend is one tap on
|
|
12
|
+
* Send rather than a retype, and the failed turn's own bubble (added optimistically, unconditionally)
|
|
13
|
+
* still shows what was said either way.
|
|
10
14
|
*
|
|
11
15
|
* The composer is locked both while a reply is outstanding and while a screen-access request is open,
|
|
12
16
|
* since a second turn queued behind an unanswered permission card has nowhere to land. `use_screenshare`
|
|
@@ -8,15 +8,30 @@
|
|
|
8
8
|
* defers updaters and loses the effects captured in them, so tool calls never execute. `messageDispatch`
|
|
9
9
|
* POSTs fire-and-forget: the reply arrives over SSE, so only a POST failure resolves the placeholder
|
|
10
10
|
* locally, and a stale-reply watchdog keyed on id AND part count re-arms on every progress line.
|
|
11
|
+
* `messageDispatch` resolves `false` on that same POST failure (`true` otherwise, including preview
|
|
12
|
+
* mode) so a caller holding the composed text — `ChatView`'s composer — can restore it instead of the
|
|
13
|
+
* visitor having to retype a message the widget already dropped from the input box.
|
|
11
14
|
*
|
|
12
15
|
* The stream effect subscribes to the `StreamClient` singleton: `handleMessage` does the bookkeeping the
|
|
13
|
-
* pure reducer cannot hold (`tool_call_id` dedupe in a bounded set, cleared on a terminal status
|
|
14
|
-
* each effect runs its browser tool, stamps progress,
|
|
15
|
-
*
|
|
16
|
-
* retriable blip settles when the reply lands on the
|
|
17
|
-
* which carries no task id. Every failure on the tool
|
|
18
|
-
* as the console: an undelivered `tool/response`
|
|
19
|
-
* the
|
|
16
|
+
* pure reducer cannot hold (`tool_call_id` dedupe in a bounded set, cleared on a terminal status; the
|
|
17
|
+
* mirror-shaped `respondedRequestIds` below), then each effect runs its browser tool, stamps progress,
|
|
18
|
+
* replies `tool/response` and only then fires `afterResponseAttempt`. `handleError` converts only a
|
|
19
|
+
* `StreamGaveUpError` into a transport failure, as a retriable blip settles when the reply lands on the
|
|
20
|
+
* reconnected stream. `stopTask` sends `chat/stop`, which carries no task id. Every failure on the tool
|
|
21
|
+
* and stop paths reaches `uiActions.setError` as well as the console: an undelivered `tool/response`
|
|
22
|
+
* leaves the agent waiting on a reply that never comes, so the run stalls with nothing on screen unless
|
|
23
|
+
* the visitor is told, and `do` mode may still be clicking.
|
|
24
|
+
*
|
|
25
|
+
* `respondedRequestIds` closes the other half of the reconnect-replay contract `StreamClient.ts`
|
|
26
|
+
* documents (the api replays a chat_id's whole turn history, not just the tail a client missed):
|
|
27
|
+
* `reduceText`'s own exact-repeat guard (`sseReducer.ts`) only catches an identical FINAL
|
|
28
|
+
* `chat/response` replayed after the answer already closed, because it only ever compares against the
|
|
29
|
+
* message's LAST part. A replayed `chat/delta` fails that same-string check (it's a partial fragment,
|
|
30
|
+
* not the full closed text) and would otherwise be appended as a brand-new, visibly duplicated text
|
|
31
|
+
* segment ahead of the closing response that then only overwrites the one it just added — leaving two
|
|
32
|
+
* copies of the same answer on screen. Scoped by `request_id`, not globally, so an unrelated later
|
|
33
|
+
* turn's genuinely new `chat/delta`/`chat/response` is untouched; marked closed only once, on the
|
|
34
|
+
* request's own terminal `chat/response`, since a delta is by definition still open.
|
|
20
35
|
*
|
|
21
36
|
* `lastStreamErrorRef`/`currentErrorRef` close the loop `handleError` alone leaves open: `StreamClient`
|
|
22
37
|
* calls `onError` on every failed dial, not only a terminal give-up, so the visitor sees "Stream
|
|
@@ -43,7 +58,7 @@ interface ChatActions {
|
|
|
43
58
|
removeMessage: (messageId: string) => void;
|
|
44
59
|
setMessages: (messages: ChatMessage[]) => void;
|
|
45
60
|
clearMessages: () => void;
|
|
46
|
-
messageDispatch: (content: string, mode?: InstructionType, skipUserMessage?: boolean) => Promise<
|
|
61
|
+
messageDispatch: (content: string, mode?: InstructionType, skipUserMessage?: boolean) => Promise<boolean>;
|
|
47
62
|
}
|
|
48
63
|
interface TaskActions {
|
|
49
64
|
resetTask: () => void;
|
|
@@ -21,7 +21,7 @@ export declare const useWidget: () => {
|
|
|
21
21
|
removeMessage: (messageId: string) => void;
|
|
22
22
|
setMessages: (messages: import("..").ChatMessage[]) => void;
|
|
23
23
|
clearMessages: () => void;
|
|
24
|
-
messageDispatch: (content: string, mode?: import("..").InstructionType, skipUserMessage?: boolean) => Promise<
|
|
24
|
+
messageDispatch: (content: string, mode?: import("..").InstructionType, skipUserMessage?: boolean) => Promise<boolean>;
|
|
25
25
|
resetTask: () => void;
|
|
26
26
|
stopTask: () => Promise<void>;
|
|
27
27
|
setActiveView: (view: import("../types").WidgetView) => void;
|
|
@@ -1,15 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `
|
|
3
|
-
* one write-time gate `models/columnSchemas.ts` registers against the column. Moved out of that file
|
|
4
|
-
* so `contracts/entities.ts` can import it to type `ActivityLogEntitySchema.metadata` precisely
|
|
5
|
-
* (a union of every branch) instead of the open `.passthrough()` it carried before — deriving from a
|
|
6
|
-
* registry that lived inside `models/columnSchemas.ts`, which itself imports from `entities.ts`,
|
|
7
|
-
* would have cycled.
|
|
2
|
+
* The strict shape of an activity log row's `metadata` column, one schema per activity type.
|
|
8
3
|
*
|
|
9
|
-
* `
|
|
10
|
-
*
|
|
11
|
-
* leaf, so this registry (and everything importing it through `entities.ts`) never pulls in
|
|
12
|
-
* `contracts/slack.ts`'s `@orpc/contract` import.
|
|
4
|
+
* `ActivityMetadataByType` maps each `ActivityLogType` to its metadata shape; `contracts/entities.ts`
|
|
5
|
+
* and `models/columnSchemas.ts` both read it, which is why it lives in its own file rather than either.
|
|
13
6
|
*/
|
|
14
7
|
import { z } from 'zod';
|
|
15
8
|
export declare const ActivityMetadataByType: {
|
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* and `contracts/slack.ts`'s command-log entity status — one home per `tests/unit/contractEnumHomes.test.ts`).
|
|
6
|
-
* Split out of `contracts/entities.ts` into this dependency-free leaf — no `@orpc/contract` import —
|
|
7
|
-
* so `contracts/activityLogMetadata.ts`'s per-type registry can import them without cycling back
|
|
8
|
-
* through `entities.ts`, which needs the registry to type `ActivityLogEntitySchema.metadata`
|
|
9
|
-
* precisely instead of `.passthrough()`, and so an audience that never touches oRPC contract routes
|
|
10
|
-
* (the internal/monitor mirror) doesn't pull `@orpc/contract` in through the metadata registry.
|
|
11
|
-
* `entities.ts` re-exports the first three (unchanged); `SlackCommandLogStatusSchema` is new here and
|
|
12
|
-
* has no `entities.ts` re-export since nothing imported it from there before.
|
|
2
|
+
* Closed vocabularies used across activity log rows: application and widget types, every activity
|
|
3
|
+
* `type` value, and Slack command log status. Kept dependency-free so other contract files can use
|
|
4
|
+
* them without pulling in unrelated imports.
|
|
13
5
|
*/
|
|
14
6
|
import { z } from 'zod';
|
|
15
7
|
export declare const ApplicationTypeSchema: z.ZodEnum<{
|
|
@@ -1,31 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* keys by the same discriminant separately. Typed off the map's own value type rather than a bare
|
|
9
|
-
* `z.ZodType`, whose inferred output is `unknown` and would erase every variant's real shape from the
|
|
10
|
-
* union.
|
|
11
|
-
* - `ToolCallRecordSchema.params`/`.result` stay `z.record(z.string(), z.unknown())` ON PURPOSE —
|
|
12
|
-
* `models/columnSchemas.ts`'s header lists a tool call's own arguments and result as one of the few
|
|
13
|
-
* open boundaries kept opaque deliberately, since a tool's shape varies per tool name with no closed
|
|
14
|
-
* vocabulary this file (or the widget/app readers of `simulation_step.tool_calls`) can type against.
|
|
15
|
-
* - `SessionStateSchema` is `simulation.session_state` (Browserbase cookies + localStorage snapshot).
|
|
16
|
-
* Lives here rather than `models/columnSchemas.ts`, which imports FROM
|
|
17
|
-
* `contracts/foundationEntities.ts` — a leaf-shaped schema this file already is one, so
|
|
18
|
-
* `contracts/foundationEntities.ts` can type `SimulationEntitySchema`'s own `session_state` field
|
|
19
|
-
* with it without cycling back through `columnSchemas.ts`. Its `cookies` field is the other
|
|
20
|
-
* deliberately-open boundary from that same registry header: a browser cookie as the browser itself
|
|
21
|
-
* reports it, no closed shape to narrow to.
|
|
22
|
-
* - `GraphNodeSummarySchema` is the whole-graph tier — `applicationGraphGet`/`simulationGraphGet` load
|
|
23
|
-
* nodes with `readGraph`, which always resolves sections to `[]` for speed; a node's real sections
|
|
24
|
-
* are a lazy drill-in fetched one at a time by `graphNodeSectionsGet` (its own
|
|
25
|
-
* `GraphSectionSchema`-shaped output), so this tier never carries them. `sequence_ids` is DROPPED
|
|
26
|
-
* (not just unselected) — the stored `graph.graph_nodes` column stays for the agent's own write-side
|
|
27
|
-
* dedupe, but no app/widget graph or heatmap component ever read the wire field, and this file's
|
|
28
|
-
* widget-closure membership means dropping it republishes the widget.
|
|
2
|
+
* Wire primitives shared across every domain: id/pagination shapes, tool call and browser session
|
|
3
|
+
* state, and the application knowledge graph.
|
|
4
|
+
*
|
|
5
|
+
* Exports helpers like `paginatedListOf`/`unionOfRecord`, the id and pagination input schemas, and the
|
|
6
|
+
* graph and session-state entity schemas. This file mirrors whole into the widget SDK, so any shape
|
|
7
|
+
* added here reaches the widget even if nothing else changes.
|
|
29
8
|
*/
|
|
30
9
|
import { z } from 'zod';
|
|
31
10
|
export declare const EntityStatusSchema: z.ZodEnum<{
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entity schemas for users, workspaces, applications, widgets and activity log rows — the shapes most
|
|
3
|
+
* other contracts build on.
|
|
4
|
+
*
|
|
5
|
+
* Exports the full entity schema and a narrower read/summary variant for each, plus the activity log's
|
|
6
|
+
* per-type metadata union. `ApplicationEntitySchema`'s `skill_distillation_status`/`_error` track the
|
|
7
|
+
* last skill-distillation attempt for that application, since a distilled skill is written directly with
|
|
8
|
+
* no separate draft row. `ApplicationReadSchema` never returns `password`; `WidgetPublicSchema` never
|
|
9
|
+
* returns the widget's own auth credentials, since an unauthenticated visitor's browser is the caller.
|
|
10
|
+
*/
|
|
1
11
|
import { z } from 'zod';
|
|
2
12
|
import { type ActivityLogType, ActivityLogTypeSchema, type ApplicationType, ApplicationTypeSchema, type WidgetType, WidgetTypeSchema } from './activityLogVocabulary';
|
|
3
13
|
export { ActivityLogTypeSchema, ApplicationTypeSchema, WidgetTypeSchema };
|
|
@@ -9,7 +19,6 @@ export declare const WorkspacePackageSchema: z.ZodEnum<{
|
|
|
9
19
|
enterprise: "enterprise";
|
|
10
20
|
}>;
|
|
11
21
|
export type PlanTier = z.infer<typeof WorkspacePackageSchema>;
|
|
12
|
-
/** The plan a Billing Cycle was opened on. `legacy_unknown` is pre-ledger history, which no plan sells. */
|
|
13
22
|
export declare const PlanSnapshotSchema: z.ZodEnum<{
|
|
14
23
|
free: "free";
|
|
15
24
|
startup: "startup";
|
|
@@ -36,11 +45,6 @@ export declare const InstructionTypeSchema: z.ZodEnum<{
|
|
|
36
45
|
do: "do";
|
|
37
46
|
}>;
|
|
38
47
|
export type InstructionType = z.infer<typeof InstructionTypeSchema>;
|
|
39
|
-
/**
|
|
40
|
-
* The workspace role vocabulary — `admin` administers, `member` does not. One spelling everywhere:
|
|
41
|
-
* DB enum, this contract, the dashboard, and the WorkOS role slug. Declared here (not `workspace.ts`)
|
|
42
|
-
* because `UserEntitySchema` needs it and `workspace.ts` already imports from this file.
|
|
43
|
-
*/
|
|
44
48
|
export declare const WorkspaceMemberRoleSchema: z.ZodEnum<{
|
|
45
49
|
admin: "admin";
|
|
46
50
|
member: "member";
|
|
@@ -135,6 +139,12 @@ export declare const WorkspaceSummarySchema: z.ZodObject<{
|
|
|
135
139
|
notify_all_members_on_question: z.ZodBoolean;
|
|
136
140
|
}, z.core.$strip>;
|
|
137
141
|
export type WorkspaceSummary = z.infer<typeof WorkspaceSummarySchema>;
|
|
142
|
+
export declare const ApplicationSkillDistillationStatusSchema: z.ZodEnum<{
|
|
143
|
+
failed: "failed";
|
|
144
|
+
idle: "idle";
|
|
145
|
+
pending: "pending";
|
|
146
|
+
}>;
|
|
147
|
+
export type ApplicationSkillDistillationStatus = z.infer<typeof ApplicationSkillDistillationStatusSchema>;
|
|
138
148
|
export declare const ApplicationEntitySchema: z.ZodObject<{
|
|
139
149
|
id: z.ZodNumber;
|
|
140
150
|
created_at: z.ZodCoercedDate<unknown>;
|
|
@@ -150,9 +160,14 @@ export declare const ApplicationEntitySchema: z.ZodObject<{
|
|
|
150
160
|
username: z.ZodNullable<z.ZodString>;
|
|
151
161
|
password: z.ZodNullable<z.ZodString>;
|
|
152
162
|
allowed_domains: z.ZodArray<z.ZodString>;
|
|
163
|
+
skill_distillation_status: z.ZodEnum<{
|
|
164
|
+
failed: "failed";
|
|
165
|
+
idle: "idle";
|
|
166
|
+
pending: "pending";
|
|
167
|
+
}>;
|
|
168
|
+
skill_distillation_error: z.ZodNullable<z.ZodString>;
|
|
153
169
|
}, z.core.$strip>;
|
|
154
170
|
export type ApplicationData = z.infer<typeof ApplicationEntitySchema>;
|
|
155
|
-
/** Used for all API responses; password is write-only and never returned to clients. */
|
|
156
171
|
export declare const ApplicationReadSchema: z.ZodObject<{
|
|
157
172
|
id: z.ZodNumber;
|
|
158
173
|
created_at: z.ZodCoercedDate<unknown>;
|
|
@@ -167,6 +182,12 @@ export declare const ApplicationReadSchema: z.ZodObject<{
|
|
|
167
182
|
workspace_id: z.ZodNumber;
|
|
168
183
|
username: z.ZodNullable<z.ZodString>;
|
|
169
184
|
allowed_domains: z.ZodArray<z.ZodString>;
|
|
185
|
+
skill_distillation_status: z.ZodEnum<{
|
|
186
|
+
failed: "failed";
|
|
187
|
+
idle: "idle";
|
|
188
|
+
pending: "pending";
|
|
189
|
+
}>;
|
|
190
|
+
skill_distillation_error: z.ZodNullable<z.ZodString>;
|
|
170
191
|
}, z.core.$strip>;
|
|
171
192
|
export type ApplicationReadData = z.infer<typeof ApplicationReadSchema>;
|
|
172
193
|
export declare const WidgetChipSchema: z.ZodObject<{
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The support widget: its settings, its public boot lookup, and the SSE event/command vocabulary that
|
|
3
|
+
* drives a live chat session.
|
|
4
|
+
*
|
|
5
|
+
* Exports the widget entity and create/update schemas, `WidgetEventSchema`/`WidgetCommandSchema`, and
|
|
6
|
+
* every widget CRUD and streaming procedure. `widgetPublicSearch` is the widget's own credentialed boot
|
|
7
|
+
* call and never returns the credentials that authenticated it.
|
|
8
|
+
*/
|
|
1
9
|
import { z } from 'zod';
|
|
2
10
|
export declare const WidgetCreateSchema: z.ZodObject<{
|
|
3
11
|
status: z.ZodOptional<z.ZodEnum<{
|
|
@@ -101,7 +109,6 @@ export declare const WidgetUpdateSchema: z.ZodObject<{
|
|
|
101
109
|
}, z.core.$strip>>;
|
|
102
110
|
}, z.core.$strip>;
|
|
103
111
|
export type WidgetUpdateData = z.infer<typeof WidgetUpdateSchema>;
|
|
104
|
-
/** Server → Widget events. */
|
|
105
112
|
export declare const WidgetEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
106
113
|
type: z.ZodLiteral<"registered">;
|
|
107
114
|
chat_id: z.ZodString;
|
|
@@ -141,7 +148,6 @@ export declare const WidgetEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
141
148
|
explanation: z.ZodOptional<z.ZodString>;
|
|
142
149
|
}, z.core.$strip>], "type">;
|
|
143
150
|
export type WidgetEvent = z.infer<typeof WidgetEventSchema>;
|
|
144
|
-
/** Widget → Server commands. */
|
|
145
151
|
export declare const WidgetCommandSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
146
152
|
type: z.ZodLiteral<"chat/tell">;
|
|
147
153
|
request_id: z.ZodString;
|
|
@@ -5,7 +5,12 @@
|
|
|
5
5
|
* browser-local key shares via `scopedKey`, so the chat-context, drag-position and resize keys all
|
|
6
6
|
* partition by tenant identically. `readLocal`/`writeLocal` are the only `localStorage` access in `src/`;
|
|
7
7
|
* a host page can deny storage outright (third-party cookies off, sandboxed iframe), so both degrade to
|
|
8
|
-
*
|
|
8
|
+
* memory and the widget keeps working unpersisted. `updateContext` calls `writeLocal` on every UI-state
|
|
9
|
+
* change (a drag, a resize, every chat message), so without `warnOnce` a denied host page would spam one
|
|
10
|
+
* console line per write for the visitor's whole session; a single warn on first denial says everything
|
|
11
|
+
* a customer's console needs. `warnOnce` is keyed by read vs. write since `readLocal` also fires once on
|
|
12
|
+
* its own (`loadContext` at module init, before any write) and both should still surface if a page
|
|
13
|
+
* somehow denies one and not the other.
|
|
9
14
|
*
|
|
10
15
|
* `loadContext` merges one parsed key over `DEFAULT_CONTEXT`, so an older widget version's payload reads
|
|
11
16
|
* as incomplete rather than corrupt, and discards anything past `CONTEXT_EXPIRY_MS` (7 days).
|
|
@@ -55,6 +60,10 @@ type MarketrixChatContext = Omit<ChatSnapshot, 'messages'> & {
|
|
|
55
60
|
};
|
|
56
61
|
export declare function tenantScope(config: MarketrixConfig): string;
|
|
57
62
|
export declare function scopedKey(name: string, config: MarketrixConfig): string;
|
|
63
|
+
/** Test-only: `warned` is module-level so a "denies storage, keeps working" proof isn't the last test in
|
|
64
|
+
* the file to touch a denied `Storage.prototype`, and a later test in the same `bun test` process (one
|
|
65
|
+
* process per file, not per test) would otherwise see zero warns instead of one. Never called from `src/`. */
|
|
66
|
+
export declare function resetStorageWarningsForTests(): void;
|
|
58
67
|
export declare function readLocal(key: string): string | null;
|
|
59
68
|
export declare function writeLocal(key: string, value: string): void;
|
|
60
69
|
declare class StorageService {
|
|
@@ -6,7 +6,10 @@
|
|
|
6
6
|
*
|
|
7
7
|
* `open` is the transport, `registered` is the chat: only the latter can carry a reply, so `isConnected` reads
|
|
8
8
|
* `registered` and nothing waits on `open`. Backoff counters reset only on `registered` — resetting at `open` would
|
|
9
|
-
* defeat the max-attempts cap if registration never lands and the stream flaps open→closed.
|
|
9
|
+
* defeat the max-attempts cap if registration never lands and the stream flaps open→closed. `scheduleReconnect`'s
|
|
10
|
+
* EQUAL JITTER (the doubling delay's own second half, chosen uniformly) keeps every dial within the documented
|
|
11
|
+
* schedule's bound while stopping every tab across every open customer page from redialing on the exact same
|
|
12
|
+
* clock tick after a shared outage — a thundering herd the deterministic schedule alone cannot prevent. Tabs share the
|
|
10
13
|
* localStorage chat id, so the server keys SSE by (chat_id, tab_id) and `tabId` stops tabs evicting each other's
|
|
11
14
|
* stream. Credentials are read at connect time, not captured at init, so a reconnect after `updateMarketrixConfig`
|
|
12
15
|
* dials with the current ones.
|