@qfei-design/make-ai-assistant 0.1.0

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,132 @@
1
+ const s = {
2
+ metric: {
3
+ schemaVersion: "1.0",
4
+ id: "fixture-metric",
5
+ kind: "metric",
6
+ title: "本月完成金额",
7
+ summary: "统计范围:本月,状态:已完成",
8
+ data: {
9
+ value: 1286420,
10
+ format: { style: "currency", currency: "CNY", precision: 0 },
11
+ delta: { value: 18.4, format: "percent", direction: "up", label: "较上月" }
12
+ },
13
+ actions: [
14
+ {
15
+ id: "metric-detail",
16
+ label: "查看明细",
17
+ intent: "open-list",
18
+ target: { entityKey: "example_record", filterKey: "completed" }
19
+ }
20
+ ]
21
+ },
22
+ comparison: {
23
+ schemaVersion: "1.0",
24
+ id: "fixture-comparison",
25
+ kind: "comparison",
26
+ title: "状态金额对比",
27
+ data: {
28
+ items: [
29
+ { id: "completed", label: "已完成", value: 1286420, format: { style: "currency", currency: "CNY", precision: 0 } },
30
+ { id: "pending", label: "待处理", value: 368200, format: { style: "currency", currency: "CNY", precision: 0 } }
31
+ ]
32
+ }
33
+ },
34
+ trend: {
35
+ schemaVersion: "1.0",
36
+ id: "fixture-trend",
37
+ kind: "trend",
38
+ title: "近 7 日趋势",
39
+ data: {
40
+ series: [
41
+ {
42
+ id: "amount",
43
+ label: "完成金额",
44
+ format: { style: "currency", currency: "CNY", precision: 0 },
45
+ points: [
46
+ { x: "周一", y: 18 },
47
+ { x: "周二", y: 26 },
48
+ { x: "周三", y: 22 },
49
+ { x: "周四", y: 35 },
50
+ { x: "周五", y: 42 },
51
+ { x: "周六", y: 28 },
52
+ { x: "周日", y: 46 }
53
+ ]
54
+ }
55
+ ]
56
+ }
57
+ },
58
+ ranking: {
59
+ schemaVersion: "1.0",
60
+ id: "fixture-ranking",
61
+ kind: "ranking",
62
+ title: "贡献排行",
63
+ data: {
64
+ items: [
65
+ { id: "one", label: "示例团队 A", value: 42e4, format: { style: "currency", currency: "CNY", precision: 0 } },
66
+ { id: "two", label: "示例团队 B", value: 31e4, format: { style: "currency", currency: "CNY", precision: 0 } },
67
+ { id: "three", label: "示例团队 C", value: 225e3, format: { style: "currency", currency: "CNY", precision: 0 } }
68
+ ]
69
+ }
70
+ },
71
+ "record-list": {
72
+ schemaVersion: "1.0",
73
+ id: "fixture-record-list",
74
+ kind: "record-list",
75
+ title: "相关记录",
76
+ data: {
77
+ entity: { key: "example_record", label: "示例记录" },
78
+ columns: [
79
+ { key: "owner", label: "负责人" },
80
+ { key: "amount", label: "金额", format: { style: "currency", currency: "CNY", precision: 0 } }
81
+ ],
82
+ records: [
83
+ { id: "record-1", title: "REC-001", values: { owner: "林小满", amount: 86e3 } },
84
+ { id: "record-2", title: "REC-002", values: { owner: "周一", amount: 148500 } },
85
+ { id: "record-3", title: "REC-003", values: { owner: "徐青", amount: 64800 } }
86
+ ],
87
+ total: 3
88
+ }
89
+ },
90
+ notice: {
91
+ schemaVersion: "1.0",
92
+ id: "fixture-notice",
93
+ kind: "notice",
94
+ title: "检查完成",
95
+ data: { tone: "success", body: "当前范围内没有发现明显异常。" }
96
+ }
97
+ }, l = (r, e) => new Promise((n, i) => {
98
+ if (e?.aborted) {
99
+ i(new DOMException("Aborted", "AbortError"));
100
+ return;
101
+ }
102
+ const t = () => {
103
+ clearTimeout(a), i(new DOMException("Aborted", "AbortError"));
104
+ }, a = setTimeout(() => {
105
+ e?.removeEventListener("abort", t), n();
106
+ }, r);
107
+ e?.addEventListener("abort", t, { once: !0 });
108
+ }), d = (r = {}) => ({
109
+ async *run(e, n) {
110
+ const i = `mock-run-${e.message.id}`, t = `mock-assistant-${e.message.id}`, a = r.response?.(e) ?? {
111
+ text: "我已根据当前上下文完成分析。",
112
+ artifacts: [s.metric]
113
+ }, c = [
114
+ { type: "message.start", runId: i, messageId: t },
115
+ { type: "message.delta", messageId: t, delta: a.text },
116
+ ...(a.artifacts ?? []).map(
117
+ (o) => ({ type: "artifact", messageId: t, artifact: o })
118
+ ),
119
+ { type: "message.complete", messageId: t },
120
+ { type: "run.complete", runId: i, threadId: e.threadId ?? "mock-thread" }
121
+ ];
122
+ for (const o of c) {
123
+ if (r.delayMs && await l(r.delayMs, n?.signal), n?.signal?.aborted)
124
+ throw new DOMException("Aborted", "AbortError");
125
+ yield o;
126
+ }
127
+ }
128
+ });
129
+ export {
130
+ s as artifactFixtures,
131
+ d as createMockAssistantTransport
132
+ };
@@ -0,0 +1,101 @@
1
+ # Artifact V1 合同
2
+
3
+ ## 设计原则
4
+
5
+ Artifact 是后端与前端共享的、可校验的展示语义,不是前端组件调用指令。服务端只能从双方协商的 `kind` 和字段中生成结果,前端只从已注册模板白名单中选择渲染器。
6
+
7
+ 所有 Artifact 都包含:
8
+
9
+ ```ts
10
+ interface BaseArtifact {
11
+ schemaVersion: "1.0";
12
+ id: string;
13
+ kind: ArtifactKind;
14
+ title?: string;
15
+ summary?: string;
16
+ presentation?: {
17
+ template?: string;
18
+ density?: "compact" | "comfortable";
19
+ };
20
+ actions?: ArtifactAction[];
21
+ meta?: Record<string, JsonValue>;
22
+ }
23
+ ```
24
+
25
+ ## V1 kind
26
+
27
+ | kind | 用途 | 核心数据 |
28
+ | --- | --- | --- |
29
+ | `metric` | 单个关键指标 | value、format、delta |
30
+ | `comparison` | 多指标并列对比 | items |
31
+ | `trend` | 时间或顺序趋势 | series、points |
32
+ | `ranking` | Top N 或贡献排行 | items |
33
+ | `record-list` | 可跳转的业务记录摘要 | entity、columns、records、total |
34
+ | `notice` | 解释、空结果、风险或成功提示 | tone、body |
35
+
36
+ ## 数值格式
37
+
38
+ `format` 是显示建议,不改变原值:
39
+
40
+ ```json
41
+ {
42
+ "style": "currency",
43
+ "currency": "CNY",
44
+ "precision": 0,
45
+ "unit": "元"
46
+ }
47
+ ```
48
+
49
+ 前端使用宿主 locale 进行格式化。无法格式化时显示原始值,不把货币、百分比或单位写死到模板。
50
+
51
+ ## 动作
52
+
53
+ ```json
54
+ {
55
+ "id": "open-completed-orders",
56
+ "label": "查看明细",
57
+ "intent": "open-list",
58
+ "target": {
59
+ "entityKey": "sales_order",
60
+ "viewKey": "completed"
61
+ }
62
+ }
63
+ ```
64
+
65
+ 动作是意图,不是 URL。宿主决定如何映射路由、是否允许执行以及失败提示。
66
+
67
+ ## 模板提示
68
+
69
+ `presentation.template` 只是提示。模板不存在、不支持该 kind 或 `canRender` 不通过时,注册表忽略它并执行正常选择。后端不能通过这个字段加载代码。
70
+
71
+ ## 协商
72
+
73
+ 每次运行请求携带前端支持的 Artifact 目录:schema 版本、kind 和可选模板 id。后端只应返回交集能力;若无法形成结构化结果,返回普通助手文本。
74
+
75
+ 机器可读 JSON Schema 位于根目录 `artifact-v1.schema.json`。
76
+
77
+ 运行时 `validateArtifact` 与 JSON Schema 使用同一白名单边界:未知字段、非法可选展示
78
+ 字段和非 JSON 值都会被拒绝。通过校验的 Artifact 才能进入模板渲染,避免服务端输入在
79
+ React 渲染阶段触发白屏。
80
+
81
+ ## 展示规模上限
82
+
83
+ 默认模板只接收适合抽屉内直接展示的摘要数据:actions 10 个、comparison 24 项、trend
84
+ 8 个 series 且每个 series 120 个点、ranking 50 项、record-list 20 列和 100 条记录。
85
+ 超过上限时,服务端应返回汇总 Artifact,并通过 `open-list` 动作交由宿主打开完整列表。
86
+
87
+ 运行时还按 Unicode code point 限制每个字符串 20,000 字符、JSON 最大深度 64、最多 10,000 个节点、累计
88
+ 字符串 1,000,000 字符、每条 record 最多 100 个 display value,并把验证问题限制在
89
+ 100 条以内。集合一旦超过展示规模会立即短路;深层、循环、非 plain object、Proxy
90
+ 异常、getter 异常、稀疏数组和 Artifact 整体资源超限都会作为校验失败返回,不向调用方
91
+ 泄漏运行时异常。JSON Schema 表达字段与单集合边界,整体节点/深度/累计文本预算由运行时
92
+ 校验补充执行。
93
+
94
+ 校验成功会返回经过结构化快照并再次校验的 Artifact,不与调用方继续共享可变对象;
95
+ 调用方后续修改原始输入不会改变已经进入会话或渲染链路的数据。
96
+
97
+ 同一集合内 action/item/series/record 的 `id` 和 record-list column 的 `key` 必须唯一,
98
+ 避免 React key 冲突以及同名列读取歧义。
99
+
100
+ `presentation.density` 只选择内置的 compact/comfortable 密度,`action.appearance` 只选择
101
+ primary/secondary/link 样式层级;它们都不能携带 CSS 或可执行代码。
@@ -0,0 +1,94 @@
1
+ # Make AI 助手后端 V1 配合合同
2
+
3
+ ## 接口能力
4
+
5
+ 后端第一版至少提供以下能力:
6
+
7
+ 1. 创建或继续一次 run;
8
+ 2. 通过 SSE 流式返回文本与 Artifact;
9
+ 3. 查询会话列表和会话消息;
10
+ 4. 停止正在执行的 run;
11
+ 5. 返回可观测的错误码和 request/run id。
12
+
13
+ 建议 Service API:
14
+
15
+ | 方法 | 路径 | 用途 |
16
+ | --- | --- | --- |
17
+ | `POST` | `/api/assistant/runs` | 发起消息并返回 SSE |
18
+ | `POST` | `/api/assistant/runs/:runId/cancel` | 取消生成 |
19
+ | `GET` | `/api/assistant/threads` | 会话列表 |
20
+ | `GET` | `/api/assistant/threads/:threadId` | 会话与历史消息 |
21
+ | `DELETE` | `/api/assistant/threads/:threadId` | 删除会话,可放到后续版本 |
22
+
23
+ 宿主 UI 只调用自己的 Service `/api`,不直接调用 Make API、模型服务或透传 Make token。
24
+
25
+ ## Run 请求
26
+
27
+ ```json
28
+ {
29
+ "threadId": "optional-thread-id",
30
+ "message": {
31
+ "id": "client-message-id",
32
+ "content": "统计本月已完成订单金额"
33
+ },
34
+ "context": {
35
+ "app": { "id": "app-id", "name": "销售管理" },
36
+ "location": { "pathname": "/orders", "routeId": "orders" },
37
+ "resource": { "entityKey": "sales_order", "viewKey": "default" },
38
+ "locale": "zh-CN",
39
+ "timezone": "Asia/Shanghai"
40
+ },
41
+ "capabilities": {
42
+ "artifactSchemaVersions": ["1.0"],
43
+ "artifactKinds": ["metric", "comparison", "trend", "ranking", "record-list", "notice"],
44
+ "templates": ["platform.metric.default"]
45
+ }
46
+ }
47
+ ```
48
+
49
+ 后端必须从服务端身份重新确认数据权限。`context` 用于理解当前工作环境,不是授权凭据。
50
+
51
+ ## SSE 事件
52
+
53
+ 使用标准 SSE 帧,`event` 对应事件类型,`data` 是 JSON:
54
+
55
+ ```text
56
+ event: message.start
57
+ data: {"runId":"run-1","messageId":"assistant-1"}
58
+
59
+ event: message.delta
60
+ data: {"messageId":"assistant-1","delta":"本月已完成订单金额为"}
61
+
62
+ event: artifact
63
+ data: {"messageId":"assistant-1","artifact":{"schemaVersion":"1.0","id":"metric-1","kind":"metric","data":{"value":1286420,"format":{"style":"currency","currency":"CNY"}}}}
64
+
65
+ event: message.complete
66
+ data: {"messageId":"assistant-1"}
67
+
68
+ event: run.complete
69
+ data: {"runId":"run-1","threadId":"thread-1"}
70
+ ```
71
+
72
+ 要求:
73
+
74
+ - delta 顺序稳定,同一 run 内可有多个 Artifact;
75
+ - 服务端定期发送注释心跳,代理层不得缓冲 SSE;
76
+ - 客户端断开或取消后及时终止下游任务;
77
+ - Artifact 在发送前按共享 Schema 校验;
78
+ - 错误事件包含稳定 `code`、可展示 `message`、`retryable` 和 `requestId`;
79
+ - 正常结束、服务端取消和失败必须分别发送 `run.complete`、`run.cancelled` 或 `error`;
80
+ - 同一流中的 `message.start`、`run.complete` 和带 id 的 `run.cancelled` 必须使用一致的
81
+ `runId`,同一会话中的 `messageId` 不得复用;
82
+ - `data` 内不得重复提供 `type` 字段,事件类型只由 SSE `event` 字段决定;
83
+ - `retryable` 必须是 JSON boolean,不能使用 `"true"` / `"false"` 字符串;
84
+ - 客户端把终止事件前的 EOF 视为传输失败,不会把不完整响应当作成功;
85
+ - 客户端停止时会立即关闭本地 run、忽略迟到事件,并取消底层 response reader;
86
+ - 如果调用前 `AbortSignal` 已取消,客户端不会发出 fetch 请求;
87
+ - 单个 SSE 事件默认不能超过 1,000,000 字符,单次累计响应文本不能超过 100,000
88
+ 字符;需要更大载荷时应返回摘要 Artifact 和明细动作,不要扩展无界流;
89
+ - HTTP 非成功响应只向 UI 暴露状态码,不直接展示任意后端 `message` 或内部错误细节;
90
+ - 日志记录入口、失败和关键分支,但不记录 token、完整敏感上下文或不必要个人数据。
91
+
92
+ ## Mock 阶段
93
+
94
+ 真实接口未就绪时,前端 Mock 必须实现相同 `AssistantTransport` 和事件顺序。Mock 数据放在测试/Gallery 或宿主开发适配器,不进入平台默认业务模板。切换真实后端时只替换 transport,不改聊天组件和 Artifact 模板。
@@ -0,0 +1,52 @@
1
+ {
2
+ "packageName": "@qfei-design/make-ai-assistant",
3
+ "minimumRuntimeVersion": "0.1.0",
4
+ "readOrder": [
5
+ "package.ai.json",
6
+ "README.md",
7
+ "PUBLIC_API.md",
8
+ "recipes.json",
9
+ "capabilities.json"
10
+ ],
11
+ "runtime": {
12
+ "environment": "browser",
13
+ "coreIsDomFree": true,
14
+ "reactPeerRequiredForUi": true,
15
+ "ssrSupported": true
16
+ },
17
+ "install": {
18
+ "pnpm": "pnpm add @qfei-design/make-ai-assistant@^0.1.0",
19
+ "npm": "npm install @qfei-design/make-ai-assistant@^0.1.0",
20
+ "yarn": "yarn add @qfei-design/make-ai-assistant@^0.1.0"
21
+ },
22
+ "exports": [
23
+ "@qfei-design/make-ai-assistant",
24
+ "@qfei-design/make-ai-assistant/react",
25
+ "@qfei-design/make-ai-assistant/sse",
26
+ "@qfei-design/make-ai-assistant/testing",
27
+ "@qfei-design/make-ai-assistant/styles.css",
28
+ "@qfei-design/make-ai-assistant/artifact-v1.schema.json"
29
+ ],
30
+ "officialDocs": {
31
+ "readme": "README.md",
32
+ "publicApi": "PUBLIC_API.md",
33
+ "recipes": "recipes.json",
34
+ "capabilities": "capabilities.json"
35
+ },
36
+ "packageResponsibilities": [
37
+ "Artifact V1 contracts and validation",
38
+ "Conversation event reduction",
39
+ "Standard abortable SSE transport",
40
+ "Template registration and capability negotiation",
41
+ "Floating launcher, right drawer and embedded assistant panel",
42
+ "Platform artifact templates",
43
+ "Testing fixtures and mock transport"
44
+ ],
45
+ "hostResponsibilities": [
46
+ "Current App and route context",
47
+ "SSE or AG-UI transport adapter",
48
+ "Service authentication and server-side authorization",
49
+ "Safe action execution and route mapping",
50
+ "Optional App-specific templates and theme variables"
51
+ ]
52
+ }
package/package.json ADDED
@@ -0,0 +1,115 @@
1
+ {
2
+ "name": "@qfei-design/make-ai-assistant",
3
+ "version": "0.1.0",
4
+ "description": "Platform-wide Make AI Assistant contracts, React shell, and context-aware artifact templates.",
5
+ "type": "module",
6
+ "sideEffects": [
7
+ "**/*.css"
8
+ ],
9
+ "main": "./dist/index.cjs",
10
+ "module": "./dist/index.mjs",
11
+ "types": "./dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.mjs",
16
+ "require": "./dist/index.cjs"
17
+ },
18
+ "./react": {
19
+ "types": "./dist/react/index.d.ts",
20
+ "import": "./dist/react.mjs",
21
+ "require": "./dist/react.cjs"
22
+ },
23
+ "./sse": {
24
+ "types": "./dist/sse.d.ts",
25
+ "import": "./dist/sse.mjs",
26
+ "require": "./dist/sse.cjs"
27
+ },
28
+ "./testing": {
29
+ "types": "./dist/testing/index.d.ts",
30
+ "import": "./dist/testing.mjs",
31
+ "require": "./dist/testing.cjs"
32
+ },
33
+ "./styles.css": {
34
+ "types": "./dist/styles.css.d.ts",
35
+ "default": "./dist/styles.css"
36
+ },
37
+ "./artifact-v1.schema.json": "./artifact-v1.schema.json"
38
+ },
39
+ "files": [
40
+ "dist",
41
+ "artifact-v1.schema.json",
42
+ "README.md",
43
+ "PUBLIC_API.md",
44
+ "package.ai.json",
45
+ "recipes.json",
46
+ "capabilities.json",
47
+ "docs/artifact-v1.md",
48
+ "docs/backend-contract.md"
49
+ ],
50
+ "scripts": {
51
+ "test": "vitest run",
52
+ "typecheck": "tsc -p tsconfig.json --noEmit",
53
+ "build": "vite build && tsc -p tsconfig.build.json --emitDeclarationOnly && node scripts/copy-styles.mjs && node scripts/smoke-dist.mjs",
54
+ "gallery:build": "vite build --config examples/gallery/vite.config.ts",
55
+ "sprint:init": "qfei-release sprint-init",
56
+ "release:init": "qfei-release release-init",
57
+ "publish:alpha": "qfei-release publish --channel alpha",
58
+ "publish:beta": "qfei-release publish --channel beta",
59
+ "publish:latest": "qfei-release publish-latest",
60
+ "release:check": "qfei-release release-check",
61
+ "ci:init": "qfei-release ci-init",
62
+ "ci:check": "qfei-release ci-check"
63
+ },
64
+ "qfeiRelease": {
65
+ "masterBranch": "master",
66
+ "ciMode": "mr-verify-manual-prerelease",
67
+ "packageManager": "pnpm",
68
+ "verifyScripts": [
69
+ "test",
70
+ "typecheck",
71
+ "build"
72
+ ],
73
+ "latestPublishTargets": [
74
+ "internal",
75
+ "npmjs"
76
+ ],
77
+ "prereleasePublishTargets": [
78
+ "internal"
79
+ ],
80
+ "npmjs": {
81
+ "registry": "https://registry.npmjs.org/",
82
+ "access": "public",
83
+ "tokenEnv": "NPMJS_TOKEN"
84
+ }
85
+ },
86
+ "peerDependencies": {
87
+ "react": ">=18.2.0 || >=19.0.0",
88
+ "react-dom": ">=18.2.0 || >=19.0.0"
89
+ },
90
+ "peerDependenciesMeta": {
91
+ "react": {
92
+ "optional": true
93
+ },
94
+ "react-dom": {
95
+ "optional": true
96
+ }
97
+ },
98
+ "devDependencies": {
99
+ "@qfei/component-release-tools": "^0.5.1",
100
+ "@types/node": "^22.10.0",
101
+ "@types/react": "^19.0.0",
102
+ "@types/react-dom": "^19.0.0",
103
+ "@vitejs/plugin-react": "^4.0.0",
104
+ "jsdom": "^29.1.1",
105
+ "react": "^19.2.0",
106
+ "react-dom": "^19.2.0",
107
+ "typescript": "^5.6.0",
108
+ "vite": "^7.0.0",
109
+ "vitest": "^4.1.5"
110
+ },
111
+ "engines": {
112
+ "node": ">=22.12.0"
113
+ },
114
+ "packageManager": "pnpm@10.20.0+sha512.cf9998222162dd85864d0a8102e7892e7ba4ceadebbf5a31f9c2fce48dfce317a9c53b9f6464d1ef9042cba2e02ae02a9f7c143a2b438cd93c91840f0192b9dd"
115
+ }
package/recipes.json ADDED
@@ -0,0 +1,81 @@
1
+ {
2
+ "packageName": "@qfei-design/make-ai-assistant",
3
+ "primaryGuide": "README.md",
4
+ "recipes": [
5
+ {
6
+ "id": "default-app-assistant",
7
+ "summary": "Add the default floating launcher and right drawer to a Make App.",
8
+ "use": [
9
+ "MakeAiAssistant",
10
+ "@qfei-design/make-ai-assistant/styles.css"
11
+ ],
12
+ "hostProvides": [
13
+ "MakeAssistantHostContext",
14
+ "AssistantTransport",
15
+ "ArtifactActionHandler"
16
+ ],
17
+ "readNext": ["README.md", "PUBLIC_API.md"],
18
+ "commonMistakes": [
19
+ "Calling Make API directly from the UI",
20
+ "Passing Make tokens through the package",
21
+ "Treating context as server authorization",
22
+ "Executing arbitrary server-generated HTML or component code"
23
+ ]
24
+ },
25
+ {
26
+ "id": "standard-sse-transport",
27
+ "summary": "Connect a browser or modern Node host to the standard named SSE contract.",
28
+ "use": [
29
+ "@qfei-design/make-ai-assistant/sse:createSseAssistantTransport"
30
+ ],
31
+ "hostProvides": [
32
+ "Service endpoint",
33
+ "Optional credentials and request headers"
34
+ ],
35
+ "readNext": ["README.md", "docs/backend-contract.md"],
36
+ "commonMistakes": [
37
+ "Importing the SSE implementation from the headless root",
38
+ "Sending Make tokens from the browser",
39
+ "Ending a stream without run.complete, run.cancelled or error"
40
+ ]
41
+ },
42
+ {
43
+ "id": "app-artifact-template",
44
+ "summary": "Register an App-specific result template without changing the platform package.",
45
+ "use": [
46
+ "ReactArtifactTemplate",
47
+ "platformArtifactTemplates",
48
+ "createPlatformArtifactRegistry"
49
+ ],
50
+ "hostProvides": [
51
+ "Stable template id",
52
+ "canRender predicate based on Artifact semantics and host context",
53
+ "Accessible React presentation"
54
+ ],
55
+ "readNext": ["README.md", "PUBLIC_API.md"],
56
+ "commonMistakes": [
57
+ "Registering a business-specific template as a platform default",
58
+ "Using a backend component name as an executable import path",
59
+ "Duplicating an existing template id"
60
+ ]
61
+ },
62
+ {
63
+ "id": "mock-before-backend",
64
+ "summary": "Develop and test the full UI before the SSE backend exists.",
65
+ "use": [
66
+ "createMockAssistantTransport",
67
+ "artifactFixtures"
68
+ ],
69
+ "hostProvides": [
70
+ "App context",
71
+ "Optional request-specific mock response"
72
+ ],
73
+ "readNext": ["README.md", "PUBLIC_API.md"],
74
+ "commonMistakes": [
75
+ "Building a second mock-only component path",
76
+ "Putting POC business fixtures into platform default templates",
77
+ "Changing UI event handling when switching to SSE"
78
+ ]
79
+ }
80
+ ]
81
+ }