@fitlab-ai/agent-infra 0.9.14 → 0.9.15

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 (250) hide show
  1. package/README.md +10 -0
  2. package/README.zh-CN.md +10 -0
  3. package/bin/internal-cli.sh +45 -0
  4. package/dist/bin/internal-cli.js +93 -30
  5. package/dist/lib/agent-clients/adapters/codex-lifecycle/capability-store.js +165 -27
  6. package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +3 -2
  7. package/dist/lib/defaults.json +103 -103
  8. package/dist/lib/fs/durable-write.js +37 -0
  9. package/dist/lib/fs/file-lock.js +111 -0
  10. package/dist/lib/host-control/audit.js +19 -0
  11. package/dist/lib/host-control/client.js +142 -0
  12. package/dist/lib/host-control/command.js +49 -0
  13. package/dist/lib/host-control/path.js +160 -0
  14. package/dist/lib/host-control/secure-fs.js +140 -0
  15. package/dist/lib/host-control/server.js +159 -0
  16. package/dist/lib/host-control/service.js +112 -0
  17. package/dist/lib/init.js +11 -2
  18. package/dist/lib/internal/cli-route-inventory.js +3 -1
  19. package/dist/lib/internal/codex-lifecycle.js +6 -6
  20. package/dist/lib/internal/demo-promotion.js +322 -0
  21. package/dist/lib/internal/demo-transcript.js +454 -0
  22. package/dist/lib/internal/host-control.js +28 -0
  23. package/dist/lib/internal/manual-validation.js +322 -0
  24. package/dist/lib/internal/platform-pr.js +18 -4
  25. package/dist/lib/internal/release-workflow.js +63 -84
  26. package/dist/lib/internal/sandbox-control.js +149 -2
  27. package/dist/lib/internal/task-artifact.js +15 -262
  28. package/dist/lib/internal/task-create.js +6 -5
  29. package/dist/lib/internal/task-event.js +37 -37
  30. package/dist/lib/internal/task-operation-registry.js +101 -3
  31. package/dist/lib/internal/task-review.js +8 -53
  32. package/dist/lib/internal/task-validate.js +30 -10
  33. package/dist/lib/owned-path.js +33 -0
  34. package/dist/lib/platform/check-status.js +11 -0
  35. package/dist/lib/platform/comment-safety.js +4 -1
  36. package/dist/lib/platform/completion-backfill.js +1 -1
  37. package/dist/lib/platform/github-data.js +241 -0
  38. package/dist/lib/platform/github-provider.js +15 -20
  39. package/dist/lib/platform/issue-comments.js +2 -2
  40. package/dist/lib/platform/issues.js +1 -179
  41. package/dist/lib/platform/pr-checks.js +12 -65
  42. package/dist/lib/platform/pr-summary.js +55 -3
  43. package/dist/lib/platform/pull-requests.js +2 -105
  44. package/dist/lib/platform/snapshots.js +2 -0
  45. package/dist/lib/platform/verification-sync.js +127 -142
  46. package/dist/lib/release/workflow.js +1 -1
  47. package/dist/lib/sandbox/commands/create.js +7 -2
  48. package/dist/lib/sandbox/commands/rm.js +3 -1514
  49. package/dist/lib/sandbox/control/audit.js +203 -0
  50. package/dist/lib/sandbox/control/client.js +93 -54
  51. package/dist/lib/sandbox/control/executor.js +129 -65
  52. package/dist/lib/sandbox/control/finalization-response.js +27 -0
  53. package/dist/lib/sandbox/control/identity-sentinel.js +107 -0
  54. package/dist/lib/sandbox/control/lifecycle.js +36 -2
  55. package/dist/lib/sandbox/control/native-file-lock.js +6 -98
  56. package/dist/lib/sandbox/control/protocol.js +55 -4
  57. package/dist/lib/sandbox/control/server.js +491 -120
  58. package/dist/lib/sandbox/control/state.js +58 -0
  59. package/dist/lib/sandbox/control/task-workflow.js +74 -0
  60. package/dist/lib/sandbox/control/workflow-executor.js +99 -0
  61. package/dist/lib/sandbox/index.js +2 -2
  62. package/dist/lib/sandbox/recovery.js +28 -4
  63. package/dist/lib/sandbox/removal.js +1717 -0
  64. package/dist/lib/sandbox/task-cleanup.js +217 -0
  65. package/dist/lib/sandbox/workspace-view.js +13 -14
  66. package/dist/lib/task/activity-intent.js +2 -1
  67. package/dist/lib/task/activity-log.js +30 -24
  68. package/dist/lib/task/artifact-command.js +101 -0
  69. package/dist/lib/task/artifact-lifecycle.js +30 -28
  70. package/dist/lib/task/artifact-name.js +36 -0
  71. package/dist/lib/task/artifact-operations.js +23 -69
  72. package/dist/lib/task/artifact-receipts.js +3 -15
  73. package/dist/lib/task/artifact-repair-intent.js +87 -16
  74. package/dist/lib/task/artifact-schema.js +6 -14
  75. package/dist/lib/task/capabilities.js +12 -19
  76. package/dist/lib/task/codex-orchestration.js +71 -25
  77. package/dist/lib/task/commit-identity.js +28 -0
  78. package/dist/lib/task/commit-operation.js +2 -16
  79. package/dist/lib/task/control-authority.js +371 -5
  80. package/dist/lib/task/control-recovery.js +128 -0
  81. package/dist/lib/task/create.js +62 -9
  82. package/dist/lib/task/decision-details.js +2 -46
  83. package/dist/lib/task/events.js +120 -9
  84. package/dist/lib/task/finalization-state.js +9 -0
  85. package/dist/lib/task/human-override.js +3 -6
  86. package/dist/lib/task/implementation-inputs.js +3 -3
  87. package/dist/lib/task/intermediate-cleanup.js +383 -0
  88. package/dist/lib/task/invalidation.js +18 -65
  89. package/dist/lib/task/ledger-intents.js +7 -22
  90. package/dist/lib/task/ledger.js +1 -3
  91. package/dist/lib/task/lifecycle.js +19 -1
  92. package/dist/lib/task/local-artifact-finalization.js +132 -157
  93. package/dist/lib/task/manual-validation-completion.js +26 -0
  94. package/dist/lib/task/manual-validation-evidence.js +130 -0
  95. package/dist/lib/task/manual-validation-receipt.js +101 -0
  96. package/dist/lib/task/manual-validation-shared.js +40 -0
  97. package/dist/lib/task/manual-validation-transaction.js +243 -0
  98. package/dist/lib/task/markdown.js +47 -0
  99. package/dist/lib/task/orchestration.js +14 -17
  100. package/dist/lib/task/qualification-audit.js +20 -34
  101. package/dist/lib/task/review-artifacts.js +2 -18
  102. package/dist/lib/task/review-command.js +25 -0
  103. package/dist/lib/task/review-finalization.js +125 -193
  104. package/dist/lib/task/review-fingerprint.js +2 -2
  105. package/dist/lib/task/sections.js +34 -56
  106. package/dist/lib/task/verification-engine.js +116 -323
  107. package/dist/lib/task/verification.js +1 -1
  108. package/dist/lib/task/workflow-command.js +17 -0
  109. package/dist/lib/task/workflow-warning-intents.js +0 -16
  110. package/dist/lib/task/workflow-warnings.js +28 -2
  111. package/dist/lib/update.js +2 -0
  112. package/dist/lifecycle-build-manifest.json +3 -3
  113. package/lib/agent-clients/adapters/codex-lifecycle/capability-store.ts +223 -33
  114. package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +3 -2
  115. package/lib/fs/durable-write.ts +29 -0
  116. package/lib/fs/file-lock.ts +113 -0
  117. package/lib/host-control/audit.ts +22 -0
  118. package/lib/host-control/client.ts +172 -0
  119. package/lib/host-control/command.ts +60 -0
  120. package/lib/host-control/path.ts +167 -0
  121. package/lib/host-control/secure-fs.ts +135 -0
  122. package/lib/host-control/server.ts +180 -0
  123. package/lib/host-control/service.ts +133 -0
  124. package/lib/init.ts +15 -2
  125. package/lib/internal/cli-route-inventory.ts +3 -1
  126. package/lib/internal/codex-lifecycle.ts +6 -6
  127. package/lib/internal/demo-promotion.ts +354 -0
  128. package/lib/internal/demo-transcript.ts +419 -0
  129. package/lib/internal/host-control.ts +28 -0
  130. package/lib/internal/manual-validation.ts +306 -0
  131. package/lib/internal/platform-pr.ts +15 -4
  132. package/lib/internal/release-workflow.ts +74 -82
  133. package/lib/internal/sandbox-control.ts +162 -1
  134. package/lib/internal/task-artifact.ts +13 -216
  135. package/lib/internal/task-create.ts +5 -5
  136. package/lib/internal/task-event.ts +20 -11
  137. package/lib/internal/task-operation-registry.ts +111 -3
  138. package/lib/internal/task-review.ts +6 -51
  139. package/lib/internal/task-validate.ts +26 -10
  140. package/lib/owned-path.ts +26 -0
  141. package/lib/platform/check-status.ts +9 -0
  142. package/lib/platform/comment-safety.ts +5 -0
  143. package/lib/platform/completion-backfill.ts +1 -1
  144. package/lib/platform/github-data.ts +322 -0
  145. package/lib/platform/github-provider.ts +15 -20
  146. package/lib/platform/issue-comments.ts +3 -4
  147. package/lib/platform/issues.ts +4 -245
  148. package/lib/platform/pr-checks.ts +13 -77
  149. package/lib/platform/pr-summary.ts +61 -5
  150. package/lib/platform/pull-requests.ts +3 -170
  151. package/lib/platform/snapshots.ts +53 -0
  152. package/lib/platform/verification-sync.ts +145 -155
  153. package/lib/release/workflow.ts +3 -3
  154. package/lib/sandbox/commands/create.ts +7 -6
  155. package/lib/sandbox/commands/rm.ts +3 -1909
  156. package/lib/sandbox/control/audit.ts +253 -0
  157. package/lib/sandbox/control/client.ts +109 -66
  158. package/lib/sandbox/control/executor.ts +134 -74
  159. package/lib/sandbox/control/finalization-response.ts +29 -0
  160. package/lib/sandbox/control/identity-sentinel.ts +137 -0
  161. package/lib/sandbox/control/lifecycle.ts +45 -3
  162. package/lib/sandbox/control/native-file-lock.ts +6 -107
  163. package/lib/sandbox/control/protocol.ts +75 -6
  164. package/lib/sandbox/control/server.ts +538 -123
  165. package/lib/sandbox/control/state.ts +78 -0
  166. package/lib/sandbox/control/task-workflow.ts +95 -0
  167. package/lib/sandbox/control/workflow-executor.ts +102 -0
  168. package/lib/sandbox/index.ts +2 -2
  169. package/lib/sandbox/recovery.ts +28 -5
  170. package/lib/sandbox/removal.ts +2144 -0
  171. package/lib/sandbox/task-cleanup.ts +209 -0
  172. package/lib/sandbox/workspace-view.ts +17 -15
  173. package/lib/task/activity-intent.ts +2 -2
  174. package/lib/task/activity-log.ts +27 -19
  175. package/lib/task/artifact-command.ts +104 -0
  176. package/lib/task/artifact-lifecycle.ts +31 -26
  177. package/lib/task/artifact-name.ts +55 -0
  178. package/lib/task/artifact-operations.ts +22 -68
  179. package/lib/task/artifact-receipts.ts +3 -14
  180. package/lib/task/artifact-repair-intent.ts +99 -18
  181. package/lib/task/artifact-schema.ts +5 -34
  182. package/lib/task/capabilities.ts +13 -22
  183. package/lib/task/codex-orchestration.ts +85 -24
  184. package/lib/task/commit-identity.ts +31 -0
  185. package/lib/task/commit-operation.ts +2 -16
  186. package/lib/task/control-authority.ts +502 -5
  187. package/lib/task/control-recovery.ts +174 -0
  188. package/lib/task/create.ts +63 -8
  189. package/lib/task/decision-details.ts +3 -71
  190. package/lib/task/events.ts +131 -10
  191. package/lib/task/finalization-state.ts +11 -0
  192. package/lib/task/human-override.ts +3 -8
  193. package/lib/task/implementation-inputs.ts +3 -3
  194. package/lib/task/intermediate-cleanup.ts +455 -0
  195. package/lib/task/invalidation.ts +18 -62
  196. package/lib/task/ledger-intents.ts +7 -24
  197. package/lib/task/ledger.ts +1 -3
  198. package/lib/task/lifecycle.ts +17 -1
  199. package/lib/task/local-artifact-finalization.ts +148 -182
  200. package/lib/task/manual-validation-completion.ts +40 -0
  201. package/lib/task/manual-validation-evidence.ts +209 -0
  202. package/lib/task/manual-validation-receipt.ts +152 -0
  203. package/lib/task/manual-validation-shared.ts +50 -0
  204. package/lib/task/manual-validation-transaction.ts +304 -0
  205. package/lib/task/markdown.ts +70 -0
  206. package/lib/task/orchestration.ts +19 -19
  207. package/lib/task/qualification-audit.ts +22 -33
  208. package/lib/task/review-artifacts.ts +1 -20
  209. package/lib/task/review-command.ts +23 -0
  210. package/lib/task/review-finalization.ts +131 -259
  211. package/lib/task/review-fingerprint.ts +2 -2
  212. package/lib/task/sections.ts +33 -54
  213. package/lib/task/verification-engine.ts +110 -366
  214. package/lib/task/verification-types.ts +17 -0
  215. package/lib/task/verification.ts +1 -1
  216. package/lib/task/workflow-command.ts +18 -0
  217. package/lib/task/workflow-warning-intents.ts +0 -13
  218. package/lib/task/workflow-warnings.ts +21 -2
  219. package/lib/update.ts +6 -0
  220. package/package.json +6 -6
  221. package/templates/.agents/hooks/lifecycle-delegation.js +6 -6
  222. package/templates/.agents/rules/testing-discipline.en.md +2 -0
  223. package/templates/.agents/rules/testing-discipline.zh-CN.md +2 -0
  224. package/templates/.agents/scripts/package.json +3 -0
  225. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +32 -20
  226. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +32 -20
  227. package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -1
  228. package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -1
  229. package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +2 -0
  230. package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +2 -0
  231. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +16 -7
  232. package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +16 -7
  233. package/templates/.agents/skills/complete-task/SKILL.en.md +1 -1
  234. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +1 -1
  235. package/templates/.agents/skills/release/SKILL.en.md +7 -3
  236. package/templates/.agents/skills/release/SKILL.zh-CN.md +7 -3
  237. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +20 -3
  238. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +20 -3
  239. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.en.md +4 -1
  240. package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.zh-CN.md +4 -1
  241. package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +2 -0
  242. package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +2 -0
  243. package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
  244. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
  245. package/templates/.agents/skills/test/SKILL.en.md +17 -6
  246. package/templates/.agents/skills/test/SKILL.zh-CN.md +17 -6
  247. package/templates/.claude/commands/run-manual-validation.en.md +1 -1
  248. package/templates/.claude/commands/run-manual-validation.zh-CN.md +1 -1
  249. package/dist/lib/platform/adapters.js +0 -56
  250. package/lib/platform/adapters.ts +0 -197
@@ -1,110 +1,110 @@
1
1
  {
2
- "platform": {
3
- "type": "github"
2
+ "platform": {
3
+ "type": "github"
4
+ },
5
+ "agentClients": [
6
+ {
7
+ "id": "claude-code",
8
+ "enabled": true,
9
+ "installInSandbox": true
4
10
  },
5
- "agentClients": [
6
- {
7
- "id": "claude-code",
8
- "enabled": true,
9
- "installInSandbox": true
10
- },
11
- {
12
- "id": "codex",
13
- "enabled": true,
14
- "installInSandbox": true
15
- },
16
- {
17
- "id": "antigravity-cli",
18
- "enabled": true,
19
- "installInSandbox": true
20
- },
21
- {
22
- "id": "opencode",
23
- "enabled": true,
24
- "installInSandbox": true
25
- },
26
- {
27
- "id": "traecli",
28
- "enabled": true,
29
- "installInSandbox": true
30
- }
31
- ],
32
- "sandbox": {
33
- "engine": null,
34
- "runtimes": [
35
- "node22"
36
- ],
37
- "tools": [
38
- "agent-infra"
39
- ],
40
- "refreshIntervalDays": 7,
41
- "dockerfile": null,
42
- "vm": {
43
- "cpu": null,
44
- "memory": null,
45
- "disk": null
46
- }
47
- },
48
- "task": {
49
- "shortIdLength": 2
11
+ {
12
+ "id": "codex",
13
+ "enabled": true,
14
+ "installInSandbox": true
50
15
  },
51
- "delivery": {
52
- "remote": "origin",
53
- "baseRef": "main"
16
+ {
17
+ "id": "antigravity-cli",
18
+ "enabled": true,
19
+ "installInSandbox": true
54
20
  },
55
- "labels": {
56
- "in": {}
21
+ {
22
+ "id": "opencode",
23
+ "enabled": true,
24
+ "installInSandbox": true
57
25
  },
58
- "files": {
59
- "managed": [
60
- ".agents/QUICKSTART.md",
61
- ".agents/README.md",
62
- ".agents/hooks/",
63
- ".agents/rules/",
64
- ".agents/scripts/",
65
- ".agents/skills/",
66
- ".agents/templates/",
67
- ".agents/workflows/",
68
- ".git-hooks/check-large-files.cjs",
69
- ".git-hooks/check-version-format.sh",
70
- ".github/scripts/",
71
- ".github/workflows/metadata-sync.yml",
72
- ".github/workflows/pr-label.yml",
73
- ".github/workflows/status-label.yml"
74
- ],
75
- "guardedManaged": [
76
- ".github/workflows/metadata-sync.yml",
77
- ".github/workflows/pr-label.yml",
78
- ".github/workflows/status-label.yml"
79
- ],
80
- "merged": [
81
- "**/post-release.*",
82
- "**/release.*",
83
- "**/test-integration.*",
84
- "**/test.*",
85
- "**/upgrade-dependency.*",
86
- ".agents/rules/testing-discipline.*",
87
- ".agents/skills/post-release/SKILL.*",
88
- ".agents/skills/release/SKILL.*",
89
- ".agents/skills/test-integration/SKILL.*",
90
- ".agents/skills/test/SKILL.*",
91
- ".agents/skills/upgrade-dependency/SKILL.*",
92
- ".git-hooks/pre-commit",
93
- ".gitignore"
94
- ],
95
- "ejected": [],
96
- "retiredManaged": [
97
- {
98
- "path": ".trae/skills/",
99
- "templateHashes": []
100
- },
101
- {
102
- "path": ".agents/workspace/README.md",
103
- "templateHashes": [
104
- "sha256:967b27ca4008154c5abf99a1df728242f80ed3ace9bd98eb2828bc1c76af826c",
105
- "sha256:15aa21942cf2a1396d27834f1d3d723b61a46f8d14600b706f39f3bebc21aea3"
106
- ]
107
- }
108
- ]
26
+ {
27
+ "id": "traecli",
28
+ "enabled": true,
29
+ "installInSandbox": true
30
+ }
31
+ ],
32
+ "sandbox": {
33
+ "engine": null,
34
+ "runtimes": [
35
+ "node22"
36
+ ],
37
+ "tools": [
38
+ "agent-infra"
39
+ ],
40
+ "refreshIntervalDays": 7,
41
+ "dockerfile": null,
42
+ "vm": {
43
+ "cpu": null,
44
+ "memory": null,
45
+ "disk": null
109
46
  }
47
+ },
48
+ "task": {
49
+ "shortIdLength": 2
50
+ },
51
+ "delivery": {
52
+ "remote": "origin",
53
+ "baseRef": "main"
54
+ },
55
+ "labels": {
56
+ "in": {}
57
+ },
58
+ "files": {
59
+ "managed": [
60
+ ".agents/QUICKSTART.md",
61
+ ".agents/README.md",
62
+ ".agents/hooks/",
63
+ ".agents/rules/",
64
+ ".agents/scripts/",
65
+ ".agents/skills/",
66
+ ".agents/templates/",
67
+ ".agents/workflows/",
68
+ ".git-hooks/check-large-files.cjs",
69
+ ".git-hooks/check-version-format.sh",
70
+ ".github/scripts/",
71
+ ".github/workflows/metadata-sync.yml",
72
+ ".github/workflows/pr-label.yml",
73
+ ".github/workflows/status-label.yml"
74
+ ],
75
+ "guardedManaged": [
76
+ ".github/workflows/metadata-sync.yml",
77
+ ".github/workflows/pr-label.yml",
78
+ ".github/workflows/status-label.yml"
79
+ ],
80
+ "merged": [
81
+ "**/post-release.*",
82
+ "**/release.*",
83
+ "**/test-integration.*",
84
+ "**/test.*",
85
+ "**/upgrade-dependency.*",
86
+ ".agents/rules/testing-discipline.*",
87
+ ".agents/skills/post-release/SKILL.*",
88
+ ".agents/skills/release/SKILL.*",
89
+ ".agents/skills/test-integration/SKILL.*",
90
+ ".agents/skills/test/SKILL.*",
91
+ ".agents/skills/upgrade-dependency/SKILL.*",
92
+ ".git-hooks/pre-commit",
93
+ ".gitignore"
94
+ ],
95
+ "ejected": [],
96
+ "retiredManaged": [
97
+ {
98
+ "path": ".trae/skills/",
99
+ "templateHashes": []
100
+ },
101
+ {
102
+ "path": ".agents/workspace/README.md",
103
+ "templateHashes": [
104
+ "sha256:967b27ca4008154c5abf99a1df728242f80ed3ace9bd98eb2828bc1c76af826c",
105
+ "sha256:15aa21942cf2a1396d27834f1d3d723b61a46f8d14600b706f39f3bebc21aea3"
106
+ ]
107
+ }
108
+ ]
109
+ }
110
110
  }
@@ -0,0 +1,37 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { randomUUID } from 'node:crypto';
4
+ export function fsyncDirectory(directory) {
5
+ const descriptor = fs.openSync(directory, 'r');
6
+ try {
7
+ fs.fsyncSync(descriptor);
8
+ }
9
+ finally {
10
+ fs.closeSync(descriptor);
11
+ }
12
+ }
13
+ /** The caller owns directory validation and the meaning of an existing target. */
14
+ export function writeDurableFile(target, content, options) {
15
+ const directory = path.dirname(target);
16
+ const temporary = path.join(directory, `.${path.basename(target)}.${process.pid}.${randomUUID()}.tmp`);
17
+ try {
18
+ const descriptor = fs.openSync(temporary, 'wx', options.mode);
19
+ try {
20
+ fs.writeFileSync(descriptor, content, { encoding: 'utf8' });
21
+ fs.fchmodSync(descriptor, options.mode);
22
+ fs.fsyncSync(descriptor);
23
+ }
24
+ finally {
25
+ fs.closeSync(descriptor);
26
+ }
27
+ if (options.replace)
28
+ fs.renameSync(temporary, target);
29
+ else
30
+ fs.linkSync(temporary, target);
31
+ fsyncDirectory(directory);
32
+ }
33
+ finally {
34
+ fs.rmSync(temporary, { force: true });
35
+ }
36
+ }
37
+ //# sourceMappingURL=durable-write.js.map
@@ -0,0 +1,111 @@
1
+ import { createRequire } from 'node:module';
2
+ import fs from 'node:fs';
3
+ const require = createRequire(import.meta.url);
4
+ export const NATIVE_LOCK_PRIMITIVE = process.platform === 'win32' ? 'LockFileEx'
5
+ : process.platform === 'linux' ? 'F_OFD_SETLK' : 'flock';
6
+ function loadNative() {
7
+ try {
8
+ return require('fs-native-extensions');
9
+ }
10
+ catch (error) {
11
+ throw new Error(`FILE_LOCK_UNSUPPORTED: native lock module is unavailable for Node ${process.version} (${process.platform}-${process.arch}). `
12
+ + 'Verify that fs-native-extensions includes a prebuilt binary for this platform and reinstall @fitlab-ai/agent-infra. '
13
+ + `Cause: ${error instanceof Error ? error.message : String(error)}`);
14
+ }
15
+ }
16
+ export function probeNativeLockCapability() {
17
+ try {
18
+ loadNative();
19
+ return {
20
+ supported: true,
21
+ primitive: NATIVE_LOCK_PRIMITIVE
22
+ };
23
+ }
24
+ catch (error) {
25
+ return {
26
+ supported: false,
27
+ primitive: 'unavailable',
28
+ reason: error instanceof Error ? error.message : String(error)
29
+ };
30
+ }
31
+ }
32
+ /** Hold a stable lock file; callers own its namespace and must never unlink it. */
33
+ export function acquireFileLock(filePath) {
34
+ const native = loadNative();
35
+ if (fs.existsSync(filePath)) {
36
+ const existing = fs.lstatSync(filePath);
37
+ if (existing.isSymbolicLink() || !existing.isFile()) {
38
+ throw new Error('FILE_LOCK_UNSUPPORTED: lock object is not a regular file');
39
+ }
40
+ if (process.platform !== 'win32' && typeof process.getuid === 'function'
41
+ && existing.uid !== process.getuid()) {
42
+ throw new Error('FILE_LOCK_UNSUPPORTED: lock object owner mismatch');
43
+ }
44
+ }
45
+ let fd;
46
+ try {
47
+ const noFollow = process.platform !== 'win32' && typeof fs.constants.O_NOFOLLOW === 'number'
48
+ ? fs.constants.O_NOFOLLOW : 0;
49
+ fd = fs.openSync(filePath, fs.constants.O_CREAT | fs.constants.O_RDWR | noFollow, 0o600);
50
+ const opened = fs.fstatSync(fd);
51
+ if (!opened.isFile())
52
+ throw new Error('lock object must be a regular file');
53
+ if (process.platform !== 'win32') {
54
+ if (typeof process.getuid === 'function' && opened.uid !== process.getuid()) {
55
+ throw new Error('lock object owner mismatch');
56
+ }
57
+ fs.fchmodSync(fd, 0o600);
58
+ }
59
+ if (!native.tryLock(fd)) {
60
+ fs.closeSync(fd);
61
+ fd = undefined;
62
+ }
63
+ else {
64
+ const current = fs.lstatSync(filePath);
65
+ if (!current.isFile() || current.dev !== opened.dev || current.ino !== opened.ino) {
66
+ throw new Error('lock object changed during acquisition');
67
+ }
68
+ }
69
+ }
70
+ catch (error) {
71
+ try {
72
+ if (fd !== undefined)
73
+ fs.closeSync(fd);
74
+ }
75
+ catch {
76
+ // Preserve the lock acquisition error.
77
+ }
78
+ throw new Error(`FILE_LOCK_UNSUPPORTED: ${error instanceof Error ? error.message : String(error)}`);
79
+ }
80
+ if (fd === undefined)
81
+ throw new Error('FILE_LOCK_BUSY');
82
+ let released = false;
83
+ return {
84
+ release() {
85
+ if (released)
86
+ return;
87
+ released = true;
88
+ let failure = null;
89
+ try {
90
+ if (fd === undefined)
91
+ throw new Error('descriptor is missing');
92
+ native.unlock(fd);
93
+ }
94
+ catch (error) {
95
+ failure = error;
96
+ }
97
+ finally {
98
+ try {
99
+ if (fd !== undefined)
100
+ fs.closeSync(fd);
101
+ }
102
+ catch (error) {
103
+ failure ??= error;
104
+ }
105
+ }
106
+ if (failure)
107
+ throw new Error(`FILE_LOCK_RELEASE_FAILED: ${failure instanceof Error ? failure.message : String(failure)}`);
108
+ }
109
+ };
110
+ }
111
+ //# sourceMappingURL=file-lock.js.map
@@ -0,0 +1,19 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ export const HOST_CONTROL_AUDIT_FILE = 'audit.ndjson';
4
+ export function hostControlAuditPath(endpoint) {
5
+ return path.join(path.dirname(endpoint), HOST_CONTROL_AUDIT_FILE);
6
+ }
7
+ export function appendHostControlAudit(endpoint, entry, at = Date.now()) {
8
+ const filePath = hostControlAuditPath(endpoint);
9
+ const descriptor = fs.openSync(filePath, 'a', 0o600);
10
+ try {
11
+ fs.fchmodSync(descriptor, 0o600);
12
+ fs.writeFileSync(descriptor, `${JSON.stringify({ version: 1, at, ...entry })}\n`, 'utf8');
13
+ fs.fsyncSync(descriptor);
14
+ }
15
+ finally {
16
+ fs.closeSync(descriptor);
17
+ }
18
+ }
19
+ //# sourceMappingURL=audit.js.map
@@ -0,0 +1,142 @@
1
+ import net from 'node:net';
2
+ import { randomUUID } from 'node:crypto';
3
+ import { inspectHostControlEndpoint, resolveHostControlEndpoint } from './path.js';
4
+ export const HOST_CONTROL_MAX_REQUEST_BYTES = 64 * 1024;
5
+ export const HOST_CONTROL_COMMANDS = Object.freeze([
6
+ 'task-lifecycle', 'task-orchestration', 'task-finalization',
7
+ 'task-artifact', 'task-review', 'task-event', 'task-ledger',
8
+ 'task-invalidation', 'task-warning'
9
+ ]);
10
+ export const HOST_CONTROL_TEST_ENVIRONMENT_KEYS = Object.freeze([
11
+ 'TZ', 'AGENT_INFRA_GH_BIN', 'AGENT_INFRA_GH_ARGS_JSON', 'GH_FAKE_PR_PATH', 'GH_FAKE_ARGS_PATH'
12
+ ]);
13
+ export class HostControlClientError extends Error {
14
+ code;
15
+ retryable;
16
+ changed;
17
+ constructor(code, message, retryable = false, submitted = false) {
18
+ super(`${code}: ${message}`);
19
+ this.name = 'HostControlClientError';
20
+ this.code = code;
21
+ this.retryable = retryable && !submitted;
22
+ this.changed = submitted ? null : false;
23
+ }
24
+ }
25
+ function reject(message) {
26
+ throw new HostControlClientError('HOST_CONTROL_REQUEST_INVALID', message);
27
+ }
28
+ export function validateHostControlRequest(value) {
29
+ if (!value || typeof value !== 'object' || Array.isArray(value))
30
+ reject('request must be an object');
31
+ const request = value;
32
+ if (Object.keys(request).sort().join(',') !== 'generation,id,operation,payload,scope,taskId,version'
33
+ || request.version !== 1 || typeof request.id !== 'string' || !/^[a-f0-9-]{16,64}$/u.test(request.id)
34
+ || (request.taskId !== null && (typeof request.taskId !== 'string' || !/^TASK-\d{8}-\d{6}$/u.test(request.taskId)))
35
+ || (request.generation !== null && (typeof request.generation !== 'string' || !request.generation))
36
+ || request.scope !== 'host-command' || !HOST_CONTROL_COMMANDS.includes(request.operation))
37
+ reject('request schema is invalid');
38
+ const payload = request.payload;
39
+ if (!payload || typeof payload !== 'object' || Array.isArray(payload)
40
+ || !['args,environment,workingDirectory', 'args,workingDirectory'].includes(Object.keys(payload).sort().join(','))
41
+ || !Array.isArray(payload.args) || payload.args.length > 128
42
+ || !payload.args.every((arg) => typeof arg === 'string' && !/[\r\n]/u.test(arg))
43
+ || typeof payload.workingDirectory !== 'string' || !payload.workingDirectory.startsWith('/'))
44
+ reject('host-command payload is invalid');
45
+ if (payload.environment !== undefined) {
46
+ if (!payload.environment || typeof payload.environment !== 'object' || Array.isArray(payload.environment))
47
+ reject('host-command environment is invalid');
48
+ for (const [key, value] of Object.entries(payload.environment)) {
49
+ if (!HOST_CONTROL_TEST_ENVIRONMENT_KEYS.includes(key)
50
+ || typeof value !== 'string' || /[\r\n]/u.test(value))
51
+ reject('host-command environment is invalid');
52
+ }
53
+ }
54
+ return request;
55
+ }
56
+ export function hostControlRequestForCommand(command, args, workingDirectory, environment = {}) {
57
+ if (!HOST_CONTROL_COMMANDS.includes(command))
58
+ reject('host-command is unsupported');
59
+ const taskArg = args[0];
60
+ const taskId = taskArg && /^TASK-\d{8}-\d{6}$/u.test(taskArg) ? taskArg : null;
61
+ return validateHostControlRequest({
62
+ version: 1,
63
+ id: randomUUID(),
64
+ taskId,
65
+ generation: null,
66
+ operation: command,
67
+ scope: 'host-command',
68
+ payload: {
69
+ workingDirectory,
70
+ args: [...args],
71
+ ...(Object.keys(environment).length > 0 ? { environment } : {})
72
+ }
73
+ });
74
+ }
75
+ function parseResponse(value, id) {
76
+ if (!value || typeof value !== 'object' || Array.isArray(value))
77
+ throw new HostControlClientError('HOST_CONTROL_RESPONSE_INVALID', 'response must be an object');
78
+ const response = value;
79
+ if (Object.keys(response).sort().join(',') !== 'error,exitCode,id,status,stderr,stdout,version'
80
+ || response.version !== 1 || response.id !== id
81
+ || !['completed', 'rejected', 'unknown'].includes(response.status)
82
+ || !Number.isSafeInteger(response.exitCode)
83
+ || typeof response.stdout !== 'string' || typeof response.stderr !== 'string'
84
+ || (response.error !== null && (!response.error || typeof response.error !== 'object'))) {
85
+ throw new HostControlClientError('HOST_CONTROL_RESPONSE_INVALID', 'response schema is invalid');
86
+ }
87
+ return response;
88
+ }
89
+ export async function requestHostControl(params) {
90
+ const request = validateHostControlRequest(params.request);
91
+ const endpoint = params.endpoint ?? resolveHostControlEndpoint();
92
+ const inspection = inspectHostControlEndpoint(endpoint, { uid: process.getuid?.() });
93
+ if (!inspection.ok)
94
+ throw new HostControlClientError(inspection.code ?? 'HOST_CONTROL_UNAVAILABLE', 'fixed host-control endpoint is unavailable', true);
95
+ const encoded = `${JSON.stringify(request)}\n`;
96
+ if (Buffer.byteLength(encoded, 'utf8') > HOST_CONTROL_MAX_REQUEST_BYTES)
97
+ throw new HostControlClientError('HOST_CONTROL_REQUEST_TOO_LARGE', 'request exceeds the control limit');
98
+ const timeoutMs = params.timeoutMs ?? 30_000;
99
+ return await new Promise((resolve, rejectPromise) => {
100
+ const socket = net.createConnection(endpoint);
101
+ let output = '';
102
+ let settled = false;
103
+ let submitted = false;
104
+ const failure = (code, message, retryable = false) => new HostControlClientError(code, message, retryable, submitted);
105
+ const finish = (error, response) => {
106
+ if (settled)
107
+ return;
108
+ settled = true;
109
+ clearTimeout(timer);
110
+ socket.destroy();
111
+ if (error)
112
+ rejectPromise(error);
113
+ else
114
+ resolve(response);
115
+ };
116
+ const timer = setTimeout(() => finish(failure('HOST_CONTROL_TIMEOUT', 'host-control did not respond; inspect task state before retrying', true)), timeoutMs);
117
+ socket.setEncoding('utf8');
118
+ socket.on('connect', () => { submitted = true; socket.end(encoded); });
119
+ socket.on('data', (chunk) => {
120
+ output += chunk;
121
+ if (Buffer.byteLength(output, 'utf8') > HOST_CONTROL_MAX_REQUEST_BYTES) {
122
+ finish(failure('HOST_CONTROL_RESPONSE_TOO_LARGE', 'host-control response exceeds the control limit'));
123
+ return;
124
+ }
125
+ const newline = output.indexOf('\n');
126
+ if (newline < 0)
127
+ return;
128
+ try {
129
+ finish(undefined, parseResponse(JSON.parse(output.slice(0, newline)), request.id));
130
+ }
131
+ catch (error) {
132
+ finish(failure('HOST_CONTROL_RESPONSE_INVALID', String(error)));
133
+ }
134
+ });
135
+ socket.on('error', (error) => finish(failure('HOST_CONTROL_UNAVAILABLE', error.message, true)));
136
+ socket.on('close', () => {
137
+ if (!settled)
138
+ finish(failure('HOST_CONTROL_RESPONSE_INVALID', 'host-control closed without a response'));
139
+ });
140
+ });
141
+ }
142
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1,49 @@
1
+ import { spawn } from 'node:child_process';
2
+ import fs from 'node:fs';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { readHostControlWorkerToken, resolveHostControlEndpoint } from './path.js';
5
+ export async function dispatchHostControlCommand(request) {
6
+ const { payload } = request;
7
+ const compiledEntry = fileURLToPath(new URL('../../bin/internal-cli.js', import.meta.url));
8
+ const sourceEntry = fileURLToPath(new URL('../../bin/internal-cli.ts', import.meta.url));
9
+ const entry = fs.existsSync(compiledEntry) ? compiledEntry : sourceEntry;
10
+ const payloadEnvironment = payload.environment ?? {};
11
+ const env = { ...process.env, ...payloadEnvironment };
12
+ for (const key of Object.keys(env)) {
13
+ if (key.startsWith('AGENT_INFRA_CONTROL_')
14
+ || key === 'AGENT_INFRA_TASK_ID'
15
+ || key === 'AGENT_INFRA_RUNTIME_DIR'
16
+ || key === 'AGENT_INFRA_EXECUTOR_MANIFEST'
17
+ || key === 'AGENT_INFRA_HOST_CONTROL_SOCKET') {
18
+ delete env[key];
19
+ }
20
+ }
21
+ delete env.NODE_OPTIONS;
22
+ delete env.NODE_PATH;
23
+ delete env.AGENT_INFRA_HOST_CONTROL_WORKER;
24
+ delete env.AGENT_INFRA_HOST_CONTROL_WORKER_TOKEN;
25
+ env.AGENT_INFRA_HOST_CONTROL_WORKER = '1';
26
+ env.AGENT_INFRA_HOST_CONTROL_WORKER_TOKEN = readHostControlWorkerToken(process.env.AGENT_INFRA_TEST_HOST_CONTROL_ENDPOINT ?? resolveHostControlEndpoint());
27
+ return await new Promise((resolve, reject) => {
28
+ const runtimeArgs = entry.endsWith('.ts') ? ['--experimental-strip-types', '--no-warnings', entry] : [entry];
29
+ const child = spawn(process.execPath, [...runtimeArgs, request.operation, ...payload.args], {
30
+ cwd: payload.workingDirectory,
31
+ env,
32
+ stdio: ['ignore', 'pipe', 'pipe']
33
+ });
34
+ let stdout = '';
35
+ let stderr = '';
36
+ child.stdout.setEncoding('utf8');
37
+ child.stderr.setEncoding('utf8');
38
+ child.stdout.on('data', (chunk) => { stdout += chunk; });
39
+ child.stderr.on('data', (chunk) => { stderr += chunk; });
40
+ child.once('error', reject);
41
+ child.once('close', (code, signal) => {
42
+ if (signal)
43
+ reject(new Error(`HOST_CONTROL_WORKER_TERMINATED: ${signal}`));
44
+ else
45
+ resolve({ stdout, stderr, exitCode: code ?? 1 });
46
+ });
47
+ });
48
+ }
49
+ //# sourceMappingURL=command.js.map