@paperclipai/server 0.3.0 → 0.3.1-canary.0

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 (178) hide show
  1. package/dist/adapters/registry.d.ts.map +1 -1
  2. package/dist/adapters/registry.js +12 -0
  3. package/dist/adapters/registry.js.map +1 -1
  4. package/dist/app.d.ts +1 -0
  5. package/dist/app.d.ts.map +1 -1
  6. package/dist/app.js +9 -2
  7. package/dist/app.js.map +1 -1
  8. package/dist/attachment-types.d.ts +33 -0
  9. package/dist/attachment-types.d.ts.map +1 -0
  10. package/dist/attachment-types.js +61 -0
  11. package/dist/attachment-types.js.map +1 -0
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +12 -2
  14. package/dist/index.js.map +1 -1
  15. package/dist/log-redaction.d.ts +10 -0
  16. package/dist/log-redaction.d.ts.map +1 -0
  17. package/dist/log-redaction.js +110 -0
  18. package/dist/log-redaction.js.map +1 -0
  19. package/dist/middleware/logger.d.ts.map +1 -1
  20. package/dist/middleware/logger.js +1 -0
  21. package/dist/middleware/logger.js.map +1 -1
  22. package/dist/routes/activity.d.ts.map +1 -1
  23. package/dist/routes/activity.js +12 -21
  24. package/dist/routes/activity.js.map +1 -1
  25. package/dist/routes/agents.d.ts.map +1 -1
  26. package/dist/routes/agents.js +102 -3
  27. package/dist/routes/agents.js.map +1 -1
  28. package/dist/routes/approvals.d.ts.map +1 -1
  29. package/dist/routes/approvals.js +87 -83
  30. package/dist/routes/approvals.js.map +1 -1
  31. package/dist/routes/assets.d.ts.map +1 -1
  32. package/dist/routes/assets.js +5 -12
  33. package/dist/routes/assets.js.map +1 -1
  34. package/dist/routes/issues.d.ts.map +1 -1
  35. package/dist/routes/issues.js +16 -11
  36. package/dist/routes/issues.js.map +1 -1
  37. package/dist/routes/sidebar-badges.d.ts.map +1 -1
  38. package/dist/routes/sidebar-badges.js +1 -4
  39. package/dist/routes/sidebar-badges.js.map +1 -1
  40. package/dist/services/activity-log.d.ts.map +1 -1
  41. package/dist/services/activity-log.js +4 -2
  42. package/dist/services/activity-log.js.map +1 -1
  43. package/dist/services/approvals.d.ts +30 -24
  44. package/dist/services/approvals.d.ts.map +1 -1
  45. package/dist/services/approvals.js +51 -42
  46. package/dist/services/approvals.js.map +1 -1
  47. package/dist/services/company-portability.d.ts.map +1 -1
  48. package/dist/services/company-portability.js +5 -1
  49. package/dist/services/company-portability.js.map +1 -1
  50. package/dist/services/dashboard.d.ts +0 -1
  51. package/dist/services/dashboard.d.ts.map +1 -1
  52. package/dist/services/dashboard.js +0 -7
  53. package/dist/services/dashboard.js.map +1 -1
  54. package/dist/services/execution-workspace-policy.d.ts +19 -0
  55. package/dist/services/execution-workspace-policy.d.ts.map +1 -0
  56. package/dist/services/execution-workspace-policy.js +117 -0
  57. package/dist/services/execution-workspace-policy.js.map +1 -0
  58. package/dist/services/goals.d.ts +26 -0
  59. package/dist/services/goals.d.ts.map +1 -1
  60. package/dist/services/goals.js +26 -1
  61. package/dist/services/goals.js.map +1 -1
  62. package/dist/services/heartbeat-run-summary.d.ts +2 -0
  63. package/dist/services/heartbeat-run-summary.d.ts.map +1 -0
  64. package/dist/services/heartbeat-run-summary.js +30 -0
  65. package/dist/services/heartbeat-run-summary.js.map +1 -0
  66. package/dist/services/heartbeat.d.ts +30 -996
  67. package/dist/services/heartbeat.d.ts.map +1 -1
  68. package/dist/services/heartbeat.js +236 -47
  69. package/dist/services/heartbeat.js.map +1 -1
  70. package/dist/services/index.d.ts +1 -0
  71. package/dist/services/index.d.ts.map +1 -1
  72. package/dist/services/index.js +1 -0
  73. package/dist/services/index.js.map +1 -1
  74. package/dist/services/issue-goal-fallback.d.ts +15 -0
  75. package/dist/services/issue-goal-fallback.d.ts.map +1 -0
  76. package/dist/services/issue-goal-fallback.js +15 -0
  77. package/dist/services/issue-goal-fallback.js.map +1 -0
  78. package/dist/services/issues.d.ts +5 -278
  79. package/dist/services/issues.d.ts.map +1 -1
  80. package/dist/services/issues.js +52 -14
  81. package/dist/services/issues.js.map +1 -1
  82. package/dist/services/projects.d.ts +4 -2
  83. package/dist/services/projects.d.ts.map +1 -1
  84. package/dist/services/projects.js +49 -6
  85. package/dist/services/projects.js.map +1 -1
  86. package/dist/services/workspace-runtime.d.ts +126 -0
  87. package/dist/services/workspace-runtime.d.ts.map +1 -0
  88. package/dist/services/workspace-runtime.js +852 -0
  89. package/dist/services/workspace-runtime.js.map +1 -0
  90. package/dist/ui-branding.d.ts +4 -0
  91. package/dist/ui-branding.d.ts.map +1 -0
  92. package/dist/ui-branding.js +37 -0
  93. package/dist/ui-branding.js.map +1 -0
  94. package/package.json +11 -10
  95. package/skills/paperclip/SKILL.md +23 -19
  96. package/ui-dist/assets/{_basePickBy-BYrQlacK.js → _basePickBy-B0xbZITw.js} +1 -1
  97. package/ui-dist/assets/{_baseUniq-DOSawgF3.js → _baseUniq-Cfd5u3qc.js} +1 -1
  98. package/ui-dist/assets/{arc-CG7T0hfG.js → arc-7Xbu8tBF.js} +1 -1
  99. package/ui-dist/assets/{architectureDiagram-VXUJARFQ-Bcn7ytDO.js → architectureDiagram-VXUJARFQ-C8F7ZRYc.js} +1 -1
  100. package/ui-dist/assets/{blockDiagram-VD42YOAC-BQGrx2lv.js → blockDiagram-VD42YOAC-Dp08a65A.js} +1 -1
  101. package/ui-dist/assets/{c4Diagram-YG6GDRKO-owH9Kb3t.js → c4Diagram-YG6GDRKO-BJfslTgZ.js} +1 -1
  102. package/ui-dist/assets/channel-BViQDbSq.js +1 -0
  103. package/ui-dist/assets/{chunk-4BX2VUAB-DY1UIe4g.js → chunk-4BX2VUAB-BhaYWH7e.js} +1 -1
  104. package/ui-dist/assets/{chunk-55IACEB6-CnWFPfPQ.js → chunk-55IACEB6-BOzJUsYW.js} +1 -1
  105. package/ui-dist/assets/{chunk-B4BG7PRW-DhlLW80l.js → chunk-B4BG7PRW-CbVcziyE.js} +1 -1
  106. package/ui-dist/assets/{chunk-DI55MBZ5-DPt7dj6c.js → chunk-DI55MBZ5-DghPtP3y.js} +1 -1
  107. package/ui-dist/assets/{chunk-FMBD7UC4-GQwzgYa4.js → chunk-FMBD7UC4-CB095Kfn.js} +1 -1
  108. package/ui-dist/assets/{chunk-QN33PNHL-BFHLVk5s.js → chunk-QN33PNHL-DfpzfDqJ.js} +1 -1
  109. package/ui-dist/assets/{chunk-QZHKN3VN-CLe3KEAf.js → chunk-QZHKN3VN-Df3d5z1y.js} +1 -1
  110. package/ui-dist/assets/{chunk-TZMSLE5B-BhccYB4e.js → chunk-TZMSLE5B-B6tX6bZI.js} +1 -1
  111. package/ui-dist/assets/classDiagram-2ON5EDUG-CjMCmxMT.js +1 -0
  112. package/ui-dist/assets/classDiagram-v2-WZHVMYZB-CjMCmxMT.js +1 -0
  113. package/ui-dist/assets/clone-Dbn9wtE1.js +1 -0
  114. package/ui-dist/assets/{cose-bilkent-S5V4N54A-DqECYL1w.js → cose-bilkent-S5V4N54A-38wg_s9V.js} +1 -1
  115. package/ui-dist/assets/{dagre-6UL2VRFP-DXeQqIJ2.js → dagre-6UL2VRFP-DPVj3XLS.js} +1 -1
  116. package/ui-dist/assets/{diagram-PSM6KHXK-DNu3Ctuy.js → diagram-PSM6KHXK-BJh89zUA.js} +1 -1
  117. package/ui-dist/assets/{diagram-QEK2KX5R-1wUR_z9S.js → diagram-QEK2KX5R-Bw0m_j10.js} +1 -1
  118. package/ui-dist/assets/{diagram-S2PKOQOG-D3IK8rZb.js → diagram-S2PKOQOG-D7_M2F3u.js} +1 -1
  119. package/ui-dist/assets/{erDiagram-Q2GNP2WA-DU3L0RbU.js → erDiagram-Q2GNP2WA-CLsjqTWP.js} +1 -1
  120. package/ui-dist/assets/{flowDiagram-NV44I4VS-CN46A5Ez.js → flowDiagram-NV44I4VS-BZZ7ezVB.js} +1 -1
  121. package/ui-dist/assets/{ganttDiagram-JELNMOA3-DGbOi1Wz.js → ganttDiagram-JELNMOA3-KzsFuwBt.js} +1 -1
  122. package/ui-dist/assets/{gitGraphDiagram-V2S2FVAM-D98N7SOj.js → gitGraphDiagram-V2S2FVAM-DSHtY7Vu.js} +1 -1
  123. package/ui-dist/assets/{graph-Cf7LCNJy.js → graph-luIG1UAS.js} +1 -1
  124. package/ui-dist/assets/{index-CP1BgxcV.js → index-00kuG4sI.js} +1 -1
  125. package/ui-dist/assets/{index-DiXE2gv-.js → index-1gX09-Fl.js} +1 -1
  126. package/ui-dist/assets/{index-CqG5WZHq.js → index-B1ZMzzs0.js} +1 -1
  127. package/ui-dist/assets/index-BHP9dico.js +1006 -0
  128. package/ui-dist/assets/{index-cx0y6-1h.js → index-B_3g3Rie.js} +1 -1
  129. package/ui-dist/assets/{index-CI56poQD.js → index-BeeKMqNU.js} +1 -1
  130. package/ui-dist/assets/{index-BfG2u5u0.js → index-BfB4lKJN.js} +1 -1
  131. package/ui-dist/assets/index-BfNaDZnn.css +1 -0
  132. package/ui-dist/assets/{index-DZdNKByU.js → index-Bv4xCjxl.js} +1 -1
  133. package/ui-dist/assets/{index--K1VLoF-.js → index-C2SZYIDA.js} +1 -1
  134. package/ui-dist/assets/{index-DB5nKqAA.js → index-C8XyGAr9.js} +1 -1
  135. package/ui-dist/assets/{index-C2-SE7P0.js → index-CaR9XM4h.js} +1 -1
  136. package/ui-dist/assets/{index-DujThSls.js → index-CbGtsjW7.js} +1 -1
  137. package/ui-dist/assets/{index-D0EsfNYg.js → index-CeDCs_2i.js} +1 -1
  138. package/ui-dist/assets/{index-OkxoZoQy.js → index-DBy0vJy3.js} +1 -1
  139. package/ui-dist/assets/{index-BoAYxRAO.js → index-DJf8diAA.js} +1 -1
  140. package/ui-dist/assets/{index-N1SX_i0z.js → index-DcfLFstG.js} +1 -1
  141. package/ui-dist/assets/{index-DXgtGequ.js → index-DnIPDZLp.js} +1 -1
  142. package/ui-dist/assets/{index-Cick_QSL.js → index-DoTq-BeR.js} +1 -1
  143. package/ui-dist/assets/{index-0BSerEC2.js → index-Ds7vLTSK.js} +1 -1
  144. package/ui-dist/assets/{index-Beb2ZlSv.js → index-RUBFVv6t.js} +1 -1
  145. package/ui-dist/assets/{index-TFF7cXd7.js → index-itc7BfMy.js} +1 -1
  146. package/ui-dist/assets/{index-BD6My-aI.js → index-nFjLambq.js} +1 -1
  147. package/ui-dist/assets/{index-B-xuGUs-.js → index-uR3zjYaD.js} +1 -1
  148. package/ui-dist/assets/{infoDiagram-HS3SLOUP-D_b1CK0Y.js → infoDiagram-HS3SLOUP-CDEfWpme.js} +1 -1
  149. package/ui-dist/assets/{journeyDiagram-XKPGCS4Q-4oCVXUve.js → journeyDiagram-XKPGCS4Q-i7nsbg_Y.js} +1 -1
  150. package/ui-dist/assets/{kanban-definition-3W4ZIXB7-0VcjP_qf.js → kanban-definition-3W4ZIXB7-DDlx1qVE.js} +1 -1
  151. package/ui-dist/assets/{layout-BQcYXlNv.js → layout-C7AtmJzX.js} +1 -1
  152. package/ui-dist/assets/{linear-nz0Lfiys.js → linear-C5jHT-WP.js} +1 -1
  153. package/ui-dist/assets/{mermaid.core-BaxvgwjG.js → mermaid.core-C8YQ4fcY.js} +4 -4
  154. package/ui-dist/assets/{mindmap-definition-VGOIOE7T-BnW6nEhl.js → mindmap-definition-VGOIOE7T-B9m9PuUg.js} +1 -1
  155. package/ui-dist/assets/{pieDiagram-ADFJNKIX-O1tvU_18.js → pieDiagram-ADFJNKIX-SvKywCSE.js} +1 -1
  156. package/ui-dist/assets/{quadrantDiagram-AYHSOK5B-BfM2aQbf.js → quadrantDiagram-AYHSOK5B-QfBPm7Y1.js} +1 -1
  157. package/ui-dist/assets/{requirementDiagram-UZGBJVZJ-rXVZupag.js → requirementDiagram-UZGBJVZJ-DnfQQuwi.js} +1 -1
  158. package/ui-dist/assets/{sankeyDiagram-TZEHDZUN-BNgaPVo6.js → sankeyDiagram-TZEHDZUN-DvLkjzIW.js} +1 -1
  159. package/ui-dist/assets/{sequenceDiagram-WL72ISMW--KnZ0qRV.js → sequenceDiagram-WL72ISMW-5Lq2rWBc.js} +1 -1
  160. package/ui-dist/assets/{stateDiagram-FKZM4ZOC-DlGdC88b.js → stateDiagram-FKZM4ZOC-DcYPHDyi.js} +1 -1
  161. package/ui-dist/assets/stateDiagram-v2-4FDKWEC3-nv50YYrl.js +1 -0
  162. package/ui-dist/assets/{timeline-definition-IT6M3QCI-CCwriy0-.js → timeline-definition-IT6M3QCI-lrN4JmWa.js} +1 -1
  163. package/ui-dist/assets/{treemap-GDKQZRPO-C-79yojr.js → treemap-GDKQZRPO-DFJKIBTQ.js} +1 -1
  164. package/ui-dist/assets/{xychartDiagram-PRI3JC2R-Dj0jcMBZ.js → xychartDiagram-PRI3JC2R-CT47vtdm.js} +1 -1
  165. package/ui-dist/index.html +4 -2
  166. package/ui-dist/worktree-favicon-16x16.png +0 -0
  167. package/ui-dist/worktree-favicon-32x32.png +0 -0
  168. package/ui-dist/worktree-favicon.ico +0 -0
  169. package/ui-dist/worktree-favicon.svg +9 -0
  170. package/skills/release/SKILL.md +0 -261
  171. package/skills/release-changelog/SKILL.md +0 -178
  172. package/ui-dist/assets/channel-DdXqC9Qy.js +0 -1
  173. package/ui-dist/assets/classDiagram-2ON5EDUG-ZV36NLFv.js +0 -1
  174. package/ui-dist/assets/classDiagram-v2-WZHVMYZB-ZV36NLFv.js +0 -1
  175. package/ui-dist/assets/clone-CvxIjPQa.js +0 -1
  176. package/ui-dist/assets/index-BYw6Loly.js +0 -900
  177. package/ui-dist/assets/index-nfAtmpEH.css +0 -1
  178. package/ui-dist/assets/stateDiagram-v2-4FDKWEC3-CuVnpOfP.js +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"heartbeat.d.ts","sourceRoot":"","sources":["../../src/services/heartbeat.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"heartbeat.d.ts","sourceRoot":"","sources":["../../src/services/heartbeat.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { and, asc, desc, eq, gt, inArray, sql } from "drizzle-orm";
4
- import { agents, agentRuntimeState, agentTaskSessions, agentWakeupRequests, heartbeatRunEvents, heartbeatRuns, costEvents, issues, projectWorkspaces, } from "@paperclipai/db";
4
+ import { agents, agentRuntimeState, agentTaskSessions, agentWakeupRequests, heartbeatRunEvents, heartbeatRuns, issues, projects, projectWorkspaces, } from "@paperclipai/db";
5
5
  import { conflict, notFound } from "../errors.js";
6
6
  import { logger } from "../middleware/logger.js";
7
7
  import { publishLiveEvent } from "./live-events.js";
@@ -9,14 +9,50 @@ import { getRunLogStore } from "./run-log-store.js";
9
9
  import { getServerAdapter, runningProcesses } from "../adapters/index.js";
10
10
  import { createLocalAgentJwt } from "../agent-auth-jwt.js";
11
11
  import { parseObject, asBoolean, asNumber, appendWithCap, MAX_EXCERPT_BYTES } from "../adapters/utils.js";
12
+ import { costService } from "./costs.js";
12
13
  import { secretService } from "./secrets.js";
13
14
  import { resolveDefaultAgentWorkspaceDir } from "../home-paths.js";
15
+ import { summarizeHeartbeatRunResultJson } from "./heartbeat-run-summary.js";
16
+ import { buildWorkspaceReadyComment, ensureRuntimeServicesForRun, persistAdapterManagedRuntimeServices, realizeExecutionWorkspace, releaseRuntimeServicesForRun, } from "./workspace-runtime.js";
17
+ import { issueService } from "./issues.js";
18
+ import { buildExecutionWorkspaceAdapterConfig, parseIssueExecutionWorkspaceSettings, parseProjectExecutionWorkspacePolicy, resolveExecutionWorkspaceMode, } from "./execution-workspace-policy.js";
19
+ import { redactCurrentUserText, redactCurrentUserValue } from "../log-redaction.js";
14
20
  const MAX_LIVE_LOG_CHUNK_BYTES = 8 * 1024;
15
21
  const HEARTBEAT_MAX_CONCURRENT_RUNS_DEFAULT = 1;
16
22
  const HEARTBEAT_MAX_CONCURRENT_RUNS_MAX = 10;
17
23
  const DEFERRED_WAKE_CONTEXT_KEY = "_paperclipWakeContext";
18
24
  const startLocksByAgent = new Map();
19
25
  const REPO_ONLY_CWD_SENTINEL = "/__paperclip_repo_only__";
26
+ const heartbeatRunListColumns = {
27
+ id: heartbeatRuns.id,
28
+ companyId: heartbeatRuns.companyId,
29
+ agentId: heartbeatRuns.agentId,
30
+ invocationSource: heartbeatRuns.invocationSource,
31
+ triggerDetail: heartbeatRuns.triggerDetail,
32
+ status: heartbeatRuns.status,
33
+ startedAt: heartbeatRuns.startedAt,
34
+ finishedAt: heartbeatRuns.finishedAt,
35
+ error: heartbeatRuns.error,
36
+ wakeupRequestId: heartbeatRuns.wakeupRequestId,
37
+ exitCode: heartbeatRuns.exitCode,
38
+ signal: heartbeatRuns.signal,
39
+ usageJson: heartbeatRuns.usageJson,
40
+ resultJson: heartbeatRuns.resultJson,
41
+ sessionIdBefore: heartbeatRuns.sessionIdBefore,
42
+ sessionIdAfter: heartbeatRuns.sessionIdAfter,
43
+ logStore: heartbeatRuns.logStore,
44
+ logRef: heartbeatRuns.logRef,
45
+ logBytes: heartbeatRuns.logBytes,
46
+ logSha256: heartbeatRuns.logSha256,
47
+ logCompressed: heartbeatRuns.logCompressed,
48
+ stdoutExcerpt: sql `NULL`.as("stdoutExcerpt"),
49
+ stderrExcerpt: sql `NULL`.as("stderrExcerpt"),
50
+ errorCode: heartbeatRuns.errorCode,
51
+ externalRunId: heartbeatRuns.externalRunId,
52
+ contextSnapshot: heartbeatRuns.contextSnapshot,
53
+ createdAt: heartbeatRuns.createdAt,
54
+ updatedAt: heartbeatRuns.updatedAt,
55
+ };
20
56
  function appendExcerpt(prev, chunk) {
21
57
  return appendWithCap(prev, chunk, MAX_EXCERPT_BYTES);
22
58
  }
@@ -294,6 +330,7 @@ function resolveNextSessionState(input) {
294
330
  export function heartbeatService(db) {
295
331
  const runLogStore = getRunLogStore();
296
332
  const secretsSvc = secretService(db);
333
+ const issuesSvc = issueService(db);
297
334
  async function getAgent(agentId) {
298
335
  return db
299
336
  .select()
@@ -551,6 +588,8 @@ export function heartbeatService(db) {
551
588
  .where(eq(agentWakeupRequests.id, wakeupRequestId));
552
589
  }
553
590
  async function appendRunEvent(run, seq, event) {
591
+ const sanitizedMessage = event.message ? redactCurrentUserText(event.message) : event.message;
592
+ const sanitizedPayload = event.payload ? redactCurrentUserValue(event.payload) : event.payload;
554
593
  await db.insert(heartbeatRunEvents).values({
555
594
  companyId: run.companyId,
556
595
  runId: run.id,
@@ -560,8 +599,8 @@ export function heartbeatService(db) {
560
599
  stream: event.stream,
561
600
  level: event.level,
562
601
  color: event.color,
563
- message: event.message,
564
- payload: event.payload,
602
+ message: sanitizedMessage,
603
+ payload: sanitizedPayload,
565
604
  });
566
605
  publishLiveEvent({
567
606
  companyId: run.companyId,
@@ -574,8 +613,8 @@ export function heartbeatService(db) {
574
613
  stream: event.stream ?? null,
575
614
  level: event.level ?? null,
576
615
  color: event.color ?? null,
577
- message: event.message ?? null,
578
- payload: event.payload ?? null,
616
+ message: sanitizedMessage ?? null,
617
+ payload: sanitizedPayload ?? null,
579
618
  },
580
619
  });
581
620
  }
@@ -739,8 +778,8 @@ export function heartbeatService(db) {
739
778
  })
740
779
  .where(eq(agentRuntimeState.agentId, agent.id));
741
780
  if (additionalCostCents > 0 || hasTokenUsage) {
742
- await db.insert(costEvents).values({
743
- companyId: agent.companyId,
781
+ const costs = costService(db);
782
+ await costs.createEvent(agent.companyId, {
744
783
  agentId: agent.id,
745
784
  provider: result.provider ?? "unknown",
746
785
  model: result.model ?? "unknown",
@@ -750,15 +789,6 @@ export function heartbeatService(db) {
750
789
  occurredAt: new Date(),
751
790
  });
752
791
  }
753
- if (additionalCostCents > 0) {
754
- await db
755
- .update(agents)
756
- .set({
757
- spentMonthlyCents: sql `${agents.spentMonthlyCents} + ${additionalCostCents}`,
758
- updatedAt: new Date(),
759
- })
760
- .where(eq(agents.id, agent.id));
761
- }
762
792
  }
763
793
  async function startNextQueuedRunForAgent(agentId) {
764
794
  return withAgentStartLock(agentId, async () => {
@@ -832,8 +862,10 @@ export function heartbeatService(db) {
832
862
  const issueAssigneeConfig = issueId
833
863
  ? await db
834
864
  .select({
865
+ projectId: issues.projectId,
835
866
  assigneeAgentId: issues.assigneeAgentId,
836
867
  assigneeAdapterOverrides: issues.assigneeAdapterOverrides,
868
+ executionWorkspaceSettings: issues.executionWorkspaceSettings,
837
869
  })
838
870
  .from(issues)
839
871
  .where(and(eq(issues.id, issueId), eq(issues.companyId, agent.companyId)))
@@ -842,6 +874,16 @@ export function heartbeatService(db) {
842
874
  const issueAssigneeOverrides = issueAssigneeConfig && issueAssigneeConfig.assigneeAgentId === agent.id
843
875
  ? parseIssueAssigneeAdapterOverrides(issueAssigneeConfig.assigneeAdapterOverrides)
844
876
  : null;
877
+ const issueExecutionWorkspaceSettings = parseIssueExecutionWorkspaceSettings(issueAssigneeConfig?.executionWorkspaceSettings);
878
+ const contextProjectId = readNonEmptyString(context.projectId);
879
+ const executionProjectId = issueAssigneeConfig?.projectId ?? contextProjectId;
880
+ const projectExecutionWorkspacePolicy = executionProjectId
881
+ ? await db
882
+ .select({ executionWorkspacePolicy: projects.executionWorkspacePolicy })
883
+ .from(projects)
884
+ .where(and(eq(projects.id, executionProjectId), eq(projects.companyId, agent.companyId)))
885
+ .then((rows) => parseProjectExecutionWorkspacePolicy(rows[0]?.executionWorkspacePolicy))
886
+ : null;
845
887
  const taskSession = taskKey
846
888
  ? await getTaskSession(agent.companyId, agent.id, agent.adapterType, taskKey)
847
889
  : null;
@@ -849,15 +891,64 @@ export function heartbeatService(db) {
849
891
  const sessionResetReason = describeSessionResetReason(context);
850
892
  const taskSessionForRun = resetTaskSession ? null : taskSession;
851
893
  const previousSessionParams = normalizeSessionParams(sessionCodec.deserialize(taskSessionForRun?.sessionParamsJson ?? null));
852
- const resolvedWorkspace = await resolveWorkspaceForRun(agent, context, previousSessionParams, { useProjectWorkspace: issueAssigneeOverrides?.useProjectWorkspace ?? null });
894
+ const config = parseObject(agent.adapterConfig);
895
+ const executionWorkspaceMode = resolveExecutionWorkspaceMode({
896
+ projectPolicy: projectExecutionWorkspacePolicy,
897
+ issueSettings: issueExecutionWorkspaceSettings,
898
+ legacyUseProjectWorkspace: issueAssigneeOverrides?.useProjectWorkspace ?? null,
899
+ });
900
+ const resolvedWorkspace = await resolveWorkspaceForRun(agent, context, previousSessionParams, { useProjectWorkspace: executionWorkspaceMode !== "agent_default" });
901
+ const workspaceManagedConfig = buildExecutionWorkspaceAdapterConfig({
902
+ agentConfig: config,
903
+ projectPolicy: projectExecutionWorkspacePolicy,
904
+ issueSettings: issueExecutionWorkspaceSettings,
905
+ mode: executionWorkspaceMode,
906
+ legacyUseProjectWorkspace: issueAssigneeOverrides?.useProjectWorkspace ?? null,
907
+ });
908
+ const mergedConfig = issueAssigneeOverrides?.adapterConfig
909
+ ? { ...workspaceManagedConfig, ...issueAssigneeOverrides.adapterConfig }
910
+ : workspaceManagedConfig;
911
+ const { config: resolvedConfig, secretKeys } = await secretsSvc.resolveAdapterConfigForRuntime(agent.companyId, mergedConfig);
912
+ const issueRef = issueId
913
+ ? await db
914
+ .select({
915
+ id: issues.id,
916
+ identifier: issues.identifier,
917
+ title: issues.title,
918
+ })
919
+ .from(issues)
920
+ .where(and(eq(issues.id, issueId), eq(issues.companyId, agent.companyId)))
921
+ .then((rows) => rows[0] ?? null)
922
+ : null;
923
+ const executionWorkspace = await realizeExecutionWorkspace({
924
+ base: {
925
+ baseCwd: resolvedWorkspace.cwd,
926
+ source: resolvedWorkspace.source,
927
+ projectId: resolvedWorkspace.projectId,
928
+ workspaceId: resolvedWorkspace.workspaceId,
929
+ repoUrl: resolvedWorkspace.repoUrl,
930
+ repoRef: resolvedWorkspace.repoRef,
931
+ },
932
+ config: resolvedConfig,
933
+ issue: issueRef,
934
+ agent: {
935
+ id: agent.id,
936
+ name: agent.name,
937
+ companyId: agent.companyId,
938
+ },
939
+ });
853
940
  const runtimeSessionResolution = resolveRuntimeSessionParamsForWorkspace({
854
941
  agentId: agent.id,
855
942
  previousSessionParams,
856
- resolvedWorkspace,
943
+ resolvedWorkspace: {
944
+ ...resolvedWorkspace,
945
+ cwd: executionWorkspace.cwd,
946
+ },
857
947
  });
858
948
  const runtimeSessionParams = runtimeSessionResolution.sessionParams;
859
949
  const runtimeWorkspaceWarnings = [
860
950
  ...resolvedWorkspace.warnings,
951
+ ...executionWorkspace.warnings,
861
952
  ...(runtimeSessionResolution.warning ? [runtimeSessionResolution.warning] : []),
862
953
  ...(resetTaskSession && sessionResetReason
863
954
  ? [
@@ -868,16 +959,32 @@ export function heartbeatService(db) {
868
959
  : []),
869
960
  ];
870
961
  context.paperclipWorkspace = {
871
- cwd: resolvedWorkspace.cwd,
872
- source: resolvedWorkspace.source,
873
- projectId: resolvedWorkspace.projectId,
874
- workspaceId: resolvedWorkspace.workspaceId,
875
- repoUrl: resolvedWorkspace.repoUrl,
876
- repoRef: resolvedWorkspace.repoRef,
962
+ cwd: executionWorkspace.cwd,
963
+ source: executionWorkspace.source,
964
+ mode: executionWorkspaceMode,
965
+ strategy: executionWorkspace.strategy,
966
+ projectId: executionWorkspace.projectId,
967
+ workspaceId: executionWorkspace.workspaceId,
968
+ repoUrl: executionWorkspace.repoUrl,
969
+ repoRef: executionWorkspace.repoRef,
970
+ branchName: executionWorkspace.branchName,
971
+ worktreePath: executionWorkspace.worktreePath,
877
972
  };
878
973
  context.paperclipWorkspaces = resolvedWorkspace.workspaceHints;
879
- if (resolvedWorkspace.projectId && !readNonEmptyString(context.projectId)) {
880
- context.projectId = resolvedWorkspace.projectId;
974
+ const runtimeServiceIntents = (() => {
975
+ const runtimeConfig = parseObject(resolvedConfig.workspaceRuntime);
976
+ return Array.isArray(runtimeConfig.services)
977
+ ? runtimeConfig.services.filter((value) => typeof value === "object" && value !== null)
978
+ : [];
979
+ })();
980
+ if (runtimeServiceIntents.length > 0) {
981
+ context.paperclipRuntimeServiceIntents = runtimeServiceIntents;
982
+ }
983
+ else {
984
+ delete context.paperclipRuntimeServiceIntents;
985
+ }
986
+ if (executionWorkspace.projectId && !readNonEmptyString(context.projectId)) {
987
+ context.projectId = executionWorkspace.projectId;
881
988
  }
882
989
  const runtimeSessionFallback = taskKey || resetTaskSession ? null : runtime.sessionId;
883
990
  const previousSessionDisplayId = truncateDisplayId(taskSessionForRun?.sessionDisplayId ??
@@ -901,6 +1008,7 @@ export function heartbeatService(db) {
901
1008
  .set({
902
1009
  startedAt,
903
1010
  sessionIdBefore: runtimeForAdapter.sessionDisplayId ?? runtimeForAdapter.sessionId,
1011
+ contextSnapshot: context,
904
1012
  updatedAt: new Date(),
905
1013
  })
906
1014
  .where(eq(heartbeatRuns.id, run.id))
@@ -946,40 +1054,76 @@ export function heartbeatService(db) {
946
1054
  })
947
1055
  .where(eq(heartbeatRuns.id, runId));
948
1056
  const onLog = async (stream, chunk) => {
1057
+ const sanitizedChunk = redactCurrentUserText(chunk);
949
1058
  if (stream === "stdout")
950
- stdoutExcerpt = appendExcerpt(stdoutExcerpt, chunk);
1059
+ stdoutExcerpt = appendExcerpt(stdoutExcerpt, sanitizedChunk);
951
1060
  if (stream === "stderr")
952
- stderrExcerpt = appendExcerpt(stderrExcerpt, chunk);
1061
+ stderrExcerpt = appendExcerpt(stderrExcerpt, sanitizedChunk);
1062
+ const ts = new Date().toISOString();
953
1063
  if (handle) {
954
1064
  await runLogStore.append(handle, {
955
1065
  stream,
956
- chunk,
957
- ts: new Date().toISOString(),
1066
+ chunk: sanitizedChunk,
1067
+ ts,
958
1068
  });
959
1069
  }
960
- const payloadChunk = chunk.length > MAX_LIVE_LOG_CHUNK_BYTES
961
- ? chunk.slice(chunk.length - MAX_LIVE_LOG_CHUNK_BYTES)
962
- : chunk;
1070
+ const payloadChunk = sanitizedChunk.length > MAX_LIVE_LOG_CHUNK_BYTES
1071
+ ? sanitizedChunk.slice(sanitizedChunk.length - MAX_LIVE_LOG_CHUNK_BYTES)
1072
+ : sanitizedChunk;
963
1073
  publishLiveEvent({
964
1074
  companyId: run.companyId,
965
1075
  type: "heartbeat.run.log",
966
1076
  payload: {
967
1077
  runId: run.id,
968
1078
  agentId: run.agentId,
1079
+ ts,
969
1080
  stream,
970
1081
  chunk: payloadChunk,
971
- truncated: payloadChunk.length !== chunk.length,
1082
+ truncated: payloadChunk.length !== sanitizedChunk.length,
972
1083
  },
973
1084
  });
974
1085
  };
975
1086
  for (const warning of runtimeWorkspaceWarnings) {
976
1087
  await onLog("stderr", `[paperclip] ${warning}\n`);
977
1088
  }
978
- const config = parseObject(agent.adapterConfig);
979
- const mergedConfig = issueAssigneeOverrides?.adapterConfig
980
- ? { ...config, ...issueAssigneeOverrides.adapterConfig }
981
- : config;
982
- const { config: resolvedConfig, secretKeys } = await secretsSvc.resolveAdapterConfigForRuntime(agent.companyId, mergedConfig);
1089
+ const adapterEnv = Object.fromEntries(Object.entries(parseObject(resolvedConfig.env)).filter((entry) => typeof entry[0] === "string" && typeof entry[1] === "string"));
1090
+ const runtimeServices = await ensureRuntimeServicesForRun({
1091
+ db,
1092
+ runId: run.id,
1093
+ agent: {
1094
+ id: agent.id,
1095
+ name: agent.name,
1096
+ companyId: agent.companyId,
1097
+ },
1098
+ issue: issueRef,
1099
+ workspace: executionWorkspace,
1100
+ config: resolvedConfig,
1101
+ adapterEnv,
1102
+ onLog,
1103
+ });
1104
+ if (runtimeServices.length > 0) {
1105
+ context.paperclipRuntimeServices = runtimeServices;
1106
+ context.paperclipRuntimePrimaryUrl =
1107
+ runtimeServices.find((service) => readNonEmptyString(service.url))?.url ?? null;
1108
+ await db
1109
+ .update(heartbeatRuns)
1110
+ .set({
1111
+ contextSnapshot: context,
1112
+ updatedAt: new Date(),
1113
+ })
1114
+ .where(eq(heartbeatRuns.id, run.id));
1115
+ }
1116
+ if (issueId && (executionWorkspace.created || runtimeServices.some((service) => !service.reused))) {
1117
+ try {
1118
+ await issuesSvc.addComment(issueId, buildWorkspaceReadyComment({
1119
+ workspace: executionWorkspace,
1120
+ runtimeServices,
1121
+ }), { agentId: agent.id });
1122
+ }
1123
+ catch (err) {
1124
+ await onLog("stderr", `[paperclip] Failed to post workspace-ready comment: ${err instanceof Error ? err.message : String(err)}\n`);
1125
+ }
1126
+ }
983
1127
  const onAdapterMeta = async (meta) => {
984
1128
  if (meta.env && secretKeys.size > 0) {
985
1129
  for (const key of secretKeys) {
@@ -1017,6 +1161,48 @@ export function heartbeatService(db) {
1017
1161
  onMeta: onAdapterMeta,
1018
1162
  authToken: authToken ?? undefined,
1019
1163
  });
1164
+ const adapterManagedRuntimeServices = adapterResult.runtimeServices
1165
+ ? await persistAdapterManagedRuntimeServices({
1166
+ db,
1167
+ adapterType: agent.adapterType,
1168
+ runId: run.id,
1169
+ agent: {
1170
+ id: agent.id,
1171
+ name: agent.name,
1172
+ companyId: agent.companyId,
1173
+ },
1174
+ issue: issueRef,
1175
+ workspace: executionWorkspace,
1176
+ reports: adapterResult.runtimeServices,
1177
+ })
1178
+ : [];
1179
+ if (adapterManagedRuntimeServices.length > 0) {
1180
+ const combinedRuntimeServices = [
1181
+ ...runtimeServices,
1182
+ ...adapterManagedRuntimeServices,
1183
+ ];
1184
+ context.paperclipRuntimeServices = combinedRuntimeServices;
1185
+ context.paperclipRuntimePrimaryUrl =
1186
+ combinedRuntimeServices.find((service) => readNonEmptyString(service.url))?.url ?? null;
1187
+ await db
1188
+ .update(heartbeatRuns)
1189
+ .set({
1190
+ contextSnapshot: context,
1191
+ updatedAt: new Date(),
1192
+ })
1193
+ .where(eq(heartbeatRuns.id, run.id));
1194
+ if (issueId) {
1195
+ try {
1196
+ await issuesSvc.addComment(issueId, buildWorkspaceReadyComment({
1197
+ workspace: executionWorkspace,
1198
+ runtimeServices: adapterManagedRuntimeServices,
1199
+ }), { agentId: agent.id });
1200
+ }
1201
+ catch (err) {
1202
+ await onLog("stderr", `[paperclip] Failed to post adapter-managed runtime comment: ${err instanceof Error ? err.message : String(err)}\n`);
1203
+ }
1204
+ }
1205
+ }
1020
1206
  const nextSessionState = resolveNextSessionState({
1021
1207
  codec: sessionCodec,
1022
1208
  adapterResult,
@@ -1060,7 +1246,7 @@ export function heartbeatService(db) {
1060
1246
  finishedAt: new Date(),
1061
1247
  error: outcome === "succeeded"
1062
1248
  ? null
1063
- : adapterResult.errorMessage ?? (outcome === "timed_out" ? "Timed out" : "Adapter failed"),
1249
+ : redactCurrentUserText(adapterResult.errorMessage ?? (outcome === "timed_out" ? "Timed out" : "Adapter failed")),
1064
1250
  errorCode: outcome === "timed_out"
1065
1251
  ? "timeout"
1066
1252
  : outcome === "cancelled"
@@ -1125,7 +1311,7 @@ export function heartbeatService(db) {
1125
1311
  await finalizeAgentStatus(agent.id, outcome);
1126
1312
  }
1127
1313
  catch (err) {
1128
- const message = err instanceof Error ? err.message : "Unknown adapter failure";
1314
+ const message = redactCurrentUserText(err instanceof Error ? err.message : "Unknown adapter failure");
1129
1315
  logger.error({ err, runId }, "heartbeat execution failed");
1130
1316
  let logSummary = null;
1131
1317
  if (handle) {
@@ -1182,6 +1368,7 @@ export function heartbeatService(db) {
1182
1368
  await finalizeAgentStatus(agent.id, "failed");
1183
1369
  }
1184
1370
  finally {
1371
+ await releaseRuntimeServicesForRun(run.id);
1185
1372
  await startNextQueuedRunForAgent(agent.id);
1186
1373
  }
1187
1374
  }
@@ -1678,18 +1865,19 @@ export function heartbeatService(db) {
1678
1865
  return newRun;
1679
1866
  }
1680
1867
  return {
1681
- list: (companyId, agentId, limit) => {
1868
+ list: async (companyId, agentId, limit) => {
1682
1869
  const query = db
1683
- .select()
1870
+ .select(heartbeatRunListColumns)
1684
1871
  .from(heartbeatRuns)
1685
1872
  .where(agentId
1686
1873
  ? and(eq(heartbeatRuns.companyId, companyId), eq(heartbeatRuns.agentId, agentId))
1687
1874
  : eq(heartbeatRuns.companyId, companyId))
1688
1875
  .orderBy(desc(heartbeatRuns.createdAt));
1689
- if (limit) {
1690
- return query.limit(limit);
1691
- }
1692
- return query;
1876
+ const rows = limit ? await query.limit(limit) : await query;
1877
+ return rows.map((row) => ({
1878
+ ...row,
1879
+ resultJson: summarizeHeartbeatRunResultJson(row.resultJson),
1880
+ }));
1693
1881
  },
1694
1882
  getRun,
1695
1883
  getRuntimeState: async (agentId) => {
@@ -1772,6 +1960,7 @@ export function heartbeatService(db) {
1772
1960
  store: run.logStore,
1773
1961
  logRef: run.logRef,
1774
1962
  ...result,
1963
+ content: redactCurrentUserText(result.content),
1775
1964
  };
1776
1965
  },
1777
1966
  invoke: async (agentId, source = "on_demand", contextSnapshot = {}, triggerDetail = "manual", actor) => enqueueWakeup(agentId, {