@tickernelz/paperclip-pro-server 2026.1012.0 → 2026.1012.1

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 (115) hide show
  1. package/dist/__tests__/helpers/runner-api-server.d.ts +1 -0
  2. package/dist/__tests__/helpers/runner-api-server.d.ts.map +1 -1
  3. package/dist/build-info.json +1 -1
  4. package/dist/routes/attention.d.ts.map +1 -1
  5. package/dist/routes/attention.js +12 -1
  6. package/dist/routes/attention.js.map +1 -1
  7. package/dist/routes/issues.d.ts.map +1 -1
  8. package/dist/routes/issues.js +106 -1
  9. package/dist/routes/issues.js.map +1 -1
  10. package/dist/routes/openapi.d.ts.map +1 -1
  11. package/dist/routes/openapi.js +30 -1
  12. package/dist/routes/openapi.js.map +1 -1
  13. package/dist/services/agents.d.ts +10 -10
  14. package/dist/services/chat-completion-delivery.d.ts +5 -0
  15. package/dist/services/chat-completion-delivery.d.ts.map +1 -1
  16. package/dist/services/chat-completion-delivery.js +16 -6
  17. package/dist/services/chat-completion-delivery.js.map +1 -1
  18. package/dist/services/connectors/slack.d.ts +13 -13
  19. package/dist/services/issue-thread-interaction-resolution.d.ts.map +1 -1
  20. package/dist/services/issue-thread-interaction-resolution.js +3 -0
  21. package/dist/services/issue-thread-interaction-resolution.js.map +1 -1
  22. package/dist/services/issue-thread-interactions.d.ts +1 -0
  23. package/dist/services/issue-thread-interactions.d.ts.map +1 -1
  24. package/dist/services/native-runtime/automatic-completion-reviews.d.ts +1 -0
  25. package/dist/services/native-runtime/automatic-completion-reviews.d.ts.map +1 -1
  26. package/dist/services/openwa/admission.d.ts.map +1 -1
  27. package/dist/services/openwa/admission.js +24 -5
  28. package/dist/services/openwa/admission.js.map +1 -1
  29. package/dist/services/openwa/approvals.d.ts +12 -0
  30. package/dist/services/openwa/approvals.d.ts.map +1 -1
  31. package/dist/services/openwa/approvals.js +35 -7
  32. package/dist/services/openwa/approvals.js.map +1 -1
  33. package/dist/services/openwa/authority.d.ts.map +1 -1
  34. package/dist/services/openwa/authority.js +1 -0
  35. package/dist/services/openwa/authority.js.map +1 -1
  36. package/dist/services/openwa/catalog.d.ts +1 -0
  37. package/dist/services/openwa/catalog.d.ts.map +1 -1
  38. package/dist/services/openwa/config-tool.d.ts.map +1 -1
  39. package/dist/services/openwa/config-tool.js +22 -3
  40. package/dist/services/openwa/config-tool.js.map +1 -1
  41. package/dist/services/openwa/guidance.d.ts +2 -0
  42. package/dist/services/openwa/guidance.d.ts.map +1 -1
  43. package/dist/services/openwa/guidance.js +27 -5
  44. package/dist/services/openwa/guidance.js.map +1 -1
  45. package/dist/services/openwa/owner-report.d.ts +24 -0
  46. package/dist/services/openwa/owner-report.d.ts.map +1 -0
  47. package/dist/services/openwa/owner-report.js +97 -0
  48. package/dist/services/openwa/owner-report.js.map +1 -0
  49. package/dist/services/openwa/owners.d.ts.map +1 -1
  50. package/dist/services/openwa/owners.js +4 -0
  51. package/dist/services/openwa/owners.js.map +1 -1
  52. package/dist/services/openwa/policy.d.ts +2 -0
  53. package/dist/services/openwa/policy.d.ts.map +1 -1
  54. package/dist/services/openwa/policy.js +11 -2
  55. package/dist/services/openwa/policy.js.map +1 -1
  56. package/dist/services/openwa/tools.d.ts +1 -0
  57. package/dist/services/openwa/tools.d.ts.map +1 -1
  58. package/dist/services/openwa/tools.js +21 -4
  59. package/dist/services/openwa/tools.js.map +1 -1
  60. package/dist/services/owner-decision-relay.d.ts +62 -0
  61. package/dist/services/owner-decision-relay.d.ts.map +1 -0
  62. package/dist/services/owner-decision-relay.js +433 -0
  63. package/dist/services/owner-decision-relay.js.map +1 -0
  64. package/package.json +21 -21
  65. package/skills/openwa/SKILL.md +51 -3
  66. package/skills/paperclip/SKILL.md +1 -1
  67. package/ui-dist/assets/{AgentAvatar-B47RVwPt.js → AgentAvatar-DySHTTwq.js} +1 -1
  68. package/ui-dist/assets/{Agents.production-CaL_roCY.js → Agents.production-CF5r1j38.js} +2 -2
  69. package/ui-dist/assets/{BreadcrumbContext-BRKP7-bF.js → BreadcrumbContext-C-JqFdLZ.js} +1 -1
  70. package/ui-dist/assets/{CompanyActivity.production-B5ko3U6C.js → CompanyActivity.production-BxAfcJub.js} +1 -1
  71. package/ui-dist/assets/{CompanyExport-D_8Cdnps.js → CompanyExport-CEeoEcyJ.js} +1 -1
  72. package/ui-dist/assets/{CompanySkills.production-DKpb4vb9.js → CompanySkills.production-DHEEarUk.js} +1 -1
  73. package/ui-dist/assets/{EmptyState-iwTwakaR.js → EmptyState-fxPFhH-R.js} +1 -1
  74. package/ui-dist/assets/{MarkdownBody-CbLdPc8E.js → MarkdownBody-CEcIElD-.js} +1 -1
  75. package/ui-dist/assets/{MarkdownEditor-98mZdmRX.js → MarkdownEditor-B6kwxxZP.js} +1 -1
  76. package/ui-dist/assets/{OrgChart.production-CpVPwEak.js → OrgChart.production-R4TqTezh.js} +1 -1
  77. package/ui-dist/assets/{PageSkeleton-Dl_gWB8z.js → PageSkeleton-iVZWoLsF.js} +1 -1
  78. package/ui-dist/assets/{RoutineDetail.production-CmUbfGto.js → RoutineDetail.production-RCCl99aO.js} +1 -1
  79. package/ui-dist/assets/{RoutineRunVariablesDialog-DrqOVV5i.js → RoutineRunVariablesDialog-BfaOkOdj.js} +1 -1
  80. package/ui-dist/assets/{Routines.production-C3-E_ij7.js → Routines.production-i7GS-uxC.js} +1 -1
  81. package/ui-dist/assets/{StatusIcon-Co-elrfc.js → StatusIcon-DxxLvme9.js} +1 -1
  82. package/ui-dist/assets/{ToastContext-CYUmn7f8.js → ToastContext-BbzJdb2r.js} +1 -1
  83. package/ui-dist/assets/{agent-avatar-url-B91C7fqh.js → agent-avatar-url-eBzFMwFS.js} +27 -27
  84. package/ui-dist/assets/{alert-dialog-CfwPsmAH.js → alert-dialog-Ctnjtpv6.js} +1 -1
  85. package/ui-dist/assets/{arrow-right-DW0tfmbi.js → arrow-right-DyKWA_SL.js} +1 -1
  86. package/ui-dist/assets/{badge-B4XIQ7B_.js → badge-CUe24HAP.js} +1 -1
  87. package/ui-dist/assets/{bot-zBrbL-yH.js → bot-wKcWfYKX.js} +1 -1
  88. package/ui-dist/assets/{card-79GDCTP3.js → card-GbQ9sLu8.js} +1 -1
  89. package/ui-dist/assets/{check-x_elx0uL.js → check-VcfFMsHr.js} +1 -1
  90. package/ui-dist/assets/{checkbox-3gl2Un2H.js → checkbox-Cm-PyDSt.js} +1 -1
  91. package/ui-dist/assets/{clipboard-_seTAJiP.js → clipboard-CYFyFXxJ.js} +1 -1
  92. package/ui-dist/assets/{company-members-BXmr5rWO.js → company-members-CSVvQnvh.js} +1 -1
  93. package/ui-dist/assets/{definition-I91EV37G.js → definition-urW_HpEG.js} +1 -1
  94. package/ui-dist/assets/{dist-G74v2gk6.js → dist-CfR2_c4p.js} +1 -1
  95. package/ui-dist/assets/{dist-Bgy8AcEI.js → dist-Dz68ZFqX.js} +1 -1
  96. package/ui-dist/assets/{dist-D4yyXwCK.js → dist-Z45aKkJm.js} +1 -1
  97. package/ui-dist/assets/{environments-x0bu3agB.js → environments-Cc8orNVy.js} +1 -1
  98. package/ui-dist/assets/{external-link-DZQH1MR8.js → external-link-CAutrcht.js} +1 -1
  99. package/ui-dist/assets/{file-text-DnkFEoqC.js → file-text-Dik8gyob.js} +1 -1
  100. package/ui-dist/assets/{health-DIsZUg4d.js → health-D_DTw2-J.js} +1 -1
  101. package/ui-dist/assets/{heartbeats-hynzhqu3.js → heartbeats-BgAe0g2m.js} +1 -1
  102. package/ui-dist/assets/{index-SsNrNOjw.js → index-st-IN4Gf.js} +139 -139
  103. package/ui-dist/assets/{input-DW5WzZI0.js → input-BARyUoy0.js} +1 -1
  104. package/ui-dist/assets/{label-BnuPQCxV.js → label-D4Q0SI3t.js} +1 -1
  105. package/ui-dist/assets/{mention-chips-DtMro9HO.js → mention-chips-BEoxPZei.js} +1 -1
  106. package/ui-dist/assets/{rotate-ccw-wat5PoA5.js → rotate-ccw-BT1r8zDE.js} +1 -1
  107. package/ui-dist/assets/{select-CtJdi3BB.js → select-yD0r8C3i.js} +1 -1
  108. package/ui-dist/assets/{sheet-5L45GZhN.js → sheet-CAjfRCp9.js} +1 -1
  109. package/ui-dist/assets/{skeleton-Cea_xEjg.js → skeleton-BFMc3stE.js} +1 -1
  110. package/ui-dist/assets/{tabs-CVzr4EnB.js → tabs-C1f963Rn.js} +1 -1
  111. package/ui-dist/assets/{use-adapter-capabilities-BzuoLi4n.js → use-adapter-capabilities-CsKGmy5W.js} +1 -1
  112. package/ui-dist/assets/{use-copy-action-D1yLO8Yp.js → use-copy-action-B-Azftuv.js} +1 -1
  113. package/ui-dist/assets/{useHiddenSettings-DuLvvhZD.js → useHiddenSettings-Uo-rfexH.js} +1 -1
  114. package/ui-dist/index.html +39 -39
  115. package/ui-dist/sw.js +1 -1
@@ -0,0 +1,433 @@
1
+ import { and, eq, inArray } from "drizzle-orm";
2
+ import { agents, chatConversations, chatDeliveries, chatEndpoints, heartbeatRuns, issueComments, issueThreadInteractionOwnerRelays, issueThreadInteractions, } from "@tickernelz/paperclip-pro-db";
3
+ import { HttpError, unprocessable } from "../errors.js";
4
+ import { attentionService } from "./attention.js";
5
+ import { boardAuthService } from "./board-auth.js";
6
+ import { openwaOwnerPrincipalOfDeliveries } from "./openwa/approvals.js";
7
+ import { readOpenwaRunContext } from "./openwa/authority.js";
8
+ import { openwaChatKey } from "./openwa/outbound.js";
9
+ import { openwaCurrentOwnerUserId } from "./openwa/owners.js";
10
+ export const OWNER_CONFIRMATION_REQUIRED_CODE = "owner_confirmation_required";
11
+ const OWNER_RELAY_REMEDIATION = "Relay a card answer only from a run the owner's own message started (an owner WhatsApp message, or their board comment), quoting that message's id as ownerMessageRef. Otherwise ask the owner to answer the card in Paperclip.";
12
+ function ownerConfirmationRequired(reason, message) {
13
+ return new HttpError(403, message, { code: OWNER_CONFIRMATION_REQUIRED_CODE, reason, remediation: OWNER_RELAY_REMEDIATION });
14
+ }
15
+ function record(value) {
16
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
17
+ }
18
+ function str(value) {
19
+ return typeof value === "string" && value.trim() ? value.trim() : null;
20
+ }
21
+ function strings(value) {
22
+ return Array.isArray(value) ? value.filter((entry) => typeof entry === "string" && entry.trim().length > 0) : [];
23
+ }
24
+ async function whatsappAuthority(db, run, ownerMessageRef) {
25
+ const openwa = readOpenwaRunContext(run.contextSnapshot);
26
+ if (!openwa)
27
+ return null;
28
+ const notOwner = () => ownerConfirmationRequired("not_owner_triggered", "Only a run started by an endpoint owner's own WhatsApp messages can relay their answer to a card");
29
+ if (openwa.triggerClass !== "owner")
30
+ throw notOwner();
31
+ const [endpoint] = await db
32
+ .select({ id: chatEndpoints.id, companyId: chatEndpoints.companyId })
33
+ .from(chatEndpoints)
34
+ .where(and(eq(chatEndpoints.id, openwa.endpointId), eq(chatEndpoints.companyId, run.companyId), eq(chatEndpoints.provider, "openwa")))
35
+ .limit(1);
36
+ const runIssueId = str(run.contextSnapshot?.issueId) ?? str(run.contextSnapshot?.taskId);
37
+ if (!endpoint || !runIssueId)
38
+ throw notOwner();
39
+ const [conversation] = await db
40
+ .select({ id: chatConversations.id })
41
+ .from(chatConversations)
42
+ .where(and(eq(chatConversations.companyId, run.companyId), eq(chatConversations.endpointId, endpoint.id), eq(chatConversations.issueId, runIssueId)))
43
+ .limit(1);
44
+ if (!conversation)
45
+ throw notOwner();
46
+ const principalId = await openwaOwnerPrincipalOfDeliveries(db, {
47
+ companyId: run.companyId,
48
+ endpointId: endpoint.id,
49
+ conversationId: conversation.id,
50
+ chatKey: openwaChatKey(openwa.chatKey),
51
+ deliveryIds: openwa.deliveryIds,
52
+ });
53
+ if (!principalId)
54
+ throw notOwner();
55
+ const deliveries = await db
56
+ .select({ id: chatDeliveries.id, normalizedEvent: chatDeliveries.normalizedEvent, receivedAt: chatDeliveries.receivedAt })
57
+ .from(chatDeliveries)
58
+ .where(and(eq(chatDeliveries.companyId, run.companyId), eq(chatDeliveries.endpointId, endpoint.id), inArray(chatDeliveries.id, openwa.deliveryIds.slice(0, 50))));
59
+ const message = deliveries.find((row) => row.id === ownerMessageRef || str(record(row.normalizedEvent.openwa).waMessageId) === ownerMessageRef);
60
+ if (!message) {
61
+ throw ownerConfirmationRequired("owner_message_not_in_run", "ownerMessageRef must be the id of one of the owner's messages that started this run");
62
+ }
63
+ const owner = await openwaCurrentOwnerUserId(db, endpoint, principalId);
64
+ if (!owner.userId) {
65
+ throw ownerConfirmationRequired("owner_not_linked", "This WhatsApp owner is not linked to a Paperclip user, so their answer cannot be recorded for them");
66
+ }
67
+ return {
68
+ ownerUserId: owner.userId,
69
+ ownerMessageRef,
70
+ ownerText: typeof record(message.normalizedEvent.message).text === "string" ? String(record(message.normalizedEvent.message).text) : "",
71
+ messageAt: message.receivedAt,
72
+ };
73
+ }
74
+ async function commentAuthority(db, run, ownerMessageRef) {
75
+ const wakeCommentIds = new Set([...strings(run.contextSnapshot?.wakeCommentIds), ...strings([run.contextSnapshot?.wakeCommentId])]);
76
+ if (wakeCommentIds.size === 0) {
77
+ throw ownerConfirmationRequired("not_owner_triggered", "Only a run started by a board user's own message can relay their answer to a card");
78
+ }
79
+ if (!wakeCommentIds.has(ownerMessageRef)) {
80
+ throw ownerConfirmationRequired("owner_message_not_in_run", "ownerMessageRef must be the id of the board comment that woke this run");
81
+ }
82
+ const [comment] = await db
83
+ .select({
84
+ authorType: issueComments.authorType,
85
+ authorUserId: issueComments.authorUserId,
86
+ authorAgentId: issueComments.authorAgentId,
87
+ createdByRunId: issueComments.createdByRunId,
88
+ deletedAt: issueComments.deletedAt,
89
+ sourceTrust: issueComments.sourceTrust,
90
+ body: issueComments.body,
91
+ createdAt: issueComments.createdAt,
92
+ })
93
+ .from(issueComments)
94
+ .where(and(eq(issueComments.id, ownerMessageRef), eq(issueComments.companyId, run.companyId)))
95
+ .limit(1);
96
+ if (!comment ||
97
+ comment.deletedAt ||
98
+ comment.authorType !== "user" ||
99
+ !comment.authorUserId ||
100
+ comment.authorAgentId ||
101
+ comment.createdByRunId ||
102
+ comment.sourceTrust?.disposition === "quarantined") {
103
+ throw ownerConfirmationRequired("not_owner_triggered", "The message that woke this run is not a board user's own message");
104
+ }
105
+ return { ownerUserId: comment.authorUserId, ownerMessageRef, ownerText: comment.body, messageAt: comment.createdAt };
106
+ }
107
+ export async function resolveOwnerRelayAuthority(db, input) {
108
+ const [run] = await db
109
+ .select({ id: heartbeatRuns.id, companyId: heartbeatRuns.companyId, agentId: heartbeatRuns.agentId, status: heartbeatRuns.status, contextSnapshot: heartbeatRuns.contextSnapshot })
110
+ .from(heartbeatRuns)
111
+ .where(and(eq(heartbeatRuns.id, input.runId), eq(heartbeatRuns.companyId, input.companyId)))
112
+ .limit(1);
113
+ if (!run || run.agentId !== input.agentId || run.status !== "running") {
114
+ throw ownerConfirmationRequired("run_not_active", "Only the agent's own active run can relay an owner's answer");
115
+ }
116
+ const relayRun = { id: run.id, companyId: run.companyId, contextSnapshot: run.contextSnapshot };
117
+ const whatsapp = await whatsappAuthority(db, relayRun, input.ownerMessageRef);
118
+ const authority = whatsapp ? { channel: "whatsapp", ...whatsapp } : { channel: "paperclip", ...(await commentAuthority(db, relayRun, input.ownerMessageRef)) };
119
+ const access = await boardAuthService(db).resolveBoardAccess(authority.ownerUserId);
120
+ if (!access.user || (!access.isInstanceAdmin && !access.companyIds.includes(input.companyId))) {
121
+ throw ownerConfirmationRequired("owner_not_member", "The owner is not an active board member of this company");
122
+ }
123
+ return authority;
124
+ }
125
+ export function ownerRelayClaimKey(ownerText, card) {
126
+ const text = ownerText.toLowerCase();
127
+ if (text.includes(card.interactionId.toLowerCase()))
128
+ return "interaction:" + card.interactionId.toLowerCase();
129
+ const named = new Set();
130
+ const uuids = text.match(/\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/g) ?? [];
131
+ for (const id of uuids)
132
+ named.add("interaction:" + id);
133
+ const prefix = card.issueIdentifier?.split("-")[0]?.toLowerCase() ?? null;
134
+ if (prefix) {
135
+ const escaped = prefix.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
136
+ for (const match of text.matchAll(new RegExp("\\b" + escaped + "-(\\d+)\\b", "g")))
137
+ named.add("issue:" + prefix + "-" + match[1]);
138
+ }
139
+ const issueKey = card.issueIdentifier ? "issue:" + card.issueIdentifier.toLowerCase() : null;
140
+ if (issueKey && named.has(issueKey))
141
+ return issueKey;
142
+ if (named.size > 0) {
143
+ throw ownerConfirmationRequired("card_not_named", "The owner's message names other cards, not this one; relay only the cards it names");
144
+ }
145
+ return "*";
146
+ }
147
+ export async function claimOwnerRelay(db, input) {
148
+ if (input.authority.messageAt.getTime() < input.cardCreatedAt.getTime()) {
149
+ throw ownerConfirmationRequired("message_predates_card", "The owner's message was sent before this card existed, so it cannot answer it");
150
+ }
151
+ const claimKey = ownerRelayClaimKey(input.authority.ownerText, { interactionId: input.interactionId, issueIdentifier: input.issueIdentifier });
152
+ const [claim] = await db
153
+ .insert(issueThreadInteractionOwnerRelays)
154
+ .values({
155
+ companyId: input.companyId,
156
+ issueId: input.issueId,
157
+ interactionId: input.interactionId,
158
+ channel: input.authority.channel,
159
+ ownerMessageRef: input.authority.ownerMessageRef,
160
+ claimKey,
161
+ ownerUserId: input.authority.ownerUserId,
162
+ relayedByAgentId: input.agentId,
163
+ runId: input.runId,
164
+ })
165
+ .onConflictDoNothing()
166
+ .returning({ id: issueThreadInteractionOwnerRelays.id });
167
+ if (!claim) {
168
+ throw ownerConfirmationRequired("owner_message_consumed", claimKey === "*"
169
+ ? "This owner message already answered a card; one message answers one card unless it names each card"
170
+ : "This owner message already answered the card it names");
171
+ }
172
+ return claim.id;
173
+ }
174
+ export async function releaseOwnerRelay(db, claimId) {
175
+ await db.delete(issueThreadInteractionOwnerRelays).where(eq(issueThreadInteractionOwnerRelays.id, claimId));
176
+ }
177
+ export async function markOwnerRelayApplied(db, input) {
178
+ await db
179
+ .update(issueThreadInteractions)
180
+ .set({ resolutionRelay: input.relay })
181
+ .where(and(eq(issueThreadInteractions.id, input.interactionId), eq(issueThreadInteractions.companyId, input.companyId), eq(issueThreadInteractions.resolvedByUserId, input.relay.ownerUserId)));
182
+ }
183
+ export function ownerRelayBlockedReason(card) {
184
+ if (card.kind === "connection_intent")
185
+ return "Connection requests are completed by the connecting user in Paperclip";
186
+ const payload = record(card.payload);
187
+ if (payload.toolAction || payload.secretProposal || payload.connectionAuthorization) {
188
+ return "Governed actions (tool runs, secret bindings, connection authorizations) use their own approval control in Paperclip";
189
+ }
190
+ if (str(payload.openwaApprovalRequestId))
191
+ return "OpenWA approval requests are resolved with openwa_approval_resolve in the owner's chat";
192
+ return null;
193
+ }
194
+ export function ownerRelayTarget(card, answer) {
195
+ const blocked = ownerRelayBlockedReason(card);
196
+ if (blocked)
197
+ throw unprocessable(blocked, { code: "owner_relay_unsupported" });
198
+ const note = answer.note === undefined ? {} : { note: answer.note };
199
+ const mismatch = (shape) => unprocessable("A " + card.kind + " card takes " + shape, { code: "owner_relay_answer_mismatch" });
200
+ switch (card.kind) {
201
+ case "request_confirmation":
202
+ case "request_checkbox_confirmation":
203
+ case "suggest_tasks": {
204
+ if (!answer.decision)
205
+ throw mismatch("decision approve or reject");
206
+ if (answer.decision === "reject")
207
+ return { action: "reject", body: { ...(answer.reason ? { reason: answer.reason } : {}), ...note } };
208
+ if (card.kind === "request_confirmation" && answer.optionIds)
209
+ throw mismatch("no optionIds");
210
+ if (card.kind === "request_checkbox_confirmation" && !answer.optionIds)
211
+ throw mismatch("the optionIds the owner chose");
212
+ const selection = card.kind === "request_checkbox_confirmation"
213
+ ? { selectedOptionIds: answer.optionIds }
214
+ : card.kind === "suggest_tasks" && answer.optionIds
215
+ ? { selectedClientKeys: answer.optionIds }
216
+ : {};
217
+ return { action: "accept", body: { ...selection, ...note } };
218
+ }
219
+ case "ask_user_questions":
220
+ if (!answer.answers)
221
+ throw mismatch("answers");
222
+ return { action: "respond", body: { answers: answer.answers } };
223
+ case "request_item_verdicts":
224
+ if (!answer.verdicts)
225
+ throw mismatch("verdicts");
226
+ return { action: "verdicts", body: { verdicts: answer.verdicts } };
227
+ default:
228
+ throw unprocessable("This card kind cannot be relayed", { code: "owner_relay_unsupported" });
229
+ }
230
+ }
231
+ export function dispatchAsOwner(handle, req, input) {
232
+ return new Promise((resolve, reject) => {
233
+ let settled = false;
234
+ const finish = (status, body) => {
235
+ if (settled)
236
+ return;
237
+ settled = true;
238
+ resolve({ status, body });
239
+ };
240
+ const inner = Object.create(req);
241
+ Object.assign(inner, { url: input.url, body: input.body, actor: input.actor, params: {} });
242
+ const headers = new Map();
243
+ const res = {
244
+ statusCode: 200,
245
+ headersSent: false,
246
+ locals: {},
247
+ status(code) {
248
+ res.statusCode = code;
249
+ return res;
250
+ },
251
+ sendStatus(code) {
252
+ res.statusCode = code;
253
+ finish(code, null);
254
+ return res;
255
+ },
256
+ json(body) {
257
+ finish(res.statusCode, body);
258
+ return res;
259
+ },
260
+ send(body) {
261
+ finish(res.statusCode, body);
262
+ return res;
263
+ },
264
+ end() {
265
+ finish(res.statusCode, null);
266
+ return res;
267
+ },
268
+ setHeader(name, value) {
269
+ headers.set(name.toLowerCase(), value);
270
+ return res;
271
+ },
272
+ set(name, value) {
273
+ if (typeof name === "string")
274
+ headers.set(name.toLowerCase(), value);
275
+ else
276
+ for (const [key, entry] of Object.entries(name))
277
+ headers.set(key.toLowerCase(), entry);
278
+ return res;
279
+ },
280
+ header(name, value) {
281
+ return res.set(name, value);
282
+ },
283
+ getHeader: (name) => headers.get(name.toLowerCase()),
284
+ get: (name) => headers.get(name.toLowerCase()),
285
+ append: () => res,
286
+ type: () => res,
287
+ vary: () => res,
288
+ on: () => res,
289
+ once: () => res,
290
+ };
291
+ handle(inner, res, (error) => {
292
+ if (settled)
293
+ return;
294
+ settled = true;
295
+ reject(error ?? new HttpError(500, "Owner relay matched no board answer route"));
296
+ });
297
+ });
298
+ }
299
+ function text(value) {
300
+ return typeof value === "string" && value.trim() ? value : null;
301
+ }
302
+ function optionList(entries, idKey, labelKey) {
303
+ return (Array.isArray(entries) ? entries : []).flatMap((entry) => {
304
+ const item = record(entry);
305
+ const id = str(item[idKey]);
306
+ const label = text(item[labelKey]);
307
+ return id && label ? [{ id, label, description: text(item.description) }] : [];
308
+ });
309
+ }
310
+ function cardShape(kind, payload) {
311
+ switch (kind) {
312
+ case "request_confirmation":
313
+ return {
314
+ prompt: text(payload.prompt),
315
+ options: [
316
+ { id: "approve", label: text(payload.acceptLabel) ?? "Approve", description: null },
317
+ { id: "reject", label: text(payload.rejectLabel) ?? "Reject", description: null },
318
+ ],
319
+ questions: [],
320
+ };
321
+ case "request_checkbox_confirmation":
322
+ case "request_item_verdicts":
323
+ return { prompt: text(payload.prompt), options: optionList(kind === "request_item_verdicts" ? payload.items : payload.options, "id", "label"), questions: [] };
324
+ case "suggest_tasks": {
325
+ const options = optionList(payload.tasks, "clientKey", "title");
326
+ return { prompt: "Create " + options.length + " suggested task" + (options.length === 1 ? "" : "s"), options, questions: [] };
327
+ }
328
+ case "ask_user_questions": {
329
+ const questions = (Array.isArray(payload.questions) ? payload.questions : []).flatMap((entry) => {
330
+ const question = record(entry);
331
+ const id = str(question.id);
332
+ const prompt = text(question.prompt);
333
+ if (!id || !prompt)
334
+ return [];
335
+ return [{ id, prompt, selectionMode: question.selectionMode === "multi" ? "multi" : "single", options: optionList(question.options, "id", "label") }];
336
+ });
337
+ return { prompt: text(payload.title) ?? questions[0]?.prompt ?? null, options: [], questions };
338
+ }
339
+ default:
340
+ return { prompt: text(payload.prompt), options: [], questions: [] };
341
+ }
342
+ }
343
+ const GOVERNED_APPROVAL_REASON = "Board approvals (hires, budgets, governed actions) carry company-level effects and budget stops; the owner decides them in Paperclip, or an agent holding company:approvals authority uses paperclipApprovalDecision";
344
+ const AGENT_DECISION_REASON = "Agent decision bundles are decided on the Paperclip Decisions desk";
345
+ export async function listPendingDecisions(db, input) {
346
+ const feed = await attentionService(db).list(input.companyId, {
347
+ userId: input.userId ?? undefined,
348
+ actor: input.actor,
349
+ includeDismissed: true,
350
+ all: true,
351
+ allowUnscopedAll: true,
352
+ sort: "decide",
353
+ });
354
+ const items = feed.items.filter((item) => ["issue_thread_interaction", "approval", "decision"].includes(item.sourceKind));
355
+ const interactionIds = items.filter((item) => item.sourceKind === "issue_thread_interaction").map((item) => item.subject.id);
356
+ const cards = interactionIds.length
357
+ ? await db
358
+ .select({
359
+ id: issueThreadInteractions.id,
360
+ kind: issueThreadInteractions.kind,
361
+ payload: issueThreadInteractions.payload,
362
+ title: issueThreadInteractions.title,
363
+ createdByUserId: issueThreadInteractions.createdByUserId,
364
+ })
365
+ .from(issueThreadInteractions)
366
+ .where(and(eq(issueThreadInteractions.companyId, input.companyId), inArray(issueThreadInteractions.id, interactionIds)))
367
+ : [];
368
+ const cardById = new Map(cards.map((card) => [card.id, card]));
369
+ const requesterIds = [
370
+ ...new Set(items.flatMap((item) => {
371
+ const metadata = record(item.subject.metadata);
372
+ return [item.resolverAudience?.createdByAgentId, str(metadata.createdByAgentId), str(metadata.requestedByAgentId), str(metadata.originAgentId)]
373
+ .filter((id) => Boolean(id));
374
+ })),
375
+ ];
376
+ const agentNames = new Map(requesterIds.length
377
+ ? (await db
378
+ .select({ id: agents.id, name: agents.name })
379
+ .from(agents)
380
+ .where(and(eq(agents.companyId, input.companyId), inArray(agents.id, requesterIds)))).map((agent) => [agent.id, agent.name])
381
+ : []);
382
+ const requester = (agentId) => ({ requestedByAgentId: agentId, requestedByAgentName: agentId ? (agentNames.get(agentId) ?? null) : null });
383
+ return items.flatMap((item) => {
384
+ const metadata = record(item.subject.metadata);
385
+ const base = {
386
+ id: item.subject.id,
387
+ issueId: item.relatedIssue?.id ?? str(metadata.issueId) ?? str(metadata.originIssueId),
388
+ issueIdentifier: item.relatedIssue?.identifier ?? null,
389
+ issueTitle: item.relatedIssue?.title ?? null,
390
+ title: item.subject.title,
391
+ createdAt: item.createdAt,
392
+ href: item.subject.href,
393
+ };
394
+ if (item.sourceKind === "issue_thread_interaction") {
395
+ const card = cardById.get(item.subject.id);
396
+ if (!card)
397
+ return [];
398
+ const blocked = ownerRelayBlockedReason(card);
399
+ return [{
400
+ ...base,
401
+ source: "interaction",
402
+ kind: card.kind,
403
+ title: card.title ?? base.title,
404
+ ...cardShape(card.kind, record(card.payload)),
405
+ humanOnly: item.resolverAudience?.effectiveResolverPolicy === "human_only",
406
+ ...requester(item.resolverAudience?.createdByAgentId ?? str(metadata.createdByAgentId)),
407
+ requestedByUserId: card.createdByUserId ?? null,
408
+ relayable: blocked === null,
409
+ relayBlockedReason: blocked,
410
+ }];
411
+ }
412
+ return [{
413
+ ...base,
414
+ source: item.sourceKind === "approval" ? "approval" : "decision",
415
+ kind: str(metadata.type) ?? item.sourceKind,
416
+ prompt: decisionPrompt(item),
417
+ options: item.decisionVerbs.map((verb) => ({ id: verb.id, label: verb.label, description: verb.description })),
418
+ questions: [],
419
+ humanOnly: true,
420
+ ...requester(str(metadata.requestedByAgentId) ?? str(metadata.originAgentId)),
421
+ requestedByUserId: str(metadata.requestedByUserId),
422
+ relayable: false,
423
+ relayBlockedReason: item.sourceKind === "approval" ? GOVERNED_APPROVAL_REASON : AGENT_DECISION_REASON,
424
+ }];
425
+ });
426
+ }
427
+ function decisionPrompt(item) {
428
+ const detail = item.detail;
429
+ if (detail && "summaryExcerpt" in detail)
430
+ return detail.summaryExcerpt;
431
+ return item.whyNow;
432
+ }
433
+ //# sourceMappingURL=owner-decision-relay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"owner-decision-relay.js","sourceRoot":"","sources":["../../src/services/owner-decision-relay.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tickernelz/paperclip-pro-server",
3
- "version": "2026.1012.0",
3
+ "version": "2026.1012.1",
4
4
  "license": "MIT",
5
5
  "homepage": "https://github.com/tickernelz/paperclip-pro",
6
6
  "bugs": {
@@ -54,25 +54,25 @@
54
54
  "@openrouter/ai-sdk-provider": "3.1.0",
55
55
  "@opentelemetry/api": "^1.9.0",
56
56
  "@photon-ai/advanced-imessage": "2.1.0",
57
- "@tickernelz/paperclip-pro-adapter-claude-local": "2026.1012.0",
58
- "@tickernelz/paperclip-pro-adapter-codex-local": "2026.1012.0",
59
- "@tickernelz/paperclip-pro-adapter-cursor-cloud": "2026.1012.0",
60
- "@tickernelz/paperclip-pro-adapter-cursor-local": "2026.1012.0",
61
- "@tickernelz/paperclip-pro-adapter-gemini-local": "2026.1012.0",
62
- "@tickernelz/paperclip-pro-adapter-grok-local": "2026.1012.0",
63
- "@tickernelz/paperclip-pro-adapter-kimi-local": "2026.1012.0",
64
- "@tickernelz/paperclip-pro-adapter-omp-local": "2026.1012.0",
65
- "@tickernelz/paperclip-pro-adapter-openclaw-gateway": "2026.1012.0",
66
- "@tickernelz/paperclip-pro-adapter-opencode-local": "2026.1012.0",
67
- "@tickernelz/paperclip-pro-adapter-pi-local": "2026.1012.0",
68
- "@tickernelz/paperclip-pro-adapter-utils": "2026.1012.0",
69
- "@tickernelz/paperclip-pro-db": "2026.1012.0",
70
- "@tickernelz/paperclip-pro-hermes-paperclip-adapter": "2026.1012.0",
71
- "@tickernelz/paperclip-pro-mcp-server": "2026.1012.0",
72
- "@tickernelz/paperclip-pro-plugin-sdk": "2026.1012.0",
73
- "@tickernelz/paperclip-pro-shared": "2026.1012.0",
74
- "@tickernelz/paperclip-pro-skills-catalog": "2026.1012.0",
75
- "@tickernelz/paperclip-pro-teams-catalog": "2026.1012.0",
57
+ "@tickernelz/paperclip-pro-adapter-claude-local": "2026.1012.1",
58
+ "@tickernelz/paperclip-pro-adapter-codex-local": "2026.1012.1",
59
+ "@tickernelz/paperclip-pro-adapter-cursor-cloud": "2026.1012.1",
60
+ "@tickernelz/paperclip-pro-adapter-cursor-local": "2026.1012.1",
61
+ "@tickernelz/paperclip-pro-adapter-gemini-local": "2026.1012.1",
62
+ "@tickernelz/paperclip-pro-adapter-grok-local": "2026.1012.1",
63
+ "@tickernelz/paperclip-pro-adapter-kimi-local": "2026.1012.1",
64
+ "@tickernelz/paperclip-pro-adapter-omp-local": "2026.1012.1",
65
+ "@tickernelz/paperclip-pro-adapter-openclaw-gateway": "2026.1012.1",
66
+ "@tickernelz/paperclip-pro-adapter-opencode-local": "2026.1012.1",
67
+ "@tickernelz/paperclip-pro-adapter-pi-local": "2026.1012.1",
68
+ "@tickernelz/paperclip-pro-adapter-utils": "2026.1012.1",
69
+ "@tickernelz/paperclip-pro-db": "2026.1012.1",
70
+ "@tickernelz/paperclip-pro-hermes-paperclip-adapter": "2026.1012.1",
71
+ "@tickernelz/paperclip-pro-mcp-server": "2026.1012.1",
72
+ "@tickernelz/paperclip-pro-plugin-sdk": "2026.1012.1",
73
+ "@tickernelz/paperclip-pro-shared": "2026.1012.1",
74
+ "@tickernelz/paperclip-pro-skills-catalog": "2026.1012.1",
75
+ "@tickernelz/paperclip-pro-teams-catalog": "2026.1012.1",
76
76
  "@vercel/connect": "2.3.3",
77
77
  "acorn": "8.18.0",
78
78
  "acpx": "0.13.1",
@@ -128,7 +128,7 @@
128
128
  "acpx"
129
129
  ],
130
130
  "devDependencies": {
131
- "@tickernelz/paperclip-pro-paperclip-runner": "2026.1012.0",
131
+ "@tickernelz/paperclip-pro-paperclip-runner": "2026.1012.1",
132
132
  "@types/compression": "^1.8.1",
133
133
  "@types/express": "^5.0.0",
134
134
  "@types/express-serve-static-core": "^5.1.3",
@@ -270,8 +270,10 @@ anew.
270
270
  either put the items in one task with a checklist or ask once with scope
271
271
  `requester` and say the count in `proposedAction`; never ask again after the
272
272
  first call. You write `messageToOwners`;
273
- it goes as one WhatsApp bubble to each owner approval chat. Then tell the
274
- requester you asked.
273
+ it goes as one WhatsApp bubble to each owner approval chat, or to the
274
+ chat's owner report group when the guidance names one. Then tell the
275
+ requester you asked. Never ask for approval by writing in a team or project
276
+ group: this tool is the only way to ask.
275
277
  2. Owners answer by replying to that bubble (quoting it) or in the OpenWA
276
278
  Approvals tab. A quoted owner reply starts an `approval_reply` run of class
277
279
  `owner`. Treat it as a conversation: when the owner asks a question, objects
@@ -315,6 +317,19 @@ anew.
315
317
  A gated call without approval fails with `approval_required` and its
316
318
  `category`; do not retry it. Live grants are listed in the wake `policy.grants`.
317
319
 
320
+ ## Reporting to the owner
321
+
322
+ A chat may have an owner report group (Settings, Chats, **Report to owner
323
+ via**), shown in the guidance as "Owner reports for this chat go to the group
324
+ ...". Then approval requests, owner_absent questions, reminders, any
325
+ `openwa_send` to an owner's number and completion reports owed to the owner go
326
+ to that group automatically: keep using the same tools and never pick the
327
+ group or the owner's direct chat yourself. The receipt of a routed send has
328
+ `ownerReportChat: true`. Owners answer there by quoting the bubble or with an
329
+ unquoted ok/ya/jangan for the newest pending request; that starts the
330
+ `approval_reply` run in the group, and the approved action runs in the origin
331
+ chat. Replies meant for the origin chat stay in it.
332
+
318
333
  ## Owner-only configuration
319
334
 
320
335
  `openwa_endpoint_config` works only in owner-triggered runs; every other run gets
@@ -323,12 +338,17 @@ A gated call without approval fails with `approval_required` and its
323
338
  - `senders: {add?: [{list, number, label?}], remove?: [{list, number}]}` with
324
339
  `list` `allow` or `deny` and an E.164 `number`. A denylisted number is ignored
325
340
  from its next message on.
326
- - `chat` plus `chatSettings: {activation?, triggers?, absenceSeconds?, replyPolicy?, note?}`
341
+ - `chat` plus `chatSettings: {activation?, triggers?, absenceSeconds?, replyPolicy?, note?, ownerReportChat?}`
327
342
  for one chat (default: the origin chat). `activation` is `auto`, `on` or
328
343
  `off`; `replyPolicy` is `allowed`, `ask_owner` or `owner_absent_only`; `null`
329
344
  clears an override. `triggers` replaces the chat's trigger overrides, so keep
330
345
  the ones it has. A dedicated group, where you handle every message without a
331
346
  mention, is `chatSettings: {activation: "on", triggers: {allMessages: true}}`.
347
+ `ownerReportChat` (a group chatRef or id, found with `openwa_find`) sends the
348
+ chat's owner reports and approval requests to that group, for example when
349
+ the owner says "laporan grup ini ke [BOT] DCM"; `null` returns to the owner's
350
+ direct chat. The group must have an owner as member and this number active in
351
+ it, otherwise the call fails with `invalid_arguments`.
332
352
  - `approvals: {createTask?, externalTools?, crossChatSend?, waAdmin?, gatewayAdmin?, reminderMinutes?, maxReminders?, pendingTtlHours?}`:
333
353
  approval toggles, reminders and the pending request lifetime in hours (1 to 168).
334
354
  - `burstWindowSeconds`: 0 to 10 (default 3, 0 = off); messages of one chat sent
@@ -355,6 +375,34 @@ accepted and audited; questions, verdicts, governed approvals and cards marked
355
375
  call `{operation: "close", idempotencyKey}` (optionally with `issues`); `list` shows the
356
376
  live windows. Other runs get `owner_only`.
357
377
 
378
+ ## Paperclip cards for the owner (owner runs only)
379
+
380
+ A Paperclip card that waits for a person (confirmation, plan approval, question,
381
+ checkbox or verdict card, human-only included) is never "only answerable in
382
+ Paperclip" when the owner is talking to you here. When an owner asks what is
383
+ waiting on them, call `paperclipListPendingDecisions` and summarize each item:
384
+ issue, what it asks, its options. When the owner's own message explicitly
385
+ approves, rejects or answers one specific card, call
386
+ `paperclipAnswerDecisionForOwner` with `issueId`, `interactionId`, the answer
387
+ (`decision` approve or reject with `optionIds` or `reason`, `answers` for
388
+ questions, `verdicts` for verdict cards) and `ownerMessageRef` set to that
389
+ message's `id` from this run's `messages`. The server checks that this run was
390
+ started by that owner's own message and records the answer as theirs, relayed by
391
+ you, through the same path as the Paperclip button; the requester wakes as usual.
392
+ Then confirm in the chat exactly what you submitted.
393
+
394
+ - Never answer a card without the owner's explicit words for that card. A
395
+ general "ok" answers the one card you just presented; ask when it could mean
396
+ more than one. One message answers one card unless it names each card
397
+ (issue identifier or card id).
398
+ - `owner_confirmation_required` (403) means this run was not started by the
399
+ owner's own message, the owner is not linked to a Paperclip user, or that
400
+ message was already used; ask the owner to answer here again or in Paperclip.
401
+ A 409 means the card is already resolved. Items marked not relayable (board
402
+ approvals, agent decisions, governed tool/secret/connection cards, OpenWA
403
+ approval requests) stay with their own controls; say so and link them.
404
+ - Members and non-owner runs cannot relay; tell them the owner must answer.
405
+
358
406
  ## Linked numbers (owner runs only)
359
407
 
360
408
  The board may link other WhatsApp numbers on the same gateway, such as an
@@ -761,7 +761,7 @@ For detailed API tables, JSON response schemas, worked examples (IC and Manager
761
761
 
762
762
  ### Conversational confirmation answers
763
763
 
764
- When the user answers a pending confirmation in a message, record the answer before acting. Read current cards and comments with `paperclipListIssueInteractions` and `paperclipListComments`, then call `paperclipApiRequest` with `method: "POST"`, `path: "/issues/{issueId}/interactions/{interactionId}/resolve-from-comment"`, and a `jsonBody` carrying `commentId`, `decision: "accept" | "reject"`, and explicit `selectedOptionIds` for checkbox acceptance (native runners use `call_api`). Ambiguous replies among proposals require clarification. Revisions are not acceptance. Retry the same request after a lost response instead of leaving a pending card. Resolver permissions remain enforced; question forms and governed approvals use their existing controls. See the API reference for scope and retry rules.
764
+ When the user answers a pending confirmation in a message, record the answer before acting. Read current cards and comments with `paperclipListIssueInteractions` and `paperclipListComments`, then call `paperclipApiRequest` with `method: "POST"`, `path: "/issues/{issueId}/interactions/{interactionId}/resolve-from-comment"`, and a `jsonBody` carrying `commentId`, `decision: "accept" | "reject"`, and explicit `selectedOptionIds` for checkbox acceptance (native runners use `call_api`). Ambiguous replies among proposals require clarification. Revisions are not acceptance. Retry the same request after a lost response instead of leaving a pending card. Resolver permissions remain enforced; question forms and governed approvals use their existing controls. See the API reference for scope and retry rules. Human-only cards are answered by a person, but that person does not have to open Paperclip. When a board user's own message started your run (an owner WhatsApp message in an OpenWA run, or their comment that woke you) and it explicitly approves, rejects or answers one specific pending card, call `paperclipAnswerDecisionForOwner` with `issueId`, `interactionId`, the answer (`decision` with `optionIds` or `reason`, `answers`, or `verdicts`) and `ownerMessageRef` set to that message's id. The server verifies the message, records the answer as that user's (relayed by you) through the board answer path, and wakes the requester. List what is waiting with `paperclipListPendingDecisions`. Never answer without the person's explicit words for that card, never reuse one message for several cards unless it names each, and confirm back what you submitted. `owner_confirmation_required` (403) means the run lacks that authority; a 409 means the card is already resolved. Board approvals, agent decisions and governed tool, secret or connection cards are listed read-only and keep their own controls.
765
765
 
766
766
  In Agent Chat, a question is optional: if the user moves on to another topic, answer that message without requiring them to answer or resolve the earlier question. Leave its card unanswered so they can reopen it later. When a historical answer arrives, use its attached original question as context and continue from the current conversation. Unrelated messages are never approval.
767
767