crewly 1.20.278 → 1.20.280
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/config/skills/agent/core/reply/SKILL.md +3 -0
- package/config/skills/agent/core/reply/execute.sh +23 -1
- package/config/skills/agent/core/reply/execute.test.sh +11 -0
- package/dist/backend/backend/src/constants.d.ts +115 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +115 -0
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/chat/agent-reply.controller.d.ts +10 -0
- package/dist/backend/backend/src/controllers/chat/agent-reply.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/chat/agent-reply.controller.js +25 -0
- package/dist/backend/backend/src/controllers/chat/agent-reply.controller.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +207 -3
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.js +4 -2
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/idle-detection.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/idle-detection.service.js +7 -0
- package/dist/backend/backend/src/services/agent/idle-detection.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/resource-mode.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/resource-mode.service.js +4 -1
- package/dist/backend/backend/src/services/agent/resource-mode.service.js.map +1 -1
- package/dist/backend/backend/src/services/briefing/briefing-cards.d.ts +99 -0
- package/dist/backend/backend/src/services/briefing/briefing-cards.d.ts.map +1 -0
- package/dist/backend/backend/src/services/briefing/briefing-cards.js +156 -0
- package/dist/backend/backend/src/services/briefing/briefing-cards.js.map +1 -0
- package/dist/backend/backend/src/services/briefing/briefing.service.d.ts +8 -0
- package/dist/backend/backend/src/services/briefing/briefing.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/briefing/briefing.service.js +31 -9
- package/dist/backend/backend/src/services/briefing/briefing.service.js.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts +33 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js +33 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.d.ts +21 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.d.ts.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js +37 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-talk-inbound.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-talk-inbound.service.js +4 -0
- package/dist/backend/backend/src/services/cloud/cloud-talk-inbound.service.js.map +1 -1
- package/dist/backend/backend/src/services/drive/drive-agent.service.d.ts +244 -0
- package/dist/backend/backend/src/services/drive/drive-agent.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/drive/drive-agent.service.js +444 -0
- package/dist/backend/backend/src/services/drive/drive-agent.service.js.map +1 -0
- package/dist/backend/backend/src/services/drive/drive-briefing-snapshot.d.ts +172 -0
- package/dist/backend/backend/src/services/drive/drive-briefing-snapshot.d.ts.map +1 -0
- package/dist/backend/backend/src/services/drive/drive-briefing-snapshot.js +301 -0
- package/dist/backend/backend/src/services/drive/drive-briefing-snapshot.js.map +1 -0
- package/dist/backend/backend/src/services/drive/drive-briefing-sync.service.d.ts +112 -0
- package/dist/backend/backend/src/services/drive/drive-briefing-sync.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/drive/drive-briefing-sync.service.js +247 -0
- package/dist/backend/backend/src/services/drive/drive-briefing-sync.service.js.map +1 -0
- package/dist/backend/backend/src/services/drive/drive-briefing.contract.d.ts +88 -0
- package/dist/backend/backend/src/services/drive/drive-briefing.contract.d.ts.map +1 -0
- package/dist/backend/backend/src/services/drive/drive-briefing.contract.js +18 -0
- package/dist/backend/backend/src/services/drive/drive-briefing.contract.js.map +1 -0
- package/dist/backend/backend/src/services/drive/drive-briefing.wiring.d.ts +73 -0
- package/dist/backend/backend/src/services/drive/drive-briefing.wiring.d.ts.map +1 -0
- package/dist/backend/backend/src/services/drive/drive-briefing.wiring.js +131 -0
- package/dist/backend/backend/src/services/drive/drive-briefing.wiring.js.map +1 -0
- package/dist/backend/backend/src/services/drive/drive-cloud.contract.d.ts +99 -0
- package/dist/backend/backend/src/services/drive/drive-cloud.contract.d.ts.map +1 -0
- package/dist/backend/backend/src/services/drive/drive-cloud.contract.js +118 -0
- package/dist/backend/backend/src/services/drive/drive-cloud.contract.js.map +1 -0
- package/dist/backend/backend/src/services/drive/drive-conversation.store.d.ts +86 -0
- package/dist/backend/backend/src/services/drive/drive-conversation.store.d.ts.map +1 -0
- package/dist/backend/backend/src/services/drive/drive-conversation.store.js +102 -0
- package/dist/backend/backend/src/services/drive/drive-conversation.store.js.map +1 -0
- package/dist/backend/backend/src/services/drive/drive-keep-warm.d.ts +72 -0
- package/dist/backend/backend/src/services/drive/drive-keep-warm.d.ts.map +1 -0
- package/dist/backend/backend/src/services/drive/drive-keep-warm.js +109 -0
- package/dist/backend/backend/src/services/drive/drive-keep-warm.js.map +1 -0
- package/dist/backend/backend/src/services/drive/drive-recall.d.ts +65 -0
- package/dist/backend/backend/src/services/drive/drive-recall.d.ts.map +1 -0
- package/dist/backend/backend/src/services/drive/drive-recall.js +91 -0
- package/dist/backend/backend/src/services/drive/drive-recall.js.map +1 -0
- package/dist/backend/backend/src/services/drive/drive-row.utils.d.ts +19 -0
- package/dist/backend/backend/src/services/drive/drive-row.utils.d.ts.map +1 -0
- package/dist/backend/backend/src/services/drive/drive-row.utils.js +20 -0
- package/dist/backend/backend/src/services/drive/drive-row.utils.js.map +1 -0
- package/dist/backend/backend/src/services/messaging/owner-hook-message.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/owner-hook-message.js +11 -5
- package/dist/backend/backend/src/services/messaging/owner-hook-message.js.map +1 -1
- package/dist/backend/backend/src/services/open-items/open-items.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/open-items/open-items.service.js +14 -2
- package/dist/backend/backend/src/services/open-items/open-items.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-agent-dm.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-agent-dm.service.js +4 -0
- package/dist/backend/backend/src/services/slack/slack-agent-dm.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-initializer.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-initializer.js +2 -1
- package/dist/backend/backend/src/services/slack/slack-initializer.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.js +7 -1
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
- package/dist/backend/backend/src/services/talk/talk-live-token.service.d.ts +23 -7
- package/dist/backend/backend/src/services/talk/talk-live-token.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/talk/talk-live-token.service.js +78 -40
- package/dist/backend/backend/src/services/talk/talk-live-token.service.js.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +115 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +115 -0
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.js +4 -2
- package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/resource-mode.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/resource-mode.service.js +4 -1
- package/dist/cli/backend/src/services/agent/resource-mode.service.js.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/chat-v2.service.d.ts +33 -1
- package/dist/cli/backend/src/services/chat-v2/chat-v2.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/chat-v2.service.js +33 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.service.js.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.d.ts +21 -0
- package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.d.ts.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.js +37 -0
- package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.js.map +1 -1
- package/dist/cli/backend/src/services/drive/drive-keep-warm.d.ts +72 -0
- package/dist/cli/backend/src/services/drive/drive-keep-warm.d.ts.map +1 -0
- package/dist/cli/backend/src/services/drive/drive-keep-warm.js +109 -0
- package/dist/cli/backend/src/services/drive/drive-keep-warm.js.map +1 -0
- package/dist/cli/backend/src/services/drive/drive-row.utils.d.ts +19 -0
- package/dist/cli/backend/src/services/drive/drive-row.utils.d.ts.map +1 -0
- package/dist/cli/backend/src/services/drive/drive-row.utils.js +20 -0
- package/dist/cli/backend/src/services/drive/drive-row.utils.js.map +1 -0
- package/dist/cli/backend/src/services/open-items/open-items.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/open-items/open-items.service.js +14 -2
- package/dist/cli/backend/src/services/open-items/open-items.service.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-agent-dm.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-agent-dm.service.js +4 -0
- package/dist/cli/backend/src/services/slack/slack-agent-dm.service.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.js +7 -1
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drive mode wire shapes, machine half (mirrors crewly-services
|
|
3
|
+
* `auth/src/drive/drive.contract.ts`). Pure.
|
|
4
|
+
*
|
|
5
|
+
* Cloud → machine: relay `talk_message` with `{v:1, kind:'drive', op,
|
|
6
|
+
* sessionId, id?, instanceId}` — ids only. The machine then fetches, with its
|
|
7
|
+
* own Cloud token:
|
|
8
|
+
* GET /api/cloud/talk/session/:sid/machine/deliveries/:id?instanceId= → the owner's words
|
|
9
|
+
* GET /api/cloud/talk/session/:sid/machine/state?instanceId= → its conversations (after `end`)
|
|
10
|
+
* GET /api/cloud/talk/session/:sid/machine/recalls/:id?instanceId= → what to recall
|
|
11
|
+
* POST /api/cloud/talk/session/:sid/machine/recalls/:id {instanceId, messages}
|
|
12
|
+
* (`op:'warm'` → `machine/state` also lists the agents to keep warm, with `warmUntil`)
|
|
13
|
+
* Machine → Cloud (an agent's `reply --drive`):
|
|
14
|
+
* POST /api/cloud/talk/session/:sid/replies {instanceId, conversationId, agentSession, text, interim?, ack?, recap?, nextStep?}
|
|
15
|
+
* Machine → Cloud (its status snapshot, specs/2026-10-09-drive-mode-v3.md):
|
|
16
|
+
* PUT /api/cloud/instances/:instanceId/briefing {snapshot}
|
|
17
|
+
*
|
|
18
|
+
* @module services/drive/drive-cloud.contract
|
|
19
|
+
*/
|
|
20
|
+
/** What the owner can talk to. */
|
|
21
|
+
export type DriveTargetKind = 'agent' | 'team' | 'channel';
|
|
22
|
+
/** A Drive mode push. */
|
|
23
|
+
export interface DriveRelayData {
|
|
24
|
+
v: 1;
|
|
25
|
+
kind: 'drive';
|
|
26
|
+
op: 'deliver' | 'end' | 'recall' | 'warm';
|
|
27
|
+
sessionId: string;
|
|
28
|
+
id?: string;
|
|
29
|
+
instanceId: string;
|
|
30
|
+
}
|
|
31
|
+
/** The owner's words, as Cloud hands them to the machine. */
|
|
32
|
+
export interface DriveDeliveryFetch {
|
|
33
|
+
id: string;
|
|
34
|
+
sessionId: string;
|
|
35
|
+
conversationId: string;
|
|
36
|
+
target: {
|
|
37
|
+
kind: DriveTargetKind;
|
|
38
|
+
name: string;
|
|
39
|
+
agentSession: string;
|
|
40
|
+
team?: string;
|
|
41
|
+
slackChannelId?: string;
|
|
42
|
+
members?: string[];
|
|
43
|
+
};
|
|
44
|
+
text: string;
|
|
45
|
+
}
|
|
46
|
+
/** A recall request. */
|
|
47
|
+
export interface DriveRecallFetch {
|
|
48
|
+
agentSessions: string[];
|
|
49
|
+
hint?: string;
|
|
50
|
+
slackChannelId?: string;
|
|
51
|
+
}
|
|
52
|
+
/** The machine's part of a session. */
|
|
53
|
+
export interface DriveStateFetch {
|
|
54
|
+
ended: boolean;
|
|
55
|
+
conversations: Array<{
|
|
56
|
+
conversationId: string;
|
|
57
|
+
agentSession: string;
|
|
58
|
+
}>;
|
|
59
|
+
/** Agents to keep warm while the session runs (v3) */
|
|
60
|
+
warm: string[];
|
|
61
|
+
/** Until when (ms); 0 when nothing is warm */
|
|
62
|
+
warmUntil: number;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* A Drive mode relay payload, or null (any other `talk_message`).
|
|
66
|
+
*
|
|
67
|
+
* @param payload - Relay payload
|
|
68
|
+
* @returns Data or null
|
|
69
|
+
*/
|
|
70
|
+
export declare function parseDriveRelayData(payload: unknown): DriveRelayData | null;
|
|
71
|
+
/**
|
|
72
|
+
* Whether a relay payload is Drive mode's (so the Talk handler leaves it alone).
|
|
73
|
+
*
|
|
74
|
+
* @param payload - Relay payload
|
|
75
|
+
* @returns True for `kind: 'drive'`
|
|
76
|
+
*/
|
|
77
|
+
export declare function isDrivePayload(payload: unknown): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Cloud's delivery answer, or null.
|
|
80
|
+
*
|
|
81
|
+
* @param data - `data` of the response
|
|
82
|
+
* @returns Delivery or null
|
|
83
|
+
*/
|
|
84
|
+
export declare function parseDeliveryFetch(data: unknown): DriveDeliveryFetch | null;
|
|
85
|
+
/**
|
|
86
|
+
* Cloud's recall request, or null.
|
|
87
|
+
*
|
|
88
|
+
* @param data - `data` of the response
|
|
89
|
+
* @returns Request or null
|
|
90
|
+
*/
|
|
91
|
+
export declare function parseRecallFetch(data: unknown): DriveRecallFetch | null;
|
|
92
|
+
/**
|
|
93
|
+
* Cloud's session state for this machine, or null.
|
|
94
|
+
*
|
|
95
|
+
* @param data - `data` of the response
|
|
96
|
+
* @returns State or null
|
|
97
|
+
*/
|
|
98
|
+
export declare function parseStateFetch(data: unknown): DriveStateFetch | null;
|
|
99
|
+
//# sourceMappingURL=drive-cloud.contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drive-cloud.contract.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/drive/drive-cloud.contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,kCAAkC;AAClC,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AAE3D,yBAAyB;AACzB,MAAM,WAAW,cAAc;IAC7B,CAAC,EAAE,CAAC,CAAC;IACL,IAAI,EAAE,OAAO,CAAC;IACd,EAAE,EAAE,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,6DAA6D;AAC7D,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE;QAAE,IAAI,EAAE,eAAe,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAClI,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAwB;AACxB,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,uCAAuC;AACvC,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,EAAE,KAAK,CAAC;QAAE,cAAc,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvE,sDAAsD;IACtD,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;CACnB;AAKD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,cAAc,GAAG,IAAI,CAU3E;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,kBAAkB,GAAG,IAAI,CA0B3E;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,gBAAgB,GAAG,IAAI,CAKvE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,eAAe,GAAG,IAAI,CAUrE"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drive mode wire shapes, machine half (mirrors crewly-services
|
|
3
|
+
* `auth/src/drive/drive.contract.ts`). Pure.
|
|
4
|
+
*
|
|
5
|
+
* Cloud → machine: relay `talk_message` with `{v:1, kind:'drive', op,
|
|
6
|
+
* sessionId, id?, instanceId}` — ids only. The machine then fetches, with its
|
|
7
|
+
* own Cloud token:
|
|
8
|
+
* GET /api/cloud/talk/session/:sid/machine/deliveries/:id?instanceId= → the owner's words
|
|
9
|
+
* GET /api/cloud/talk/session/:sid/machine/state?instanceId= → its conversations (after `end`)
|
|
10
|
+
* GET /api/cloud/talk/session/:sid/machine/recalls/:id?instanceId= → what to recall
|
|
11
|
+
* POST /api/cloud/talk/session/:sid/machine/recalls/:id {instanceId, messages}
|
|
12
|
+
* (`op:'warm'` → `machine/state` also lists the agents to keep warm, with `warmUntil`)
|
|
13
|
+
* Machine → Cloud (an agent's `reply --drive`):
|
|
14
|
+
* POST /api/cloud/talk/session/:sid/replies {instanceId, conversationId, agentSession, text, interim?, ack?, recap?, nextStep?}
|
|
15
|
+
* Machine → Cloud (its status snapshot, specs/2026-10-09-drive-mode-v3.md):
|
|
16
|
+
* PUT /api/cloud/instances/:instanceId/briefing {snapshot}
|
|
17
|
+
*
|
|
18
|
+
* @module services/drive/drive-cloud.contract
|
|
19
|
+
*/
|
|
20
|
+
import { DRIVE_CONSTANTS } from '../../constants.js';
|
|
21
|
+
const obj = (v) => (v && typeof v === 'object' && !Array.isArray(v) ? v : null);
|
|
22
|
+
const str = (v) => (typeof v === 'string' && v.trim() ? v : null);
|
|
23
|
+
/**
|
|
24
|
+
* A Drive mode relay payload, or null (any other `talk_message`).
|
|
25
|
+
*
|
|
26
|
+
* @param payload - Relay payload
|
|
27
|
+
* @returns Data or null
|
|
28
|
+
*/
|
|
29
|
+
export function parseDriveRelayData(payload) {
|
|
30
|
+
const p = obj(payload);
|
|
31
|
+
if (!p || p['kind'] !== DRIVE_CONSTANTS.RELAY_KIND || p['v'] !== 1)
|
|
32
|
+
return null;
|
|
33
|
+
const op = p['op'];
|
|
34
|
+
const sessionId = str(p['sessionId']);
|
|
35
|
+
const instanceId = str(p['instanceId']);
|
|
36
|
+
if ((op !== 'deliver' && op !== 'end' && op !== 'recall' && op !== 'warm') || !sessionId || !DRIVE_CONSTANTS.SESSION_ID_PATTERN.test(sessionId) || !instanceId)
|
|
37
|
+
return null;
|
|
38
|
+
const id = str(p['id']);
|
|
39
|
+
if ((op === 'deliver' || op === 'recall') && !id)
|
|
40
|
+
return null;
|
|
41
|
+
return { v: 1, kind: 'drive', op, sessionId, instanceId, ...(id ? { id } : {}) };
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Whether a relay payload is Drive mode's (so the Talk handler leaves it alone).
|
|
45
|
+
*
|
|
46
|
+
* @param payload - Relay payload
|
|
47
|
+
* @returns True for `kind: 'drive'`
|
|
48
|
+
*/
|
|
49
|
+
export function isDrivePayload(payload) {
|
|
50
|
+
return obj(payload)?.['kind'] === DRIVE_CONSTANTS.RELAY_KIND;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Cloud's delivery answer, or null.
|
|
54
|
+
*
|
|
55
|
+
* @param data - `data` of the response
|
|
56
|
+
* @returns Delivery or null
|
|
57
|
+
*/
|
|
58
|
+
export function parseDeliveryFetch(data) {
|
|
59
|
+
const d = obj(data);
|
|
60
|
+
const t = obj(d?.['target']);
|
|
61
|
+
if (!d || !t)
|
|
62
|
+
return null;
|
|
63
|
+
const kind = t['kind'];
|
|
64
|
+
const id = str(d['id']);
|
|
65
|
+
const sessionId = str(d['sessionId']);
|
|
66
|
+
const conversationId = str(d['conversationId']);
|
|
67
|
+
const text = str(d['text']);
|
|
68
|
+
const agentSession = str(t['agentSession']);
|
|
69
|
+
if ((kind !== 'agent' && kind !== 'team' && kind !== 'channel') || !id || !sessionId || !conversationId || !text || !agentSession)
|
|
70
|
+
return null;
|
|
71
|
+
const members = Array.isArray(t['members']) ? t['members'].filter((m) => typeof m === 'string') : undefined;
|
|
72
|
+
return {
|
|
73
|
+
id,
|
|
74
|
+
sessionId,
|
|
75
|
+
conversationId,
|
|
76
|
+
text,
|
|
77
|
+
target: {
|
|
78
|
+
kind,
|
|
79
|
+
name: str(t['name']) ?? agentSession,
|
|
80
|
+
agentSession,
|
|
81
|
+
...(str(t['team']) ? { team: t['team'] } : {}),
|
|
82
|
+
...(str(t['slackChannelId']) ? { slackChannelId: t['slackChannelId'] } : {}),
|
|
83
|
+
...(members ? { members } : {}),
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Cloud's recall request, or null.
|
|
89
|
+
*
|
|
90
|
+
* @param data - `data` of the response
|
|
91
|
+
* @returns Request or null
|
|
92
|
+
*/
|
|
93
|
+
export function parseRecallFetch(data) {
|
|
94
|
+
const d = obj(data);
|
|
95
|
+
const sessions = Array.isArray(d?.['agentSessions']) ? (d?.['agentSessions']).filter((s) => typeof s === 'string' && !!s) : [];
|
|
96
|
+
if (!d || sessions.length === 0)
|
|
97
|
+
return null;
|
|
98
|
+
return { agentSessions: sessions, ...(str(d['hint']) ? { hint: d['hint'] } : {}), ...(str(d['slackChannelId']) ? { slackChannelId: d['slackChannelId'] } : {}) };
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Cloud's session state for this machine, or null.
|
|
102
|
+
*
|
|
103
|
+
* @param data - `data` of the response
|
|
104
|
+
* @returns State or null
|
|
105
|
+
*/
|
|
106
|
+
export function parseStateFetch(data) {
|
|
107
|
+
const d = obj(data);
|
|
108
|
+
if (!d || !Array.isArray(d['conversations']))
|
|
109
|
+
return null;
|
|
110
|
+
const conversations = d['conversations']
|
|
111
|
+
.map(obj)
|
|
112
|
+
.filter((c) => !!c && !!str(c['conversationId']) && !!str(c['agentSession']))
|
|
113
|
+
.map((c) => ({ conversationId: c['conversationId'], agentSession: c['agentSession'] }));
|
|
114
|
+
const warm = Array.isArray(d['warm']) ? d['warm'].filter((s) => typeof s === 'string' && !!s.trim()).slice(0, DRIVE_CONSTANTS.MAX_WARM) : [];
|
|
115
|
+
const until = typeof d['warmUntil'] === 'string' ? Date.parse(d['warmUntil']) : NaN;
|
|
116
|
+
return { ended: d['ended'] === true, conversations, warm, warmUntil: warm.length && Number.isFinite(until) ? until : 0 };
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=drive-cloud.contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drive-cloud.contract.js","sourceRoot":"","sources":["../../../../../../backend/src/services/drive/drive-cloud.contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This machine's Drive mode conversations (specs/2026-10-08-drive-mode.md
|
|
3
|
+
* §7): where each one is recorded (the agent's DM, or the room's thread), who
|
|
4
|
+
* answers it, its turns (for the recap) and whether it is closed — in
|
|
5
|
+
* `<crewlyHome>/drive-conversations.json`, so a restart mid-drive still
|
|
6
|
+
* routes the agents' answers and recaps. Cloud keeps the session itself.
|
|
7
|
+
*
|
|
8
|
+
* @module services/drive/drive-conversation.store
|
|
9
|
+
*/
|
|
10
|
+
import type { DriveTargetKind } from './drive-cloud.contract.js';
|
|
11
|
+
/** One turn. */
|
|
12
|
+
export interface DriveLocalTurn {
|
|
13
|
+
from: 'owner' | 'agent';
|
|
14
|
+
name: string;
|
|
15
|
+
text: string;
|
|
16
|
+
/** ISO */
|
|
17
|
+
at: string;
|
|
18
|
+
interim?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/** One Drive mode conversation on this machine. */
|
|
21
|
+
export interface DriveLocalConversation {
|
|
22
|
+
sessionId: string;
|
|
23
|
+
conversationId: string;
|
|
24
|
+
kind: DriveTargetKind;
|
|
25
|
+
/** "Ella", "CE", "#ce" */
|
|
26
|
+
targetName: string;
|
|
27
|
+
/** Who answers (the agent, the lead) */
|
|
28
|
+
agentSession: string;
|
|
29
|
+
/** Others who may answer (team / room members) */
|
|
30
|
+
members?: string[];
|
|
31
|
+
/** chat-v2 channel it is recorded in */
|
|
32
|
+
channelId: string;
|
|
33
|
+
/** Thread root (room conversations) */
|
|
34
|
+
threadId?: string;
|
|
35
|
+
/** ISO */
|
|
36
|
+
startedAt: string;
|
|
37
|
+
turns: DriveLocalTurn[];
|
|
38
|
+
/** ISO — the recap was asked for */
|
|
39
|
+
recapAskedAt?: string;
|
|
40
|
+
/** ISO — the recap was posted; closed */
|
|
41
|
+
closedAt?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The key of a conversation.
|
|
45
|
+
*
|
|
46
|
+
* @param sessionId - Session
|
|
47
|
+
* @param conversationId - Conversation
|
|
48
|
+
* @returns `<sessionId>:<conversationId>`
|
|
49
|
+
*/
|
|
50
|
+
export declare function localKey(sessionId: string, conversationId: string): string;
|
|
51
|
+
/** Read / change local Drive mode conversations. Writes are serialised. */
|
|
52
|
+
export declare class DriveConversationStore {
|
|
53
|
+
private readonly filePath?;
|
|
54
|
+
private chain;
|
|
55
|
+
/**
|
|
56
|
+
* @param filePath - File; default `<crewlyHome>/drive-conversations.json` (resolved per call)
|
|
57
|
+
*/
|
|
58
|
+
constructor(filePath?: string | undefined);
|
|
59
|
+
/** @returns Absolute path */
|
|
60
|
+
getFilePath(): string;
|
|
61
|
+
/** @returns Every conversation (empty when missing or unreadable) */
|
|
62
|
+
list(): Promise<DriveLocalConversation[]>;
|
|
63
|
+
/**
|
|
64
|
+
* One conversation.
|
|
65
|
+
*
|
|
66
|
+
* @param sessionId - Session
|
|
67
|
+
* @param conversationId - Conversation
|
|
68
|
+
* @returns It, or null
|
|
69
|
+
*/
|
|
70
|
+
get(sessionId: string, conversationId: string): Promise<DriveLocalConversation | null>;
|
|
71
|
+
/**
|
|
72
|
+
* Change one conversation; `fn` gets it (or null) and returns the new one,
|
|
73
|
+
* or null to leave it. Conversations older than
|
|
74
|
+
* {@link DRIVE_CONSTANTS.KEEP_MS} are dropped on the way.
|
|
75
|
+
*
|
|
76
|
+
* @param sessionId - Session
|
|
77
|
+
* @param conversationId - Conversation
|
|
78
|
+
* @param fn - Updater
|
|
79
|
+
* @param nowMs - Clock
|
|
80
|
+
* @returns The new conversation (or null)
|
|
81
|
+
*/
|
|
82
|
+
update(sessionId: string, conversationId: string, fn: (cur: DriveLocalConversation | null) => DriveLocalConversation | null, nowMs?: number): Promise<DriveLocalConversation | null>;
|
|
83
|
+
private read;
|
|
84
|
+
private write;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=drive-conversation.store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drive-conversation.store.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/drive/drive-conversation.store.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAEjE,gBAAgB;AAChB,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU;IACV,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,mDAAmD;AACnD,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,eAAe,CAAC;IACtB,0BAA0B;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,YAAY,EAAE,MAAM,CAAC;IACrB,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU;IACV,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,oCAAoC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAQD;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAE1E;AAED,2EAA2E;AAC3E,qBAAa,sBAAsB;IAMrB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;IALtC,OAAO,CAAC,KAAK,CAAuC;IAEpD;;OAEG;gBAC0B,QAAQ,CAAC,EAAE,MAAM,YAAA;IAE9C,6BAA6B;IAC7B,WAAW,IAAI,MAAM;IAIrB,qEAAqE;IAC/D,IAAI,IAAI,OAAO,CAAC,sBAAsB,EAAE,CAAC;IAK/C;;;;;;OAMG;IACG,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC;IAK5F;;;;;;;;;;OAUG;IACH,MAAM,CACJ,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,EACtB,EAAE,EAAE,CAAC,GAAG,EAAE,sBAAsB,GAAG,IAAI,KAAK,sBAAsB,GAAG,IAAI,EACzE,KAAK,GAAE,MAAmB,GACzB,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC;YAiB3B,IAAI;YAUJ,KAAK;CAOpB"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This machine's Drive mode conversations (specs/2026-10-08-drive-mode.md
|
|
3
|
+
* §7): where each one is recorded (the agent's DM, or the room's thread), who
|
|
4
|
+
* answers it, its turns (for the recap) and whether it is closed — in
|
|
5
|
+
* `<crewlyHome>/drive-conversations.json`, so a restart mid-drive still
|
|
6
|
+
* routes the agents' answers and recaps. Cloud keeps the session itself.
|
|
7
|
+
*
|
|
8
|
+
* @module services/drive/drive-conversation.store
|
|
9
|
+
*/
|
|
10
|
+
import * as fs from 'fs';
|
|
11
|
+
import * as path from 'path';
|
|
12
|
+
import { DRIVE_CONSTANTS } from '../../constants.js';
|
|
13
|
+
import { getCrewlyHomePath } from '../core/crewly-home.utils.js';
|
|
14
|
+
/**
|
|
15
|
+
* The key of a conversation.
|
|
16
|
+
*
|
|
17
|
+
* @param sessionId - Session
|
|
18
|
+
* @param conversationId - Conversation
|
|
19
|
+
* @returns `<sessionId>:<conversationId>`
|
|
20
|
+
*/
|
|
21
|
+
export function localKey(sessionId, conversationId) {
|
|
22
|
+
return `${sessionId}:${conversationId}`;
|
|
23
|
+
}
|
|
24
|
+
/** Read / change local Drive mode conversations. Writes are serialised. */
|
|
25
|
+
export class DriveConversationStore {
|
|
26
|
+
filePath;
|
|
27
|
+
chain = Promise.resolve();
|
|
28
|
+
/**
|
|
29
|
+
* @param filePath - File; default `<crewlyHome>/drive-conversations.json` (resolved per call)
|
|
30
|
+
*/
|
|
31
|
+
constructor(filePath) {
|
|
32
|
+
this.filePath = filePath;
|
|
33
|
+
}
|
|
34
|
+
/** @returns Absolute path */
|
|
35
|
+
getFilePath() {
|
|
36
|
+
return this.filePath ?? path.join(getCrewlyHomePath(), DRIVE_CONSTANTS.STATE_FILENAME);
|
|
37
|
+
}
|
|
38
|
+
/** @returns Every conversation (empty when missing or unreadable) */
|
|
39
|
+
async list() {
|
|
40
|
+
await this.chain;
|
|
41
|
+
return Object.values((await this.read()).conversations);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* One conversation.
|
|
45
|
+
*
|
|
46
|
+
* @param sessionId - Session
|
|
47
|
+
* @param conversationId - Conversation
|
|
48
|
+
* @returns It, or null
|
|
49
|
+
*/
|
|
50
|
+
async get(sessionId, conversationId) {
|
|
51
|
+
await this.chain;
|
|
52
|
+
return (await this.read()).conversations[localKey(sessionId, conversationId)] ?? null;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Change one conversation; `fn` gets it (or null) and returns the new one,
|
|
56
|
+
* or null to leave it. Conversations older than
|
|
57
|
+
* {@link DRIVE_CONSTANTS.KEEP_MS} are dropped on the way.
|
|
58
|
+
*
|
|
59
|
+
* @param sessionId - Session
|
|
60
|
+
* @param conversationId - Conversation
|
|
61
|
+
* @param fn - Updater
|
|
62
|
+
* @param nowMs - Clock
|
|
63
|
+
* @returns The new conversation (or null)
|
|
64
|
+
*/
|
|
65
|
+
update(sessionId, conversationId, fn, nowMs = Date.now()) {
|
|
66
|
+
const run = this.chain.then(async () => {
|
|
67
|
+
const state = await this.read();
|
|
68
|
+
const key = localKey(sessionId, conversationId);
|
|
69
|
+
const cur = state.conversations[key] ? structuredClone(state.conversations[key]) : null;
|
|
70
|
+
const next = fn(cur);
|
|
71
|
+
for (const [k, c] of Object.entries(state.conversations)) {
|
|
72
|
+
if (nowMs - Date.parse(c.startedAt) > DRIVE_CONSTANTS.KEEP_MS)
|
|
73
|
+
delete state.conversations[k];
|
|
74
|
+
}
|
|
75
|
+
if (next)
|
|
76
|
+
state.conversations[key] = next;
|
|
77
|
+
await this.write(state);
|
|
78
|
+
return next;
|
|
79
|
+
});
|
|
80
|
+
this.chain = run.catch(() => undefined);
|
|
81
|
+
return run;
|
|
82
|
+
}
|
|
83
|
+
async read() {
|
|
84
|
+
try {
|
|
85
|
+
const raw = JSON.parse(await fs.promises.readFile(this.getFilePath(), 'utf8'));
|
|
86
|
+
if (raw && raw.version === 1 && raw.conversations && typeof raw.conversations === 'object')
|
|
87
|
+
return { version: 1, conversations: raw.conversations };
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
// missing or unreadable: start empty
|
|
91
|
+
}
|
|
92
|
+
return { version: 1, conversations: {} };
|
|
93
|
+
}
|
|
94
|
+
async write(state) {
|
|
95
|
+
const file = this.getFilePath();
|
|
96
|
+
await fs.promises.mkdir(path.dirname(file), { recursive: true });
|
|
97
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
98
|
+
await fs.promises.writeFile(tmp, JSON.stringify(state, null, 2), { mode: 0o600 });
|
|
99
|
+
await fs.promises.rename(tmp, file);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=drive-conversation.store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drive-conversation.store.js","sourceRoot":"","sources":["../../../../../../backend/src/services/drive/drive-conversation.store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drive mode keep-warm (specs/2026-10-09-drive-mode-v3.md §5): while the
|
|
3
|
+
* owner is in a Drive mode session, the agents he names and the team leads
|
|
4
|
+
* he talks to stay running, so the next thing he says to them is answered in
|
|
5
|
+
* seconds instead of after a cold start.
|
|
6
|
+
*
|
|
7
|
+
* Crewly Cloud tells this machine which of its agents to keep warm (relay
|
|
8
|
+
* push `op:'warm'`, the list read back from `machine/state` with this
|
|
9
|
+
* machine's token) and repeats it every few minutes while the phone is
|
|
10
|
+
* connected. Each list holds until its `until` time (or the session's end),
|
|
11
|
+
* so a phone that drops never pins agents for long.
|
|
12
|
+
*
|
|
13
|
+
* Consulted by every path that stops an idle agent or frees a running slot
|
|
14
|
+
* (idle stop, memory-pressure stop, slot freeing, reconciler wake eviction)
|
|
15
|
+
* and by the start gate, which lets a warm agent's start go ahead of
|
|
16
|
+
* ordinary starts.
|
|
17
|
+
*
|
|
18
|
+
* @module services/drive/drive-keep-warm
|
|
19
|
+
*/
|
|
20
|
+
/** Which agents Drive mode keeps running right now. */
|
|
21
|
+
export declare class DriveKeepWarm {
|
|
22
|
+
private readonly now;
|
|
23
|
+
private readonly sessions;
|
|
24
|
+
/**
|
|
25
|
+
* @param now - Clock (ms)
|
|
26
|
+
*/
|
|
27
|
+
constructor(now?: () => number);
|
|
28
|
+
/**
|
|
29
|
+
* Replace a session's warm list.
|
|
30
|
+
*
|
|
31
|
+
* @param driveSessionId - Drive mode session
|
|
32
|
+
* @param agents - Agent sessions to keep warm
|
|
33
|
+
* @param untilMs - Until when (ms)
|
|
34
|
+
* @returns The agents that were not warm before (to pre-start)
|
|
35
|
+
*/
|
|
36
|
+
set(driveSessionId: string, agents: readonly string[], untilMs: number): string[];
|
|
37
|
+
/**
|
|
38
|
+
* The session ended: its agents are no longer kept warm.
|
|
39
|
+
*
|
|
40
|
+
* @param driveSessionId - Drive mode session
|
|
41
|
+
*/
|
|
42
|
+
end(driveSessionId: string): void;
|
|
43
|
+
/**
|
|
44
|
+
* Whether an agent is kept warm by any live session.
|
|
45
|
+
*
|
|
46
|
+
* @param agentSession - Agent session name
|
|
47
|
+
* @returns True while a session's list holds it
|
|
48
|
+
*/
|
|
49
|
+
isWarm(agentSession: string): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Every agent kept warm now (expired lists are dropped).
|
|
52
|
+
*
|
|
53
|
+
* @returns Agent sessions
|
|
54
|
+
*/
|
|
55
|
+
warmAgents(): string[];
|
|
56
|
+
}
|
|
57
|
+
/** @returns The process-wide keep-warm registry */
|
|
58
|
+
export declare function getDriveKeepWarm(): DriveKeepWarm;
|
|
59
|
+
/**
|
|
60
|
+
* Replace the registry (tests).
|
|
61
|
+
*
|
|
62
|
+
* @param registry - Registry
|
|
63
|
+
*/
|
|
64
|
+
export declare function setDriveKeepWarm(registry: DriveKeepWarm): void;
|
|
65
|
+
/**
|
|
66
|
+
* Whether Drive mode keeps an agent running right now. Never throws.
|
|
67
|
+
*
|
|
68
|
+
* @param agentSession - Agent session name
|
|
69
|
+
* @returns True while the owner's Drive mode session keeps it warm
|
|
70
|
+
*/
|
|
71
|
+
export declare function isDriveWarm(agentSession: string): boolean;
|
|
72
|
+
//# sourceMappingURL=drive-keep-warm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drive-keep-warm.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/drive/drive-keep-warm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAQH,uDAAuD;AACvD,qBAAa,aAAa;IAMZ,OAAO,CAAC,QAAQ,CAAC,GAAG;IALhC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8B;IAEvD;;OAEG;gBAC0B,GAAG,GAAE,MAAM,MAAiB;IAEzD;;;;;;;OAOG;IACH,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE;IAOjF;;;;OAIG;IACH,GAAG,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI;IAIjC;;;;;OAKG;IACH,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAIrC;;;;OAIG;IACH,UAAU,IAAI,MAAM,EAAE;CAYvB;AAID,mDAAmD;AACnD,wBAAgB,gBAAgB,IAAI,aAAa,CAEhD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAE9D;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAMzD"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drive mode keep-warm (specs/2026-10-09-drive-mode-v3.md §5): while the
|
|
3
|
+
* owner is in a Drive mode session, the agents he names and the team leads
|
|
4
|
+
* he talks to stay running, so the next thing he says to them is answered in
|
|
5
|
+
* seconds instead of after a cold start.
|
|
6
|
+
*
|
|
7
|
+
* Crewly Cloud tells this machine which of its agents to keep warm (relay
|
|
8
|
+
* push `op:'warm'`, the list read back from `machine/state` with this
|
|
9
|
+
* machine's token) and repeats it every few minutes while the phone is
|
|
10
|
+
* connected. Each list holds until its `until` time (or the session's end),
|
|
11
|
+
* so a phone that drops never pins agents for long.
|
|
12
|
+
*
|
|
13
|
+
* Consulted by every path that stops an idle agent or frees a running slot
|
|
14
|
+
* (idle stop, memory-pressure stop, slot freeing, reconciler wake eviction)
|
|
15
|
+
* and by the start gate, which lets a warm agent's start go ahead of
|
|
16
|
+
* ordinary starts.
|
|
17
|
+
*
|
|
18
|
+
* @module services/drive/drive-keep-warm
|
|
19
|
+
*/
|
|
20
|
+
/** Which agents Drive mode keeps running right now. */
|
|
21
|
+
export class DriveKeepWarm {
|
|
22
|
+
now;
|
|
23
|
+
sessions = new Map();
|
|
24
|
+
/**
|
|
25
|
+
* @param now - Clock (ms)
|
|
26
|
+
*/
|
|
27
|
+
constructor(now = Date.now) {
|
|
28
|
+
this.now = now;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Replace a session's warm list.
|
|
32
|
+
*
|
|
33
|
+
* @param driveSessionId - Drive mode session
|
|
34
|
+
* @param agents - Agent sessions to keep warm
|
|
35
|
+
* @param untilMs - Until when (ms)
|
|
36
|
+
* @returns The agents that were not warm before (to pre-start)
|
|
37
|
+
*/
|
|
38
|
+
set(driveSessionId, agents, untilMs) {
|
|
39
|
+
const before = new Set(this.warmAgents());
|
|
40
|
+
if (agents.length === 0 || untilMs <= this.now())
|
|
41
|
+
this.sessions.delete(driveSessionId);
|
|
42
|
+
else
|
|
43
|
+
this.sessions.set(driveSessionId, { agents: new Set(agents), until: untilMs });
|
|
44
|
+
return agents.filter((a) => !before.has(a));
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The session ended: its agents are no longer kept warm.
|
|
48
|
+
*
|
|
49
|
+
* @param driveSessionId - Drive mode session
|
|
50
|
+
*/
|
|
51
|
+
end(driveSessionId) {
|
|
52
|
+
this.sessions.delete(driveSessionId);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Whether an agent is kept warm by any live session.
|
|
56
|
+
*
|
|
57
|
+
* @param agentSession - Agent session name
|
|
58
|
+
* @returns True while a session's list holds it
|
|
59
|
+
*/
|
|
60
|
+
isWarm(agentSession) {
|
|
61
|
+
return this.warmAgents().includes(agentSession);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Every agent kept warm now (expired lists are dropped).
|
|
65
|
+
*
|
|
66
|
+
* @returns Agent sessions
|
|
67
|
+
*/
|
|
68
|
+
warmAgents() {
|
|
69
|
+
const now = this.now();
|
|
70
|
+
const out = new Set();
|
|
71
|
+
for (const [id, s] of this.sessions) {
|
|
72
|
+
if (s.until <= now) {
|
|
73
|
+
this.sessions.delete(id);
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
for (const a of s.agents)
|
|
77
|
+
out.add(a);
|
|
78
|
+
}
|
|
79
|
+
return [...out];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
let instance = new DriveKeepWarm();
|
|
83
|
+
/** @returns The process-wide keep-warm registry */
|
|
84
|
+
export function getDriveKeepWarm() {
|
|
85
|
+
return instance;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Replace the registry (tests).
|
|
89
|
+
*
|
|
90
|
+
* @param registry - Registry
|
|
91
|
+
*/
|
|
92
|
+
export function setDriveKeepWarm(registry) {
|
|
93
|
+
instance = registry;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Whether Drive mode keeps an agent running right now. Never throws.
|
|
97
|
+
*
|
|
98
|
+
* @param agentSession - Agent session name
|
|
99
|
+
* @returns True while the owner's Drive mode session keeps it warm
|
|
100
|
+
*/
|
|
101
|
+
export function isDriveWarm(agentSession) {
|
|
102
|
+
try {
|
|
103
|
+
return instance.isWarm(agentSession);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=drive-keep-warm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drive-keep-warm.js","sourceRoot":"","sources":["../../../../../../backend/src/services/drive/drive-keep-warm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAQH,uDAAuD;AACvD,MAAM,OAAO,aAAa;IAMK;IALZ,QAAQ,GAAG,IAAI,GAAG,EAAmB,CAAC;IAEvD;;OAEG;IACH,YAA6B,MAAoB,IAAI,CAAC,GAAG;QAA5B,QAAG,GAAH,GAAG,CAAyB;IAAG,CAAC;IAE7D;;;;;;;OAOG;IACH,GAAG,CAAC,cAAsB,EAAE,MAAyB,EAAE,OAAe;QACpE,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;QAC1C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,IAAI,IAAI,CAAC,GAAG,EAAE;YAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;;YAClF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QACpF,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED;;;;OAIG;IACH,GAAG,CAAC,cAAsB;QACxB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IACvC,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,YAAoB;QACzB,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IAClD,CAAC;IAED;;;;OAIG;IACH,UAAU;QACR,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;QAC9B,KAAK,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpC,IAAI,CAAC,CAAC,KAAK,IAAI,GAAG,EAAE,CAAC;gBACnB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACzB,SAAS;YACX,CAAC;YACD,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM;gBAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACvC,CAAC;QACD,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC;IAClB,CAAC;CACF;AAED,IAAI,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;AAEnC,mDAAmD;AACnD,MAAM,UAAU,gBAAgB;IAC9B,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAuB;IACtD,QAAQ,GAAG,QAAQ,CAAC;AACtB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,YAAoB;IAC9C,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|