reflectt-node 0.1.14 → 0.1.16
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 +54 -0
- package/defaults/TEAM-ROLES.starter.yaml +87 -0
- package/defaults/lane-templates/ops.json +32 -0
- package/defaults/lane-templates/workflow.json +32 -0
- package/defaults/reviewer-routing.yaml +34 -0
- package/dist/activationEvents.d.ts +7 -1
- package/dist/activationEvents.d.ts.map +1 -1
- package/dist/activationEvents.js +29 -3
- package/dist/activationEvents.js.map +1 -1
- package/dist/activity-stream-normalizer.d.ts +37 -0
- package/dist/activity-stream-normalizer.d.ts.map +1 -0
- package/dist/activity-stream-normalizer.js +101 -0
- package/dist/activity-stream-normalizer.js.map +1 -0
- package/dist/agent-exec-guardrail.d.ts +9 -0
- package/dist/agent-exec-guardrail.d.ts.map +1 -0
- package/dist/agent-exec-guardrail.js +24 -0
- package/dist/agent-exec-guardrail.js.map +1 -0
- package/dist/agent-exec-guardrail.test.d.ts +2 -0
- package/dist/agent-exec-guardrail.test.d.ts.map +1 -0
- package/dist/agent-exec-guardrail.test.js +55 -0
- package/dist/agent-exec-guardrail.test.js.map +1 -0
- package/dist/agent-interface.d.ts +137 -0
- package/dist/agent-interface.d.ts.map +1 -0
- package/dist/agent-interface.js +463 -0
- package/dist/agent-interface.js.map +1 -0
- package/dist/agent-notifications.d.ts +51 -0
- package/dist/agent-notifications.d.ts.map +1 -0
- package/dist/agent-notifications.js +104 -0
- package/dist/agent-notifications.js.map +1 -0
- package/dist/agent-runs.d.ts +31 -7
- package/dist/agent-runs.d.ts.map +1 -1
- package/dist/agent-runs.js +137 -28
- package/dist/agent-runs.js.map +1 -1
- package/dist/artifact-mirror.d.ts.map +1 -1
- package/dist/artifact-mirror.js +4 -1
- package/dist/artifact-mirror.js.map +1 -1
- package/dist/assignment.d.ts.map +1 -1
- package/dist/assignment.js +54 -2
- package/dist/assignment.js.map +1 -1
- package/dist/boardHealthWorker.d.ts.map +1 -1
- package/dist/boardHealthWorker.js +15 -1
- package/dist/boardHealthWorker.js.map +1 -1
- package/dist/canvas-auto-state.d.ts +58 -0
- package/dist/canvas-auto-state.d.ts.map +1 -0
- package/dist/canvas-auto-state.js +89 -0
- package/dist/canvas-auto-state.js.map +1 -0
- package/dist/canvas-routes.d.ts +36 -0
- package/dist/canvas-routes.d.ts.map +1 -0
- package/dist/canvas-routes.js +47 -0
- package/dist/canvas-routes.js.map +1 -0
- package/dist/capability-readiness.d.ts +28 -0
- package/dist/capability-readiness.d.ts.map +1 -0
- package/dist/capability-readiness.js +162 -0
- package/dist/capability-readiness.js.map +1 -0
- package/dist/channels.d.ts.map +1 -1
- package/dist/channels.js +1 -0
- package/dist/channels.js.map +1 -1
- package/dist/cli.js +179 -4
- package/dist/cli.js.map +1 -1
- package/dist/cloud.d.ts +5 -0
- package/dist/cloud.d.ts.map +1 -1
- package/dist/cloud.js +485 -18
- package/dist/cloud.js.map +1 -1
- package/dist/comms-routing-policy.d.ts +31 -0
- package/dist/comms-routing-policy.d.ts.map +1 -0
- package/dist/comms-routing-policy.js +128 -0
- package/dist/comms-routing-policy.js.map +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/continuity-loop.d.ts.map +1 -1
- package/dist/continuity-loop.js +26 -0
- package/dist/continuity-loop.js.map +1 -1
- package/dist/cost-enforcement.d.ts.map +1 -1
- package/dist/cost-enforcement.js +22 -0
- package/dist/cost-enforcement.js.map +1 -1
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +56 -5
- package/dist/db.js.map +1 -1
- package/dist/doctor.js +2 -2
- package/dist/e2e-loop-proof.test.js +11 -1
- package/dist/e2e-loop-proof.test.js.map +1 -1
- package/dist/events.d.ts +4 -2
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +22 -1
- package/dist/events.js.map +1 -1
- package/dist/executionSweeper.d.ts.map +1 -1
- package/dist/executionSweeper.js +155 -0
- package/dist/executionSweeper.js.map +1 -1
- package/dist/health.d.ts +21 -1
- package/dist/health.d.ts.map +1 -1
- package/dist/health.js +164 -19
- package/dist/health.js.map +1 -1
- package/dist/inbox.d.ts +4 -0
- package/dist/inbox.d.ts.map +1 -1
- package/dist/inbox.js +38 -1
- package/dist/inbox.js.map +1 -1
- package/dist/index.js +90 -14
- package/dist/index.js.map +1 -1
- package/dist/insight-auto-tagger.d.ts +58 -0
- package/dist/insight-auto-tagger.d.ts.map +1 -0
- package/dist/insight-auto-tagger.js +331 -0
- package/dist/insight-auto-tagger.js.map +1 -0
- package/dist/insight-task-bridge.d.ts +9 -0
- package/dist/insight-task-bridge.d.ts.map +1 -1
- package/dist/insight-task-bridge.js +43 -7
- package/dist/insight-task-bridge.js.map +1 -1
- package/dist/insights.d.ts +6 -0
- package/dist/insights.d.ts.map +1 -1
- package/dist/insights.js +13 -0
- package/dist/insights.js.map +1 -1
- package/dist/lane-config.d.ts.map +1 -1
- package/dist/lane-config.js +1 -0
- package/dist/lane-config.js.map +1 -1
- package/dist/lane-template-successor.d.ts +13 -0
- package/dist/lane-template-successor.d.ts.map +1 -0
- package/dist/lane-template-successor.js +132 -0
- package/dist/lane-template-successor.js.map +1 -0
- package/dist/local-whisper.d.ts +21 -0
- package/dist/local-whisper.d.ts.map +1 -0
- package/dist/local-whisper.js +137 -0
- package/dist/local-whisper.js.map +1 -0
- package/dist/macos-accessibility.d.ts +50 -0
- package/dist/macos-accessibility.d.ts.map +1 -0
- package/dist/macos-accessibility.js +185 -0
- package/dist/macos-accessibility.js.map +1 -0
- package/dist/manage.d.ts.map +1 -1
- package/dist/manage.js +47 -1
- package/dist/manage.js.map +1 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +123 -0
- package/dist/mcp.js.map +1 -1
- package/dist/notification-worker.d.ts +66 -0
- package/dist/notification-worker.d.ts.map +1 -0
- package/dist/notification-worker.js +232 -0
- package/dist/notification-worker.js.map +1 -0
- package/dist/openclaw-usage-sync.d.ts +28 -0
- package/dist/openclaw-usage-sync.d.ts.map +1 -0
- package/dist/openclaw-usage-sync.js +161 -0
- package/dist/openclaw-usage-sync.js.map +1 -0
- package/dist/policy.js +1 -1
- package/dist/policy.js.map +1 -1
- package/dist/pr-link-reconciler.d.ts +61 -0
- package/dist/pr-link-reconciler.d.ts.map +1 -0
- package/dist/pr-link-reconciler.js +127 -0
- package/dist/pr-link-reconciler.js.map +1 -0
- package/dist/preflight.js +2 -2
- package/dist/presence-narrator.d.ts +52 -0
- package/dist/presence-narrator.d.ts.map +1 -0
- package/dist/presence-narrator.js +193 -0
- package/dist/presence-narrator.js.map +1 -0
- package/dist/presence.d.ts +2 -0
- package/dist/presence.d.ts.map +1 -1
- package/dist/presence.js +23 -3
- package/dist/presence.js.map +1 -1
- package/dist/product-observation-source.d.ts +52 -0
- package/dist/product-observation-source.d.ts.map +1 -0
- package/dist/product-observation-source.js +326 -0
- package/dist/product-observation-source.js.map +1 -0
- package/dist/reflection-automation.d.ts +25 -0
- package/dist/reflection-automation.d.ts.map +1 -1
- package/dist/reflection-automation.js +163 -42
- package/dist/reflection-automation.js.map +1 -1
- package/dist/review-autoclose.d.ts +62 -0
- package/dist/review-autoclose.d.ts.map +1 -0
- package/dist/review-autoclose.js +75 -0
- package/dist/review-autoclose.js.map +1 -0
- package/dist/routing-enforcement.test.js +32 -56
- package/dist/routing-enforcement.test.js.map +1 -1
- package/dist/sentry-webhook.d.ts +69 -0
- package/dist/sentry-webhook.d.ts.map +1 -0
- package/dist/sentry-webhook.js +88 -0
- package/dist/sentry-webhook.js.map +1 -0
- package/dist/sentry.d.ts +29 -0
- package/dist/sentry.d.ts.map +1 -0
- package/dist/sentry.js +86 -0
- package/dist/sentry.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +5130 -233
- package/dist/server.js.map +1 -1
- package/dist/stale-candidate-reconciler.d.ts +69 -0
- package/dist/stale-candidate-reconciler.d.ts.map +1 -0
- package/dist/stale-candidate-reconciler.js +236 -0
- package/dist/stale-candidate-reconciler.js.map +1 -0
- package/dist/system-loop-state.d.ts +1 -1
- package/dist/system-loop-state.d.ts.map +1 -1
- package/dist/system-loop-state.js +1 -0
- package/dist/system-loop-state.js.map +1 -1
- package/dist/taskPrecheck.d.ts.map +1 -1
- package/dist/taskPrecheck.js +47 -2
- package/dist/taskPrecheck.js.map +1 -1
- package/dist/tasks.d.ts.map +1 -1
- package/dist/tasks.js +130 -0
- package/dist/tasks.js.map +1 -1
- package/dist/trust-events.d.ts +61 -0
- package/dist/trust-events.d.ts.map +1 -0
- package/dist/trust-events.js +148 -0
- package/dist/trust-events.js.map +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/usage-tracking.d.ts +6 -0
- package/dist/usage-tracking.d.ts.map +1 -1
- package/dist/usage-tracking.js +14 -0
- package/dist/usage-tracking.js.map +1 -1
- package/dist/voice-sessions.d.ts +51 -0
- package/dist/voice-sessions.d.ts.map +1 -0
- package/dist/voice-sessions.js +143 -0
- package/dist/voice-sessions.js.map +1 -0
- package/dist/workflow-templates.d.ts.map +1 -1
- package/dist/workflow-templates.js +18 -3
- package/dist/workflow-templates.js.map +1 -1
- package/dist/working-contract.d.ts +22 -1
- package/dist/working-contract.d.ts.map +1 -1
- package/dist/working-contract.js +31 -2
- package/dist/working-contract.js.map +1 -1
- package/package.json +4 -4
- package/public/dashboard.js +12 -4
- package/public/docs.md +98 -10
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canvas Routes (Phase 1) — extracted from server.ts
|
|
3
|
+
*
|
|
4
|
+
* Fastify plugin that registers a first batch of /canvas/* endpoints.
|
|
5
|
+
* Each extracted route is replaced with this plugin in server.ts.
|
|
6
|
+
* Remaining routes stay in server.ts for Phase 2+ extraction.
|
|
7
|
+
*
|
|
8
|
+
* Extraction strategy: start with simple, self-contained routes.
|
|
9
|
+
* Complex routes with deep state coupling remain in server.ts.
|
|
10
|
+
*
|
|
11
|
+
* task-1773681272865
|
|
12
|
+
*/
|
|
13
|
+
import type { FastifyInstance } from 'fastify';
|
|
14
|
+
export type CanvasState = 'floor' | 'ambient' | 'thinking' | 'rendering' | 'decision' | 'handoff' | 'urgent' | 'presenting';
|
|
15
|
+
export interface CanvasStateEntry {
|
|
16
|
+
state: CanvasState;
|
|
17
|
+
sensors: string | null;
|
|
18
|
+
payload: unknown;
|
|
19
|
+
updatedAt: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Dependencies injected from server.ts.
|
|
23
|
+
* Each dep is a narrow interface — no coupling to the full module.
|
|
24
|
+
*/
|
|
25
|
+
export interface CanvasRouteDeps {
|
|
26
|
+
canvasSlots: {
|
|
27
|
+
getActive: () => unknown[];
|
|
28
|
+
getAll: () => unknown[];
|
|
29
|
+
getStats: () => unknown;
|
|
30
|
+
};
|
|
31
|
+
getRecentRejections: () => unknown[];
|
|
32
|
+
}
|
|
33
|
+
export declare const CANVAS_STATES: string[];
|
|
34
|
+
export declare const SENSOR_VALUES: string[];
|
|
35
|
+
export declare function canvasReadRoutes(app: FastifyInstance, deps: CanvasRouteDeps): Promise<void>;
|
|
36
|
+
//# sourceMappingURL=canvas-routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas-routes.d.ts","sourceRoot":"","sources":["../src/canvas-routes.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAK9C,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,YAAY,CAAA;AAE3H,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,WAAW,CAAA;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,OAAO,EAAE,OAAO,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE;QACX,SAAS,EAAE,MAAM,OAAO,EAAE,CAAA;QAC1B,MAAM,EAAE,MAAM,OAAO,EAAE,CAAA;QACvB,QAAQ,EAAE,MAAM,OAAO,CAAA;KACxB,CAAA;IACD,mBAAmB,EAAE,MAAM,OAAO,EAAE,CAAA;CACrC;AAID,eAAO,MAAM,aAAa,UAEzB,CAAA;AACD,eAAO,MAAM,aAAa,UAEzB,CAAA;AAID,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,eAAe,iBAsCjF"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) Reflectt AI
|
|
3
|
+
import { emitActivationEvent } from './activationEvents.js';
|
|
4
|
+
// ── Constants (moved from server.ts) ──
|
|
5
|
+
export const CANVAS_STATES = [
|
|
6
|
+
'floor', 'listening', 'thinking', 'rendering', 'ambient', 'decision', 'urgent', 'handoff', 'presenting',
|
|
7
|
+
];
|
|
8
|
+
export const SENSOR_VALUES = [
|
|
9
|
+
'voice_active', 'screen_share', 'camera', 'typing', 'idle', 'scroll', 'hover', 'focus',
|
|
10
|
+
];
|
|
11
|
+
// ── Plugin ──
|
|
12
|
+
export async function canvasReadRoutes(app, deps) {
|
|
13
|
+
// GET /canvas/states — valid state + sensor values (discovery)
|
|
14
|
+
app.get('/canvas/states', async (request) => {
|
|
15
|
+
const query = request.query;
|
|
16
|
+
const userId = typeof query.userId === 'string' && query.userId.trim()
|
|
17
|
+
? query.userId.trim()
|
|
18
|
+
: 'anonymous';
|
|
19
|
+
emitActivationEvent('canvas_opened', userId).catch(() => { });
|
|
20
|
+
return ({
|
|
21
|
+
states: CANVAS_STATES,
|
|
22
|
+
sensors: SENSOR_VALUES,
|
|
23
|
+
schema: {
|
|
24
|
+
state: 'floor | listening | thinking | rendering | ambient | decision | urgent | handoff',
|
|
25
|
+
sensors: 'null | mic | camera | mic+camera (non-dismissable trust indicator)',
|
|
26
|
+
agentId: 'required — which agent is driving the canvas',
|
|
27
|
+
payload: 'optional — text, media, decision, agents, summary',
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
// GET /canvas/slots — current active slots
|
|
32
|
+
app.get('/canvas/slots', async () => {
|
|
33
|
+
return {
|
|
34
|
+
slots: deps.canvasSlots.getActive(),
|
|
35
|
+
stats: deps.canvasSlots.getStats(),
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
// GET /canvas/slots/all — all slots including stale (debug)
|
|
39
|
+
app.get('/canvas/slots/all', async () => {
|
|
40
|
+
return { slots: deps.canvasSlots.getAll() };
|
|
41
|
+
});
|
|
42
|
+
// GET /canvas/rejections — recent render rejections (debug)
|
|
43
|
+
app.get('/canvas/rejections', async () => {
|
|
44
|
+
return { rejections: deps.getRecentRejections() };
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=canvas-routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas-routes.js","sourceRoot":"","sources":["../src/canvas-routes.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,4BAA4B;AAgB5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AA0B3D,yCAAyC;AAEzC,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY;CACxG,CAAA;AACD,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,cAAc,EAAE,cAAc,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO;CACvF,CAAA;AAED,eAAe;AAEf,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,GAAoB,EAAE,IAAqB;IAEhF,+DAA+D;IAC/D,GAAG,CAAC,GAAG,CAAC,gBAAgB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAgC,CAAA;QACtD,MAAM,MAAM,GAAG,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE;YACpE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE;YACrB,CAAC,CAAC,WAAW,CAAA;QACf,mBAAmB,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAC5D,OAAO,CAAC;YACR,MAAM,EAAE,aAAa;YACrB,OAAO,EAAE,aAAa;YACtB,MAAM,EAAE;gBACN,KAAK,EAAE,kFAAkF;gBACzF,OAAO,EAAE,oEAAoE;gBAC7E,OAAO,EAAE,8CAA8C;gBACvD,OAAO,EAAE,mDAAmD;aAC7D;SACF,CAAC,CAAA;IACF,CAAC,CAAC,CAAA;IAEF,2CAA2C;IAC3C,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,KAAK,IAAI,EAAE;QAClC,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE;YACnC,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE;SACnC,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,4DAA4D;IAC5D,GAAG,CAAC,GAAG,CAAC,mBAAmB,EAAE,KAAK,IAAI,EAAE;QACtC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE,CAAA;IAC7C,CAAC,CAAC,CAAA;IAEF,4DAA4D;IAC5D,GAAG,CAAC,GAAG,CAAC,oBAAoB,EAAE,KAAK,IAAI,EAAE;QACvC,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,mBAAmB,EAAE,EAAE,CAAA;IACnD,CAAC,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type ReadinessStatus = 'ready' | 'degraded' | 'not_ready' | 'unknown';
|
|
2
|
+
export interface CapabilityReadiness {
|
|
3
|
+
capability: string;
|
|
4
|
+
status: ReadinessStatus;
|
|
5
|
+
last_success_at: number | null;
|
|
6
|
+
last_error: string | null;
|
|
7
|
+
dependencies: DependencyCheck[];
|
|
8
|
+
hint: string | null;
|
|
9
|
+
}
|
|
10
|
+
export interface DependencyCheck {
|
|
11
|
+
name: string;
|
|
12
|
+
status: 'ok' | 'missing' | 'error';
|
|
13
|
+
detail?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ReadinessReport {
|
|
16
|
+
overall: ReadinessStatus;
|
|
17
|
+
capabilities: CapabilityReadiness[];
|
|
18
|
+
checked_at: number;
|
|
19
|
+
}
|
|
20
|
+
export declare function getCapabilityReadiness(opts: {
|
|
21
|
+
cloudConnected: boolean;
|
|
22
|
+
cloudUrl: string;
|
|
23
|
+
webhooks: Array<{
|
|
24
|
+
provider: string;
|
|
25
|
+
active: boolean;
|
|
26
|
+
}>;
|
|
27
|
+
}): ReadinessReport;
|
|
28
|
+
//# sourceMappingURL=capability-readiness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability-readiness.d.ts","sourceRoot":"","sources":["../src/capability-readiness.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,UAAU,GAAG,WAAW,GAAG,SAAS,CAAA;AAE5E,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,eAAe,CAAA;IACvB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,YAAY,EAAE,eAAe,EAAE,CAAA;IAC/B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,IAAI,GAAG,SAAS,GAAG,OAAO,CAAA;IAClC,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,eAAe,CAAA;IACxB,YAAY,EAAE,mBAAmB,EAAE,CAAA;IACnC,UAAU,EAAE,MAAM,CAAA;CACnB;AAsKD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAC3C,cAAc,EAAE,OAAO,CAAA;IACvB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;CACvD,GAAG,eAAe,CAgBlB"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Capability readiness contract — per-capability status with dependency checks.
|
|
3
|
+
// Powers GET /capabilities/readiness and cloud UI badges.
|
|
4
|
+
// ── Browser ──────────────────────────────────────────────────────────────────
|
|
5
|
+
function checkBrowserReadiness() {
|
|
6
|
+
const deps = [];
|
|
7
|
+
const errors = [];
|
|
8
|
+
// Check if Stagehand package is available
|
|
9
|
+
try {
|
|
10
|
+
require.resolve('@browserbasehq/stagehand');
|
|
11
|
+
deps.push({ name: 'stagehand_package', status: 'ok' });
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
deps.push({ name: 'stagehand_package', status: 'missing', detail: '@browserbasehq/stagehand not installed' });
|
|
15
|
+
errors.push('Stagehand package not installed');
|
|
16
|
+
}
|
|
17
|
+
// Check for ANTHROPIC_API_KEY or OPENAI_API_KEY (required by Stagehand)
|
|
18
|
+
const hasAnthropicKey = !!(process.env.ANTHROPIC_API_KEY);
|
|
19
|
+
const hasOpenAIKey = !!(process.env.OPENAI_API_KEY);
|
|
20
|
+
if (hasAnthropicKey || hasOpenAIKey) {
|
|
21
|
+
deps.push({ name: 'llm_api_key', status: 'ok', detail: hasAnthropicKey ? 'ANTHROPIC_API_KEY set' : 'OPENAI_API_KEY set' });
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
deps.push({ name: 'llm_api_key', status: 'missing', detail: 'ANTHROPIC_API_KEY or OPENAI_API_KEY required for Stagehand' });
|
|
25
|
+
errors.push('LLM API key missing (ANTHROPIC_API_KEY or OPENAI_API_KEY)');
|
|
26
|
+
}
|
|
27
|
+
// Check BROWSERBASE_API_KEY (optional — cloud browser)
|
|
28
|
+
const hasBrowserbaseKey = !!(process.env.BROWSERBASE_API_KEY);
|
|
29
|
+
deps.push({
|
|
30
|
+
name: 'browserbase_api_key',
|
|
31
|
+
status: hasBrowserbaseKey ? 'ok' : 'missing',
|
|
32
|
+
detail: hasBrowserbaseKey ? 'BROWSERBASE_API_KEY set' : 'Optional — uses local browser if absent',
|
|
33
|
+
});
|
|
34
|
+
const status = errors.length === 0 ? 'ready'
|
|
35
|
+
: errors.some(e => e.includes('package')) ? 'not_ready'
|
|
36
|
+
: 'degraded';
|
|
37
|
+
return {
|
|
38
|
+
capability: 'browser',
|
|
39
|
+
status,
|
|
40
|
+
last_success_at: null,
|
|
41
|
+
last_error: errors.length > 0 ? errors[0] : null,
|
|
42
|
+
dependencies: deps,
|
|
43
|
+
hint: status !== 'ready'
|
|
44
|
+
? 'Install @browserbasehq/stagehand and set ANTHROPIC_API_KEY to enable browser automation.'
|
|
45
|
+
: null,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
// ── Email ─────────────────────────────────────────────────────────────────────
|
|
49
|
+
function checkEmailReadiness(cloudConnected, cloudUrl, webhooks) {
|
|
50
|
+
const deps = [];
|
|
51
|
+
const errors = [];
|
|
52
|
+
// Cloud connection required for relay
|
|
53
|
+
deps.push({
|
|
54
|
+
name: 'cloud_connection',
|
|
55
|
+
status: cloudConnected ? 'ok' : 'missing',
|
|
56
|
+
detail: cloudConnected ? `Connected to ${cloudUrl}` : 'Not enrolled with Reflectt Cloud',
|
|
57
|
+
});
|
|
58
|
+
if (!cloudConnected)
|
|
59
|
+
errors.push('Cloud connection required for email relay');
|
|
60
|
+
// Check inbound webhook route (resend)
|
|
61
|
+
const resendWebhook = webhooks.find(w => w.provider === 'resend' && w.active);
|
|
62
|
+
deps.push({
|
|
63
|
+
name: 'inbound_webhook',
|
|
64
|
+
status: resendWebhook ? 'ok' : 'missing',
|
|
65
|
+
detail: resendWebhook ? 'Resend inbound webhook active' : 'No active Resend inbound webhook configured',
|
|
66
|
+
});
|
|
67
|
+
if (!resendWebhook)
|
|
68
|
+
errors.push('Resend inbound webhook not configured — replies will not be received');
|
|
69
|
+
const status = errors.length === 0 ? 'ready'
|
|
70
|
+
: !cloudConnected ? 'not_ready'
|
|
71
|
+
: 'degraded';
|
|
72
|
+
return {
|
|
73
|
+
capability: 'email',
|
|
74
|
+
status,
|
|
75
|
+
last_success_at: null,
|
|
76
|
+
last_error: errors.length > 0 ? errors[0] : null,
|
|
77
|
+
dependencies: deps,
|
|
78
|
+
hint: status !== 'ready'
|
|
79
|
+
? !cloudConnected
|
|
80
|
+
? 'Enroll this host with Reflectt Cloud to enable email relay.'
|
|
81
|
+
: 'Configure a Resend inbound webhook via POST /provisioning/webhooks to receive replies.'
|
|
82
|
+
: null,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
// ── SMS ───────────────────────────────────────────────────────────────────────
|
|
86
|
+
function checkSmsReadiness(cloudConnected, cloudUrl, webhooks) {
|
|
87
|
+
const deps = [];
|
|
88
|
+
const errors = [];
|
|
89
|
+
deps.push({
|
|
90
|
+
name: 'cloud_connection',
|
|
91
|
+
status: cloudConnected ? 'ok' : 'missing',
|
|
92
|
+
detail: cloudConnected ? `Connected to ${cloudUrl}` : 'Not enrolled with Reflectt Cloud',
|
|
93
|
+
});
|
|
94
|
+
if (!cloudConnected)
|
|
95
|
+
errors.push('Cloud connection required for SMS relay');
|
|
96
|
+
// Check for Twilio inbound webhook route
|
|
97
|
+
const twilioWebhook = webhooks.find(w => (w.provider === 'twilio' || w.provider === 'sms') && w.active);
|
|
98
|
+
deps.push({
|
|
99
|
+
name: 'inbound_webhook',
|
|
100
|
+
status: twilioWebhook ? 'ok' : 'missing',
|
|
101
|
+
detail: twilioWebhook ? 'SMS inbound webhook active' : 'No active SMS inbound webhook configured',
|
|
102
|
+
});
|
|
103
|
+
if (!twilioWebhook)
|
|
104
|
+
errors.push('SMS inbound webhook not configured — replies will not be received');
|
|
105
|
+
const status = errors.length === 0 ? 'ready'
|
|
106
|
+
: !cloudConnected ? 'not_ready'
|
|
107
|
+
: 'degraded';
|
|
108
|
+
return {
|
|
109
|
+
capability: 'sms',
|
|
110
|
+
status,
|
|
111
|
+
last_success_at: null,
|
|
112
|
+
last_error: errors.length > 0 ? errors[0] : null,
|
|
113
|
+
dependencies: deps,
|
|
114
|
+
hint: status !== 'ready'
|
|
115
|
+
? !cloudConnected
|
|
116
|
+
? 'Enroll this host with Reflectt Cloud to enable SMS relay.'
|
|
117
|
+
: 'Configure a Twilio inbound webhook via POST /provisioning/webhooks to receive SMS replies.'
|
|
118
|
+
: null,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
// ── Calendar ──────────────────────────────────────────────────────────────────
|
|
122
|
+
function checkCalendarReadiness() {
|
|
123
|
+
const deps = [];
|
|
124
|
+
const errors = [];
|
|
125
|
+
// Calendar is always locally available (no external deps required for basic scheduling)
|
|
126
|
+
deps.push({ name: 'calendar_module', status: 'ok', detail: 'Local calendar storage active' });
|
|
127
|
+
// Optional: Google Calendar sync env var
|
|
128
|
+
const hasGoogleCal = !!(process.env.GOOGLE_CALENDAR_CLIENT_ID && process.env.GOOGLE_CALENDAR_CLIENT_SECRET);
|
|
129
|
+
deps.push({
|
|
130
|
+
name: 'google_calendar_sync',
|
|
131
|
+
status: hasGoogleCal ? 'ok' : 'missing',
|
|
132
|
+
detail: hasGoogleCal
|
|
133
|
+
? 'Google Calendar credentials configured'
|
|
134
|
+
: 'Optional — GOOGLE_CALENDAR_CLIENT_ID + GOOGLE_CALENDAR_CLIENT_SECRET for sync',
|
|
135
|
+
});
|
|
136
|
+
// iCal import is always available
|
|
137
|
+
deps.push({ name: 'ical_import', status: 'ok', detail: 'iCal import/export available' });
|
|
138
|
+
return {
|
|
139
|
+
capability: 'calendar',
|
|
140
|
+
status: errors.length === 0 ? 'ready' : 'degraded',
|
|
141
|
+
last_success_at: null,
|
|
142
|
+
last_error: errors.length > 0 ? errors[0] : null,
|
|
143
|
+
dependencies: deps,
|
|
144
|
+
hint: null,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
// ── Main readiness check ──────────────────────────────────────────────────────
|
|
148
|
+
export function getCapabilityReadiness(opts) {
|
|
149
|
+
const capabilities = [
|
|
150
|
+
checkBrowserReadiness(),
|
|
151
|
+
checkEmailReadiness(opts.cloudConnected, opts.cloudUrl, opts.webhooks),
|
|
152
|
+
checkSmsReadiness(opts.cloudConnected, opts.cloudUrl, opts.webhooks),
|
|
153
|
+
checkCalendarReadiness(),
|
|
154
|
+
];
|
|
155
|
+
// Overall: ready if all ready, degraded if any degraded, not_ready if any not_ready
|
|
156
|
+
const overall = capabilities.some(c => c.status === 'not_ready') ? 'not_ready'
|
|
157
|
+
: capabilities.some(c => c.status === 'degraded') ? 'degraded'
|
|
158
|
+
: capabilities.every(c => c.status === 'ready') ? 'ready'
|
|
159
|
+
: 'unknown';
|
|
160
|
+
return { overall, capabilities, checked_at: Date.now() };
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=capability-readiness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability-readiness.js","sourceRoot":"","sources":["../src/capability-readiness.ts"],"names":[],"mappings":"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"}
|
package/dist/channels.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channels.d.ts","sourceRoot":"","sources":["../src/channels.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;EAUtB,CAAA;AAEV,eAAO,MAAM,qBAAqB,gGAAiD,CAAA;AAEnF,eAAO,MAAM,2BAA2B,
|
|
1
|
+
{"version":3,"file":"channels.d.ts","sourceRoot":"","sources":["../src/channels.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;EAUtB,CAAA;AAEV,eAAO,MAAM,qBAAqB,gGAAiD,CAAA;AAEnF,eAAO,MAAM,2BAA2B,UAQvC,CAAA"}
|
package/dist/channels.js
CHANGED
package/dist/channels.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channels.js","sourceRoot":"","sources":["../src/channels.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,4BAA4B;AAE5B,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;IAClC,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE;IACtC,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE;IACpC,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;IAClC,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE;IACpC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE;IAC1B,wEAAwE;IACxE,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,kBAAkB,EAAE;IAC5C,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE;CAC1B,CAAA;AAEV,MAAM,CAAC,MAAM,qBAAqB,GAAG,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;AAEnF,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,SAAS;IACT,WAAW;IACX,UAAU;IACV,SAAS;IACT,UAAU;IACV,UAAU;CACX,CAAA"}
|
|
1
|
+
{"version":3,"file":"channels.js","sourceRoot":"","sources":["../src/channels.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,4BAA4B;AAE5B,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;IAClC,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE;IACtC,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE;IACpC,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;IAClC,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE;IACpC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE;IAC1B,wEAAwE;IACxE,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,kBAAkB,EAAE;IAC5C,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE;CAC1B,CAAA;AAEV,MAAM,CAAC,MAAM,qBAAqB,GAAG,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;AAEnF,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,SAAS;IACT,QAAQ;IACR,WAAW;IACX,UAAU;IACV,SAAS;IACT,UAAU;IACV,UAAU;CACX,CAAA"}
|
package/dist/cli.js
CHANGED
|
@@ -114,10 +114,105 @@ function buildServerEnv(config) {
|
|
|
114
114
|
}
|
|
115
115
|
return env;
|
|
116
116
|
}
|
|
117
|
-
|
|
117
|
+
/**
|
|
118
|
+
* Check if dist/ is stale compared to src/ (i.e. source files were modified after last build).
|
|
119
|
+
* Returns a warning message if stale, or null if fresh.
|
|
120
|
+
*/
|
|
121
|
+
function checkBuildFreshness() {
|
|
122
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
123
|
+
const projectRoot = join(dirname(__filename), '..');
|
|
124
|
+
const distDir = join(projectRoot, 'dist');
|
|
125
|
+
const srcDir = join(projectRoot, 'src');
|
|
126
|
+
if (!existsSync(distDir)) {
|
|
127
|
+
return `❌ Build output missing: ${distDir} does not exist. Run 'npm run build' before starting.`;
|
|
128
|
+
}
|
|
129
|
+
const distIndex = join(distDir, 'server.js');
|
|
130
|
+
if (!existsSync(distIndex)) {
|
|
131
|
+
return `❌ Build output incomplete: dist/server.js not found. Run 'npm run build' before starting.`;
|
|
132
|
+
}
|
|
133
|
+
try {
|
|
134
|
+
const distMtime = statSync(distIndex).mtimeMs;
|
|
135
|
+
// Check a few key source files — if any are newer than dist, build is stale
|
|
136
|
+
const checkFiles = ['server.ts', 'cli.ts', 'config.ts', 'chat.ts'];
|
|
137
|
+
for (const file of checkFiles) {
|
|
138
|
+
const srcFile = join(srcDir, file);
|
|
139
|
+
if (existsSync(srcFile)) {
|
|
140
|
+
const srcMtime = statSync(srcFile).mtimeMs;
|
|
141
|
+
if (srcMtime > distMtime) {
|
|
142
|
+
return `⚠️ Build may be stale: src/${file} is newer than dist/server.js. Run 'npm run build' to rebuild.`;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
// If stat fails, don't block startup
|
|
149
|
+
}
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Auto-rebuild dist/ when stale or missing.
|
|
154
|
+
* Returns true if rebuild succeeded, false if it failed.
|
|
155
|
+
*/
|
|
156
|
+
function autoRebuild(projectRoot) {
|
|
157
|
+
console.log('🔨 Build is stale or missing — auto-rebuilding...');
|
|
158
|
+
try {
|
|
159
|
+
execSync('npm run build', { cwd: projectRoot, stdio: 'inherit', timeout: 60_000 });
|
|
160
|
+
console.log('✅ Build complete');
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
console.error('❌ Auto-rebuild failed:', err.message);
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function startServerDetached(config, forceTsx = false) {
|
|
118
169
|
const { projectRoot, serverPath, useNode } = getRuntimePaths();
|
|
170
|
+
// --tsx flag: always use tsx, skip dist entirely
|
|
171
|
+
if (forceTsx) {
|
|
172
|
+
const tsxPath = join(projectRoot, 'src', 'index.ts');
|
|
173
|
+
if (!existsSync(tsxPath)) {
|
|
174
|
+
throw new Error(`Source file not found: ${tsxPath}`);
|
|
175
|
+
}
|
|
176
|
+
const child = spawn('npx', ['tsx', tsxPath], {
|
|
177
|
+
env: buildServerEnv(config),
|
|
178
|
+
detached: true,
|
|
179
|
+
stdio: 'ignore',
|
|
180
|
+
cwd: projectRoot,
|
|
181
|
+
});
|
|
182
|
+
child.unref();
|
|
183
|
+
writeFileSync(PID_FILE, String(child.pid));
|
|
184
|
+
return child.pid;
|
|
185
|
+
}
|
|
119
186
|
if (!existsSync(serverPath)) {
|
|
120
|
-
|
|
187
|
+
// Try auto-rebuild before giving up
|
|
188
|
+
if (useNode && autoRebuild(projectRoot)) {
|
|
189
|
+
// Re-check after rebuild
|
|
190
|
+
if (!existsSync(serverPath)) {
|
|
191
|
+
throw new Error(`Server file still not found after rebuild: ${serverPath}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
else if (useNode) {
|
|
195
|
+
throw new Error(`Server file not found: ${serverPath}. Auto-rebuild failed.`);
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
throw new Error(`Server file not found: ${serverPath}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// Check build freshness for compiled mode — auto-rebuild if stale
|
|
202
|
+
if (useNode) {
|
|
203
|
+
const warning = checkBuildFreshness();
|
|
204
|
+
if (warning) {
|
|
205
|
+
if (warning.startsWith('❌') || warning.startsWith('⚠️')) {
|
|
206
|
+
if (!autoRebuild(projectRoot)) {
|
|
207
|
+
console.warn(warning);
|
|
208
|
+
if (warning.startsWith('❌')) {
|
|
209
|
+
throw new Error('Cannot start: build output is missing and auto-rebuild failed.');
|
|
210
|
+
}
|
|
211
|
+
// Stale warning but rebuild failed — continue with stale dist and warn
|
|
212
|
+
console.warn('⚠️ Continuing with potentially stale build');
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
121
216
|
}
|
|
122
217
|
const cmd = useNode ? 'node' : 'npx';
|
|
123
218
|
const args = useNode ? [serverPath] : ['tsx', serverPath];
|
|
@@ -488,6 +583,7 @@ program
|
|
|
488
583
|
.command('start')
|
|
489
584
|
.description('Start the reflectt server')
|
|
490
585
|
.option('-d, --detach', 'Run in background')
|
|
586
|
+
.option('--tsx', 'Use tsx (TypeScript) directly — no build step needed')
|
|
491
587
|
.action(async (options) => {
|
|
492
588
|
if (!existsSync(REFLECTT_HOME)) {
|
|
493
589
|
console.log('📦 First run — initializing reflectt...');
|
|
@@ -545,9 +641,88 @@ program
|
|
|
545
641
|
// Port not responding — safe to start
|
|
546
642
|
}
|
|
547
643
|
const { projectRoot, serverPath, useNode } = getRuntimePaths();
|
|
644
|
+
// --tsx flag: always use tsx, skip dist entirely
|
|
645
|
+
if (options.tsx) {
|
|
646
|
+
const tsxPath = join(projectRoot, 'src', 'index.ts');
|
|
647
|
+
if (!existsSync(tsxPath)) {
|
|
648
|
+
console.error(`❌ Source file not found: ${tsxPath}`);
|
|
649
|
+
console.error(' --tsx requires a source checkout (not an npm install)');
|
|
650
|
+
process.exit(1);
|
|
651
|
+
}
|
|
652
|
+
if (options.detach) {
|
|
653
|
+
const pid = startServerDetached(config, true);
|
|
654
|
+
const clientHost2 = (config.host === '0.0.0.0' || config.host === '::') ? '127.0.0.1' : config.host;
|
|
655
|
+
console.log(`⏳ Starting reflectt server via tsx (PID: ${pid})...`);
|
|
656
|
+
let healthy = false;
|
|
657
|
+
for (let i = 0; i < 20; i++) {
|
|
658
|
+
await new Promise(r => setTimeout(r, 500));
|
|
659
|
+
try {
|
|
660
|
+
const ctrl = new AbortController();
|
|
661
|
+
const t = setTimeout(() => ctrl.abort(), 2000);
|
|
662
|
+
const r = await fetch(`http://${clientHost2}:${config.port}/health`, { signal: ctrl.signal });
|
|
663
|
+
clearTimeout(t);
|
|
664
|
+
if (r.ok) {
|
|
665
|
+
healthy = true;
|
|
666
|
+
break;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
catch { /* not ready */ }
|
|
670
|
+
}
|
|
671
|
+
console.log(healthy ? '✅ Server is running (tsx mode)!' : '⚠️ Server started but not responding yet');
|
|
672
|
+
process.exit(0);
|
|
673
|
+
}
|
|
674
|
+
console.log('🚀 Starting reflectt server (tsx mode — no build step)...');
|
|
675
|
+
const env = buildServerEnv(config);
|
|
676
|
+
const child = spawn('npx', ['tsx', tsxPath], {
|
|
677
|
+
env,
|
|
678
|
+
stdio: 'inherit',
|
|
679
|
+
cwd: projectRoot,
|
|
680
|
+
});
|
|
681
|
+
child.on('exit', (code) => process.exit(code ?? 1));
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
548
684
|
if (!existsSync(serverPath)) {
|
|
549
|
-
|
|
550
|
-
|
|
685
|
+
// Auto-rebuild if dist is missing
|
|
686
|
+
if (useNode) {
|
|
687
|
+
console.log(`Server file not found: ${serverPath}`);
|
|
688
|
+
if (autoRebuild(projectRoot)) {
|
|
689
|
+
if (!existsSync(serverPath)) {
|
|
690
|
+
console.error('❌ Build succeeded but server file still missing');
|
|
691
|
+
process.exit(1);
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
else {
|
|
695
|
+
// Rebuild failed — try tsx fallback if source exists
|
|
696
|
+
const tsxFallback = join(projectRoot, 'src', 'index.ts');
|
|
697
|
+
if (existsSync(tsxFallback)) {
|
|
698
|
+
console.log('💡 Falling back to tsx (source mode)...');
|
|
699
|
+
const env = buildServerEnv(config);
|
|
700
|
+
const child = spawn('npx', ['tsx', tsxFallback], {
|
|
701
|
+
env,
|
|
702
|
+
stdio: 'inherit',
|
|
703
|
+
cwd: projectRoot,
|
|
704
|
+
});
|
|
705
|
+
child.on('exit', (code) => process.exit(code ?? 1));
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
708
|
+
console.error('❌ Cannot start: no dist/ and no src/. Is this a valid reflectt-node checkout?');
|
|
709
|
+
process.exit(1);
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
else {
|
|
713
|
+
console.error(`❌ Server file not found: ${serverPath}`);
|
|
714
|
+
process.exit(1);
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
// Auto-rebuild if stale
|
|
718
|
+
if (useNode) {
|
|
719
|
+
const warning = checkBuildFreshness();
|
|
720
|
+
if (warning && (warning.startsWith('❌') || warning.startsWith('⚠️'))) {
|
|
721
|
+
if (!autoRebuild(projectRoot)) {
|
|
722
|
+
console.warn(warning);
|
|
723
|
+
console.warn('⚠️ Continuing with potentially stale build');
|
|
724
|
+
}
|
|
725
|
+
}
|
|
551
726
|
}
|
|
552
727
|
const env = buildServerEnv(config);
|
|
553
728
|
const cmd = useNode ? 'node' : 'npx';
|