@loom-framework/core 0.1.0-alpha.153 → 0.1.0-alpha.155
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/builtin-skills/app-skill/SKILL.md +6 -2
- package/builtin-skills/app-skill/references/notification.md +123 -0
- package/builtin-skills/app-skill/references/process-builder.md +38 -0
- package/builtin-skills/app-skill/references/process.md +72 -4
- package/dist/backend/ai/engine.d.ts.map +1 -1
- package/dist/backend/ai/engine.js +27 -6
- package/dist/backend/ai/engine.js.map +1 -1
- package/dist/backend/auth/rbac.d.ts +2 -0
- package/dist/backend/auth/rbac.d.ts.map +1 -1
- package/dist/backend/auth/rbac.js +4 -0
- package/dist/backend/auth/rbac.js.map +1 -1
- package/dist/backend/index.d.ts +4 -0
- package/dist/backend/index.d.ts.map +1 -1
- package/dist/backend/index.js +48 -1
- package/dist/backend/index.js.map +1 -1
- package/dist/backend/notifications/interpolate.d.ts +6 -0
- package/dist/backend/notifications/interpolate.d.ts.map +1 -0
- package/dist/backend/notifications/interpolate.js +11 -0
- package/dist/backend/notifications/interpolate.js.map +1 -0
- package/dist/backend/notifications/notification-storage.d.ts +25 -0
- package/dist/backend/notifications/notification-storage.d.ts.map +1 -0
- package/dist/backend/notifications/notification-storage.js +158 -0
- package/dist/backend/notifications/notification-storage.js.map +1 -0
- package/dist/backend/process/engine.d.ts +18 -0
- package/dist/backend/process/engine.d.ts.map +1 -1
- package/dist/backend/process/engine.js +65 -0
- package/dist/backend/process/engine.js.map +1 -1
- package/dist/backend/process/metrics-store.d.ts +30 -0
- package/dist/backend/process/metrics-store.d.ts.map +1 -0
- package/dist/backend/process/metrics-store.js +106 -0
- package/dist/backend/process/metrics-store.js.map +1 -0
- package/dist/backend/process/queue.d.ts +2 -0
- package/dist/backend/process/queue.d.ts.map +1 -1
- package/dist/backend/process/queue.js +14 -0
- package/dist/backend/process/queue.js.map +1 -1
- package/dist/backend/routes/auth-routes.js +2 -2
- package/dist/backend/routes/auth-routes.js.map +1 -1
- package/dist/backend/routes/index.d.ts +2 -0
- package/dist/backend/routes/index.d.ts.map +1 -1
- package/dist/backend/routes/index.js +1 -0
- package/dist/backend/routes/index.js.map +1 -1
- package/dist/backend/routes/notification-routes.d.ts +22 -0
- package/dist/backend/routes/notification-routes.d.ts.map +1 -0
- package/dist/backend/routes/notification-routes.js +128 -0
- package/dist/backend/routes/notification-routes.js.map +1 -0
- package/dist/backend/routes/process-routes.d.ts.map +1 -1
- package/dist/backend/routes/process-routes.js +67 -1
- package/dist/backend/routes/process-routes.js.map +1 -1
- package/dist/cli/commands/generate-notification.d.ts +9 -0
- package/dist/cli/commands/generate-notification.d.ts.map +1 -0
- package/dist/cli/commands/generate-notification.js +24 -0
- package/dist/cli/commands/generate-notification.js.map +1 -0
- package/dist/cli/commands/init.js +6 -1
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/notification.d.ts +8 -0
- package/dist/cli/commands/notification.d.ts.map +1 -0
- package/dist/cli/commands/notification.js +175 -0
- package/dist/cli/commands/notification.js.map +1 -0
- package/dist/cli/commands/process.d.ts.map +1 -1
- package/dist/cli/commands/process.js +147 -0
- package/dist/cli/commands/process.js.map +1 -1
- package/dist/cli/generators/capability-generator.d.ts.map +1 -1
- package/dist/cli/generators/capability-generator.js +85 -2
- package/dist/cli/generators/capability-generator.js.map +1 -1
- package/dist/cli/helpers/app-tsx-wiring.d.ts +11 -0
- package/dist/cli/helpers/app-tsx-wiring.d.ts.map +1 -1
- package/dist/cli/helpers/app-tsx-wiring.js +113 -0
- package/dist/cli/helpers/app-tsx-wiring.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/templates/process-management-page.d.ts.map +1 -1
- package/dist/cli/templates/process-management-page.js +143 -30
- package/dist/cli/templates/process-management-page.js.map +1 -1
- package/dist/config.d.ts +128 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +10 -0
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/types/ai.d.ts +6 -0
- package/dist/types/ai.d.ts.map +1 -1
- package/dist/types/event.d.ts +18 -4
- package/dist/types/event.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/notification.d.ts +31 -0
- package/dist/types/notification.d.ts.map +1 -0
- package/dist/types/notification.js +5 -0
- package/dist/types/notification.js.map +1 -0
- package/dist/types/process.d.ts +43 -1
- package/dist/types/process.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: {{projectName}}
|
|
3
3
|
description: |
|
|
4
4
|
⚠️ TODO: 根据下方 [TODO] 标记补全触发短语。阅读 references/models.md 中的数据模型和 AI 按钮定义,
|
|
5
|
-
编写触发短语,包含:用户语言中的常见增删改查动词、各数据模型相关的操作、AI 按钮的标签<!-- AUTH_DESC --><!-- EVENTS_DESC --><!-- PROCESS_DESC -->
|
|
5
|
+
编写触发短语,包含:用户语言中的常见增删改查动词、各数据模型相关的操作、AI 按钮的标签<!-- AUTH_DESC --><!-- EVENTS_DESC --><!-- PROCESS_DESC --><!-- NOTIFICATION_DESC -->
|
|
6
6
|
格式:"This skill should be used when the user asks to '短语1', '短语2',
|
|
7
7
|
or any request about <此项目管理的内容> in the {{projectName}} project."
|
|
8
8
|
version: 1.0.0
|
|
@@ -19,6 +19,7 @@ version: 1.0.0
|
|
|
19
19
|
<!-- AUTH_OVERVIEW -->
|
|
20
20
|
<!-- EVENTS_OVERVIEW -->
|
|
21
21
|
<!-- PROCESS_OVERVIEW -->
|
|
22
|
+
<!-- NOTIFICATION_OVERVIEW -->
|
|
22
23
|
|
|
23
24
|
## Usage Scenarios
|
|
24
25
|
|
|
@@ -27,11 +28,13 @@ version: 1.0.0
|
|
|
27
28
|
- data-semantics.md — 当前项目的数据模型名称列表、write 的 --data JSON 构造规则(字段类型格式、enum 取值约束、贴合业务的真实示例值)、read 的 --filter JSON 构造规则(优先用 enum/boolean 字段筛选、跨模型关联查询)。
|
|
28
29
|
<!-- AUTH_SCENARIOS_LOAD -->
|
|
29
30
|
<!-- PROCESS_SCENARIOS_LOAD -->
|
|
31
|
+
<!-- NOTIFICATION_SCENARIOS_LOAD -->
|
|
30
32
|
|
|
31
33
|
[TODO: 生成5-10个典型用户请求,每个格式:用户说的话 → 对应的 `loom data` CLI 命令。每个数据模型至少包含一个场景。]
|
|
32
34
|
<!-- AUTH_SCENARIOS -->
|
|
33
35
|
<!-- EVENTS_SCENARIOS -->
|
|
34
36
|
<!-- PROCESS_SCENARIOS -->
|
|
37
|
+
<!-- NOTIFICATION_SCENARIOS -->
|
|
35
38
|
|
|
36
39
|
## Technical Reference
|
|
37
40
|
|
|
@@ -40,4 +43,5 @@ version: 1.0.0
|
|
|
40
43
|
- 语义引导(示例数据生成、筛选选择、关系推断):**references/data-semantics.md**
|
|
41
44
|
<!-- AUTH_REF -->
|
|
42
45
|
<!-- EVENTS_REF -->
|
|
43
|
-
<!-- PROCESS_REF -->
|
|
46
|
+
<!-- PROCESS_REF -->
|
|
47
|
+
<!-- NOTIFICATION_REF -->
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Notification Commands Reference
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Loom provides a built-in notification system for persistent server-side notifications. Notifications are user-scoped and support CRUD operations via both HTTP API and CLI.
|
|
6
|
+
|
|
7
|
+
## CLI Commands
|
|
8
|
+
|
|
9
|
+
### List notifications
|
|
10
|
+
```bash
|
|
11
|
+
loom notification list [--unread] [--limit 20] [--offset 0] --token <TOKEN>
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### Mark as read
|
|
15
|
+
```bash
|
|
16
|
+
loom notification read <id> --token <TOKEN>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Mark all as read
|
|
20
|
+
```bash
|
|
21
|
+
loom notification read-all --token <TOKEN>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Delete notification
|
|
25
|
+
```bash
|
|
26
|
+
loom notification delete <id> --token <TOKEN>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Clear all notifications
|
|
30
|
+
```bash
|
|
31
|
+
loom notification clear --token <TOKEN>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Send notification (admin only)
|
|
35
|
+
```bash
|
|
36
|
+
loom notification send --userId <userId> --type <type> --title <title> [--description DESC] --token <TOKEN>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## HTTP API
|
|
40
|
+
|
|
41
|
+
| Method | Path | Auth | Permission | Description |
|
|
42
|
+
|--------|------|------|------------|-------------|
|
|
43
|
+
| GET | `/api/v1/notifications` | Required | Own only | List (paginated) |
|
|
44
|
+
| GET | `/api/v1/notifications/unread-count` | Required | Own only | Unread count |
|
|
45
|
+
| PUT | `/api/v1/notifications/:id/read` | Required | Own only | Mark read |
|
|
46
|
+
| PUT | `/api/v1/notifications/read-all` | Required | Own only | Mark all read |
|
|
47
|
+
| DELETE | `/api/v1/notifications/:id` | Required | Own only | Delete single |
|
|
48
|
+
| DELETE | `/api/v1/notifications` | Required | Own only | Clear all |
|
|
49
|
+
| POST | `/api/v1/notifications` | Required | Admin | Create notification |
|
|
50
|
+
|
|
51
|
+
## Notification Types
|
|
52
|
+
|
|
53
|
+
- `success` — Green, operation completed successfully
|
|
54
|
+
- `error` — Red, operation failed
|
|
55
|
+
- `warning` — Orange, attention needed
|
|
56
|
+
- `info` — Blue, informational
|
|
57
|
+
|
|
58
|
+
## Source Types
|
|
59
|
+
|
|
60
|
+
- `system` — Generated by Loom framework
|
|
61
|
+
- `event` — Generated by EventBus subscription
|
|
62
|
+
- `cli` — Created via CLI command
|
|
63
|
+
|
|
64
|
+
## EventBus notify Handler
|
|
65
|
+
|
|
66
|
+
Configure automatic notification generation from events in `loom.config.ts`:
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
export default defineConfig({
|
|
70
|
+
events: {
|
|
71
|
+
subscriptions: [
|
|
72
|
+
{
|
|
73
|
+
pattern: 'data:create:orders',
|
|
74
|
+
handler: 'notify',
|
|
75
|
+
config: {
|
|
76
|
+
type: 'success',
|
|
77
|
+
title: 'New Order Created',
|
|
78
|
+
description: 'Order {{id}} created in orders model',
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
pattern: 'user:login',
|
|
83
|
+
handler: 'notify',
|
|
84
|
+
config: {
|
|
85
|
+
type: 'info',
|
|
86
|
+
title: 'User Logged In',
|
|
87
|
+
broadcastAll: true,
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Config Options
|
|
96
|
+
|
|
97
|
+
| Field | Type | Required | Description |
|
|
98
|
+
|-------|------|----------|-------------|
|
|
99
|
+
| `type` | `'success' \| 'error' \| 'warning' \| 'info'` | Yes | Notification severity |
|
|
100
|
+
| `title` | `string` | Yes | Notification title (supports `{{var}}` interpolation) |
|
|
101
|
+
| `description` | `string` | No | Notification body (supports `{{var}}` interpolation) |
|
|
102
|
+
| `broadcastAll` | `boolean` | No | Broadcast to all users when event has no userId (default: false) |
|
|
103
|
+
|
|
104
|
+
### Interpolation
|
|
105
|
+
|
|
106
|
+
Title and description support `{{var}}` interpolation from event payload:
|
|
107
|
+
- `{{id}}` — Record ID
|
|
108
|
+
- `{{model}}` — Model name
|
|
109
|
+
- Any field from the event payload
|
|
110
|
+
|
|
111
|
+
Missing variables are replaced with empty string.
|
|
112
|
+
|
|
113
|
+
### Behavior
|
|
114
|
+
|
|
115
|
+
- If event has `userId`: notification sent to that user only
|
|
116
|
+
- If event has no `userId` and `broadcastAll: true`: sent to all users (capped at 100)
|
|
117
|
+
- If event has no `userId` and `broadcastAll: false` (default): notification is skipped
|
|
118
|
+
|
|
119
|
+
## Permissions
|
|
120
|
+
|
|
121
|
+
- Users can only read/modify their own notifications
|
|
122
|
+
- Only admin users can create notifications for other users via POST API or `loom notification send`
|
|
123
|
+
- Notifications are auto-pruned after 30 days or when exceeding 500 items
|
|
@@ -63,6 +63,9 @@ loom process add --name "weekly-report" \
|
|
|
63
63
|
--cron "0 9 * * 1" \
|
|
64
64
|
--process "weekly-report" \
|
|
65
65
|
--owner admin
|
|
66
|
+
|
|
67
|
+
# Step 5: Initialize metrics view config (if PROCESS.md has ## Metrics section)
|
|
68
|
+
loom process init-metrics weekly-report
|
|
66
69
|
```
|
|
67
70
|
|
|
68
71
|
### 4. Verify
|
|
@@ -117,6 +120,41 @@ How this process should improve:
|
|
|
117
120
|
- Use `loom data` commands for data operations, not direct file I/O
|
|
118
121
|
- Include error handling in Decision Points
|
|
119
122
|
|
|
123
|
+
## Metrics Definition
|
|
124
|
+
|
|
125
|
+
When defining `## Metrics` in PROCESS.md, follow these guidelines so the system can properly track and visualize them:
|
|
126
|
+
|
|
127
|
+
### Format
|
|
128
|
+
|
|
129
|
+
Each metric should include:
|
|
130
|
+
- **Name**: A clear, concise identifier (e.g., "错题 review 率")
|
|
131
|
+
- **Meaning**: What this metric measures and why it matters
|
|
132
|
+
- **Direction**: Whether the metric should increase, decrease, or approach a target
|
|
133
|
+
- `increasing` = higher is better (e.g., success rate)
|
|
134
|
+
- `decreasing` = lower is better (e.g., error count)
|
|
135
|
+
- `target` = should approach a specific value (e.g., 100% coverage)
|
|
136
|
+
- **Target** (optional): The goal value
|
|
137
|
+
- **Unit** (optional): Measurement unit (e.g., "%", "条", "次")
|
|
138
|
+
|
|
139
|
+
### Example
|
|
140
|
+
|
|
141
|
+
```markdown
|
|
142
|
+
## Metrics
|
|
143
|
+
|
|
144
|
+
- **错题 review 率**: 每次触发后,是否成功将错题写入 review_plans。方向:趋近目标值。目标:100%。单位:%。
|
|
145
|
+
- **错题重复出现率**: 统计相同错误模式的错题数量趋势。方向:越低越好。单位:条。
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### After Registration
|
|
149
|
+
|
|
150
|
+
After registering a full process with `--process`, initialize the metrics view config:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
loom process init-metrics <name>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
This reads the `## Metrics` section and generates dashboard chart configuration. If you modify the metrics later, re-run with `--force` to regenerate.
|
|
157
|
+
|
|
120
158
|
## Common Cron Patterns
|
|
121
159
|
|
|
122
160
|
| Pattern | Schedule |
|
|
@@ -153,6 +153,72 @@ Create PROCESS.md scaffold directory (for full process mode). Called by AI, not
|
|
|
153
153
|
loom process generate daily-report --description "Daily report generator"
|
|
154
154
|
```
|
|
155
155
|
|
|
156
|
+
### `loom process metrics-report <name>`
|
|
157
|
+
|
|
158
|
+
Report a business metric snapshot. Used by AI agent during process execution.
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
# Basic report
|
|
162
|
+
loom process metrics-report my-process --metric-name "成功率" --value 0.95 --unit "%"
|
|
163
|
+
|
|
164
|
+
# With target and dimensions
|
|
165
|
+
loom process metrics-report my-process \
|
|
166
|
+
--metric-name "错题重复率" \
|
|
167
|
+
--value 3 \
|
|
168
|
+
--unit "条" \
|
|
169
|
+
--target 0 \
|
|
170
|
+
--dimensions '{"subject":"数学"}' \
|
|
171
|
+
--run-id $LOOM_RUN_ID
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**Options:**
|
|
175
|
+
| Flag | Required | Description |
|
|
176
|
+
|------|----------|-------------|
|
|
177
|
+
| `--metric-name` | Yes | Human-readable metric name |
|
|
178
|
+
| `--value` | Yes | Numeric metric value |
|
|
179
|
+
| `--run-id` | No | Run ID (defaults to LOOM_RUN_ID env var) |
|
|
180
|
+
| `--timestamp` | No | ISO timestamp (defaults to now) |
|
|
181
|
+
| `--dimensions` | No | Dimension labels as JSON |
|
|
182
|
+
| `--target` | No | Target value for goal-line |
|
|
183
|
+
| `--unit` | No | Unit label (e.g., "%", "条") |
|
|
184
|
+
| `--token` | No | Auth token (or set LOOM_TOKEN) |
|
|
185
|
+
| `--server` | No | Server URL (or set LOOM_SERVER) |
|
|
186
|
+
|
|
187
|
+
### `loom process metrics-set-view-config <name>`
|
|
188
|
+
|
|
189
|
+
Set or update the business metrics view configuration (G2 chart specs).
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
# From JSON string
|
|
193
|
+
loom process metrics-set-view-config my-process --config '{"version":1,"metrics":[...],"charts":[...]}'
|
|
194
|
+
|
|
195
|
+
# From file
|
|
196
|
+
loom process metrics-set-view-config my-process --config @./view-config.json
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
**Options:**
|
|
200
|
+
| Flag | Required | Description |
|
|
201
|
+
|------|----------|-------------|
|
|
202
|
+
| `--config` | Yes | View config JSON (use @file to read from file) |
|
|
203
|
+
| `--token` | No | Auth token (or set LOOM_TOKEN) |
|
|
204
|
+
| `--server` | No | Server URL (or set LOOM_SERVER) |
|
|
205
|
+
|
|
206
|
+
### `loom process init-metrics <name>`
|
|
207
|
+
|
|
208
|
+
Initialize the metrics view config from PROCESS.md's `## Metrics` section. Run after `loom process add`.
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
loom process init-metrics my-process
|
|
212
|
+
loom process init-metrics my-process --force # Overwrite existing config
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Options:**
|
|
216
|
+
| Flag | Required | Description |
|
|
217
|
+
|------|----------|-------------|
|
|
218
|
+
| `--force` | No | Overwrite existing view config |
|
|
219
|
+
| `--token` | No | Auth token (or set LOOM_TOKEN) |
|
|
220
|
+
| `--server` | No | Server URL (or set LOOM_SERVER) |
|
|
221
|
+
|
|
156
222
|
### `loom process export <name>`
|
|
157
223
|
|
|
158
224
|
Export process definition as JSON.
|
|
@@ -208,10 +274,12 @@ When auth is enabled, processes need a service token to operate:
|
|
|
208
274
|
|
|
209
275
|
1. Trigger fires → entry enqueued
|
|
210
276
|
2. Queue slot available → process starts
|
|
211
|
-
3. AI prompt built (PROCESS.md + references + event context)
|
|
212
|
-
4. Claude Code engine executes with timeout
|
|
213
|
-
5.
|
|
214
|
-
6.
|
|
277
|
+
3. AI prompt built (PROCESS.md + references + event context + metrics protocol)
|
|
278
|
+
4. Claude Code engine executes with timeout, env vars injected: LOOM_SERVER, LOOM_PROCESS_NAME, LOOM_RUN_ID
|
|
279
|
+
5. Agent may call `loom process metrics-report` to report business metrics during execution
|
|
280
|
+
6. Result logged to `.loom/process-logs/{name}/{runId}.json`
|
|
281
|
+
7. Metric snapshots stored in `.loom/process-metrics/{name}/metrics.jsonl`
|
|
282
|
+
8. Event emitted: `process:started`, `process:completed`, or `process:failed`
|
|
215
283
|
|
|
216
284
|
## Concurrency
|
|
217
285
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/backend/ai/engine.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAM5F,wCAAwC;AACxC,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,QAAQ,GAAG,cAAc,GAAG,iBAAiB,GAAG,QAAQ,GAAG,cAAc,CAAC;AAEnH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,cAAc,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;AAE3D,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,gBAAgB,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED;;;;;;GAMG;AACH,qBAAa,gBAAiB,YAAW,QAAQ;IAC/C,QAAQ,CAAC,IAAI,iBAAiB;IAE9B,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,eAAe,CAAwC;IAC/D,OAAO,CAAC,MAAM,CAAC,CAAe;gBAElB,OAAO,EAAE,uBAAuB;IAM5C,OAAO,CAAC,GAAG;IAUX;;OAEG;IACI,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,cAAc,CAAC,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/backend/ai/engine.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAM5F,wCAAwC;AACxC,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,QAAQ,GAAG,cAAc,GAAG,iBAAiB,GAAG,QAAQ,GAAG,cAAc,CAAC;AAEnH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,cAAc,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;AAE3D,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,gBAAgB,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED;;;;;;GAMG;AACH,qBAAa,gBAAiB,YAAW,QAAQ;IAC/C,QAAQ,CAAC,IAAI,iBAAiB;IAE9B,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,eAAe,CAAwC;IAC/D,OAAO,CAAC,MAAM,CAAC,CAAe;gBAElB,OAAO,EAAE,uBAAuB;IAM5C,OAAO,CAAC,GAAG;IAUX;;OAEG;IACI,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,cAAc,CAAC,OAAO,CAAC;IA2K5E;;OAEG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAUvC;;OAEG;IACH,OAAO,IAAI,IAAI;CAQhB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAC5C,MAAM,CAQR"}
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
import { spawn } from 'child_process';
|
|
8
8
|
import path from 'path';
|
|
9
9
|
import { parseClaudeOutput } from './output-parser.js';
|
|
10
|
-
/** Default timeout for Claude Code processes (
|
|
11
|
-
const DEFAULT_PROCESS_TIMEOUT_MS =
|
|
10
|
+
/** Default timeout for Claude Code processes (60 minutes) */
|
|
11
|
+
const DEFAULT_PROCESS_TIMEOUT_MS = 3_600_000;
|
|
12
12
|
/**
|
|
13
13
|
* ClaudeCodeEngine - Spawns Claude Code in headless mode
|
|
14
14
|
*
|
|
@@ -93,6 +93,9 @@ export class ClaudeCodeEngine {
|
|
|
93
93
|
...process.env,
|
|
94
94
|
CLAUDE_PLUGIN_ROOT: pluginRoot,
|
|
95
95
|
...(options.userToken ? { LOOM_TOKEN: options.userToken } : {}),
|
|
96
|
+
...(options.serverUrl ? { LOOM_SERVER: options.serverUrl } : {}),
|
|
97
|
+
...(options.processName ? { LOOM_PROCESS_NAME: options.processName } : {}),
|
|
98
|
+
...(options.runId ? { LOOM_RUN_ID: options.runId } : {}),
|
|
96
99
|
},
|
|
97
100
|
});
|
|
98
101
|
// Track active process for cleanup
|
|
@@ -105,12 +108,23 @@ export class ClaudeCodeEngine {
|
|
|
105
108
|
this.log('STDERR', options.sessionId, text.trim());
|
|
106
109
|
});
|
|
107
110
|
// Wait for process completion with timeout
|
|
111
|
+
// Track error separately to prevent unhandled rejection when generator consumer
|
|
112
|
+
// (e.g. SSE route) has already stopped reading due to client disconnect.
|
|
113
|
+
let completionError;
|
|
108
114
|
let timeoutHandle;
|
|
109
|
-
const completionPromise = new Promise((resolve
|
|
115
|
+
const completionPromise = new Promise((resolve) => {
|
|
116
|
+
const fail = (err) => {
|
|
117
|
+
completionError = err;
|
|
118
|
+
// Do NOT reject the promise — this prevents unhandled rejection
|
|
119
|
+
// when the generator consumer (SSE route) has already returned.
|
|
120
|
+
// The error is captured in completionError and yielded as an error chunk.
|
|
121
|
+
resolve();
|
|
122
|
+
};
|
|
110
123
|
timeoutHandle = setTimeout(() => {
|
|
111
124
|
childProcess.kill('SIGTERM');
|
|
112
125
|
setTimeout(() => childProcess.kill('SIGKILL'), 5_000);
|
|
113
|
-
|
|
126
|
+
this.log('PROCESS_EXIT', options.sessionId, `Process timed out after ${timeout}ms`);
|
|
127
|
+
fail(new Error(`Claude Code process timed out after ${timeout}ms`));
|
|
114
128
|
}, timeout);
|
|
115
129
|
childProcess.on('close', (code) => {
|
|
116
130
|
if (timeoutHandle)
|
|
@@ -125,7 +139,7 @@ export class ClaudeCodeEngine {
|
|
|
125
139
|
if (timeoutHandle)
|
|
126
140
|
clearTimeout(timeoutHandle);
|
|
127
141
|
this.activeProcesses.delete(options.sessionId);
|
|
128
|
-
|
|
142
|
+
fail(err);
|
|
129
143
|
});
|
|
130
144
|
});
|
|
131
145
|
// Send prompt via stdin then close
|
|
@@ -163,8 +177,15 @@ export class ClaudeCodeEngine {
|
|
|
163
177
|
error: error instanceof Error ? error.message : String(error),
|
|
164
178
|
};
|
|
165
179
|
}
|
|
166
|
-
// Wait for process completion
|
|
180
|
+
// Wait for process completion (safe — never rejects, error captured in completionError)
|
|
167
181
|
await completionPromise;
|
|
182
|
+
// Yield timeout/exit error if process didn't finish cleanly
|
|
183
|
+
if (completionError) {
|
|
184
|
+
yield {
|
|
185
|
+
type: 'error',
|
|
186
|
+
error: completionError.message,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
168
189
|
yield { type: 'done' };
|
|
169
190
|
}
|
|
170
191
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../src/backend/ai/engine.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,EAAqB,MAAM,eAAe,CAAC;AACzD,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAuB,MAAM,oBAAoB,CAAC;AAE5E,
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../src/backend/ai/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,6 +15,8 @@ export declare function getRequiredLevel(method: string, config: AuthConfig): Au
|
|
|
15
15
|
export declare function resolvePermission(model: string, roleName: string, config: AuthConfig): AuthPermissionLevel;
|
|
16
16
|
/** Check if user level meets required level */
|
|
17
17
|
export declare function hasPermission(userLevel: AuthPermissionLevel, requiredLevel: AuthPermissionLevel): boolean;
|
|
18
|
+
/** Check if a role has admin-level wildcard permission */
|
|
19
|
+
export declare function isAdmin(role: string, config: AuthConfig): boolean;
|
|
18
20
|
/** Extend FastifyRequest with user info */
|
|
19
21
|
declare module 'fastify' {
|
|
20
22
|
interface FastifyRequest {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rbac.d.ts","sourceRoot":"","sources":["../../../src/backend/auth/rbac.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAwB,MAAM,qBAAqB,CAAC;AAoBjG,4FAA4F;AAC5F,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,mBAAmB,CAOxF;AASD,0EAA0E;AAC1E,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,UAAU,GACjB,mBAAmB,CAcrB;AAED,+CAA+C;AAC/C,wBAAgB,aAAa,CAAC,SAAS,EAAE,mBAAmB,EAAE,aAAa,EAAE,mBAAmB,GAAG,OAAO,CAEzG;AAED,2CAA2C;AAC3C,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,cAAc;QACtB,IAAI,CAAC,EAAE;YACL,MAAM,EAAE,MAAM,CAAC;YACf,QAAQ,EAAE,MAAM,CAAC;YACjB,IAAI,EAAE,MAAM,CAAC;YACb,mFAAmF;YACnF,KAAK,CAAC,EAAE,MAAM,CAAC;SAChB,CAAC;KACH;CACF;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,IAGnD,SAAS,cAAc,EAAE,OAAO,YAAY,mBA8D3D"}
|
|
1
|
+
{"version":3,"file":"rbac.d.ts","sourceRoot":"","sources":["../../../src/backend/auth/rbac.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAwB,MAAM,qBAAqB,CAAC;AAoBjG,4FAA4F;AAC5F,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,mBAAmB,CAOxF;AASD,0EAA0E;AAC1E,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,UAAU,GACjB,mBAAmB,CAcrB;AAED,+CAA+C;AAC/C,wBAAgB,aAAa,CAAC,SAAS,EAAE,mBAAmB,EAAE,aAAa,EAAE,mBAAmB,GAAG,OAAO,CAEzG;AAED,0DAA0D;AAC1D,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAEjE;AAED,2CAA2C;AAC3C,OAAO,QAAQ,SAAS,CAAC;IACvB,UAAU,cAAc;QACtB,IAAI,CAAC,EAAE;YACL,MAAM,EAAE,MAAM,CAAC;YACf,QAAQ,EAAE,MAAM,CAAC;YACjB,IAAI,EAAE,MAAM,CAAC;YACb,mFAAmF;YACnF,KAAK,CAAC,EAAE,MAAM,CAAC;SAChB,CAAC;KACH;CACF;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,IAGnD,SAAS,cAAc,EAAE,OAAO,YAAY,mBA8D3D"}
|
|
@@ -58,6 +58,10 @@ export function resolvePermission(model, roleName, config) {
|
|
|
58
58
|
export function hasPermission(userLevel, requiredLevel) {
|
|
59
59
|
return LEVEL_HIERARCHY[userLevel] >= LEVEL_HIERARCHY[requiredLevel];
|
|
60
60
|
}
|
|
61
|
+
/** Check if a role has admin-level wildcard permission */
|
|
62
|
+
export function isAdmin(role, config) {
|
|
63
|
+
return hasPermission(resolvePermission('*', role, config), 'admin');
|
|
64
|
+
}
|
|
61
65
|
export function createAuthMiddleware(options) {
|
|
62
66
|
const { config } = options;
|
|
63
67
|
return async (request, reply) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rbac.js","sourceRoot":"","sources":["../../../src/backend/auth/rbac.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EAAE,WAAW,EAAqB,MAAM,UAAU,CAAC;AAE1D,wDAAwD;AACxD,MAAM,eAAe,GAAwC;IAC3D,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;CACT,CAAC;AAEF,0GAA0G;AAC1G,MAAM,iBAAiB,GAAwC;IAC7D,GAAG,EAAE,MAAM;IACX,IAAI,EAAE,OAAO;IACb,GAAG,EAAE,OAAO;IACZ,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,OAAO;CAChB,CAAC;AAEF,4FAA4F;AAC5F,MAAM,UAAU,gBAAgB,CAAC,MAAc,EAAE,MAAkB;IACjE,MAAM,IAAI,GAAG,iBAAiB,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC;IACjD,mGAAmG;IACnG,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,mBAAmB,KAAK,IAAI,EAAE,CAAC;QACpF,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,sCAAsC;AACtC,MAAM,YAAY,GAAG;IACnB,oBAAoB;IACpB,uBAAuB;IACvB,sBAAsB;CACvB,CAAC;AAEF,0EAA0E;AAC1E,MAAM,UAAU,iBAAiB,CAC/B,KAAa,EACb,QAAgB,EAChB,MAAkB;IAElB,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;IACzD,IAAI,CAAC,IAAI;QAAE,OAAO,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC;IAEnD,kCAAkC;IAClC,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;IAChE,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC,KAAK,CAAC;IAEtC,4BAA4B;IAC5B,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,GAAG,CAAC,CAAC;IACjE,IAAI,YAAY;QAAE,OAAO,YAAY,CAAC,KAAK,CAAC;IAE5C,wCAAwC;IACxC,OAAO,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC;AAC1C,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,aAAa,CAAC,SAA8B,EAAE,aAAkC;IAC9F,OAAO,eAAe,CAAC,SAAS,CAAC,IAAI,eAAe,CAAC,aAAa,CAAC,CAAC;AACtE,CAAC;AAmBD,MAAM,UAAU,oBAAoB,CAAC,OAA8B;IACjE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAE3B,OAAO,KAAK,EAAE,OAAuB,EAAE,KAAmB,EAAE,EAAE;QAC5D,mDAAmD;QACnD,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;YACxB,IAAI,OAAO,CAAC,GAAG,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;YACnC,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,GAAG,GAAG,CAAC;gBAAE,OAAO,IAAI,CAAC;YACpF,OAAO,KAAK,CAAC;QACf,CAAC,CAAC,EAAE,CAAC;YACH,OAAO;QACT,CAAC;QAED,2BAA2B;QAC3B,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC;QACjD,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,yBAAyB,EAAE,CAAC,CAAC;YAC3D,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YAC3C,4CAA4C;YAC5C,IAAK,OAA4C,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBACrE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,8CAA8C,EAAE,CAAC,CAAC;gBAChF,OAAO;YACT,CAAC;YACD,OAAO,CAAC,IAAI,GAAG;gBACb,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,KAAK;aACN,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC,CAAC;YAC5D,OAAO;QACT,CAAC;QAED,8DAA8D;QAC9D,MAAM,KAAK,GAAI,OAAO,CAAC,MAA6C,EAAE,KAAK,CAAC;QAC5E,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAC9B,MAAM,aAAa,GAAG,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAEvD,MAAM,SAAS,GAAG,iBAAiB,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAEtE,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,aAAa,CAAC,EAAE,CAAC;gBAC7C,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;oBACf,MAAM,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM;oBAC5B,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI;oBACxB,KAAK;oBACL,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,QAAQ,EAAE,aAAa;oBACvB,MAAM,EAAE,SAAS;iBAClB,EAAE,yBAAyB,CAAC,CAAC;gBAC9B,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACnB,KAAK,EAAE,0BAA0B;oBACjC,QAAQ,EAAE,aAAa;oBACvB,MAAM,EAAE,SAAS;iBAClB,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;QACH,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"rbac.js","sourceRoot":"","sources":["../../../src/backend/auth/rbac.ts"],"names":[],"mappings":"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"}
|
package/dist/backend/index.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ import { TokenStore } from './auth/token-store.js';
|
|
|
16
16
|
import { EventBus } from './events/event-bus.js';
|
|
17
17
|
import { EventRegistry } from './events/event-registry.js';
|
|
18
18
|
import { ProcessEngine } from './process/engine.js';
|
|
19
|
+
import { NotificationStorage } from './notifications/notification-storage.js';
|
|
19
20
|
export interface LoomServerOptions {
|
|
20
21
|
/** Project root directory containing loom.config.ts */
|
|
21
22
|
projectRoot: string;
|
|
@@ -40,6 +41,7 @@ export declare class LoomServer {
|
|
|
40
41
|
private eventBus?;
|
|
41
42
|
private eventRegistry?;
|
|
42
43
|
private processEngine?;
|
|
44
|
+
private notificationStorage?;
|
|
43
45
|
private projectRoot;
|
|
44
46
|
private options;
|
|
45
47
|
constructor(options: LoomServerOptions);
|
|
@@ -71,6 +73,8 @@ export declare class LoomServer {
|
|
|
71
73
|
getEventRegistry(): EventRegistry | undefined;
|
|
72
74
|
/** Expose process engine for testing */
|
|
73
75
|
getProcessEngine(): ProcessEngine | undefined;
|
|
76
|
+
/** Expose notification storage for testing */
|
|
77
|
+
getNotificationStorage(): NotificationStorage | undefined;
|
|
74
78
|
}
|
|
75
79
|
/**
|
|
76
80
|
* Create and start a LoomServer from a project root
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,OAAO,MAAM,SAAS,CAAC;AAM9B,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAUvD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,OAAO,MAAM,SAAS,CAAC;AAM9B,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAUvD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAI9E,MAAM,WAAW,iBAAiB;IAChC,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,YAAY,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IACrC,kEAAkE;IAClE,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,qEAAqE;IACrE,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,mBAAmB;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,iBAAiB,CAAuB;IAChD,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,SAAS,CAAC,CAAY;IAC9B,OAAO,CAAC,UAAU,CAAC,CAAa;IAChC,OAAO,CAAC,QAAQ,CAAC,CAAW;IAC5B,OAAO,CAAC,aAAa,CAAC,CAAgB;IACtC,OAAO,CAAC,aAAa,CAAC,CAAgB;IACtC,OAAO,CAAC,mBAAmB,CAAC,CAAsB;IAClD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,OAAO,CAAoB;gBAEvB,OAAO,EAAE,iBAAiB;IAKtC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAoSjC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAW3B,0CAA0C;IAC1C,UAAU,IAAI,UAAU,CAAC,OAAO,OAAO,CAAC;IAIxC,gCAAgC;IAChC,SAAS,IAAI,UAAU;IAIvB,iCAAiC;IACjC,UAAU,IAAI,WAAW;IAIzB,oCAAoC;IACpC,YAAY,IAAI,SAAS,GAAG,SAAS;IAIrC,qCAAqC;IACrC,aAAa,IAAI,UAAU,GAAG,SAAS;IAIvC,mCAAmC;IACnC,WAAW,IAAI,QAAQ,GAAG,SAAS;IAInC,wCAAwC;IACxC,gBAAgB,IAAI,aAAa,GAAG,SAAS;IAI7C,wCAAwC;IACxC,gBAAgB,IAAI,aAAa,GAAG,SAAS;IAI7C,8CAA8C;IAC9C,sBAAsB,IAAI,mBAAmB,GAAG,SAAS;CAG1D;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAK1E"}
|
package/dist/backend/index.js
CHANGED
|
@@ -16,7 +16,7 @@ import { createAdapter } from '../adapters/factory.js';
|
|
|
16
16
|
import { ClaudeCodeEngine } from './ai/engine.js';
|
|
17
17
|
import { SessionManager } from './ai/session-manager.js';
|
|
18
18
|
import { AIInteractionLogger } from './observe/index.js';
|
|
19
|
-
import { registerDataRoutes, registerHealthRoute, registerUploadRoutes, registerChatRoutes, registerSkillRoutes, registerAIConfigRoutes, registerAuthRoutes, registerEventRoutes, registerProcessRoutes } from './routes/index.js';
|
|
19
|
+
import { registerDataRoutes, registerHealthRoute, registerUploadRoutes, registerChatRoutes, registerSkillRoutes, registerAIConfigRoutes, registerAuthRoutes, registerEventRoutes, registerProcessRoutes, registerNotificationRoutes } from './routes/index.js';
|
|
20
20
|
import { createAuthMiddleware } from './auth/rbac.js';
|
|
21
21
|
import { issueServiceToken } from './auth/service-token.js';
|
|
22
22
|
import { UserStore } from './auth/user-store.js';
|
|
@@ -26,6 +26,8 @@ import { EventBus } from './events/event-bus.js';
|
|
|
26
26
|
import { EventEmittingAdapter } from './events/event-emitting-adapter.js';
|
|
27
27
|
import { EventRegistry } from './events/event-registry.js';
|
|
28
28
|
import { ProcessEngine } from './process/engine.js';
|
|
29
|
+
import { NotificationStorage } from './notifications/notification-storage.js';
|
|
30
|
+
import { interpolate } from './notifications/interpolate.js';
|
|
29
31
|
export class LoomServer {
|
|
30
32
|
config;
|
|
31
33
|
engine;
|
|
@@ -38,6 +40,7 @@ export class LoomServer {
|
|
|
38
40
|
eventBus;
|
|
39
41
|
eventRegistry;
|
|
40
42
|
processEngine;
|
|
43
|
+
notificationStorage;
|
|
41
44
|
projectRoot;
|
|
42
45
|
options;
|
|
43
46
|
constructor(options) {
|
|
@@ -164,6 +167,16 @@ export class LoomServer {
|
|
|
164
167
|
projectRoot: this.projectRoot,
|
|
165
168
|
modelNames: this.config.data.models.map(m => m.name),
|
|
166
169
|
});
|
|
170
|
+
// Notification system initialization
|
|
171
|
+
this.notificationStorage = new NotificationStorage(this.projectRoot);
|
|
172
|
+
await this.notificationStorage.initialize();
|
|
173
|
+
registerNotificationRoutes(this.fastify, {
|
|
174
|
+
notificationStorage: this.notificationStorage,
|
|
175
|
+
userStore: this.userStore,
|
|
176
|
+
config: this.config.auth,
|
|
177
|
+
});
|
|
178
|
+
// Prune expired notifications every 24 hours
|
|
179
|
+
setInterval(() => { void this.notificationStorage?.prune(); }, 24 * 60 * 60 * 1000);
|
|
167
180
|
}
|
|
168
181
|
// Static file serving in production
|
|
169
182
|
if (serverConfig.staticDir) {
|
|
@@ -206,6 +219,7 @@ export class LoomServer {
|
|
|
206
219
|
eventRegistry: this.eventRegistry,
|
|
207
220
|
authConfig: this.config.auth,
|
|
208
221
|
userStore: this.userStore,
|
|
222
|
+
serverUrl: `http://localhost:${this.config.server?.port || 3000}`,
|
|
209
223
|
});
|
|
210
224
|
await this.processEngine.initialize();
|
|
211
225
|
registerProcessRoutes(this.fastify, {
|
|
@@ -258,6 +272,35 @@ export class LoomServer {
|
|
|
258
272
|
catch { /* fire-and-forget */ }
|
|
259
273
|
});
|
|
260
274
|
}
|
|
275
|
+
else if (sub.handler === 'notify') {
|
|
276
|
+
const ntfCfg = sub.config;
|
|
277
|
+
this.eventBus.on(sub.pattern, (event) => {
|
|
278
|
+
if (event.pattern.startsWith('notification:'))
|
|
279
|
+
return;
|
|
280
|
+
const title = interpolate(ntfCfg.title, event.payload);
|
|
281
|
+
const description = ntfCfg.description
|
|
282
|
+
? interpolate(ntfCfg.description, event.payload) : undefined;
|
|
283
|
+
if (event.userId) {
|
|
284
|
+
void this.notificationStorage.create({
|
|
285
|
+
userId: event.userId, type: ntfCfg.type,
|
|
286
|
+
title, description, source: 'event', eventPattern: event.pattern,
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
else if (ntfCfg.broadcastAll && this.userStore) {
|
|
290
|
+
void (async () => {
|
|
291
|
+
const users = await this.userStore.listUsers();
|
|
292
|
+
const capped = users.slice(0, 100);
|
|
293
|
+
if (users.length > 100) {
|
|
294
|
+
this.fastify.log.warn(`Notification broadcast capped at 100 users (total: ${users.length})`);
|
|
295
|
+
}
|
|
296
|
+
await this.notificationStorage.createBatch(capped.map(u => ({
|
|
297
|
+
userId: u.userId, type: ntfCfg.type,
|
|
298
|
+
title, description, source: 'event', eventPattern: event.pattern,
|
|
299
|
+
})));
|
|
300
|
+
})();
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
}
|
|
261
304
|
}
|
|
262
305
|
}
|
|
263
306
|
// Graceful shutdown handlers
|
|
@@ -327,6 +370,10 @@ export class LoomServer {
|
|
|
327
370
|
getProcessEngine() {
|
|
328
371
|
return this.processEngine;
|
|
329
372
|
}
|
|
373
|
+
/** Expose notification storage for testing */
|
|
374
|
+
getNotificationStorage() {
|
|
375
|
+
return this.notificationStorage;
|
|
376
|
+
}
|
|
330
377
|
}
|
|
331
378
|
/**
|
|
332
379
|
* Create and start a LoomServer from a project root
|