Commit Graph

40 Commits

Author SHA1 Message Date
ec055f6948 fix(infra,cowork): remove broken Cosmos emulator; harden IPC bridge
docker-compose:
  - Drop the cosmos-emulator service block. Both image variants we
    tried were unfit for the prototype: `:vnext-preview` returned
    plain-text PGCosmosError strings that crashed @azure/cosmos at
    JSON.parse, and `:latest` core-dumped under load. The container
    has been Exited(255) for weeks and was blocking depends_on chains.
  - Real Azure Cosmos account `cosmos-mywisprai` (db `bytelyst`,
    West US 2) is now the single source of truth; all services pick
    up COSMOS_ENDPOINT/KEY/DATABASE from `.env` (already mounted via
    `env_file: .env`).
  - extraction-service: drop hardcoded `COSMOS_ENDPOINT=…cosmos-emulator…`,
    `NODE_TLS_REJECT_UNAUTHORIZED=0`, and `depends_on: cosmos-emulator`.
  - cowork-service: same cleanup.

cowork-service IPC bridge:
  - Add `error` listeners to the spawned child's stdin/stdout/stderr.
    Without them, an EPIPE on stdin (child died mid-write) or a
    teardown-time stream error surfaced as an unhandled error and
    crashed vitest after all 140 tests had passed.
  - Removes the only failing recursive test in the workspace.

Test status after this commit:
  - 94 workspace packages, all green
  - cowork-service: 19 passed | 1 skipped (140 tests)
  - platform-service: 131 test files passed
  - extraction-service: 13 test files passed
  - All other packages: passing

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-30 10:27:12 +00:00
Saravanakumar D
fb47d939a7 fix: resolve test failures across workspace
- packages/llm: use nullish coalescing (??) in GeminiProvider constructor
  so explicit empty-string apiKey is not overridden by env var
- dashboards/admin-web,tracker-web: exclude .next/ from vitest test glob
  to prevent Next.js internal test files from being picked up
- services/cowork-service: use platform-safe .kill() instead of SIGTERM
  which is invalid on Windows
- packages/use-keyboard-shortcuts: add @testing-library/react devDep
- scripts/npmrc.template: use https:// for Gitea registry

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-30 00:16:44 -07:00
6978ddb209 chore(cowork-service): type test doubles
Replace cowork-service test any casts with structural test doubles for IPC bridges, Fastify request payloads, and private IPC bridge probes.

Verification: pnpm --filter @lysnrai/cowork-service build; pnpm --filter @lysnrai/cowork-service test; pnpm --filter @lysnrai/cowork-service exec eslint . --ext .ts,.tsx; pnpm lint.
2026-05-04 15:25:43 -07:00
saravanakumardb1
dda74c2d20 feat(cowork-service): POST /api/plugins/reload
Hot-reload the orchestrator's on-disk plugin registry without a
restart. Routes to the reload_plugins Rust IPC method, gated by the
same authz the orchestrator enforces (admin role OR platform-signed
JWT) so a forbidden caller gets a canonical ForbiddenError envelope
instead of a raw IPC error passthrough. The response body is a
ReloadStats { loaded, added, removed, updated, errors } summary,
validated against ReloadResponseSchema before being returned to the
caller.

Tests cover: admin success (200 + envelope), user-without-platform
(403 before IPC), bridge unavailable (400), orchestrator -32003 →
ForbiddenError, other IPC errors → BadRequestError, malformed
orchestrator payloads → BadRequestError.

Phase: 3.1
Verified: pnpm -r typecheck, pnpm --filter @lysnrai/cowork-service {lint,build,test}
(140 passed, 6 new reload tests)
2026-04-16 15:45:42 -07:00
saravanakumardb1
b92aee729f feat(docker): INFRA-gap-01 wire cowork-service into compose stack
Adds cowork-service (port 4009) to docker-compose.yml with healthcheck,
depends_on gates for cosmos-emulator and platform-service, env_file
integration, and Traefik labels. Unblocks Phase 3 ecosystem wiring of
the ByteLyst roadmap.

Also adds the services/cowork-service/Dockerfile that compose builds
from. Pattern mirrors services/mcp-server/Dockerfile but copies the
full workspace in one step rather than enumerating every package.json,
to stay resilient to workspace membership changes. Production stage
runs `node dist/server.js` on :4009 with BusyBox-wget healthcheck
(bundled with node:22-alpine — no apk install required).

.env.example gains a Cowork-Service section documenting:
- ANTHROPIC_API_KEY, RUST_RUNTIME_BIN, RUST_RUNTIME_TIMEOUT_MS
- OLLAMA_URL, OLLAMA_MODELS
- FEATURE_FLAGS_ENABLED
The 13th clawcowork flag telemetry_enabled already ships via COMMON_FLAGS
in services/platform-service/src/modules/flags/seed.ts so seed.ts was not
touched.

Gap: INFRA-gap-01
Verified: docker compose config (YAML validity + env substitution),
          pnpm -r typecheck / lint / build / test (all green),
          docker compose build cowork-service (image built),
          docker compose up -d cowork-service --no-deps --wait (Healthy),
          curl -fsS localhost:4009/health → {"status":"ok","service":"cowork-service",...}.

Note: full-stack `docker compose up cosmos-emulator platform-service
cowork-service --wait` is blocked by a pre-existing issue in
services/platform-service/Dockerfile (react-native-platform-sdk prepare
script fails during pnpm install --frozen-lockfile in the image build).
That is outside W1 scope; cowork-service starts clean on its own and
becomes Healthy when platform-service is available out-of-band.
2026-04-16 13:07:11 -07:00
82a44c249f feat(runtime): add Cowork checkpoint drill-in 2026-04-04 17:29:12 -07:00
59ae0e1943 feat(runtime): add checkpoint artifact id contract 2026-04-04 14:27:26 -07:00
32b46f0625 feat(cowork-service): map enriched checkpoint refs and IPC ids 2026-04-04 13:51:57 -07:00
9aeb9bbd59 feat(runtime): add checkpoint summaries to shared and cowork surfaces 2026-04-04 12:13:46 -07:00
97b731e14f feat(cowork-service): add runtime todo projection 2026-04-04 11:32:46 -07:00
fdf9286e34 fix(audit): preserve source event timestamps 2026-04-04 11:27:21 -07:00
a57b367fe5 feat(cowork-service): prefer canonical audit event ids 2026-04-04 11:19:25 -07:00
ff8c5eb704 fix(runtime): add queued agent run state 2026-04-04 11:11:45 -07:00
b8242b4601 feat(cowork-service): add runtime action log projection 2026-04-04 02:20:19 -07:00
01201f8f56 feat(cowork-service): add runtime task projection 2026-04-04 02:18:47 -07:00
023826e413 feat(cowork-service): add runtime projection routes 2026-04-04 01:52:04 -07:00
6936c007c7 fix(cowork-service): preserve budget policy auth errors 2026-04-03 14:09:52 -07:00
6c2e9a67ca test(cowork-service): skip integration suite without credentials 2026-04-03 13:58:28 -07:00
5c08832a3e feat(cowork-service): H.9 push notification stubs 2026-04-03 13:55:10 -07:00
2f8fe13c43 test(cowork-service): ecosystem integration tests (H.1-H.12) 2026-04-03 13:53:29 -07:00
a7468eaa3f feat(cowork-service): add budget policy proxy routes 2026-04-03 13:48:52 -07:00
be2f29d1b8 feat(cowork-service): add deferred IPC modules 2026-04-03 13:44:13 -07:00
saravanakumardb1
2d70eeeeb0 fix(cowork-service): audit fixes — JWT auth forwarding + temperature:0 falsy bug
Marketplace proxy:
- Forward Authorization header to platform-service for consumer/author
  routes that call requireAuth() — without this, all authenticated
  marketplace endpoints would 401
- Add 2 tests: auth header forwarding + omission when absent
  (100 tests, was 98)

IPC intercept_llm handler:
- Replace || with ?? for temperature and max_tokens — temperature:0
  is a valid value (deterministic) but || treated it as falsy, passing
  undefined to the LLM router instead
2026-04-03 01:32:34 -07:00
saravanakumardb1
bba26f2d5f feat(cowork-service): H.12 marketplace proxy — migrate TO platform marketplace
Add marketplace module that proxies all requests to platform-service's
marketplace module. Replaces the local plugin marketplace (Phase 10)
with the shared ByteLyst platform marketplace.

Endpoints proxied (18 routes):
  Public: browse catalog, listing detail, reviews, featured, categories
  Consumer: install/uninstall, my installs, add review, vote toggle
  Author: create/update/delete listings, my listings, submit, publish

Changes:
- modules/marketplace/types.ts: Zod schemas for query validation
- modules/marketplace/routes.ts: 18 proxy routes with proxyGet/proxyMutate
  helpers, productId injection, x-request-id forwarding
- modules/marketplace/routes.test.ts: 13 tests (public, consumer, author,
  error handling, 502 fallback, query validation)
- server.ts: Register marketplaceRoutes (8th module), fix costUsd type cast
- server.test.ts: Add marketplace mock, update register count 7→8

Test count: 98 (was 85)
2026-04-03 01:26:30 -07:00
saravanakumardb1
d838cd658b feat(cowork-service): IPC LLM interception — Rust runtime delegates LLM calls to multi-provider router
Add reverse-IPC protocol support: Rust runtime can send intercept_llm
requests to cowork-service, which routes them through @bytelyst/llm-router.

Changes:
- ipc-bridge.ts: handleLine now detects incoming requests (has 'method' field)
  vs normal responses. New handleIncoming() + sendResponse() for reverse IPC.
  New onIncomingRequest() to register the handler.
- server.ts: Wires intercept_llm handler — validates messages, calls
  getLlmRouter().chat(), records spend for budget tracking, logs provider/model.
- ipc-bridge.test.ts: 5 new tests for reverse IPC (handler registration,
  routing, error handling, request vs response disambiguation).
- server.test.ts: Updated IPC bridge mock with onIncomingRequest.

Test count: 85 (was 80)
2026-04-03 01:11:34 -07:00
saravanakumardb1
a9d4c63e03 fix(cowork-service): audit proxy missing taskId and tool query param forwarding
AuditQuerySchema now accepts taskId and tool optional fields.
Route forwards them as query params to platform-service GET /audit.
Previously these filters sent by the frontend were silently stripped.
2026-04-03 01:05:56 -07:00
saravanakumardb1
8e12409938 test(cowork-service): integration tests for proxy routes — 80 tests passing
Add test files for all 4 new proxy route modules:
- audit/routes.test.ts (5 tests): query, stats, 502 fallback, non-ok forward
- usage/routes.test.ts (5 tests): summary, check-limits, 502 fallback, non-ok forward
- notifications/routes.test.ts (8 tests): prefs get/put, webhooks CRUD, 502 fallback
- extraction/routes.test.ts (5 tests): extract, models, 502 fallback, non-ok forward

All tests use mocked fetch to verify proxy behavior without real services.
80 tests passing (13 test files), typecheck clean.
2026-04-03 00:13:13 -07:00
saravanakumardb1
62997bb1db feat(cowork-service): H.10 extraction proxy routes + EXTRACTION_SERVICE_URL config
Add extraction proxy routes to cowork-service for hybrid document processing:
- POST /api/extract — proxy to extraction-service POST /extract
- GET /api/extract/models — list available extraction models
- modules/extraction/routes.ts — proxy routes with error handling
- lib/config.ts — add EXTRACTION_SERVICE_URL (default: http://localhost:4005)
- server.ts — register extractionRoutes (7 route modules total)
- server.test.ts — add extraction routes mock, update register count to 7

Hybrid approach: Rust skills server handles local doc processing (PDF/xlsx/docx/pptx)
inside Docker sandbox, extraction-service provides AI-powered entity extraction.

57 tests passing, 9 test files, typecheck clean
2026-04-03 00:04:11 -07:00
saravanakumardb1
88cc18549c feat(cowork-service): H.9 notification + webhook proxy routes
Add notification and webhook management routes to cowork-service:
- GET /api/notifications/prefs — get user notification preferences
- PUT /api/notifications/prefs — update user notification preferences
- GET /api/webhooks — list webhook subscriptions
- POST /api/webhooks — create webhook subscription
- DELETE /api/webhooks/:id — delete webhook subscription
- modules/notifications/routes.ts — proxy routes with error handling
- server.ts — register notificationRoutes (6 route modules total)
- server.test.ts — add notification routes mock, update register count to 6

57 tests passing, 9 test files, typecheck clean
2026-04-03 00:00:14 -07:00
saravanakumardb1
cd5483c95b feat(cowork-service): H.6 usage/budget proxy routes
Add usage query routes to cowork-service that proxy to platform-service:
- GET /api/usage/summary — user's aggregated usage with days filter
- POST /api/usage/check-limits — check if user is within plan limits
- modules/usage/types.ts — UsageSummaryQuerySchema, CheckLimitsSchema (Zod)
- modules/usage/routes.ts — proxy routes with error handling
- server.ts — register usageRoutes (5 route modules total)
- server.test.ts — add usage routes mock, update register count to 5

57 tests passing, 9 test files, typecheck clean
2026-04-02 23:58:14 -07:00
saravanakumardb1
dc27ee9f21 feat(cowork-service): H.5 audit proxy routes — dual-source audit queries
Add audit query routes to cowork-service that proxy to platform-service:
- GET /api/audit — query audit logs with action/category/days/limit/offset filters
- GET /api/audit/stats — aggregated audit stats
- modules/audit/types.ts — AuditQuerySchema (Zod)
- modules/audit/routes.ts — proxy routes with error handling
- server.ts — register auditRoutes
- server.test.ts — add audit routes mock, update register count to 4

57 tests passing, 9 test files, typecheck clean
2026-04-02 23:54:42 -07:00
saravanakumardb1
ca7c3e571e fix(cowork-service): audit H.7 — fix LLM timeout, harden test mocks, add Ollama config
Bug fixes from systematic review of H.7 LLM router wiring:
- lib/llm-router.ts: remove RUST_RUNTIME_TIMEOUT_MS (300s IPC timeout) override
  — let LlmRouter use its built-in 30s default, appropriate for cloud API calls
- server.test.ts: add debug/error to appMock.log — prevents fragile failures
  if any startup path hits those log levels
- server.test.ts: add OLLAMA_URL + OLLAMA_MODELS to config mock

New feature:
- config.ts: add OLLAMA_URL + OLLAMA_MODELS env vars for local Ollama support
- server.ts: wire Ollama env vars into initLlmRouter() — set
  OLLAMA_MODELS=model1,model2 to auto-add local Ollama as a provider

57 tests passing, 9 test files, typecheck clean
2026-04-02 23:37:50 -07:00
saravanakumardb1
f542160784 feat(cowork-service): H.7 — wire @bytelyst/llm-router for multi-model routing
Added LLM routing module to cowork-service:
- lib/llm-router.ts — singleton LlmRouter with cloud + local Ollama support
- modules/llm/types.ts — Zod request schemas
- modules/llm/routes.ts — POST /api/llm/chat, GET /api/llm/providers, GET /api/llm/health
- All endpoints gated by llm_multi_model_enabled feature flag
- Best-effort init: service works without API keys (router stays uninitialized)
- 8 new tests (routes), server test updated for 3 route modules
- 57 total tests passing, typecheck clean
2026-04-02 23:10:07 -07:00
saravanakumardb1
53c3565874 fix(cowork-service): audit flush field name mismatch + server test mock gap
BUG: flush-scheduler.ts flushAudit() read 'events' from IPC response but
Rust handle_flush_audit() returns { count, entries }. Audit events were
silently lost (always empty array). Fixed to read 'entries'.

Also fixed:
- server.test.ts: added missing flush-scheduler.js mock (new import in server.ts)
- feature-flags.ts: doc comment '12 flags' → '13 flags'
- flush-scheduler.test.ts: mock data aligned to Rust response shape

49 tests passing, 8 test files, typecheck clean.
2026-04-02 23:02:38 -07:00
saravanakumardb1
9fc5af5b2b test(cowork-service): platform-client + flush-scheduler tests (17 new tests)
New test files:
- lib/platform-client.test.ts (8 tests): audit posting, telemetry batch,
  usage records, flag polling, error handling, query params
- lib/flush-scheduler.test.ts (9 tests): lifecycle start/stop, flushAll with
  IPC drain → platform-service posting, IPC error handling, empty responses,
  pollAndSyncFlags with local registry + IPC update, failure graceful handling

49 tests passing (was 32), 8 test files, typecheck clean.
2026-04-02 22:53:04 -07:00
saravanakumardb1
f8f3cdc242 feat(cowork-service): platform-client + flush scheduler (H.4-H.8 TS wiring)
New files:
- lib/platform-client.ts — REST client for platform-service endpoints:
  POST /audit, POST /telemetry/events, POST /usage, GET /flags/poll

- lib/flush-scheduler.ts — periodic drain of IPC buffers → platform-service:
  - flushAll(): drains audit, telemetry, budget from Rust IPC → REST
  - pollAndSyncFlags(): GET /flags/poll → update TS registry + push to IPC
  - Singleton pattern with start/stop/finalFlush lifecycle
  - All operations best-effort (logged, never crash service)

Updated server.ts:
- Starts flush scheduler after IPC bridge connects
- finalFlush() before shutdown (drain remaining events)

32 tests passing, typecheck clean.
2026-04-02 22:50:00 -07:00
saravanakumardb1
ff433e172d test(cowork-service): add product-config, feature-flags, health routes tests
New test files (3):
- lib/product-config.test.ts — 3 tests: PRODUCT_ID, productConfig fields, consistency
- lib/feature-flags.test.ts — 3 tests: 13 flag names match seed.ts, defaults correct, setFlag override
- modules/health/routes.test.ts — 2 tests: degraded when IPC disconnected, connected status reporting

32 tests passing (was 24), 6 test files, typecheck clean.
2026-04-02 22:22:59 -07:00
saravanakumardb1
2191427605 fix(cowork-service): 3 bugs — flag names, IPC call guard, health status
BUG 1: feature-flags.ts had 3 wrong flag names + missing 3 from seed.ts
  - Removed: browser_extension_enabled, institutional_knowledge_enabled
  - Renamed: connectors_enabled → mcp_connectors_enabled
  - Added: llm_multi_model_enabled, telemetry_enabled, platform_auth_required
  - Fixed defaults to match seed.ts (marketplace_enabled=true, dispatch_api_enabled=true)
  - Now 13 flags exactly matching platform-service/src/modules/flags/seed.ts

BUG 2: ipc-bridge.ts call() had 'initialize' exemption that allowed null deref
  - If call('initialize') was invoked externally without start(), the guard
    passed but this.child!.stdin!.write() would crash with null dereference
  - During normal start(), child.stdin.writable is true so no exemption needed
  - Removed the method !== 'initialize' exemption

BUG 3: health routes didn't factor IPC bridge into overall health status
  - allOk only checked platform-service reachability
  - Now allOk = depsOk && ipcConnected — service reports 503 when bridge is down
  - IPC bridge disconnection makes health 'degraded' (correct — fallback mode works)

24 tests passing, typecheck clean.
2026-04-02 22:20:52 -07:00
saravanakumardb1
19674c7ef7 feat(cowork-service): ecosystem alignment + IPC bridge to Rust runtime
ECOSYSTEM GAPS CLOSED — cowork-service now matches the pattern used by
all other product backends (FlowMonk, ActionTrail, NoteLett, etc.):

New lib files (6):
- lib/product-config.ts — canonical product identity (PRODUCT_ID, productConfig)
- lib/auth.ts — @bytelyst/fastify-auth createAuthMiddleware
- lib/request-context.ts — getUserId(), getRequestProductId()
- lib/telemetry.ts — @bytelyst/backend-telemetry buffer
- lib/feature-flags.ts — @bytelyst/backend-flags with 12 cowork flags
- lib/ipc-bridge.ts — IpcBridge class: spawn Rust child, JSON-RPC, 13 methods

Updated files:
- lib/config.ts — extends @bytelyst/backend-config baseBackendConfigSchema
- server.ts — JWT context, bootstrap endpoint, IPC startup, graceful shutdown
- modules/tasks/routes.ts — IPC bridge forwarding with in-memory fallback
- modules/health/routes.ts — productId from product-config, IPC status
- package.json — 7 new @bytelyst/* workspace deps

IPC bridge features:
- Spawns cowork-orchestrator --ipc-bridge as child process
- JSON-RPC 2.0 over stdin/stdout (line-delimited)
- 13 convenience methods matching Rust IpcHandler
- Timeout + pending request tracking
- Graceful shutdown with SIGTERM
- Singleton pattern with setIpcBridge() for testing

24 tests passing (was 8), typecheck clean.
2026-04-02 22:14:24 -07:00
saravanakumardb1
a87c533fd3 feat(cowork-service): scaffold Fastify bridge + seed clawcowork feature flags (H.1 + H.2)
H.1: Product registration
- Added 12 clawcowork feature flags to platform-service flags/seed.ts
  (sandbox, plugins, mcp, scheduling, computer_use, parallel_agents,
   marketplace, wasm, llm_multi_model, audit, platform_auth, dispatch_api)

H.2: cowork-service scaffold (services/cowork-service/)
- @lysnrai/cowork-service on port 4009, productId clawcowork
- createServiceApp + startService from @bytelyst/fastify-core
- Modules: health (dependency check), tasks (submit/list/get/cancel)
- Zod-validated config, Swagger, readiness endpoint
- 8 tests passing (1 bootstrap + 7 task routes), typecheck clean
2026-04-02 20:39:22 -07:00