crewly 1.20.152 → 1.20.153

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 (71) hide show
  1. package/config/roles/orchestrator/prompt.md +7 -0
  2. package/config/roles/team-leader/prompt.md +6 -0
  3. package/config/sops/developer/git-workflow.md +1 -0
  4. package/dist/backend/backend/src/constants.d.ts +92 -0
  5. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  6. package/dist/backend/backend/src/constants.js +92 -0
  7. package/dist/backend/backend/src/constants.js.map +1 -1
  8. package/dist/backend/backend/src/controllers/worktree-janitor/worktree-janitor.routes.d.ts +29 -0
  9. package/dist/backend/backend/src/controllers/worktree-janitor/worktree-janitor.routes.d.ts.map +1 -0
  10. package/dist/backend/backend/src/controllers/worktree-janitor/worktree-janitor.routes.js +63 -0
  11. package/dist/backend/backend/src/controllers/worktree-janitor/worktree-janitor.routes.js.map +1 -0
  12. package/dist/backend/backend/src/index.d.ts +7 -0
  13. package/dist/backend/backend/src/index.d.ts.map +1 -1
  14. package/dist/backend/backend/src/index.js +114 -2
  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 +3 -0
  18. package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
  19. package/dist/backend/backend/src/services/ai/prompt-modules/decision-rights.module.d.ts +18 -3
  20. package/dist/backend/backend/src/services/ai/prompt-modules/decision-rights.module.d.ts.map +1 -1
  21. package/dist/backend/backend/src/services/ai/prompt-modules/decision-rights.module.js +28 -4
  22. package/dist/backend/backend/src/services/ai/prompt-modules/decision-rights.module.js.map +1 -1
  23. package/dist/backend/backend/src/services/cloud/cloud-sync.types.d.ts +1 -1
  24. package/dist/backend/backend/src/services/cloud/cloud-sync.types.d.ts.map +1 -1
  25. package/dist/backend/backend/src/services/cloud/cloud-sync.types.js +1 -0
  26. package/dist/backend/backend/src/services/cloud/cloud-sync.types.js.map +1 -1
  27. package/dist/backend/backend/src/services/cloud/waiting-actions-inbound.service.d.ts +128 -0
  28. package/dist/backend/backend/src/services/cloud/waiting-actions-inbound.service.d.ts.map +1 -0
  29. package/dist/backend/backend/src/services/cloud/waiting-actions-inbound.service.js +279 -0
  30. package/dist/backend/backend/src/services/cloud/waiting-actions-inbound.service.js.map +1 -0
  31. package/dist/backend/backend/src/services/cloud/waiting-items-sync.service.d.ts +122 -0
  32. package/dist/backend/backend/src/services/cloud/waiting-items-sync.service.d.ts.map +1 -0
  33. package/dist/backend/backend/src/services/cloud/waiting-items-sync.service.js +261 -0
  34. package/dist/backend/backend/src/services/cloud/waiting-items-sync.service.js.map +1 -0
  35. package/dist/backend/backend/src/services/cloud/waiting-items.contract.d.ts +101 -0
  36. package/dist/backend/backend/src/services/cloud/waiting-items.contract.d.ts.map +1 -0
  37. package/dist/backend/backend/src/services/cloud/waiting-items.contract.js +113 -0
  38. package/dist/backend/backend/src/services/cloud/waiting-items.contract.js.map +1 -0
  39. package/dist/backend/backend/src/services/slack/slack-initializer.d.ts.map +1 -1
  40. package/dist/backend/backend/src/services/slack/slack-initializer.js +2 -1
  41. package/dist/backend/backend/src/services/slack/slack-initializer.js.map +1 -1
  42. package/dist/backend/backend/src/services/v3/request.service.d.ts +19 -0
  43. package/dist/backend/backend/src/services/v3/request.service.d.ts.map +1 -1
  44. package/dist/backend/backend/src/services/v3/request.service.js +36 -0
  45. package/dist/backend/backend/src/services/v3/request.service.js.map +1 -1
  46. package/dist/backend/backend/src/services/worktree/worktree-janitor.git.d.ts +131 -0
  47. package/dist/backend/backend/src/services/worktree/worktree-janitor.git.d.ts.map +1 -0
  48. package/dist/backend/backend/src/services/worktree/worktree-janitor.git.js +238 -0
  49. package/dist/backend/backend/src/services/worktree/worktree-janitor.git.js.map +1 -0
  50. package/dist/backend/backend/src/services/worktree/worktree-janitor.service.d.ts +241 -0
  51. package/dist/backend/backend/src/services/worktree/worktree-janitor.service.d.ts.map +1 -0
  52. package/dist/backend/backend/src/services/worktree/worktree-janitor.service.js +504 -0
  53. package/dist/backend/backend/src/services/worktree/worktree-janitor.service.js.map +1 -0
  54. package/dist/backend/build-info.json +2 -2
  55. package/dist/cli/backend/src/constants.d.ts +92 -0
  56. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  57. package/dist/cli/backend/src/constants.js +92 -0
  58. package/dist/cli/backend/src/constants.js.map +1 -1
  59. package/dist/cli/backend/src/services/ai/prompt-modules/decision-rights.module.d.ts +18 -3
  60. package/dist/cli/backend/src/services/ai/prompt-modules/decision-rights.module.d.ts.map +1 -1
  61. package/dist/cli/backend/src/services/ai/prompt-modules/decision-rights.module.js +28 -4
  62. package/dist/cli/backend/src/services/ai/prompt-modules/decision-rights.module.js.map +1 -1
  63. package/dist/cli/backend/src/services/cloud/cloud-sync.types.d.ts +1 -1
  64. package/dist/cli/backend/src/services/cloud/cloud-sync.types.d.ts.map +1 -1
  65. package/dist/cli/backend/src/services/cloud/cloud-sync.types.js +1 -0
  66. package/dist/cli/backend/src/services/cloud/cloud-sync.types.js.map +1 -1
  67. package/dist/cli/backend/src/services/v3/request.service.d.ts +19 -0
  68. package/dist/cli/backend/src/services/v3/request.service.d.ts.map +1 -1
  69. package/dist/cli/backend/src/services/v3/request.service.js +36 -0
  70. package/dist/cli/backend/src/services/v3/request.service.js.map +1 -1
  71. package/package.json +1 -1
@@ -0,0 +1,261 @@
1
+ /**
2
+ * WaitingItemsSyncService — keeps Crewly Cloud's "Waiting on you" list in
3
+ * step with this machine (specs/unified-conversations-cloud-store.md §F,
4
+ * Phase 5).
5
+ *
6
+ * "Waiting on you" = tickets in 待验收 (board column `to_review`): work an
7
+ * agent handed back for the owner's OK. The column is derived, not stored,
8
+ * so this service recomputes the set and uploads a text snapshot
9
+ * (`POST /api/cloud/conversations/waiting/ingest`, `full: true`) whenever it
10
+ * changed:
11
+ *
12
+ * - on a Request write (RequestService.onChange), gathered for 2 s;
13
+ * - on a 30 s check (a WorkItem finishing can move a ticket into 待验收
14
+ * without touching its Request file) — uploads only when the set differs
15
+ * from what Cloud last took;
16
+ * - every 5 minutes regardless (a full resync: Cloud refreshes the items'
17
+ * `syncedAt`, so the portal knows the machine is alive, and drops anything
18
+ * this machine no longer has);
19
+ * - after an accept / send-back from the portal was carried out.
20
+ *
21
+ * Every upload is the whole set, so a ticket that left 待验收 disappears in
22
+ * Cloud with the next upload. Uses the machine's own Cloud token (same as
23
+ * the conversation uploader); signed out = nothing is sent. The conversation
24
+ * sync kill switch (`CREWLY_CONVERSATION_SYNC=0`) turns this off too.
25
+ *
26
+ * @module services/cloud/waiting-items-sync.service
27
+ */
28
+ import { WAITING_SYNC_CONSTANTS } from '../../constants.js';
29
+ import { LoggerService } from '../core/logger.service.js';
30
+ import { accountIdOfToken, isConversationSyncDisabled } from './conversation-cloud-sync.service.js';
31
+ import { INSTANCE_ID_PATTERN } from './conversation-ingest.contract.js';
32
+ import { toWaitingIngestItem } from './waiting-items.contract.js';
33
+ const C = WAITING_SYNC_CONSTANTS;
34
+ /** Uploads the machine's "waiting on you" set to Crewly Cloud. */
35
+ export class WaitingItemsSyncService {
36
+ deps;
37
+ logger;
38
+ fetchImpl;
39
+ now;
40
+ setTimer;
41
+ clearTimer;
42
+ started = false;
43
+ running = null;
44
+ rerun = false;
45
+ checkTimer = null;
46
+ debounceTimer = null;
47
+ unsubscribe = null;
48
+ /** Snapshot Cloud last took (items + capabilities), per account. */
49
+ lastKey = null;
50
+ lastAccount = null;
51
+ lastFullAt = 0;
52
+ failures = 0;
53
+ pausedUntil = 0;
54
+ pauseLogged = false;
55
+ constructor(deps) {
56
+ this.deps = deps;
57
+ this.logger = deps.logger ?? LoggerService.getInstance().createComponentLogger('WaitingItemsSync');
58
+ this.fetchImpl = deps.fetchImpl ?? ((input, init) => fetch(input, init));
59
+ this.now = deps.now ?? Date.now;
60
+ this.setTimer = deps.setTimeout ?? ((fn, ms) => setTimeout(fn, ms));
61
+ this.clearTimer = deps.clearTimeout ?? ((h) => clearTimeout(h));
62
+ }
63
+ /** Start watching tickets and the periodic check. Idempotent; never throws. */
64
+ start() {
65
+ if (this.started)
66
+ return;
67
+ this.started = true;
68
+ try {
69
+ this.unsubscribe = this.deps.onTicketChange?.(() => this.requestSync()) ?? null;
70
+ }
71
+ catch {
72
+ this.unsubscribe = null;
73
+ }
74
+ this.scheduleCheck(0);
75
+ }
76
+ /** Stop timers and the ticket subscription. */
77
+ stop() {
78
+ this.started = false;
79
+ if (this.checkTimer)
80
+ this.clearTimer(this.checkTimer);
81
+ if (this.debounceTimer)
82
+ this.clearTimer(this.debounceTimer);
83
+ this.checkTimer = null;
84
+ this.debounceTimer = null;
85
+ try {
86
+ this.unsubscribe?.();
87
+ }
88
+ catch {
89
+ // ignore
90
+ }
91
+ this.unsubscribe = null;
92
+ }
93
+ /**
94
+ * Upload soon (after the 2 s gather) — a ticket changed, or an action from
95
+ * the portal was carried out.
96
+ */
97
+ requestSync() {
98
+ if (!this.started || this.debounceTimer)
99
+ return;
100
+ this.debounceTimer = this.setTimer(() => {
101
+ this.debounceTimer = null;
102
+ void this.syncNow();
103
+ }, C.DEBOUNCE_MS);
104
+ }
105
+ /** Keep the periodic check going. */
106
+ scheduleCheck(delayMs = C.CHECK_INTERVAL_MS) {
107
+ if (!this.started)
108
+ return;
109
+ this.checkTimer = this.setTimer(() => {
110
+ this.checkTimer = null;
111
+ void this.syncNow().finally(() => this.scheduleCheck());
112
+ }, delayMs);
113
+ }
114
+ /**
115
+ * Recompute the set and upload it when it changed (or a full resync is
116
+ * due). One upload at a time; a call during one runs again after it.
117
+ * Never throws.
118
+ *
119
+ * @param force - Upload even when nothing changed
120
+ * @returns What happened
121
+ */
122
+ async syncNow(force = false) {
123
+ if (this.running) {
124
+ this.rerun = true;
125
+ return this.running;
126
+ }
127
+ this.running = (async () => {
128
+ let outcome = 'skipped';
129
+ try {
130
+ do {
131
+ this.rerun = false;
132
+ outcome = await this.pass(force);
133
+ } while (this.rerun);
134
+ }
135
+ catch (error) {
136
+ this.logger.warn('Waiting items sync failed', { error: error instanceof Error ? error.message : String(error) });
137
+ outcome = 'failed';
138
+ }
139
+ return outcome;
140
+ })();
141
+ try {
142
+ return await this.running;
143
+ }
144
+ finally {
145
+ this.running = null;
146
+ }
147
+ }
148
+ async pass(force) {
149
+ if (isConversationSyncDisabled(this.deps.env ?? process.env))
150
+ return 'skipped';
151
+ const token = this.deps.cloud.getToken();
152
+ const base = this.deps.cloud.getCloudUrl();
153
+ if (!token || !base)
154
+ return 'skipped';
155
+ if (this.now() < this.pausedUntil)
156
+ return 'paused';
157
+ const account = accountIdOfToken(token);
158
+ if (account !== this.lastAccount) {
159
+ // New sign-in or another account: the first upload is a full one.
160
+ this.lastAccount = account;
161
+ this.lastKey = null;
162
+ this.lastFullAt = 0;
163
+ }
164
+ const { instanceId, deviceName } = await this.deps.identity();
165
+ if (!INSTANCE_ID_PATTERN.test(instanceId))
166
+ return 'skipped';
167
+ const rows = await this.deps.listWaiting();
168
+ const names = await this.deps.agentNames?.().catch(() => new Map());
169
+ const items = rows
170
+ .filter((r) => r.column === 'to_review')
171
+ .map((r) => toWaitingIngestItem(r, (s) => names?.get(s)))
172
+ .sort((a, b) => a.ticketId.localeCompare(b.ticketId));
173
+ let capabilities = [];
174
+ try {
175
+ capabilities = this.deps.capabilities?.() ?? [];
176
+ }
177
+ catch {
178
+ capabilities = [];
179
+ }
180
+ const key = JSON.stringify([items, capabilities, deviceName ?? null]);
181
+ const fullDue = this.now() - this.lastFullAt >= C.FULL_SYNC_INTERVAL_MS;
182
+ if (!force && !fullDue && key === this.lastKey)
183
+ return 'unchanged';
184
+ const version = (await this.deps.crewlyVersion?.().catch(() => undefined)) ?? undefined;
185
+ const body = {
186
+ instanceId,
187
+ ...(deviceName ? { deviceName } : {}),
188
+ ...(version ? { crewlyVersion: version } : {}),
189
+ full: true,
190
+ items,
191
+ capabilities,
192
+ };
193
+ return this.upload(base, token, body, key);
194
+ }
195
+ /** POST the snapshot and book the outcome. */
196
+ async upload(base, token, body, key) {
197
+ const url = `${base.replace(/\/$/, '')}${C.INGEST_PATH}`;
198
+ let status = 0;
199
+ let code = null;
200
+ try {
201
+ const response = await this.fetchImpl(url, {
202
+ method: 'POST',
203
+ headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
204
+ body: JSON.stringify(body),
205
+ signal: AbortSignal.timeout(C.REQUEST_TIMEOUT_MS),
206
+ });
207
+ status = response.status;
208
+ if (response.ok) {
209
+ this.lastKey = key;
210
+ this.lastFullAt = this.now();
211
+ this.failures = 0;
212
+ if (this.pauseLogged) {
213
+ this.pauseLogged = false;
214
+ this.logger.info('Crewly Cloud is taking "waiting on you" updates again');
215
+ }
216
+ this.logger.debug('Waiting items uploaded', { count: body.items.length });
217
+ return 'uploaded';
218
+ }
219
+ const parsed = (await response.json().catch(() => null));
220
+ code = typeof parsed?.code === 'string' ? parsed.code : null;
221
+ }
222
+ catch (error) {
223
+ code = error instanceof Error ? error.message : String(error);
224
+ }
225
+ if (status === 404 || status === 400 || status === 503 || (status === 403 && code === 'sync_disabled')) {
226
+ // Not deployed yet, refused, key missing or switched off: check again in an hour.
227
+ this.pausedUntil = this.now() + C.UNAVAILABLE_RETRY_MS;
228
+ if (!this.pauseLogged) {
229
+ this.pauseLogged = true;
230
+ this.logger.info('Crewly Cloud is not taking "waiting on you" updates right now; checking again in an hour', { status, code });
231
+ }
232
+ return 'paused';
233
+ }
234
+ if (status === 401)
235
+ void this.deps.cloud.tryRefreshToken?.().catch(() => false);
236
+ this.failures += 1;
237
+ const delay = Math.min(C.BACKOFF_INITIAL_MS * 2 ** (this.failures - 1), C.BACKOFF_MAX_MS);
238
+ this.pausedUntil = this.now() + delay;
239
+ if (this.failures === 1)
240
+ this.logger.warn('Waiting items upload failed; will retry', { status, code, retryInMs: delay });
241
+ return 'failed';
242
+ }
243
+ }
244
+ let instance = null;
245
+ /**
246
+ * Install the process-wide instance (composition root).
247
+ *
248
+ * @param service - The service, or null
249
+ */
250
+ export function setWaitingItemsSyncService(service) {
251
+ instance = service;
252
+ }
253
+ /**
254
+ * The process-wide instance, or null before wiring.
255
+ *
256
+ * @returns The service or null
257
+ */
258
+ export function getWaitingItemsSyncService() {
259
+ return instance;
260
+ }
261
+ //# sourceMappingURL=waiting-items-sync.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"waiting-items-sync.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/cloud/waiting-items-sync.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * "Waiting on you" wire contract, machine side — mirrors
3
+ * `AUTH:conversations/waiting.contract.ts` (crewly-services). Change them
4
+ * together.
5
+ *
6
+ * POST /api/cloud/conversations/waiting/ingest machine snapshot of its 待验收 tickets
7
+ * GET /api/cloud/conversations/waiting/actions/:actionId?instanceId= fetch a pushed action
8
+ * POST /api/cloud/conversations/waiting/actions/:actionId/result report what happened
9
+ * relay `waiting_action` {v, actionId, itemId, instanceId, ticketId} Cloud → machine (ids only)
10
+ *
11
+ * Pure (no I/O).
12
+ *
13
+ * @module services/cloud/waiting-items.contract
14
+ */
15
+ import type { TicketListItem } from '../v3/ticket-intake.service.js';
16
+ /** One ticket in 待验收 as the machine uploads it (text only). */
17
+ export interface WaitingIngestItem {
18
+ /** Request id (stable). */
19
+ ticketId: string;
20
+ /** `TKT-12` */
21
+ tkt?: string;
22
+ title: string;
23
+ /** Start of the agent's answer. */
24
+ excerpt?: string;
25
+ /** Agent that answered (local session name). */
26
+ agentSession?: string;
27
+ agentName?: string;
28
+ /** When it went to 待验收 (ISO). */
29
+ since: string;
30
+ /** When silence accepts it (ISO), or null. */
31
+ autoAcceptAt: string | null;
32
+ rejectCount: number;
33
+ /** Ticket's last change (ISO). */
34
+ updatedAt: string;
35
+ }
36
+ /** `POST /waiting/ingest` body. */
37
+ export interface WaitingIngestRequest {
38
+ instanceId: string;
39
+ deviceName?: string;
40
+ crewlyVersion?: string;
41
+ /** True = `items` is the whole set; Cloud removes this machine's other items. */
42
+ full: boolean;
43
+ items: WaitingIngestItem[];
44
+ /** Tickets that left 待验收 (delta uploads). */
45
+ removed?: string[];
46
+ capabilities?: string[];
47
+ }
48
+ /** `data` of a `waiting_action` relay push. */
49
+ export interface WaitingActionRelayData {
50
+ v: 1;
51
+ actionId: string;
52
+ itemId: string;
53
+ instanceId: string;
54
+ ticketId: string;
55
+ }
56
+ /** What the owner asked for. */
57
+ export type WaitingActionKind = 'accept' | 'send_back';
58
+ /** `GET /waiting/actions/:actionId?instanceId=` → `data`. */
59
+ export interface WaitingActionFetchResponse {
60
+ actionId: string;
61
+ itemId: string;
62
+ instanceId: string;
63
+ ticketId: string;
64
+ kind: WaitingActionKind;
65
+ /** With `send_back`: what still needs fixing. */
66
+ reason?: string;
67
+ state: 'queued' | 'sent' | 'failed';
68
+ }
69
+ /** `POST /waiting/actions/:actionId/result` body. */
70
+ export interface WaitingActionResultRequest {
71
+ instanceId: string;
72
+ ok: boolean;
73
+ /** Refusal code from the ticket service (`not_in_review`, `open_work`, …). */
74
+ code?: string;
75
+ /** Owner-readable reason when not ok. */
76
+ error?: string;
77
+ }
78
+ /**
79
+ * Validate the `data` of a `waiting_action` push. Never throws.
80
+ *
81
+ * @param raw - `IncomingMessage.payload`
82
+ * @returns The push, or null when it is not one
83
+ */
84
+ export declare function parseWaitingActionRelayData(raw: unknown): WaitingActionRelayData | null;
85
+ /**
86
+ * Validate Cloud's answer to the action fetch. Never throws.
87
+ *
88
+ * @param raw - Parsed JSON body (`{success, data}`)
89
+ * @returns The action, or null when the body is not usable
90
+ */
91
+ export declare function parseWaitingActionFetchResponse(raw: unknown): WaitingActionFetchResponse | null;
92
+ /**
93
+ * Shape one board row in 待验收 for Cloud. Ticket mechanics stay internal
94
+ * (the portal shows the title, the agent's words and who said them).
95
+ *
96
+ * @param row - Board row (`column === 'to_review'`)
97
+ * @param nameOf - Display name of an agent session, when known
98
+ * @returns The upload item
99
+ */
100
+ export declare function toWaitingIngestItem(row: TicketListItem, nameOf?: (session: string) => string | undefined): WaitingIngestItem;
101
+ //# sourceMappingURL=waiting-items.contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"waiting-items.contract.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/cloud/waiting-items.contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAErE,+DAA+D;AAC/D,MAAM,WAAW,iBAAiB;IAChC,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,mCAAmC;AACnC,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,+CAA+C;AAC/C,MAAM,WAAW,sBAAsB;IACrC,CAAC,EAAE,CAAC,CAAC;IACL,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,gCAAgC;AAChC,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEvD,6DAA6D;AAC7D,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,iBAAiB,CAAC;IACxB,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC;CACrC;AAED,qDAAqD;AACrD,MAAM,WAAW,0BAA0B;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,OAAO,CAAC;IACZ,8EAA8E;IAC9E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAuBD;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,OAAO,GAAG,sBAAsB,GAAG,IAAI,CAKvF;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,OAAO,GAAG,0BAA0B,GAAG,IAAI,CAgB/F;AAcD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,GAAG,iBAAiB,CAgB5H"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * "Waiting on you" wire contract, machine side — mirrors
3
+ * `AUTH:conversations/waiting.contract.ts` (crewly-services). Change them
4
+ * together.
5
+ *
6
+ * POST /api/cloud/conversations/waiting/ingest machine snapshot of its 待验收 tickets
7
+ * GET /api/cloud/conversations/waiting/actions/:actionId?instanceId= fetch a pushed action
8
+ * POST /api/cloud/conversations/waiting/actions/:actionId/result report what happened
9
+ * relay `waiting_action` {v, actionId, itemId, instanceId, ticketId} Cloud → machine (ids only)
10
+ *
11
+ * Pure (no I/O).
12
+ *
13
+ * @module services/cloud/waiting-items.contract
14
+ */
15
+ import { WAITING_SYNC_CONSTANTS } from '../../constants.js';
16
+ /**
17
+ * Whether a value is a plain object.
18
+ *
19
+ * @param value - Anything
20
+ * @returns True for a non-array object
21
+ */
22
+ function isRecord(value) {
23
+ return !!value && typeof value === 'object' && !Array.isArray(value);
24
+ }
25
+ /**
26
+ * Whether a value is a non-empty string of at most `max` characters.
27
+ *
28
+ * @param value - Anything
29
+ * @param max - Longest accepted length
30
+ * @returns True when usable as an id
31
+ */
32
+ function nonEmpty(value, max = 128) {
33
+ return typeof value === 'string' && value.length > 0 && value.length <= max;
34
+ }
35
+ /**
36
+ * Validate the `data` of a `waiting_action` push. Never throws.
37
+ *
38
+ * @param raw - `IncomingMessage.payload`
39
+ * @returns The push, or null when it is not one
40
+ */
41
+ export function parseWaitingActionRelayData(raw) {
42
+ if (!isRecord(raw))
43
+ return null;
44
+ const { actionId, itemId, instanceId, ticketId } = raw;
45
+ if (!nonEmpty(actionId) || !nonEmpty(itemId, 64) || !nonEmpty(instanceId) || !nonEmpty(ticketId))
46
+ return null;
47
+ return { v: 1, actionId, itemId, instanceId, ticketId };
48
+ }
49
+ /**
50
+ * Validate Cloud's answer to the action fetch. Never throws.
51
+ *
52
+ * @param raw - Parsed JSON body (`{success, data}`)
53
+ * @returns The action, or null when the body is not usable
54
+ */
55
+ export function parseWaitingActionFetchResponse(raw) {
56
+ const data = isRecord(raw) && isRecord(raw['data']) ? raw['data'] : null;
57
+ if (!data)
58
+ return null;
59
+ const { actionId, itemId, instanceId, ticketId, kind, reason, state } = data;
60
+ if (!nonEmpty(actionId) || !nonEmpty(itemId, 64) || !nonEmpty(instanceId) || !nonEmpty(ticketId))
61
+ return null;
62
+ if (kind !== 'accept' && kind !== 'send_back')
63
+ return null;
64
+ if (kind === 'send_back' && (typeof reason !== 'string' || reason.trim().length === 0))
65
+ return null;
66
+ return {
67
+ actionId,
68
+ itemId,
69
+ instanceId,
70
+ ticketId,
71
+ kind,
72
+ ...(kind === 'send_back' ? { reason: reason.trim() } : {}),
73
+ state: state === 'queued' || state === 'failed' ? state : 'sent',
74
+ };
75
+ }
76
+ /**
77
+ * Cut text to `max` characters on a character boundary.
78
+ *
79
+ * @param text - Text
80
+ * @param max - Longest length
81
+ * @returns The text, shortened with an ellipsis when needed
82
+ */
83
+ function cut(text, max) {
84
+ if (text.length <= max)
85
+ return text;
86
+ return `${Array.from(text).slice(0, max - 1).join('')}…`;
87
+ }
88
+ /**
89
+ * Shape one board row in 待验收 for Cloud. Ticket mechanics stay internal
90
+ * (the portal shows the title, the agent's words and who said them).
91
+ *
92
+ * @param row - Board row (`column === 'to_review'`)
93
+ * @param nameOf - Display name of an agent session, when known
94
+ * @returns The upload item
95
+ */
96
+ export function toWaitingIngestItem(row, nameOf) {
97
+ const agentSession = row.reply?.by ?? row.assignee ?? undefined;
98
+ const agentName = agentSession ? nameOf?.(agentSession) : undefined;
99
+ const excerpt = (row.reply?.excerpt ?? row.description ?? '').trim();
100
+ return {
101
+ ticketId: row.id,
102
+ ...(row.tkt ? { tkt: row.tkt } : {}),
103
+ title: cut(row.title.trim() || row.tkt || row.id, WAITING_SYNC_CONSTANTS.MAX_TITLE_CHARS),
104
+ ...(excerpt ? { excerpt: cut(excerpt, WAITING_SYNC_CONSTANTS.MAX_EXCERPT_CHARS) } : {}),
105
+ ...(agentSession ? { agentSession } : {}),
106
+ ...(agentName ? { agentName } : {}),
107
+ since: row.submittedAt ?? row.updatedAt,
108
+ autoAcceptAt: row.autoAcceptAt,
109
+ rejectCount: row.rejectCount,
110
+ updatedAt: row.updatedAt,
111
+ };
112
+ }
113
+ //# sourceMappingURL=waiting-items.contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"waiting-items.contract.js","sourceRoot":"","sources":["../../../../../../backend/src/services/cloud/waiting-items.contract.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"slack-initializer.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/slack/slack-initializer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"slack-initializer.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/slack/slack-initializer.ts"],"names":[],"mappings":"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"}
@@ -15,6 +15,7 @@ import { getSlackAgentIdentityService } from './slack-agent-identity.service.js'
15
15
  import { loadSlackSourcePreference, saveSlackSourcePreference, } from './slack-source-preference.service.js';
16
16
  import { getSlackTeamChannelService } from './slack-team-channel.service.js';
17
17
  import { cloudTalkCapabilities } from '../cloud/cloud-talk-inbound.service.js';
18
+ import { waitingActionCapabilities } from '../cloud/waiting-actions-inbound.service.js';
18
19
  import { SLACK_CLOUD_CONSTANTS, CREWLY_CONSTANTS, SLACK_AGENT_DM_CONSTANTS, SLACK_TYPING_CONSTANTS } from '../../constants.js';
19
20
  import * as path from 'path';
20
21
  import { getCrewlyHomePath } from '../core/crewly-home.utils.js';
@@ -514,7 +515,7 @@ export async function ensureSlackInstanceRegistry() {
514
515
  getTeamChannels: () => getSlackTeamChannelService(),
515
516
  getBoundWorkspaceId: () => getSlackCloudConfigService()?.getConfig()?.workspace.slackTeamId || null,
516
517
  isAgentAwake: (agentSession) => sessionBackendExists(agentSession),
517
- capabilities: () => cloudTalkCapabilities(),
518
+ capabilities: () => [...cloudTalkCapabilities(), ...waitingActionCapabilities()],
518
519
  });
519
520
  setSlackInstanceRegistryService(registry);
520
521
  }