jfl 0.9.0 → 0.9.2
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/README.md +35 -4
- package/dist/commands/context-hub.d.ts.map +1 -1
- package/dist/commands/context-hub.js +118 -2
- package/dist/commands/context-hub.js.map +1 -1
- package/dist/commands/digest.d.ts +6 -0
- package/dist/commands/digest.d.ts.map +1 -1
- package/dist/commands/digest.js +70 -69
- package/dist/commands/digest.js.map +1 -1
- package/dist/commands/eval.d.ts +40 -0
- package/dist/commands/eval.d.ts.map +1 -1
- package/dist/commands/eval.js +8 -8
- package/dist/commands/eval.js.map +1 -1
- package/dist/commands/findings.d.ts +7 -0
- package/dist/commands/findings.d.ts.map +1 -1
- package/dist/commands/findings.js +4 -4
- package/dist/commands/findings.js.map +1 -1
- package/dist/commands/ide.d.ts.map +1 -1
- package/dist/commands/ide.js +25 -2
- package/dist/commands/ide.js.map +1 -1
- package/dist/commands/kanban.js +6 -6
- package/dist/commands/kanban.js.map +1 -1
- package/dist/commands/linear.d.ts.map +1 -1
- package/dist/commands/linear.js +24 -0
- package/dist/commands/linear.js.map +1 -1
- package/dist/commands/pi.d.ts +3 -0
- package/dist/commands/pi.d.ts.map +1 -1
- package/dist/commands/pi.js +19 -0
- package/dist/commands/pi.js.map +1 -1
- package/dist/commands/portfolio.d.ts +5 -0
- package/dist/commands/portfolio.d.ts.map +1 -1
- package/dist/commands/portfolio.js +193 -203
- package/dist/commands/portfolio.js.map +1 -1
- package/dist/commands/predict.d.ts +19 -0
- package/dist/commands/predict.d.ts.map +1 -1
- package/dist/commands/predict.js +4 -4
- package/dist/commands/predict.js.map +1 -1
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +106 -7
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/start.d.ts +25 -0
- package/dist/commands/start.d.ts.map +1 -0
- package/dist/commands/start.js +191 -0
- package/dist/commands/start.js.map +1 -0
- package/dist/commands/tenet-agents.js +2 -2
- package/dist/commands/tenet-agents.js.map +1 -1
- package/dist/commands/tenet-setup.d.ts +2 -1
- package/dist/commands/tenet-setup.d.ts.map +1 -1
- package/dist/commands/tenet-setup.js +22 -18
- package/dist/commands/tenet-setup.js.map +1 -1
- package/dist/commands/viz.d.ts +33 -0
- package/dist/commands/viz.d.ts.map +1 -1
- package/dist/commands/viz.js +9 -9
- package/dist/commands/viz.js.map +1 -1
- package/dist/index.js +97 -43
- package/dist/index.js.map +1 -1
- package/dist/lib/advanced-setup.d.ts +1 -1
- package/dist/lib/advanced-setup.d.ts.map +1 -1
- package/dist/lib/advanced-setup.js +22 -22
- package/dist/lib/advanced-setup.js.map +1 -1
- package/dist/lib/discovery-agent.js +4 -4
- package/dist/lib/discovery-agent.js.map +1 -1
- package/dist/lib/linear-id-map.d.ts.map +1 -1
- package/dist/lib/linear-id-map.js +2 -0
- package/dist/lib/linear-id-map.js.map +1 -1
- package/dist/lib/linear-webhook.d.ts +50 -0
- package/dist/lib/linear-webhook.d.ts.map +1 -0
- package/dist/lib/linear-webhook.js +92 -0
- package/dist/lib/linear-webhook.js.map +1 -0
- package/dist/lib/onboarding.d.ts +1 -1
- package/dist/lib/onboarding.js +14 -14
- package/dist/lib/onboarding.js.map +1 -1
- package/dist/lib/rl-manager.d.ts +1 -1
- package/dist/lib/rl-manager.d.ts.map +1 -1
- package/dist/lib/rl-manager.js +5 -4
- package/dist/lib/rl-manager.js.map +1 -1
- package/dist/lib/setup/starter-intelligence.d.ts +25 -0
- package/dist/lib/setup/starter-intelligence.d.ts.map +1 -0
- package/dist/lib/setup/starter-intelligence.js +309 -0
- package/dist/lib/setup/starter-intelligence.js.map +1 -0
- package/dist/lib/tool-schemas.d.ts +35 -0
- package/dist/lib/tool-schemas.d.ts.map +1 -0
- package/dist/lib/tool-schemas.js +246 -0
- package/dist/lib/tool-schemas.js.map +1 -0
- package/dist/lib/workspace/data-pipeline.d.ts.map +1 -1
- package/dist/lib/workspace/data-pipeline.js +29 -20
- package/dist/lib/workspace/data-pipeline.js.map +1 -1
- package/dist/lib/workspace/engine.d.ts +1 -0
- package/dist/lib/workspace/engine.d.ts.map +1 -1
- package/dist/lib/workspace/engine.js +10 -0
- package/dist/lib/workspace/engine.js.map +1 -1
- package/dist/lib/workspace/surface-registry.d.ts.map +1 -1
- package/dist/lib/workspace/surface-registry.js +5 -0
- package/dist/lib/workspace/surface-registry.js.map +1 -1
- package/dist/lib/workspace/surfaces/sidebar.d.ts.map +1 -1
- package/dist/lib/workspace/surfaces/sidebar.js +5 -1
- package/dist/lib/workspace/surfaces/sidebar.js.map +1 -1
- package/dist/lib/workspace/tmux-adapter.d.ts +8 -5
- package/dist/lib/workspace/tmux-adapter.d.ts.map +1 -1
- package/dist/lib/workspace/tmux-adapter.js +38 -7
- package/dist/lib/workspace/tmux-adapter.js.map +1 -1
- package/dist/lib/workspace/tmux-sidebar.d.ts +14 -0
- package/dist/lib/workspace/tmux-sidebar.d.ts.map +1 -0
- package/dist/lib/workspace/tmux-sidebar.js +230 -0
- package/dist/lib/workspace/tmux-sidebar.js.map +1 -0
- package/dist/mcp/context-hub-mcp.js +7 -1
- package/dist/mcp/context-hub-mcp.js.map +1 -1
- package/dist/types/telemetry.d.ts +1 -0
- package/dist/types/telemetry.d.ts.map +1 -1
- package/dist/utils/jfl-config.d.ts +7 -2
- package/dist/utils/jfl-config.d.ts.map +1 -1
- package/dist/utils/jfl-config.js +14 -4
- package/dist/utils/jfl-config.js.map +1 -1
- package/package.json +1 -1
- package/packages/pi/assets/boot.mp3 +0 -0
- package/packages/pi/extensions/autoresearch.ts +3 -2
- package/packages/pi/extensions/context.ts +29 -66
- package/packages/pi/extensions/eval.ts +2 -1
- package/packages/pi/extensions/hub-tools.ts +267 -0
- package/packages/pi/extensions/hud-tool.ts +230 -69
- package/packages/pi/extensions/index.ts +43 -63
- package/packages/pi/extensions/jfl-resolve.ts +98 -0
- package/packages/pi/extensions/journal.ts +91 -6
- package/packages/pi/extensions/map-bridge.ts +31 -0
- package/packages/pi/extensions/memory-tool.ts +84 -4
- package/packages/pi/extensions/onboarding-v2.ts +367 -399
- package/packages/pi/extensions/peter-parker.ts +2 -1
- package/packages/pi/extensions/policy-head-tool.ts +3 -2
- package/packages/pi/extensions/portfolio-bridge.ts +3 -4
- package/packages/pi/extensions/service-skills.ts +214 -0
- package/packages/pi/extensions/session.ts +91 -15
- package/packages/pi/extensions/stratus-bridge.ts +2 -1
- package/packages/pi/extensions/synopsis-tool.ts +6 -1
- package/packages/pi/extensions/training-buffer-tool.ts +3 -2
- package/packages/pi/extensions/types.ts +2 -0
- package/packages/pi/package.json +3 -1
- package/packages/pi/skills/viz/SKILL.md +204 -0
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<a href="https://www.npmjs.com/package/jfl"><img src="https://img.shields.io/npm/v/jfl.svg" alt="npm version" /></a>
|
|
9
9
|
<a href="https://github.com/402goose/jfl-cli/actions"><img src="https://img.shields.io/github/actions/workflow/status/402goose/jfl-cli/ci.yml?branch=main" alt="CI" /></a>
|
|
10
10
|
<a href="https://github.com/402goose/jfl-cli"><img src="https://img.shields.io/github/stars/402goose/jfl-cli" alt="GitHub stars" /></a>
|
|
11
|
-
<img src="https://img.shields.io/badge/tests-
|
|
11
|
+
<img src="https://img.shields.io/badge/tests-1270%20passing-brightgreen" alt="tests" />
|
|
12
12
|
<a href="https://github.com/402goose/jfl-cli/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT license" /></a>
|
|
13
13
|
</p>
|
|
14
14
|
|
|
@@ -59,7 +59,7 @@ You (or agent) works in a session
|
|
|
59
59
|
| **MAP Event Bus** | Nervous system | Events flow between agents, services, and flows. SSE + WebSocket. |
|
|
60
60
|
| **Flow Engine** | Declarative automation | YAML trigger-action flows: `eval:scored` → auto-merge, `telemetry:insight` → spawn fix. |
|
|
61
61
|
| **Pi Runtime** | Multi-model TUI agent | JFL extension for Pi — full context injection, tools, custom rendering. |
|
|
62
|
-
| **Kanban** | Task board | GitHub Issues-backed cards
|
|
62
|
+
| **Kanban** | Task board | GitHub Issues-backed cards with Linear bidirectional sync. PP picks up and ships autonomously. |
|
|
63
63
|
|
|
64
64
|
---
|
|
65
65
|
|
|
@@ -89,9 +89,12 @@ GTMs are context layers — they never house product code. Services register to
|
|
|
89
89
|
|
|
90
90
|
```bash
|
|
91
91
|
jfl status # Project status
|
|
92
|
+
jfl whoami # Current user, project, and root
|
|
92
93
|
jfl hud # Campaign dashboard
|
|
93
94
|
jfl synopsis [hours] # Work summary
|
|
94
95
|
jfl ask "what did we decide?" # Search memory
|
|
96
|
+
jfl doctor # Health check
|
|
97
|
+
jfl doctor --json # Machine-readable health output (for CI/evals)
|
|
95
98
|
jfl ide # Terminal workspace (tmux/cmux)
|
|
96
99
|
```
|
|
97
100
|
|
|
@@ -111,9 +114,22 @@ jfl eval list # Recent eval entries
|
|
|
111
114
|
jfl eval trajectory -a shadow # Score over time
|
|
112
115
|
jfl peter experiment # Run autonomous improvement cycle
|
|
113
116
|
jfl predict run --proposal "Fix auth" --goal "improve tests"
|
|
117
|
+
jfl train policy-head # Train RL policy head on journal data
|
|
118
|
+
jfl train status # Training pipeline status
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Kanban & Linear
|
|
122
|
+
|
|
123
|
+
```bash
|
|
114
124
|
jfl kanban ls # Task board
|
|
115
125
|
jfl kanban add "Fix the thing" # Add card
|
|
116
126
|
jfl kanban pick --agent cash # Agent picks top card
|
|
127
|
+
jfl kanban bootstrap # Create kanban labels in GitHub repo
|
|
128
|
+
jfl linear sync # Bidirectional GitHub ↔ Linear sync
|
|
129
|
+
jfl linear sync --direction github # Push GitHub state to Linear
|
|
130
|
+
jfl linear sync --direction linear # Pull Linear into GitHub
|
|
131
|
+
jfl linear link # Link repo to Linear project
|
|
132
|
+
jfl linear status # Sync status and config
|
|
117
133
|
```
|
|
118
134
|
|
|
119
135
|
### Services
|
|
@@ -122,6 +138,7 @@ jfl kanban pick --agent cash # Agent picks top card
|
|
|
122
138
|
jfl onboard /path/to/repo # Register a service
|
|
123
139
|
jfl services # Interactive TUI
|
|
124
140
|
jfl services validate --fix # Auto-repair config issues
|
|
141
|
+
jfl ci setup # Deploy eval + review CI workflows
|
|
125
142
|
```
|
|
126
143
|
|
|
127
144
|
### Pi Runtime
|
|
@@ -162,7 +179,21 @@ Agents detect issues, create fixes, and the system auto-merges if eval scores im
|
|
|
162
179
|
| Cost spike | `telemetry:insight` (high) | Create fix PR |
|
|
163
180
|
| Predict first | `peter:pr-proposed` | Stratus prediction gate |
|
|
164
181
|
|
|
165
|
-
**CI closes the loop:** `jfl-eval.yml` runs eval on PP pull requests. `jfl-review.yml` does AI code review. Both post events to Context Hub.
|
|
182
|
+
**CI closes the loop:** `jfl-eval.yml` runs eval on PP pull requests. `jfl-review.yml` does AI code review. Both post events to Context Hub. `jfl ci setup` deploys both workflows to any repo.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Linear Integration
|
|
187
|
+
|
|
188
|
+
JFL syncs GitHub Issues ↔ Linear bidirectionally. When a PR is merged, the linked Linear issue moves to Done automatically.
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
jfl linear link # Connect to your Linear workspace
|
|
192
|
+
jfl linear sync # Full bidirectional sync
|
|
193
|
+
jfl linear sync --direction github --json # CI-friendly output
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
The `linear-sync` GitHub Actions workflow runs on every issue event and on a 30-minute cron for drift correction. PP picks up Linear issues, creates PRs with cross-repo references (`Closes org/repo#N`), and the kanban moves them through `backlog → in-progress → eval → done`.
|
|
166
197
|
|
|
167
198
|
---
|
|
168
199
|
|
|
@@ -207,7 +238,7 @@ git clone https://github.com/402goose/jfl-cli
|
|
|
207
238
|
cd jfl-cli
|
|
208
239
|
npm install
|
|
209
240
|
npm run build
|
|
210
|
-
npm test #
|
|
241
|
+
npm test # 1270 tests
|
|
211
242
|
npm link # Use local build globally
|
|
212
243
|
```
|
|
213
244
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-hub.d.ts","sourceRoot":"","sources":["../../src/commands/context-hub.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"context-hub.d.ts","sourceRoot":"","sources":["../../src/commands/context-hub.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAktFH,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAiBjF;AAkMD,wBAAsB,qBAAqB,CAAC,IAAI,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAiHxF;AAMD,wBAAsB,iBAAiB,CACrC,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,iBA8lBzF"}
|
|
@@ -318,6 +318,74 @@ function readCodeContext(projectRoot, limit = 30) {
|
|
|
318
318
|
}
|
|
319
319
|
return items;
|
|
320
320
|
}
|
|
321
|
+
/**
|
|
322
|
+
* Read GTM content artifacts — drafts, specs, content, scripts.
|
|
323
|
+
* Used instead of code indexing for GTM-type projects.
|
|
324
|
+
*/
|
|
325
|
+
function readGtmContent(projectRoot, limit = 40) {
|
|
326
|
+
const items = [];
|
|
327
|
+
const gtmDirs = [
|
|
328
|
+
{ dir: "content", type: "content" },
|
|
329
|
+
{ dir: "drafts", type: "draft" },
|
|
330
|
+
{ dir: "specs", type: "spec" },
|
|
331
|
+
{ dir: "scripts", type: "script" },
|
|
332
|
+
];
|
|
333
|
+
const mdExtensions = [".md", ".txt"];
|
|
334
|
+
const scriptExtensions = [".sh", ".py", ".mjs", ".js"];
|
|
335
|
+
for (const { dir, type } of gtmDirs) {
|
|
336
|
+
const fullDir = path.join(projectRoot, dir);
|
|
337
|
+
if (!fs.existsSync(fullDir))
|
|
338
|
+
continue;
|
|
339
|
+
function scanDir(d, depth = 0) {
|
|
340
|
+
if (depth > 3 || items.length >= limit)
|
|
341
|
+
return;
|
|
342
|
+
try {
|
|
343
|
+
const entries = fs.readdirSync(d, { withFileTypes: true });
|
|
344
|
+
for (const entry of entries) {
|
|
345
|
+
if (items.length >= limit)
|
|
346
|
+
break;
|
|
347
|
+
if (entry.name.startsWith(".") || entry.name === "node_modules")
|
|
348
|
+
continue;
|
|
349
|
+
const fullPath = path.join(d, entry.name);
|
|
350
|
+
if (entry.isDirectory()) {
|
|
351
|
+
scanDir(fullPath, depth + 1);
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
const isMarkdown = mdExtensions.some(ext => entry.name.endsWith(ext));
|
|
355
|
+
const isScript = type === "script" && scriptExtensions.some(ext => entry.name.endsWith(ext));
|
|
356
|
+
if (isMarkdown || isScript) {
|
|
357
|
+
try {
|
|
358
|
+
const raw = fs.readFileSync(fullPath, "utf-8");
|
|
359
|
+
// Extract first heading + first paragraph as summary
|
|
360
|
+
const lines = raw.split("\n").filter(l => l.trim());
|
|
361
|
+
const heading = lines.find(l => l.startsWith("#"))?.replace(/^#+\s*/, "") || entry.name;
|
|
362
|
+
const bodyLines = lines.filter(l => !l.startsWith("#") && !l.startsWith("---"));
|
|
363
|
+
const summary = bodyLines.slice(0, 5).join(" ").slice(0, 500);
|
|
364
|
+
if (summary.length > 20) {
|
|
365
|
+
items.push({
|
|
366
|
+
source: "content",
|
|
367
|
+
type,
|
|
368
|
+
title: heading,
|
|
369
|
+
content: summary,
|
|
370
|
+
path: fullPath
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
catch {
|
|
375
|
+
// Skip unreadable files
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
catch {
|
|
382
|
+
// Skip unreadable directories
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
scanDir(fullDir);
|
|
386
|
+
}
|
|
387
|
+
return items;
|
|
388
|
+
}
|
|
321
389
|
// ============================================================================
|
|
322
390
|
// Search & Scoring (TF-IDF style)
|
|
323
391
|
// ============================================================================
|
|
@@ -401,11 +469,24 @@ function semanticSearch(items, query) {
|
|
|
401
469
|
// ============================================================================
|
|
402
470
|
// Orchestrator
|
|
403
471
|
// ============================================================================
|
|
472
|
+
function getProjectType(projectRoot) {
|
|
473
|
+
const configPath = path.join(projectRoot, ".jfl", "config.json");
|
|
474
|
+
if (fs.existsSync(configPath)) {
|
|
475
|
+
try {
|
|
476
|
+
const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
477
|
+
return config.type || "standalone";
|
|
478
|
+
}
|
|
479
|
+
catch { }
|
|
480
|
+
}
|
|
481
|
+
return "standalone";
|
|
482
|
+
}
|
|
404
483
|
function getUnifiedContext(projectRoot, query, taskType) {
|
|
405
484
|
const journalItems = readJournalEntries(projectRoot);
|
|
406
485
|
const knowledgeItems = readKnowledgeDocs(projectRoot);
|
|
486
|
+
const projectType = getProjectType(projectRoot);
|
|
407
487
|
const codeItems = readCodeContext(projectRoot);
|
|
408
|
-
|
|
488
|
+
const contentItems = projectType === "gtm" ? readGtmContent(projectRoot) : [];
|
|
489
|
+
let items = [...journalItems, ...knowledgeItems, ...codeItems, ...contentItems];
|
|
409
490
|
// Apply semantic search if query provided
|
|
410
491
|
if (query) {
|
|
411
492
|
items = semanticSearch(items, query);
|
|
@@ -416,6 +497,7 @@ function getUnifiedContext(projectRoot, query, taskType) {
|
|
|
416
497
|
journal: journalItems.length > 0,
|
|
417
498
|
knowledge: knowledgeItems.length > 0,
|
|
418
499
|
code: codeItems.length > 0,
|
|
500
|
+
content: contentItems.length > 0,
|
|
419
501
|
memory: fs.existsSync(path.join(projectRoot, ".jfl", "memory.db")),
|
|
420
502
|
},
|
|
421
503
|
query,
|
|
@@ -476,8 +558,11 @@ async function fetchChildContext(child, endpoint, body) {
|
|
|
476
558
|
async function getPortfolioContext(projectRoot, query, taskType, maxItems) {
|
|
477
559
|
const local = getUnifiedContext(projectRoot, query, taskType);
|
|
478
560
|
const children = getChildHubs(projectRoot);
|
|
479
|
-
if (children.length === 0)
|
|
561
|
+
if (children.length === 0) {
|
|
562
|
+
if (maxItems)
|
|
563
|
+
local.items = local.items.slice(0, maxItems);
|
|
480
564
|
return local;
|
|
565
|
+
}
|
|
481
566
|
const endpoint = query ? "/api/context/search" : "/api/context";
|
|
482
567
|
const body = { maxItems: maxItems || 20 };
|
|
483
568
|
if (query)
|
|
@@ -707,6 +792,7 @@ function createServer(projectRoot, port, eventBus, flowEngine) {
|
|
|
707
792
|
journal_count: context.items.filter(i => i.source === 'journal').length,
|
|
708
793
|
knowledge_count: context.items.filter(i => i.source === 'knowledge').length,
|
|
709
794
|
code_count: context.items.filter(i => i.source === 'code').length,
|
|
795
|
+
content_count: context.items.filter(i => i.source === 'content').length,
|
|
710
796
|
query_length: query ? query.length : 0,
|
|
711
797
|
});
|
|
712
798
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
@@ -2274,6 +2360,36 @@ function createServer(projectRoot, port, eventBus, flowEngine) {
|
|
|
2274
2360
|
}
|
|
2275
2361
|
return;
|
|
2276
2362
|
}
|
|
2363
|
+
// POST /api/webhooks/linear — handle Linear webhook events
|
|
2364
|
+
if (url.pathname === "/api/webhooks/linear" && req.method === "POST") {
|
|
2365
|
+
let body = "";
|
|
2366
|
+
req.on("data", (chunk) => { body += chunk; });
|
|
2367
|
+
req.on("end", async () => {
|
|
2368
|
+
try {
|
|
2369
|
+
const payload = JSON.parse(body || "{}");
|
|
2370
|
+
const { handleLinearWebhook } = await import("../lib/linear-webhook.js");
|
|
2371
|
+
const result = handleLinearWebhook(payload, projectRoot);
|
|
2372
|
+
if (result.handled && eventBus) {
|
|
2373
|
+
eventBus.emit({
|
|
2374
|
+
type: "linear:document-sync",
|
|
2375
|
+
source: "linear-webhook",
|
|
2376
|
+
data: {
|
|
2377
|
+
action: payload.action,
|
|
2378
|
+
documentTitle: payload.data?.title,
|
|
2379
|
+
journalFile: result.journalFile,
|
|
2380
|
+
},
|
|
2381
|
+
});
|
|
2382
|
+
}
|
|
2383
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
2384
|
+
res.end(JSON.stringify(result));
|
|
2385
|
+
}
|
|
2386
|
+
catch (err) {
|
|
2387
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
2388
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
2389
|
+
}
|
|
2390
|
+
});
|
|
2391
|
+
return;
|
|
2392
|
+
}
|
|
2277
2393
|
// 404
|
|
2278
2394
|
res.writeHead(404, { "Content-Type": "application/json" });
|
|
2279
2395
|
res.end(JSON.stringify({ error: "Not found" }));
|