crewly 1.20.276 → 1.20.278

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.
Files changed (59) hide show
  1. package/dist/backend/backend/src/constants.d.ts +85 -0
  2. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  3. package/dist/backend/backend/src/constants.js +85 -0
  4. package/dist/backend/backend/src/constants.js.map +1 -1
  5. package/dist/backend/backend/src/controllers/briefing/briefing.controller.d.ts +23 -0
  6. package/dist/backend/backend/src/controllers/briefing/briefing.controller.d.ts.map +1 -0
  7. package/dist/backend/backend/src/controllers/briefing/briefing.controller.js +79 -0
  8. package/dist/backend/backend/src/controllers/briefing/briefing.controller.js.map +1 -0
  9. package/dist/backend/backend/src/controllers/talk/talk-live-token.controller.d.ts +34 -0
  10. package/dist/backend/backend/src/controllers/talk/talk-live-token.controller.d.ts.map +1 -0
  11. package/dist/backend/backend/src/controllers/talk/talk-live-token.controller.js +72 -0
  12. package/dist/backend/backend/src/controllers/talk/talk-live-token.controller.js.map +1 -0
  13. package/dist/backend/backend/src/index.d.ts.map +1 -1
  14. package/dist/backend/backend/src/index.js +69 -1
  15. package/dist/backend/backend/src/index.js.map +1 -1
  16. package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
  17. package/dist/backend/backend/src/routes/api.routes.js +6 -0
  18. package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
  19. package/dist/backend/backend/src/services/briefing/briefing-state.store.d.ts +45 -0
  20. package/dist/backend/backend/src/services/briefing/briefing-state.store.d.ts.map +1 -0
  21. package/dist/backend/backend/src/services/briefing/briefing-state.store.js +93 -0
  22. package/dist/backend/backend/src/services/briefing/briefing-state.store.js.map +1 -0
  23. package/dist/backend/backend/src/services/briefing/briefing.service.d.ts +214 -0
  24. package/dist/backend/backend/src/services/briefing/briefing.service.d.ts.map +1 -0
  25. package/dist/backend/backend/src/services/briefing/briefing.service.js +585 -0
  26. package/dist/backend/backend/src/services/briefing/briefing.service.js.map +1 -0
  27. package/dist/backend/backend/src/services/briefing/briefing.types.d.ts +172 -0
  28. package/dist/backend/backend/src/services/briefing/briefing.types.d.ts.map +1 -0
  29. package/dist/backend/backend/src/services/briefing/briefing.types.js +27 -0
  30. package/dist/backend/backend/src/services/briefing/briefing.types.js.map +1 -0
  31. package/dist/backend/backend/src/services/briefing/briefing.utils.d.ts +71 -0
  32. package/dist/backend/backend/src/services/briefing/briefing.utils.d.ts.map +1 -0
  33. package/dist/backend/backend/src/services/briefing/briefing.utils.js +134 -0
  34. package/dist/backend/backend/src/services/briefing/briefing.utils.js.map +1 -0
  35. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.d.ts.map +1 -1
  36. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js +8 -0
  37. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js.map +1 -1
  38. package/dist/backend/backend/src/services/decisions/decision.service.d.ts +14 -1
  39. package/dist/backend/backend/src/services/decisions/decision.service.d.ts.map +1 -1
  40. package/dist/backend/backend/src/services/decisions/decision.service.js +24 -2
  41. package/dist/backend/backend/src/services/decisions/decision.service.js.map +1 -1
  42. package/dist/backend/backend/src/services/talk/talk-live-token.service.d.ts +166 -0
  43. package/dist/backend/backend/src/services/talk/talk-live-token.service.d.ts.map +1 -0
  44. package/dist/backend/backend/src/services/talk/talk-live-token.service.js +287 -0
  45. package/dist/backend/backend/src/services/talk/talk-live-token.service.js.map +1 -0
  46. package/dist/backend/backend/src/types/decision.types.d.ts +3 -3
  47. package/dist/backend/backend/src/types/decision.types.d.ts.map +1 -1
  48. package/dist/backend/build-info.json +2 -2
  49. package/dist/cli/backend/src/constants.d.ts +85 -0
  50. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  51. package/dist/cli/backend/src/constants.js +85 -0
  52. package/dist/cli/backend/src/constants.js.map +1 -1
  53. package/dist/cli/backend/src/services/decisions/decision.service.d.ts +14 -1
  54. package/dist/cli/backend/src/services/decisions/decision.service.d.ts.map +1 -1
  55. package/dist/cli/backend/src/services/decisions/decision.service.js +24 -2
  56. package/dist/cli/backend/src/services/decisions/decision.service.js.map +1 -1
  57. package/dist/cli/backend/src/types/decision.types.d.ts +3 -3
  58. package/dist/cli/backend/src/types/decision.types.d.ts.map +1 -1
  59. package/package.json +1 -1
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Drive mode briefing API (specs/2026-10-08-drive-mode.md), mounted at
3
+ * `/api/briefing` and reached from the portal over the relay.
4
+ *
5
+ * - `GET /` — the owner's queue, ordered by urgency then age
6
+ * - `POST /:id/answer` — `{ optionKey? , text?, confirm?, confirmToken? }`
7
+ * - `POST /:id/skip` — `{ dismiss? }` — next (hide for a while) / drop it
8
+ * - `POST /:id/later` — `{ at?: ISO }` — remind later (default tomorrow morning)
9
+ * - `POST /:id/ask` — `{ question }` — hand a follow-up to the agent
10
+ *
11
+ * Owner only: an agent gets 403, a caller without an owner credential 401.
12
+ * Nothing the owner says is logged.
13
+ *
14
+ * @module controllers/briefing/briefing.controller
15
+ */
16
+ import { Router } from 'express';
17
+ import { BRIEFING_CONSTANTS } from '../../constants.js';
18
+ import { rejectNonOwner } from '../../middleware/caller-identity.middleware.js';
19
+ import { BriefingError } from '../../services/briefing/briefing.types.js';
20
+ import { getBriefingService } from '../../services/briefing/briefing.service.js';
21
+ const C = BRIEFING_CONSTANTS;
22
+ /**
23
+ * Run an owner-only handler and map its errors.
24
+ *
25
+ * @param req - Request
26
+ * @param res - Response
27
+ * @param fn - Handler given the running service
28
+ */
29
+ async function handle(req, res, fn) {
30
+ if (rejectNonOwner(req, res, { success: false, code: C.CODES.OWNER_ONLY, error: 'Only the owner can use Drive mode.' }))
31
+ return;
32
+ const service = getBriefingService();
33
+ if (!service) {
34
+ res.status(503).json({ success: false, code: C.CODES.NOT_READY, error: 'Drive mode is not ready yet — Crewly is still starting.' });
35
+ return;
36
+ }
37
+ try {
38
+ res.json({ success: true, data: await fn(service) });
39
+ }
40
+ catch (error) {
41
+ if (error instanceof BriefingError) {
42
+ res.status(error.status).json({ success: false, code: error.code, error: error.message });
43
+ return;
44
+ }
45
+ res.status(500).json({ success: false, code: C.CODES.FAILED, error: 'That did not work.' });
46
+ }
47
+ }
48
+ /**
49
+ * The request body as an object.
50
+ *
51
+ * @param req - Request
52
+ * @returns Body
53
+ */
54
+ function body(req) {
55
+ return req.body && typeof req.body === 'object' ? req.body : {};
56
+ }
57
+ /**
58
+ * Create the briefing router.
59
+ *
60
+ * @returns Express router
61
+ */
62
+ export function createBriefingRouter() {
63
+ const router = Router();
64
+ router.get('/', (req, res) => handle(req, res, (s) => s.queue()));
65
+ router.post('/:id/answer', (req, res) => handle(req, res, (s) => {
66
+ const b = body(req);
67
+ return s.answer(req.params.id, {
68
+ optionKey: b.optionKey,
69
+ text: b.text,
70
+ confirm: b.confirm === true,
71
+ confirmToken: b.confirmToken,
72
+ });
73
+ }));
74
+ router.post('/:id/skip', (req, res) => handle(req, res, (s) => s.skip(req.params.id, { dismiss: body(req).dismiss === true })));
75
+ router.post('/:id/later', (req, res) => handle(req, res, (s) => s.later(req.params.id, { at: body(req).at })));
76
+ router.post('/:id/ask', (req, res) => handle(req, res, (s) => s.ask(req.params.id, body(req).question)));
77
+ return router;
78
+ }
79
+ //# sourceMappingURL=briefing.controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"briefing.controller.js","sourceRoot":"","sources":["../../../../../../backend/src/controllers/briefing/briefing.controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Drive mode voice token (specs/2026-10-08-drive-mode.md §3), mounted at
3
+ * `/api/talk/live-token` and reached from the portal over the relay.
4
+ *
5
+ * - `GET /status` — `{ hasKey, model }` (no network)
6
+ * - `POST /` — `{ language? }` → a Gemini Live ephemeral token locked to the briefer
7
+ *
8
+ * Owner only: an agent gets 403, a caller without an owner credential 401.
9
+ * The API key never leaves this machine; the token is never logged.
10
+ *
11
+ * @module controllers/talk/talk-live-token.controller
12
+ */
13
+ import { Router, type Request, type Response } from 'express';
14
+ /**
15
+ * GET /api/talk/live-token/status
16
+ *
17
+ * @param req - Request
18
+ * @param res - Response
19
+ */
20
+ export declare function getLiveTokenStatus(req: Request, res: Response): void;
21
+ /**
22
+ * POST /api/talk/live-token — mint one token.
23
+ *
24
+ * @param req - Request (`{ language? }`)
25
+ * @param res - Response
26
+ */
27
+ export declare function mintLiveToken(req: Request, res: Response): Promise<void>;
28
+ /**
29
+ * Create the live-token router.
30
+ *
31
+ * @returns Express router
32
+ */
33
+ export declare function createTalkLiveTokenRouter(): Router;
34
+ //# sourceMappingURL=talk-live-token.controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"talk-live-token.controller.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/controllers/talk/talk-live-token.controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,MAAM,EAAE,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAC;AAkB9D;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI,CAIpE;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAY9E;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAKlD"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Drive mode voice token (specs/2026-10-08-drive-mode.md §3), mounted at
3
+ * `/api/talk/live-token` and reached from the portal over the relay.
4
+ *
5
+ * - `GET /status` — `{ hasKey, model }` (no network)
6
+ * - `POST /` — `{ language? }` → a Gemini Live ephemeral token locked to the briefer
7
+ *
8
+ * Owner only: an agent gets 403, a caller without an owner credential 401.
9
+ * The API key never leaves this machine; the token is never logged.
10
+ *
11
+ * @module controllers/talk/talk-live-token.controller
12
+ */
13
+ import { Router } from 'express';
14
+ import { TALK_LIVE_CONSTANTS } from '../../constants.js';
15
+ import { rejectNonOwner } from '../../middleware/caller-identity.middleware.js';
16
+ import { getTalkLiveTokenService, parseLiveLanguage, TalkLiveTokenError } from '../../services/talk/talk-live-token.service.js';
17
+ const C = TALK_LIVE_CONSTANTS;
18
+ /**
19
+ * Refuse callers that are not the owner.
20
+ *
21
+ * @param req - Request
22
+ * @param res - Response
23
+ * @returns True when refused (response written)
24
+ */
25
+ function refuseNonOwner(req, res) {
26
+ return rejectNonOwner(req, res, { success: false, code: C.CODES.OWNER_ONLY, error: 'Only the owner can use Drive mode.' });
27
+ }
28
+ /**
29
+ * GET /api/talk/live-token/status
30
+ *
31
+ * @param req - Request
32
+ * @param res - Response
33
+ */
34
+ export function getLiveTokenStatus(req, res) {
35
+ if (refuseNonOwner(req, res))
36
+ return;
37
+ const service = getTalkLiveTokenService();
38
+ res.json({ success: true, data: { hasKey: service.hasKey(), model: service.buildSetup(C.DEFAULT_LANGUAGE).model.replace(/^models\//, '') } });
39
+ }
40
+ /**
41
+ * POST /api/talk/live-token — mint one token.
42
+ *
43
+ * @param req - Request (`{ language? }`)
44
+ * @param res - Response
45
+ */
46
+ export async function mintLiveToken(req, res) {
47
+ if (refuseNonOwner(req, res))
48
+ return;
49
+ const language = parseLiveLanguage((req.body ?? {}).language);
50
+ try {
51
+ res.json({ success: true, data: await getTalkLiveTokenService().mint(language) });
52
+ }
53
+ catch (error) {
54
+ if (error instanceof TalkLiveTokenError) {
55
+ res.status(error.status).json({ success: false, code: error.code, error: error.message });
56
+ return;
57
+ }
58
+ res.status(500).json({ success: false, code: C.CODES.FAILED, error: 'Could not start the voice session.' });
59
+ }
60
+ }
61
+ /**
62
+ * Create the live-token router.
63
+ *
64
+ * @returns Express router
65
+ */
66
+ export function createTalkLiveTokenRouter() {
67
+ const router = Router();
68
+ router.get('/status', getLiveTokenStatus);
69
+ router.post('/', mintLiveToken);
70
+ return router;
71
+ }
72
+ //# sourceMappingURL=talk-live-token.controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"talk-live-token.controller.js","sourceRoot":"","sources":["../../../../../../backend/src/controllers/talk/talk-live-token.controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,MAAM,EAA+B,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,gDAAgD,CAAC;AAChF,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,gDAAgD,CAAC;AAEhI,MAAM,CAAC,GAAG,mBAAmB,CAAC;AAE9B;;;;;;GAMG;AACH,SAAS,cAAc,CAAC,GAAY,EAAE,GAAa;IAClD,OAAO,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,EAAE,oCAAoC,EAAE,CAAC,CAAC;AAC5H,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAY,EAAE,GAAa;IAC7D,IAAI,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC;QAAE,OAAO;IACrC,MAAM,OAAO,GAAG,uBAAuB,EAAE,CAAC;IAC1C,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;AAC/I,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAY,EAAE,GAAa;IAC9D,IAAI,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC;QAAE,OAAO;IACrC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC9D,IAAI,CAAC;QACJ,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,uBAAuB,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACnF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,IAAI,KAAK,YAAY,kBAAkB,EAAE,CAAC;YACzC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC1F,OAAO;QACR,CAAC;QACD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,oCAAoC,EAAE,CAAC,CAAC;IAC7G,CAAC;AACF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB;IACxC,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;IAC1C,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IAChC,OAAO,MAAM,CAAC;AACf,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../backend/src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../backend/src/index.ts"],"names":[],"mappings":"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"}
@@ -76,7 +76,8 @@ import { parseInboundOrigin } from './services/orc/orc-reply-route.service.js';
76
76
  import { parseSlackThreadKey } from './services/slack/slack-thread-key.js';
77
77
  import { LIVENESS_MONITOR_CONSTANTS, INPUT_CIRCUIT_CONSTANTS, INPUT_BLOCKED_RETRY_CONSTANTS } from './constants.js';
78
78
  import { InputBlockedRetryService } from './services/messaging/input-blocked-retry.service.js';
79
- import { SUB_AGENT_QUEUE_CONSTANTS, CHAT_CONTEXT_CONSTANTS, SAFE_RESTART, AUTO_UPDATE_CONSTANTS, PROCESS_EXIT_CODES, CLAUDE_STARTUP_CONSTANTS, WEB_CONSTANTS, TICKET_CONSTANTS, UNASSIGNED_ROUTE_CONSTANTS, CLOUD_TALK_CONSTANTS, STANDING_ANSWERS_CONSTANTS, TICKET_AUTOPILOT_CONSTANTS, EXPERIMENT_CONSTANTS, WORK_ITEM_DESTINATION_CONSTANTS, CODEX_USAGE_SYNC_CONSTANTS, ANTIGRAVITY_USAGE_SYNC_CONSTANTS, OWNER_AUTH_CONSTANTS, CREWLY_APPS_CONSTANTS } from './constants.js';
79
+ import { SUB_AGENT_QUEUE_CONSTANTS, CHAT_CONTEXT_CONSTANTS, SAFE_RESTART, AUTO_UPDATE_CONSTANTS, PROCESS_EXIT_CODES, CLAUDE_STARTUP_CONSTANTS, WEB_CONSTANTS, TICKET_CONSTANTS, UNASSIGNED_ROUTE_CONSTANTS, CLOUD_TALK_CONSTANTS, STANDING_ANSWERS_CONSTANTS, TICKET_AUTOPILOT_CONSTANTS, EXPERIMENT_CONSTANTS, WORK_ITEM_DESTINATION_CONSTANTS, CODEX_USAGE_SYNC_CONSTANTS, ANTIGRAVITY_USAGE_SYNC_CONSTANTS, OWNER_AUTH_CONSTANTS, CREWLY_APPS_CONSTANTS, SLACK_AGENT_DM_CONSTANTS, BRIEFING_CONSTANTS } from './constants.js';
80
+ import { randomUUID } from 'crypto';
80
81
  import { PtyActivityTrackerService } from './services/agent/pty-activity-tracker.service.js';
81
82
  import { InFlightTurnTracker } from './services/restart/in-flight-turn-tracker.service.js';
82
83
  import { TicketIntakeService, setTicketIntakeService, resolveTicketIdForSession, } from './services/v3/ticket-intake.service.js';
@@ -2437,6 +2438,73 @@ export class CrewlyServer {
2437
2438
  // this holder at request time, so it picks up broadcast +
2438
2439
  // dispatch without a re-mount.
2439
2440
  setChatV2RealtimeDeps({ gateway: chatGateway, dispatcher: chatDispatcher });
2441
+ // Drive mode briefing (specs/2026-10-08-drive-mode.md): the owner's
2442
+ // queue across agents for the phone's voice briefer. Answers reuse the
2443
+ // existing paths — the decision service, the agent's conversation (a
2444
+ // Talk-style owner turn tagged voice) and the ticket review.
2445
+ try {
2446
+ const [{ BriefingService, setBriefingService }, { BriefingStateStore }, { DecisionService }, { OpenItemsService }, { getTicketIntakeService }, { getTicketReviewService }, { buildAgentRoster }, { intakeChatV2OwnerMessage },] = await Promise.all([
2447
+ import('./services/briefing/briefing.service.js'),
2448
+ import('./services/briefing/briefing-state.store.js'),
2449
+ import('./services/decisions/decision.service.js'),
2450
+ import('./services/open-items/open-items.service.js'),
2451
+ import('./services/v3/ticket-intake.service.js'),
2452
+ import('./services/v3/ticket-review.service.js'),
2453
+ import('./services/cloud/agent-roster.utils.js'),
2454
+ import('./services/v3/ticket-channel-hooks.js'),
2455
+ ]);
2456
+ const owner = { userId: SLACK_AGENT_DM_CONSTANTS.OWNER_USER_ID, source: 'oss' };
2457
+ setBriefingService(new BriefingService({
2458
+ decisions: () => DecisionService.getInstance(),
2459
+ listRequests: () => RequestService.getInstance().listAll(),
2460
+ listReviewTickets: async () => {
2461
+ const intake = getTicketIntakeService();
2462
+ if (!intake)
2463
+ return [];
2464
+ const candidates = (await RequestService.getInstance().listAll()).filter((r) => typeof r.ticketNumber === 'number' && r.requiresConfirmation && r.status !== 'done' && r.status !== 'cancelled');
2465
+ const rows = await Promise.all(candidates.map((r) => intake.toListItem(r)));
2466
+ return rows.filter((row) => row.column === 'to_review');
2467
+ },
2468
+ review: () => getTicketReviewService(),
2469
+ dismissOpenItem: async (requestId, itemId) => {
2470
+ const openItems = OpenItemsService.getInstance();
2471
+ if (!openItems)
2472
+ throw new Error('open items are not ready');
2473
+ return openItems.skipItem(requestId, itemId);
2474
+ },
2475
+ roster: async () => buildAgentRoster(await this.storageService.getTeams()),
2476
+ postOwnerMessage: async (target, text) => {
2477
+ const channelId = target.channelId ?? chatService.ensureDmChannel({ agentSession: target.agentSession, principal: owner }).channel.id;
2478
+ const { message } = chatService.recordTurn({
2479
+ channelId,
2480
+ senderType: 'user',
2481
+ senderId: owner.userId,
2482
+ content: text,
2483
+ ...(target.threadId ? { threadId: target.threadId } : {}),
2484
+ clientMessageId: `voice-${randomUUID()}`,
2485
+ // Talk's source keeps the reply on the owner's Talk surface; `inputMode` says it was spoken.
2486
+ metadata: { source: 'cloud-talk', inputMode: 'voice', via: 'drive-mode' },
2487
+ });
2488
+ const channel = chatService.getChannel(channelId, owner);
2489
+ const toDispatch = await intakeChatV2OwnerMessage(getTicketIntakeService(), channel, message, CLOUD_TALK_CONSTANTS.INTAKE_ORIGIN);
2490
+ await chatDispatcher.dispatchMessage(channel, toDispatch);
2491
+ return { channelId, ...(message.threadId ? { threadId: message.threadId } : {}) };
2492
+ },
2493
+ findAgentReply: async (agentSession, channelId, threadId, sinceMs) => {
2494
+ const { items } = chatService.getAgentTimeline({ agentSession, principal: owner, limit: BRIEFING_CONSTANTS.LOOKUP_SCAN_LIMIT });
2495
+ const reply = items
2496
+ .filter((m) => m.channelId === channelId && m.senderType === 'agent' && m.createdAt > sinceMs && (!threadId || m.threadId === threadId || m.id === threadId))
2497
+ .sort((a, b) => a.createdAt - b.createdAt)[0];
2498
+ return reply ? { text: reply.content, at: new Date(reply.createdAt).toISOString() } : null;
2499
+ },
2500
+ store: new BriefingStateStore(),
2501
+ }));
2502
+ }
2503
+ catch (briefingErr) {
2504
+ this.logger.warn('Drive mode briefing wiring skipped', {
2505
+ error: briefingErr instanceof Error ? briefingErr.message : String(briefingErr),
2506
+ });
2507
+ }
2440
2508
  this.logger.info('chat-v2 WebSocket gateway + dispatcher started', {
2441
2509
  path: '/ws/chat',
2442
2510
  authMode: jwtSecret ? 'jwt' : 'dev-anonymous',