crewly 1.20.188 → 1.20.190
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/attach-file/execute.sh +13 -4
- package/config/skills/agent/core/complete-task/execute.sh +3 -0
- package/config/skills/agent/core/reply/SKILL.md +32 -4
- package/config/skills/agent/core/reply/execute.sh +23 -1
- package/config/skills/agent/core/reply/execute.test.sh +9 -0
- package/config/skills/agent/core/reply-chat/SKILL.md +9 -2
- package/config/skills/agent/core/reply-chat/execute.sh +13 -1
- package/config/skills/agent/core/report-status/execute.sh +5 -0
- package/config/skills/agent/core/send-chat-response/execute.sh +1 -1
- package/dist/backend/backend/src/constants.d.ts +23 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +27 -1
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/chat/agent-reply.controller.d.ts +14 -1
- 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 +66 -78
- package/dist/backend/backend/src/controllers/chat/agent-reply.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/chat/chat.controller.d.ts +12 -0
- package/dist/backend/backend/src/controllers/chat/chat.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/chat/chat.controller.js +148 -24
- package/dist/backend/backend/src/controllers/chat/chat.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.js +62 -0
- package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/slack/slack.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/slack/slack.controller.js +120 -35
- package/dist/backend/backend/src/controllers/slack/slack.controller.js.map +1 -1
- package/dist/backend/backend/src/scripts/repair-orphan-superseded-decisions.d.ts +56 -0
- package/dist/backend/backend/src/scripts/repair-orphan-superseded-decisions.d.ts.map +1 -0
- package/dist/backend/backend/src/scripts/repair-orphan-superseded-decisions.js +114 -0
- package/dist/backend/backend/src/scripts/repair-orphan-superseded-decisions.js.map +1 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts +7 -0
- 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 +9 -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 +7 -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 +19 -0
- package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js.map +1 -1
- package/dist/backend/backend/src/services/decisions/decision.service.d.ts +4 -1
- package/dist/backend/backend/src/services/decisions/decision.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/decisions/decision.service.js +10 -3
- package/dist/backend/backend/src/services/decisions/decision.service.js.map +1 -1
- package/dist/backend/backend/src/services/memory/project-memory.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/memory/project-memory.service.js +21 -10
- package/dist/backend/backend/src/services/memory/project-memory.service.js.map +1 -1
- package/dist/backend/backend/src/services/open-items/open-items.service.d.ts +29 -0
- 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 +92 -8
- package/dist/backend/backend/src/services/open-items/open-items.service.js.map +1 -1
- package/dist/backend/backend/src/services/open-items/open-items.wiring.js +2 -2
- package/dist/backend/backend/src/services/open-items/open-items.wiring.js.map +1 -1
- package/dist/backend/backend/src/services/orc/agent-prompt-reference.service.d.ts +81 -0
- package/dist/backend/backend/src/services/orc/agent-prompt-reference.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/orc/agent-prompt-reference.service.js +88 -0
- package/dist/backend/backend/src/services/orc/agent-prompt-reference.service.js.map +1 -0
- package/dist/backend/backend/src/services/orc/orc-reply-route.service.d.ts +8 -0
- package/dist/backend/backend/src/services/orc/orc-reply-route.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/orc/orc-reply-route.service.js +11 -0
- package/dist/backend/backend/src/services/orc/orc-reply-route.service.js.map +1 -1
- package/dist/backend/backend/src/services/orc/reply-destination-resolver.d.ts +218 -0
- package/dist/backend/backend/src/services/orc/reply-destination-resolver.d.ts.map +1 -0
- package/dist/backend/backend/src/services/orc/reply-destination-resolver.js +343 -0
- package/dist/backend/backend/src/services/orc/reply-destination-resolver.js.map +1 -0
- package/dist/backend/backend/src/services/orc/reply-destination.wiring.d.ts +98 -0
- package/dist/backend/backend/src/services/orc/reply-destination.wiring.d.ts.map +1 -0
- package/dist/backend/backend/src/services/orc/reply-destination.wiring.js +362 -0
- package/dist/backend/backend/src/services/orc/reply-destination.wiring.js.map +1 -0
- package/dist/backend/backend/src/services/slack/slack-agent-dm.service.d.ts +9 -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 +32 -7
- package/dist/backend/backend/src/services/slack/slack-agent-dm.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-agent-post.service.d.ts +2 -2
- package/dist/backend/backend/src/services/slack/slack-agent-post.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-agent-post.service.js +9 -0
- package/dist/backend/backend/src/services/slack/slack-agent-post.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 +4 -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 +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 +24 -4
- package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.d.ts +89 -7
- package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.js +159 -21
- package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.js.map +1 -1
- package/dist/backend/backend/src/services/v3/ticket-intake.service.d.ts +23 -4
- package/dist/backend/backend/src/services/v3/ticket-intake.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/ticket-intake.service.js +42 -4
- package/dist/backend/backend/src/services/v3/ticket-intake.service.js.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +23 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +27 -1
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/chat-v2.service.d.ts +7 -0
- 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 +9 -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 +7 -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 +19 -0
- package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.js.map +1 -1
- package/dist/cli/backend/src/services/decisions/decision.service.d.ts +4 -1
- package/dist/cli/backend/src/services/decisions/decision.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/decisions/decision.service.js +10 -3
- package/dist/cli/backend/src/services/decisions/decision.service.js.map +1 -1
- package/dist/cli/backend/src/services/memory/project-memory.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/memory/project-memory.service.js +21 -10
- package/dist/cli/backend/src/services/memory/project-memory.service.js.map +1 -1
- package/dist/cli/backend/src/services/open-items/open-items.service.d.ts +457 -0
- package/dist/cli/backend/src/services/open-items/open-items.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/open-items/open-items.service.js +1158 -0
- package/dist/cli/backend/src/services/open-items/open-items.service.js.map +1 -0
- package/dist/cli/backend/src/services/orc/agent-prompt-reference.service.d.ts +81 -0
- package/dist/cli/backend/src/services/orc/agent-prompt-reference.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/orc/agent-prompt-reference.service.js +88 -0
- package/dist/cli/backend/src/services/orc/agent-prompt-reference.service.js.map +1 -0
- package/dist/cli/backend/src/services/orc/orc-reply-route.service.d.ts +8 -0
- package/dist/cli/backend/src/services/orc/orc-reply-route.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/orc/orc-reply-route.service.js +11 -0
- package/dist/cli/backend/src/services/orc/orc-reply-route.service.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-agent-dm.service.d.ts +9 -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 +32 -7
- 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 +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 +24 -4
- package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.d.ts +89 -7
- package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.js +159 -21
- package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.js.map +1 -1
- package/dist/cli/backend/src/services/v3/ticket-intake.service.d.ts +23 -4
- package/dist/cli/backend/src/services/v3/ticket-intake.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/v3/ticket-intake.service.js +42 -4
- package/dist/cli/backend/src/services/v3/ticket-intake.service.js.map +1 -1
- package/package.json +1 -1
|
@@ -232,6 +232,14 @@ export declare class OrcReplyRouteService {
|
|
|
232
232
|
* @param sessionName - Agent session
|
|
233
233
|
* @returns Its state, created on first use
|
|
234
234
|
*/
|
|
235
|
+
/**
|
|
236
|
+
* The head of the last message delivered to a session (owner, system or
|
|
237
|
+
* harness prompt) — specs/2026-10-02-harness-owned-routing.md §1 step 5.
|
|
238
|
+
*
|
|
239
|
+
* @param sessionName - Agent session
|
|
240
|
+
* @returns Its first characters, or undefined when nothing was delivered
|
|
241
|
+
*/
|
|
242
|
+
getLastDelivered(sessionName: string): string | undefined;
|
|
235
243
|
private stateFor;
|
|
236
244
|
}
|
|
237
245
|
//# sourceMappingURL=orc-reply-route.service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orc-reply-route.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/orc/orc-reply-route.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAKH,+CAA+C;AAC/C,MAAM,WAAW,UAAU;IACzB,0EAA0E;IAC1E,cAAc,EAAE,MAAM,CAAC;IACvB,8EAA8E;IAC9E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,+CAA+C;IAC/C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,oDAAoD;AACpD,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;AAE3D,yEAAyE;AACzE,MAAM,MAAM,gBAAgB;AAC1B,mCAAmC;AACjC,cAAc;AAChB,8DAA8D;GAC5D,qBAAqB;AACvB,2EAA2E;GACzE,oBAAoB;AACtB,8EAA8E;GAC5E,WAAW,CAAC;AAEhB,yCAAyC;AACzC,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,gBAAgB,CAAC;IACzB,qDAAqD;IACrD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED,+CAA+C;AAC/C,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,cAAc,GAAG,oBAAoB,CAAC;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED,6CAA6C;AAC7C,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAAC;AAErD,6CAA6C;AAC7C,MAAM,WAAW,cAAc;IAC7B,oEAAoE;IACpE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gCAAgC;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAmBD;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAcxE;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAEzD;
|
|
1
|
+
{"version":3,"file":"orc-reply-route.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/orc/orc-reply-route.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -114,6 +114,7 @@ export class OrcReplyRouteService {
|
|
|
114
114
|
* @returns The new origin, or null when the message was system-originated
|
|
115
115
|
*/
|
|
116
116
|
noteDelivery(sessionName, message, now = Date.now()) {
|
|
117
|
+
this.stateFor(sessionName).lastDelivered = String(message ?? '').slice(0, ORC_REPLY_ROUTE_CONSTANTS.LAST_DELIVERED_HEAD_CHARS);
|
|
117
118
|
const parsed = parseInboundOrigin(message);
|
|
118
119
|
if (!parsed)
|
|
119
120
|
return null;
|
|
@@ -303,6 +304,16 @@ export class OrcReplyRouteService {
|
|
|
303
304
|
* @param sessionName - Agent session
|
|
304
305
|
* @returns Its state, created on first use
|
|
305
306
|
*/
|
|
307
|
+
/**
|
|
308
|
+
* The head of the last message delivered to a session (owner, system or
|
|
309
|
+
* harness prompt) — specs/2026-10-02-harness-owned-routing.md §1 step 5.
|
|
310
|
+
*
|
|
311
|
+
* @param sessionName - Agent session
|
|
312
|
+
* @returns Its first characters, or undefined when nothing was delivered
|
|
313
|
+
*/
|
|
314
|
+
getLastDelivered(sessionName) {
|
|
315
|
+
return this.sessions.get(sessionName)?.lastDelivered;
|
|
316
|
+
}
|
|
306
317
|
stateFor(sessionName) {
|
|
307
318
|
let state = this.sessions.get(sessionName);
|
|
308
319
|
if (!state) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orc-reply-route.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/orc/orc-reply-route.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAqE5F;;;;;GAKG;AACH,MAAM,WAAW,GAAG,iCAAiC,CAAC;AAEtD;;;GAGG;AACH,MAAM,wBAAwB,GAAG,wBAAwB,CAAC;AAE1D,uEAAuE;AACvE,MAAM,YAAY,GAAG,uCAAuC,CAAC;AAE7D;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,MAAM,EAAE,GAAG,wBAAwB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAkB,EAAE,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;IACnE,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzC,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,CAAC,cAAc,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACjC,IAAI,KAAK,CAAC,CAAC,CAAC;YAAE,MAAM,CAAC,aAAa,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC;IACD,MAAM,CAAC,SAAS,CAAC,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACpD,IAAI,SAAS;QAAE,MAAM,CAAC,cAAc,GAAG,oBAAoB,CAAC,SAAS,CAAC,cAAc,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC1G,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,cAAsB;IAC9C,OAAO,cAAc,CAAC,UAAU,CAAC,yBAAyB,CAAC,eAAe,CAAC,CAAC;AAC9E,CAAC;
|
|
1
|
+
{"version":3,"file":"orc-reply-route.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/orc/orc-reply-route.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAqE5F;;;;;GAKG;AACH,MAAM,WAAW,GAAG,iCAAiC,CAAC;AAEtD;;;GAGG;AACH,MAAM,wBAAwB,GAAG,wBAAwB,CAAC;AAE1D,uEAAuE;AACvE,MAAM,YAAY,GAAG,uCAAuC,CAAC;AAE7D;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,MAAM,EAAE,GAAG,wBAAwB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAkB,EAAE,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;IACnE,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzC,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,CAAC,cAAc,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACjC,IAAI,KAAK,CAAC,CAAC,CAAC;YAAE,MAAM,CAAC,aAAa,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC;IACD,MAAM,CAAC,SAAS,CAAC,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACpD,IAAI,SAAS;QAAE,MAAM,CAAC,cAAc,GAAG,oBAAoB,CAAC,SAAS,CAAC,cAAc,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC1G,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,cAAsB;IAC9C,OAAO,cAAc,CAAC,UAAU,CAAC,yBAAyB,CAAC,eAAe,CAAC,CAAC;AAC9E,CAAC;AAeD;;;GAGG;AACH,MAAM,OAAO,oBAAoB;IACvB,MAAM,CAAC,QAAQ,GAAgC,IAAI,CAAC;IAE3C,QAAQ,GAAG,IAAI,GAAG,EAA6B,CAAC;IAEjE;;OAEG;IACH,MAAM,CAAC,WAAW;QAChB,IAAI,CAAC,oBAAoB,CAAC,QAAQ;YAAE,oBAAoB,CAAC,QAAQ,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC/F,OAAO,oBAAoB,CAAC,QAAQ,CAAC;IACvC,CAAC;IAED,yCAAyC;IACzC,MAAM,CAAC,aAAa;QAClB,oBAAoB,CAAC,QAAQ,GAAG,IAAI,CAAC;IACvC,CAAC;IAED;;;;;;;;;;OAUG;IACH,YAAY,CAAC,WAAmB,EAAE,OAAe,EAAE,MAAc,IAAI,CAAC,GAAG,EAAE;QACzE,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,aAAa,GAAG,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,yBAAyB,CAAC,yBAAyB,CAAC,CAAC;QAC/H,MAAM,MAAM,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QACzC,MAAM,MAAM,GAAe,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC;QAC1D,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QAC1D,IAAI,IAAI;YAAE,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC;QACrC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;QACtB,QAAQ,CAAC,KAAK,CAAC,aAAa,EAAE,MAAM,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;QAC1D,IAAI,MAAM,CAAC,cAAc;YAAE,QAAQ,CAAC,KAAK,CAAC,aAAa,EAAE,MAAM,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;QACrF,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;;;;OAQG;IACH,gBAAgB,CAAC,WAAmB,EAAE,cAAsB,EAAE,QAA4B;QACxF,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QACzC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QACzC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;QAChD,OAAO,KAAK,CAAC,WAAW,CAAC,IAAI,GAAG,yBAAyB,CAAC,yBAAyB,EAAE,CAAC;YACpF,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;YACrD,IAAI,MAAM,KAAK,SAAS;gBAAE,MAAM;YAChC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,EAAE,cAAc,KAAK,cAAc,EAAE,CAAC;YACpD,IAAI,QAAQ;gBAAE,KAAK,CAAC,MAAM,CAAC,YAAY,GAAG,QAAQ,CAAC;;gBAC9C,OAAO,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC;QACxC,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,aAAa,CAAC,WAAmB;QAC/B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAChD,CAAC;IAED;;;;;;OAMG;IACH,cAAc,CAAC,WAAmB,EAAE,MAAc,IAAI,CAAC,GAAG,EAAE;QAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM;YAAE,OAAO,SAAS,CAAC;QAC9B,OAAO,GAAG,GAAG,MAAM,CAAC,UAAU,IAAI,yBAAyB,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IACjG,CAAC;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,wBAAwB,CACtB,WAAmB,EACnB,SAA6B,EAC7B,UAA0B,EAAE;QAE5B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QACtC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;YAC7C,OAAO,IAAI;gBACT,CAAC,CAAC,EAAE,MAAM,EAAE,qBAAqB,EAAE,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,mEAAmE,EAAE;gBACnK,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,gDAAgD,EAAE,CAAC;QACxF,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;QACrD,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAC;QAC1G,IAAI,SAAS,KAAK,MAAM,CAAC,cAAc,EAAE,CAAC;YACxC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC;QACrG,CAAC;QACD,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;YACtB,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,EAAE,CAAC;QACtG,CAAC;QACD,IAAI,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,CAAC,EAAE,CAAC;YACzF,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,wCAAwC,EAAE,CAAC;QACzH,CAAC;QACD,OAAO;YACL,MAAM,EAAE,oBAAoB;YAC5B,cAAc,EAAE,MAAM,CAAC,cAAc;YACrC,MAAM;YACN,MAAM,EAAE,+EAA+E;SACxF,CAAC;IACJ,CAAC;IAED;;;;;;;;;;OAUG;IACH,iBAAiB,CACf,WAAmB,EACnB,cAAsB,EACtB,UAA8D,EAAE;QAEhE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QACtC,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,CAAC;YAC/B,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,sCAAsC,EAAE,CAAC;QACpF,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;QACrD,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAC;QAC/E,MAAM,WAAW,GAAG,MAAM,CAAC,cAAc,IAAI,OAAO,CAAC,oBAAoB,CAAC;QAC1E,IAAI,WAAW,KAAK,cAAc,EAAE,CAAC;YACnC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC;QAC1E,CAAC;QACD,IAAI,OAAO,CAAC,SAAS;YAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,EAAE,CAAC;QAChG,IAAI,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,aAAa,EAAE,cAAc,EAAE,GAAG,CAAC,EAAE,CAAC;YAC9F,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,wCAAwC,EAAE,CAAC;QAC9F,CAAC;QACD,OAAO;YACL,MAAM,EAAE,oBAAoB;YAC5B,MAAM;YACN,MAAM,EAAE,+EAA+E;SACxF,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,cAAc,CACZ,WAAmB,EACnB,MAAqE,EACrE,kBAAkE,EAClE,MAAc,IAAI,CAAC,GAAG,EAAE;QAExB,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;QACpD,MAAM,oBAAoB,GACxB,KAAK,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,kBAAkB,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACxF,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,CAAC,WAAW,EAAE,MAAM,CAAC,SAAS,EAAE;YACrE,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,oBAAoB;YACpB,GAAG;SACJ,CAAC,CAAC;QACH,IAAI,QAAQ,CAAC,MAAM,KAAK,oBAAoB,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YACjE,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,CAAC;QACvG,CAAC;QACD,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;QAC/B,MAAM,IAAI,GAAmB,MAAM,CAAC,cAAc;YAChD,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,cAAc,EAAE,QAAQ,EAAE,MAAM,CAAC,aAAa,EAAE;YACrF,CAAC,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,CAAC;QACpE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAC5B,CAAC;IAED;;;;;;;OAOG;IACK,gBAAgB,CAAC,IAAqC,EAAE,GAAW,EAAE,GAAW;QACtF,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;QAC1B,OAAO,EAAE,KAAK,SAAS,IAAI,GAAG,GAAG,EAAE,IAAI,yBAAyB,CAAC,iBAAiB,CAAC;IACrF,CAAC;IAED;;;OAGG;IACH;;;;;;OAMG;IACH,gBAAgB,CAAC,WAAmB;QAClC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,aAAa,CAAC;IACvD,CAAC;IAEO,QAAQ,CAAC,WAAmB;QAClC,IAAI,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC3C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG,EAAE,aAAa,EAAE,IAAI,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,GAAG,EAAE,EAAE,WAAW,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;YACvF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;;AAGH;;;;;;;GAOG;AACH,SAAS,QAAQ,CAAC,GAAwB,EAAE,GAAW,EAAE,EAAU;IACjE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAChB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACjB,OAAO,GAAG,CAAC,IAAI,GAAG,yBAAyB,CAAC,yBAAyB,EAAE,CAAC;QACtE,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;QACvC,IAAI,MAAM,KAAK,SAAS;YAAE,MAAM;QAChC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACrB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where an agent's message to the owner goes — decided by the harness from
|
|
3
|
+
* references, never from places the agent guessed
|
|
4
|
+
* (specs/2026-10-02-harness-owned-routing.md §1).
|
|
5
|
+
*
|
|
6
|
+
* Incident (TKT-187, 2026-10-02): Owen ran `reply-chat --thread <#pro-ce key>`
|
|
7
|
+
* with no conversation; the endpoint stored it against the globally newest
|
|
8
|
+
* conversation (an unrelated huddle), filed it as status for the
|
|
9
|
+
* orchestrator and answered `success: true`. The follow-up work item knew the
|
|
10
|
+
* right thread the whole time.
|
|
11
|
+
*
|
|
12
|
+
* Order:
|
|
13
|
+
* 1. the referenced message's conversation / thread;
|
|
14
|
+
* 2. the referenced ticket's thread (request ticket chat thread, project
|
|
15
|
+
* ticket thread binding) or decision card's thread;
|
|
16
|
+
* 3. the referenced work item's origin / destination;
|
|
17
|
+
* 4. validated hints (agent-supplied conversation / thread ids);
|
|
18
|
+
* 5. the reference the harness last prompted the agent about, when newer
|
|
19
|
+
* than its last owner turn;
|
|
20
|
+
* 6. the agent's turn origin / current work;
|
|
21
|
+
* 7. the agent's owner DM.
|
|
22
|
+
*
|
|
23
|
+
* Pure decision logic; collaborators are injected
|
|
24
|
+
* (`reply-destination.wiring.ts` wires the real ones).
|
|
25
|
+
*
|
|
26
|
+
* @module services/orc/reply-destination-resolver
|
|
27
|
+
*/
|
|
28
|
+
import type { WorkItem } from '../../types/v2/work-item.types.js';
|
|
29
|
+
import type { TurnOrigin } from './orc-reply-route.service.js';
|
|
30
|
+
import { type PromptReference, type ReplyReference } from './agent-prompt-reference.service.js';
|
|
31
|
+
import { type WorkDestination } from './work-item-destination.js';
|
|
32
|
+
export type { ReplyReference } from './agent-prompt-reference.service.js';
|
|
33
|
+
/** Agent-supplied ids: hints only. */
|
|
34
|
+
export interface ReplyHints {
|
|
35
|
+
/** `--conversation` / `--channel` (chat-v2 id) */
|
|
36
|
+
conversationId?: string;
|
|
37
|
+
/** `--thread`: a Slack thread key `C…:ts` or a chat-v2 message id */
|
|
38
|
+
thread?: string;
|
|
39
|
+
/** `slack-post --target` / upload channel (a Slack channel id), when one was named */
|
|
40
|
+
slackChannelId?: string;
|
|
41
|
+
}
|
|
42
|
+
/** Which step decided. */
|
|
43
|
+
export type ReplyDestinationSource = 'message' | 'ticket' | 'decision' | 'work-item' | 'hint' | 'prompt' | 'turn-origin' | 'current-work' | 'owner-dm';
|
|
44
|
+
/** Where the message goes. */
|
|
45
|
+
export type ReplyDestination =
|
|
46
|
+
/** A chat-v2 conversation the agent belongs to (DM / room / huddle), in `thread` (Slack key or chat-v2 root id) */
|
|
47
|
+
{
|
|
48
|
+
kind: 'conversation';
|
|
49
|
+
conversationId: string;
|
|
50
|
+
thread?: string;
|
|
51
|
+
source: ReplyDestinationSource;
|
|
52
|
+
reason: string;
|
|
53
|
+
}
|
|
54
|
+
/** A Slack place outside any chat conversation (ticket thread, trigger destination, team channel top level) */
|
|
55
|
+
| {
|
|
56
|
+
kind: 'work';
|
|
57
|
+
destination: Exclude<WorkDestination, {
|
|
58
|
+
kind: 'owner-origin';
|
|
59
|
+
}>;
|
|
60
|
+
source: ReplyDestinationSource;
|
|
61
|
+
reason: string;
|
|
62
|
+
}
|
|
63
|
+
/** Nothing the harness can stand behind; `fix` is the command to tell the agent */
|
|
64
|
+
| {
|
|
65
|
+
kind: 'unresolved';
|
|
66
|
+
reason: string;
|
|
67
|
+
fix: string;
|
|
68
|
+
};
|
|
69
|
+
/** A hint that was not used, and why (logged by the caller). */
|
|
70
|
+
export interface IgnoredHint {
|
|
71
|
+
hint: string;
|
|
72
|
+
why: string;
|
|
73
|
+
}
|
|
74
|
+
/** Result of {@link resolveReplyDestination}. */
|
|
75
|
+
export interface ReplyResolution {
|
|
76
|
+
destination: ReplyDestination;
|
|
77
|
+
ignoredHints: IgnoredHint[];
|
|
78
|
+
}
|
|
79
|
+
/** The chat-v2 message fields the resolver reads. */
|
|
80
|
+
export interface ResolverChatMessage {
|
|
81
|
+
id: string;
|
|
82
|
+
channelId: string;
|
|
83
|
+
threadId?: string;
|
|
84
|
+
metadata?: Record<string, unknown>;
|
|
85
|
+
}
|
|
86
|
+
/** A request ticket's conversation. */
|
|
87
|
+
export interface ResolverRequestTicket {
|
|
88
|
+
id: string;
|
|
89
|
+
label: string;
|
|
90
|
+
conversationId?: string;
|
|
91
|
+
threadRootId?: string;
|
|
92
|
+
slackChannelId?: string;
|
|
93
|
+
threadTs?: string;
|
|
94
|
+
}
|
|
95
|
+
/** A decision's card place. */
|
|
96
|
+
export interface ResolverDecision {
|
|
97
|
+
id: string;
|
|
98
|
+
asker: string;
|
|
99
|
+
requestedBy?: string;
|
|
100
|
+
slackChannelId?: string;
|
|
101
|
+
threadTs?: string;
|
|
102
|
+
ticket?: {
|
|
103
|
+
projectPath: string;
|
|
104
|
+
id: string;
|
|
105
|
+
title?: string;
|
|
106
|
+
};
|
|
107
|
+
teamId?: string;
|
|
108
|
+
}
|
|
109
|
+
/** Collaborators. */
|
|
110
|
+
export interface ReplyResolverDeps {
|
|
111
|
+
/** A chat-v2 message by id */
|
|
112
|
+
getMessage(id: string): ResolverChatMessage | null;
|
|
113
|
+
/** Whether the agent may post in a chat-v2 conversation (its DM, a room it is in) */
|
|
114
|
+
ownsConversation(session: string, conversationId: string): Promise<boolean>;
|
|
115
|
+
/** The Slack channel a chat-v2 conversation is mirrored to (team channel / DM link), or null */
|
|
116
|
+
slackChannelOfConversation(conversationId: string): string | null;
|
|
117
|
+
/** The chat-v2 conversation (and thread root) a Slack thread lives in, or null */
|
|
118
|
+
conversationOfSlackThread(slackChannelId: string, threadTs: string): {
|
|
119
|
+
conversationId: string;
|
|
120
|
+
threadRootId?: string;
|
|
121
|
+
} | null;
|
|
122
|
+
/** A request ticket by number */
|
|
123
|
+
requestTicket(ticketNumber: number): Promise<ResolverRequestTicket | null>;
|
|
124
|
+
/** A project ticket the agent can be talking about */
|
|
125
|
+
projectTicket(session: string, ticketId: string): Promise<{
|
|
126
|
+
projectPath: string;
|
|
127
|
+
ticketId: string;
|
|
128
|
+
title?: string;
|
|
129
|
+
teamId?: string;
|
|
130
|
+
} | null>;
|
|
131
|
+
/** A decision by id */
|
|
132
|
+
decision(id: string): Promise<ResolverDecision | null>;
|
|
133
|
+
/** A work item by id */
|
|
134
|
+
workItem(id: string): Promise<WorkItem | null>;
|
|
135
|
+
/** Every pool item (for the agent's current work) */
|
|
136
|
+
poolItems(): Promise<WorkItem[]>;
|
|
137
|
+
/** The agent's last owner turn origin */
|
|
138
|
+
turnOrigin(session: string): TurnOrigin | undefined;
|
|
139
|
+
/** What the harness last prompted the agent about */
|
|
140
|
+
promptReference(session: string): PromptReference | undefined;
|
|
141
|
+
/** Whether the agent owes the owner an answer (owner-message watchdog) */
|
|
142
|
+
owesOwner(session: string): boolean;
|
|
143
|
+
/** Head of the last message delivered to the agent */
|
|
144
|
+
lastDelivered(session: string): string | undefined;
|
|
145
|
+
/** The agent's owner DM conversation (chat-v2), or null */
|
|
146
|
+
ownerDm(session: string): Promise<string | null>;
|
|
147
|
+
/** Clock (epoch ms) */
|
|
148
|
+
now(): number;
|
|
149
|
+
}
|
|
150
|
+
/** Input of {@link resolveReplyDestination}. */
|
|
151
|
+
export interface ReplyResolveInput {
|
|
152
|
+
session: string;
|
|
153
|
+
reference?: ReplyReference;
|
|
154
|
+
hints?: ReplyHints;
|
|
155
|
+
/**
|
|
156
|
+
* Skip the owner-DM fallback (step 7) — for posts that must not land in
|
|
157
|
+
* the DM, e.g. the `[DONE]` notice.
|
|
158
|
+
*/
|
|
159
|
+
noOwnerDm?: boolean;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* The thread an answer to `msg` belongs in: its Slack thread key when the
|
|
163
|
+
* conversation is mirrored to Slack and the message knows its Slack thread,
|
|
164
|
+
* else its chat-v2 thread root.
|
|
165
|
+
*
|
|
166
|
+
* @param msg - chat-v2 message
|
|
167
|
+
* @param slackChannelId - The conversation's Slack channel, if any
|
|
168
|
+
* @returns Thread reference
|
|
169
|
+
*/
|
|
170
|
+
export declare function threadOfMessage(msg: ResolverChatMessage, slackChannelId: string | null): string;
|
|
171
|
+
/**
|
|
172
|
+
* The command the agent should run when its message could not be placed.
|
|
173
|
+
*
|
|
174
|
+
* @param prompt - The agent's last prompt reference, if any
|
|
175
|
+
* @returns An English instruction
|
|
176
|
+
*/
|
|
177
|
+
export declare function fixCommand(prompt?: ReplyReference): string;
|
|
178
|
+
/**
|
|
179
|
+
* Resolve one reference (steps 1–3).
|
|
180
|
+
*
|
|
181
|
+
* @param session - Agent
|
|
182
|
+
* @param ref - Reference
|
|
183
|
+
* @param deps - Collaborators
|
|
184
|
+
* @returns A destination; `unresolved` when the reference is wrong; null when it names nothing usable (continue)
|
|
185
|
+
*/
|
|
186
|
+
export declare function resolveReference(session: string, ref: ReplyReference, deps: ReplyResolverDeps): Promise<ReplyDestination | null>;
|
|
187
|
+
/**
|
|
188
|
+
* Validate agent-supplied ids (step 4).
|
|
189
|
+
*
|
|
190
|
+
* @param session - Agent
|
|
191
|
+
* @param hints - Its ids
|
|
192
|
+
* @param origin - Its turn origin (an origin in the same conversation supplies the thread)
|
|
193
|
+
* @param deps - Collaborators
|
|
194
|
+
* @returns The conversation they validly name (or null) and every hint ignored
|
|
195
|
+
*/
|
|
196
|
+
export declare function validateHints(session: string, hints: ReplyHints, origin: TurnOrigin | undefined, deps: ReplyResolverDeps): Promise<{
|
|
197
|
+
destination: ReplyDestination | null;
|
|
198
|
+
ignored: IgnoredHint[];
|
|
199
|
+
}>;
|
|
200
|
+
/**
|
|
201
|
+
* Whether a prompt reference may steer a bare reply: the agent owes the
|
|
202
|
+
* owner nothing, and the last message delivered to it is that prompt.
|
|
203
|
+
*
|
|
204
|
+
* @param session - Agent
|
|
205
|
+
* @param prompt - Its prompt reference
|
|
206
|
+
* @param deps - Collaborators
|
|
207
|
+
* @returns True to use it
|
|
208
|
+
*/
|
|
209
|
+
export declare function promptIsCurrent(session: string, prompt: PromptReference, deps: Pick<ReplyResolverDeps, 'owesOwner' | 'lastDelivered'>): boolean;
|
|
210
|
+
/**
|
|
211
|
+
* Decide where an agent's message goes. See module docs for the order.
|
|
212
|
+
*
|
|
213
|
+
* @param input - Agent, references, hints
|
|
214
|
+
* @param deps - Collaborators
|
|
215
|
+
* @returns The destination and the hints that were ignored
|
|
216
|
+
*/
|
|
217
|
+
export declare function resolveReplyDestination(input: ReplyResolveInput, deps: ReplyResolverDeps): Promise<ReplyResolution>;
|
|
218
|
+
//# sourceMappingURL=reply-destination-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reply-destination-resolver.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/orc/reply-destination-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where an agent's message to the owner goes — decided by the harness from
|
|
3
|
+
* references, never from places the agent guessed
|
|
4
|
+
* (specs/2026-10-02-harness-owned-routing.md §1).
|
|
5
|
+
*
|
|
6
|
+
* Incident (TKT-187, 2026-10-02): Owen ran `reply-chat --thread <#pro-ce key>`
|
|
7
|
+
* with no conversation; the endpoint stored it against the globally newest
|
|
8
|
+
* conversation (an unrelated huddle), filed it as status for the
|
|
9
|
+
* orchestrator and answered `success: true`. The follow-up work item knew the
|
|
10
|
+
* right thread the whole time.
|
|
11
|
+
*
|
|
12
|
+
* Order:
|
|
13
|
+
* 1. the referenced message's conversation / thread;
|
|
14
|
+
* 2. the referenced ticket's thread (request ticket chat thread, project
|
|
15
|
+
* ticket thread binding) or decision card's thread;
|
|
16
|
+
* 3. the referenced work item's origin / destination;
|
|
17
|
+
* 4. validated hints (agent-supplied conversation / thread ids);
|
|
18
|
+
* 5. the reference the harness last prompted the agent about, when newer
|
|
19
|
+
* than its last owner turn;
|
|
20
|
+
* 6. the agent's turn origin / current work;
|
|
21
|
+
* 7. the agent's owner DM.
|
|
22
|
+
*
|
|
23
|
+
* Pure decision logic; collaborators are injected
|
|
24
|
+
* (`reply-destination.wiring.ts` wires the real ones).
|
|
25
|
+
*
|
|
26
|
+
* @module services/orc/reply-destination-resolver
|
|
27
|
+
*/
|
|
28
|
+
import { REPLY_ROUTING_CONSTANTS, SLACK_THREAD_KEY_CONSTANTS } from '../../constants.js';
|
|
29
|
+
import { parseTicketNumber } from '../../types/v2/ticket.types.js';
|
|
30
|
+
import { formatSlackThreadKey, parseSlackThreadKey } from '../slack/slack-thread-key.js';
|
|
31
|
+
import { hasReference } from './agent-prompt-reference.service.js';
|
|
32
|
+
import { currentWorkItemOf, originOfWorkItem, planWorkDestination } from './work-item-destination.js';
|
|
33
|
+
/**
|
|
34
|
+
* The thread an answer to `msg` belongs in: its Slack thread key when the
|
|
35
|
+
* conversation is mirrored to Slack and the message knows its Slack thread,
|
|
36
|
+
* else its chat-v2 thread root.
|
|
37
|
+
*
|
|
38
|
+
* @param msg - chat-v2 message
|
|
39
|
+
* @param slackChannelId - The conversation's Slack channel, if any
|
|
40
|
+
* @returns Thread reference
|
|
41
|
+
*/
|
|
42
|
+
export function threadOfMessage(msg, slackChannelId) {
|
|
43
|
+
const meta = msg.metadata ?? {};
|
|
44
|
+
const named = parseSlackThreadKey(meta[SLACK_THREAD_KEY_CONSTANTS.METADATA_KEY]);
|
|
45
|
+
if (named)
|
|
46
|
+
return formatSlackThreadKey(named.slackChannelId, named.threadTs);
|
|
47
|
+
const ts = typeof meta.slackThreadTs === 'string' && meta.slackThreadTs ? meta.slackThreadTs : undefined;
|
|
48
|
+
if (ts && slackChannelId)
|
|
49
|
+
return formatSlackThreadKey(slackChannelId, ts);
|
|
50
|
+
return msg.threadId ?? msg.id;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The command the agent should run when its message could not be placed.
|
|
54
|
+
*
|
|
55
|
+
* @param prompt - The agent's last prompt reference, if any
|
|
56
|
+
* @returns An English instruction
|
|
57
|
+
*/
|
|
58
|
+
export function fixCommand(prompt) {
|
|
59
|
+
if (prompt?.ticket)
|
|
60
|
+
return `reply --ticket ${prompt.ticket} "<your message>"`;
|
|
61
|
+
if (prompt?.decisionId)
|
|
62
|
+
return `reply --decision ${prompt.decisionId} "<your message>"`;
|
|
63
|
+
if (prompt?.workItemId)
|
|
64
|
+
return `reply --work-item ${prompt.workItemId} "<your message>"`;
|
|
65
|
+
if (prompt?.messageId)
|
|
66
|
+
return `reply --to ${prompt.messageId} "<your message>"`;
|
|
67
|
+
return 'reply "<your message>"';
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Resolve one reference (steps 1–3).
|
|
71
|
+
*
|
|
72
|
+
* @param session - Agent
|
|
73
|
+
* @param ref - Reference
|
|
74
|
+
* @param deps - Collaborators
|
|
75
|
+
* @returns A destination; `unresolved` when the reference is wrong; null when it names nothing usable (continue)
|
|
76
|
+
*/
|
|
77
|
+
export async function resolveReference(session, ref, deps) {
|
|
78
|
+
if (ref.messageId) {
|
|
79
|
+
const msg = deps.getMessage(ref.messageId);
|
|
80
|
+
if (!msg)
|
|
81
|
+
return { kind: 'unresolved', reason: `there is no message ${ref.messageId}`, fix: fixCommand() };
|
|
82
|
+
if (!(await deps.ownsConversation(session, msg.channelId))) {
|
|
83
|
+
return { kind: 'unresolved', reason: `you are not in the conversation of message ${ref.messageId}`, fix: fixCommand() };
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
kind: 'conversation',
|
|
87
|
+
conversationId: msg.channelId,
|
|
88
|
+
thread: threadOfMessage(msg, deps.slackChannelOfConversation(msg.channelId)),
|
|
89
|
+
source: 'message',
|
|
90
|
+
reason: `answering message ${ref.messageId}`,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
if (ref.ticket) {
|
|
94
|
+
const label = ref.ticket.trim();
|
|
95
|
+
const n = REPLY_ROUTING_CONSTANTS.REQUEST_TICKET_PATTERN.test(label) ? parseTicketNumber(label) : null;
|
|
96
|
+
if (n !== null) {
|
|
97
|
+
const t = await deps.requestTicket(n);
|
|
98
|
+
if (!t)
|
|
99
|
+
return { kind: 'unresolved', reason: `there is no ticket ${label}`, fix: fixCommand() };
|
|
100
|
+
const key = t.slackChannelId && t.threadTs ? formatSlackThreadKey(t.slackChannelId, t.threadTs) : undefined;
|
|
101
|
+
if (t.conversationId) {
|
|
102
|
+
return {
|
|
103
|
+
kind: 'conversation',
|
|
104
|
+
conversationId: t.conversationId,
|
|
105
|
+
...(key || t.threadRootId ? { thread: key ?? t.threadRootId } : {}),
|
|
106
|
+
source: 'ticket',
|
|
107
|
+
reason: `ticket ${t.label}'s thread`,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
if (t.slackChannelId && t.threadTs) {
|
|
111
|
+
const mapped = deps.conversationOfSlackThread(t.slackChannelId, t.threadTs);
|
|
112
|
+
if (mapped)
|
|
113
|
+
return { kind: 'conversation', conversationId: mapped.conversationId, thread: key, source: 'ticket', reason: `ticket ${t.label}'s thread` };
|
|
114
|
+
return {
|
|
115
|
+
kind: 'work',
|
|
116
|
+
destination: { kind: 'slack', target: t.slackChannelId, threadTs: t.threadTs, reason: `ticket ${t.label}'s Slack thread` },
|
|
117
|
+
source: 'ticket',
|
|
118
|
+
reason: `ticket ${t.label}'s Slack thread`,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
return { kind: 'unresolved', reason: `ticket ${t.label} has no conversation to answer in`, fix: 'reply --to <message id from your prompt> "<your message>"' };
|
|
122
|
+
}
|
|
123
|
+
if (REPLY_ROUTING_CONSTANTS.PROJECT_TICKET_PATTERN.test(label)) {
|
|
124
|
+
const pt = await deps.projectTicket(session, label);
|
|
125
|
+
if (!pt)
|
|
126
|
+
return { kind: 'unresolved', reason: `there is no project ticket ${label} you are working on`, fix: fixCommand() };
|
|
127
|
+
return {
|
|
128
|
+
kind: 'work',
|
|
129
|
+
destination: {
|
|
130
|
+
kind: 'ticket-thread',
|
|
131
|
+
projectPath: pt.projectPath,
|
|
132
|
+
ticketId: pt.ticketId,
|
|
133
|
+
...(pt.title ? { title: pt.title } : {}),
|
|
134
|
+
...(pt.teamId ? { teamId: pt.teamId } : {}),
|
|
135
|
+
reason: `ticket ${pt.ticketId}'s thread`,
|
|
136
|
+
},
|
|
137
|
+
source: 'ticket',
|
|
138
|
+
reason: `ticket ${pt.ticketId}'s thread`,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
return { kind: 'unresolved', reason: `"${label}" is not a ticket id (TKT-187 or CE-7)`, fix: fixCommand() };
|
|
142
|
+
}
|
|
143
|
+
if (ref.decisionId) {
|
|
144
|
+
const d = await deps.decision(ref.decisionId.trim().toUpperCase());
|
|
145
|
+
if (!d)
|
|
146
|
+
return { kind: 'unresolved', reason: `there is no decision ${ref.decisionId}`, fix: fixCommand() };
|
|
147
|
+
if (d.asker !== session && d.requestedBy !== session) {
|
|
148
|
+
return { kind: 'unresolved', reason: `decision ${d.id} was not asked by you`, fix: fixCommand() };
|
|
149
|
+
}
|
|
150
|
+
if (d.slackChannelId && d.threadTs) {
|
|
151
|
+
const mapped = deps.conversationOfSlackThread(d.slackChannelId, d.threadTs);
|
|
152
|
+
if (mapped && (await deps.ownsConversation(session, mapped.conversationId))) {
|
|
153
|
+
return { kind: 'conversation', conversationId: mapped.conversationId, thread: formatSlackThreadKey(d.slackChannelId, d.threadTs), source: 'decision', reason: `decision ${d.id}'s thread` };
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
kind: 'work',
|
|
157
|
+
destination: { kind: 'slack', target: d.slackChannelId, threadTs: d.threadTs, reason: `decision ${d.id}'s card thread` },
|
|
158
|
+
source: 'decision',
|
|
159
|
+
reason: `decision ${d.id}'s card thread`,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
if (d.ticket) {
|
|
163
|
+
return {
|
|
164
|
+
kind: 'work',
|
|
165
|
+
destination: { kind: 'ticket-thread', projectPath: d.ticket.projectPath, ticketId: d.ticket.id, ...(d.ticket.title ? { title: d.ticket.title } : {}), ...(d.teamId ? { teamId: d.teamId } : {}), reason: `decision ${d.id}'s ticket thread` },
|
|
166
|
+
source: 'decision',
|
|
167
|
+
reason: `decision ${d.id}'s ticket thread`,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
if (ref.workItemId) {
|
|
173
|
+
const wi = await deps.workItem(ref.workItemId);
|
|
174
|
+
if (!wi)
|
|
175
|
+
return { kind: 'unresolved', reason: `there is no work item ${ref.workItemId}`, fix: fixCommand() };
|
|
176
|
+
return fromWorkItem(wi, 'work-item', deps);
|
|
177
|
+
}
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Where a work item's answer goes (its origin / destination). A work item
|
|
182
|
+
* with no recorded origin gives null (continue with the next step).
|
|
183
|
+
*
|
|
184
|
+
* @param wi - Work item
|
|
185
|
+
* @param source - Step label
|
|
186
|
+
* @param deps - Collaborators (clock)
|
|
187
|
+
* @returns Destination or null
|
|
188
|
+
*/
|
|
189
|
+
function fromWorkItem(wi, source, deps) {
|
|
190
|
+
if (!originOfWorkItem(wi))
|
|
191
|
+
return null;
|
|
192
|
+
const planned = planWorkDestination({ workItem: wi, now: deps.now() });
|
|
193
|
+
if (planned.kind === 'owner-origin') {
|
|
194
|
+
const o = planned.origin;
|
|
195
|
+
const thread = o.slackThreadKey ?? o.chatThreadId;
|
|
196
|
+
return { kind: 'conversation', conversationId: o.conversationId, ...(thread ? { thread } : {}), source, reason: planned.reason };
|
|
197
|
+
}
|
|
198
|
+
return { kind: 'work', destination: planned, source, reason: planned.reason };
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Validate agent-supplied ids (step 4).
|
|
202
|
+
*
|
|
203
|
+
* @param session - Agent
|
|
204
|
+
* @param hints - Its ids
|
|
205
|
+
* @param origin - Its turn origin (an origin in the same conversation supplies the thread)
|
|
206
|
+
* @param deps - Collaborators
|
|
207
|
+
* @returns The conversation they validly name (or null) and every hint ignored
|
|
208
|
+
*/
|
|
209
|
+
export async function validateHints(session, hints, origin, deps) {
|
|
210
|
+
const ignored = [];
|
|
211
|
+
const conv = hints.conversationId?.trim() || undefined;
|
|
212
|
+
const rawThread = hints.thread?.trim() || undefined;
|
|
213
|
+
const key = parseSlackThreadKey(rawThread);
|
|
214
|
+
const target = hints.slackChannelId?.trim() || undefined;
|
|
215
|
+
if (key) {
|
|
216
|
+
const keyText = formatSlackThreadKey(key.slackChannelId, key.threadTs);
|
|
217
|
+
if (target && target !== key.slackChannelId) {
|
|
218
|
+
ignored.push({ hint: `target ${target}`, why: `thread ${keyText} is in channel ${key.slackChannelId}, not ${target}` });
|
|
219
|
+
}
|
|
220
|
+
if (conv) {
|
|
221
|
+
const convSlack = deps.slackChannelOfConversation(conv);
|
|
222
|
+
if (convSlack === key.slackChannelId && (await deps.ownsConversation(session, conv))) {
|
|
223
|
+
return { destination: { kind: 'conversation', conversationId: conv, thread: keyText, source: 'hint', reason: 'named its conversation and thread' }, ignored };
|
|
224
|
+
}
|
|
225
|
+
ignored.push({
|
|
226
|
+
hint: `conversation ${conv}`,
|
|
227
|
+
why: convSlack === key.slackChannelId ? 'you are not in that conversation' : `thread ${keyText} is not in that conversation (its Slack channel is ${convSlack ?? 'none'})`,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
const mapped = deps.conversationOfSlackThread(key.slackChannelId, key.threadTs);
|
|
231
|
+
if (mapped && (await deps.ownsConversation(session, mapped.conversationId))) {
|
|
232
|
+
return { destination: { kind: 'conversation', conversationId: mapped.conversationId, thread: keyText, source: 'hint', reason: `Slack thread ${keyText} mapped to its conversation` }, ignored };
|
|
233
|
+
}
|
|
234
|
+
ignored.push({ hint: `thread ${keyText}`, why: mapped ? 'you are not in the conversation of that thread' : 'no known conversation has that Slack thread' });
|
|
235
|
+
return { destination: null, ignored };
|
|
236
|
+
}
|
|
237
|
+
if (rawThread) {
|
|
238
|
+
const msg = deps.getMessage(rawThread);
|
|
239
|
+
if (msg && (!conv || msg.channelId === conv) && (await deps.ownsConversation(session, msg.channelId))) {
|
|
240
|
+
return {
|
|
241
|
+
destination: { kind: 'conversation', conversationId: msg.channelId, thread: threadOfMessage(msg, deps.slackChannelOfConversation(msg.channelId)), source: 'hint', reason: 'named a thread in its conversation' },
|
|
242
|
+
ignored,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
ignored.push({ hint: `thread ${rawThread}`, why: !msg ? 'no such message' : msg.channelId !== conv && conv ? `that message is not in conversation ${conv}` : 'you are not in its conversation' });
|
|
246
|
+
// A thread that is ANOTHER conversation's message contradicts the
|
|
247
|
+
// conversation: neither is used. An unknown id only loses the thread.
|
|
248
|
+
if (conv && msg) {
|
|
249
|
+
ignored.push({ hint: `conversation ${conv}`, why: 'its thread is in another conversation' });
|
|
250
|
+
return { destination: null, ignored };
|
|
251
|
+
}
|
|
252
|
+
if (!conv)
|
|
253
|
+
return { destination: null, ignored };
|
|
254
|
+
}
|
|
255
|
+
if (conv) {
|
|
256
|
+
if (await deps.ownsConversation(session, conv)) {
|
|
257
|
+
const thread = origin?.conversationId === conv ? origin.slackThreadKey ?? origin.chatThreadId : undefined;
|
|
258
|
+
return { destination: { kind: 'conversation', conversationId: conv, ...(thread ? { thread } : {}), source: 'hint', reason: 'named its own conversation' }, ignored };
|
|
259
|
+
}
|
|
260
|
+
ignored.push({ hint: `conversation ${conv}`, why: 'not a conversation you are in' });
|
|
261
|
+
}
|
|
262
|
+
return { destination: null, ignored };
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Whether a prompt reference may steer a bare reply: the agent owes the
|
|
266
|
+
* owner nothing, and the last message delivered to it is that prompt.
|
|
267
|
+
*
|
|
268
|
+
* @param session - Agent
|
|
269
|
+
* @param prompt - Its prompt reference
|
|
270
|
+
* @param deps - Collaborators
|
|
271
|
+
* @returns True to use it
|
|
272
|
+
*/
|
|
273
|
+
export function promptIsCurrent(session, prompt, deps) {
|
|
274
|
+
if (!prompt.marker)
|
|
275
|
+
return false;
|
|
276
|
+
if (deps.owesOwner(session))
|
|
277
|
+
return false;
|
|
278
|
+
return (deps.lastDelivered(session) ?? '').includes(prompt.marker);
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Decide where an agent's message goes. See module docs for the order.
|
|
282
|
+
*
|
|
283
|
+
* @param input - Agent, references, hints
|
|
284
|
+
* @param deps - Collaborators
|
|
285
|
+
* @returns The destination and the hints that were ignored
|
|
286
|
+
*/
|
|
287
|
+
export async function resolveReplyDestination(input, deps) {
|
|
288
|
+
const { session } = input;
|
|
289
|
+
const ignoredHints = [];
|
|
290
|
+
const prompt = deps.promptReference(session);
|
|
291
|
+
// 1–3. Explicit references are authoritative: a wrong one is an error.
|
|
292
|
+
if (hasReference(input.reference)) {
|
|
293
|
+
const d = await resolveReference(session, input.reference, deps);
|
|
294
|
+
if (d)
|
|
295
|
+
return { destination: d, ignoredHints };
|
|
296
|
+
}
|
|
297
|
+
const origin = deps.turnOrigin(session);
|
|
298
|
+
// 4. Hints the harness can stand behind.
|
|
299
|
+
if (input.hints && (input.hints.conversationId || input.hints.thread)) {
|
|
300
|
+
const v = await validateHints(session, input.hints, origin, deps);
|
|
301
|
+
ignoredHints.push(...v.ignored);
|
|
302
|
+
if (v.destination)
|
|
303
|
+
return { destination: v.destination, ignoredHints };
|
|
304
|
+
}
|
|
305
|
+
// 5. What the harness last prompted the agent about — only when the agent
|
|
306
|
+
// owes the owner nothing and that prompt is the last thing it was given:
|
|
307
|
+
// a bare answer to a 10:00 owner question must not land in the thread of
|
|
308
|
+
// a 10:02 TKT-150 nudge (and close its promise).
|
|
309
|
+
if (prompt && promptIsCurrent(session, prompt, deps)) {
|
|
310
|
+
const d = await resolveReference(session, prompt.reference, deps);
|
|
311
|
+
if (d && d.kind !== 'unresolved')
|
|
312
|
+
return { destination: { ...d, source: 'prompt', reason: `the harness prompted you about it (${d.reason})` }, ignoredHints };
|
|
313
|
+
}
|
|
314
|
+
// 6. Turn origin / current work.
|
|
315
|
+
const items = await deps.poolItems().catch(() => []);
|
|
316
|
+
const workItem = currentWorkItemOf(items, session);
|
|
317
|
+
const planned = planWorkDestination({ workItem, ownerOrigin: origin, now: deps.now() });
|
|
318
|
+
if (planned.kind === 'owner-origin') {
|
|
319
|
+
const o = planned.origin;
|
|
320
|
+
const thread = o.slackThreadKey ?? o.chatThreadId;
|
|
321
|
+
const fromOwner = o === origin;
|
|
322
|
+
return {
|
|
323
|
+
destination: { kind: 'conversation', conversationId: o.conversationId, ...(thread ? { thread } : {}), source: fromOwner ? 'turn-origin' : 'current-work', reason: planned.reason },
|
|
324
|
+
ignoredHints,
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
const isScheduled = !!workItem && originOfWorkItem(workItem)?.kind === 'trigger';
|
|
328
|
+
if (planned.kind !== 'new-top-level' || isScheduled) {
|
|
329
|
+
return { destination: { kind: 'work', destination: planned, source: 'current-work', reason: planned.reason }, ignoredHints };
|
|
330
|
+
}
|
|
331
|
+
// 7. The owner DM; a team-channel top-level post only when there is none.
|
|
332
|
+
if (!input.noOwnerDm) {
|
|
333
|
+
const dm = await deps.ownerDm(session).catch(() => null);
|
|
334
|
+
if (dm)
|
|
335
|
+
return { destination: { kind: 'conversation', conversationId: dm, source: 'owner-dm', reason: `${planned.reason} — your DM with the owner` }, ignoredHints };
|
|
336
|
+
return { destination: { kind: 'work', destination: planned, source: 'current-work', reason: `${planned.reason} (no owner DM)` }, ignoredHints };
|
|
337
|
+
}
|
|
338
|
+
return {
|
|
339
|
+
destination: { kind: 'unresolved', reason: planned.reason, fix: fixCommand(prompt?.reference) },
|
|
340
|
+
ignoredHints,
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
//# sourceMappingURL=reply-destination-resolver.js.map
|