@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
@@ -0,0 +1,454 @@
1
+ import crypto from 'node:crypto';
2
+ import fs from 'node:fs';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { loadNodePty } from '../sandbox/clipboard/node-pty.js';
6
+ const DEMO_COLUMNS = 128;
7
+ const DEMO_ROWS = 40;
8
+ const DEMO_TIMEOUT_MS = 30_000;
9
+ const CHECKPOINT = '\u001b]9;agent-infra-demo-checkpoint\u0007';
10
+ const TREE_CHECKPOINT = '\u001b]9;agent-infra-demo-tree-checkpoint\u0007';
11
+ const TEMP_PROJECT_PATTERN = /(^|[\s"'`=])((?:[A-Za-z]:[\\/]|[\\/])(?:[^\\/\s"'`]+[\\/])*(?:agent-infra-demo-project-|agent-infra-demo-|agent-infra-)[^\s"'`]+)/g;
12
+ const QUOTED_TEMP_PROJECT_PATTERN = /(^|[\s"'`=])('(?:[^']|'\\'')*\/(?:agent-infra-demo-project-|agent-infra-demo-|agent-infra-)(?:[^']|'\\'')*')(?=[\s"'`=]|$)/g;
13
+ const QUOTED_RELATIVE_TEMP_PROJECT_PATTERN = /(^|[\s"'`=])('(?:[^']|'\\'')*(?:agent-infra-demo-project-|agent-infra-demo-|agent-infra-)(?:[^']|'\\'')*')(?=[\s"'`=]|$)/g;
14
+ const DEMO_PROJECT_PATH = '/tmp/my-awesome-project';
15
+ const DEMO_VISIBLE_COMMANDS = Object.freeze({
16
+ prepare: `rm -rf ${DEMO_PROJECT_PATH} && mkdir -p ${DEMO_PROJECT_PATH} && cd ${DEMO_PROJECT_PATH}`,
17
+ git: 'git init -q && git remote add origin git@github.com:acme-corp/my-awesome-project.git',
18
+ init: 'ai init',
19
+ language: 'en',
20
+ clients: '1,2,3,4',
21
+ tree: 'tree .agents/ .claude/ .opencode/ -L 2 --dirsfirst'
22
+ });
23
+ function blankRow() {
24
+ return Array.from({ length: DEMO_COLUMNS }, () => ' ');
25
+ }
26
+ function blankScreen() {
27
+ return Array.from({ length: DEMO_ROWS }, blankRow);
28
+ }
29
+ function clamp(value, minimum, maximum) {
30
+ return Math.max(minimum, Math.min(maximum, value));
31
+ }
32
+ class TerminalDisplay {
33
+ screen = blankScreen();
34
+ history = [];
35
+ cursorX = 0;
36
+ cursorY = 0;
37
+ savedCursor = { x: 0, y: 0 };
38
+ mainScreen = null;
39
+ feed(value) {
40
+ for (let index = 0; index < value.length; index += 1) {
41
+ const character = value[index];
42
+ if (character === '\u001b') {
43
+ index = this.escape(value, index);
44
+ }
45
+ else if (character === '\n') {
46
+ this.lineFeed();
47
+ }
48
+ else if (character === '\r') {
49
+ this.cursorX = 0;
50
+ }
51
+ else if (character === '\b') {
52
+ this.cursorX = Math.max(0, this.cursorX - 1);
53
+ }
54
+ else if (character === '\t') {
55
+ this.cursorX = Math.min(DEMO_COLUMNS - 1, Math.floor(this.cursorX / 8 + 1) * 8);
56
+ }
57
+ else if (character.charCodeAt(0) < 0x20 || character === '\u007f') {
58
+ continue;
59
+ }
60
+ else {
61
+ this.print(character);
62
+ }
63
+ }
64
+ }
65
+ render() {
66
+ const rendered = [...this.history, ...this.screen.map((row) => row.join(''))]
67
+ .map((line) => line.replace(/\s+$/u, ''))
68
+ .join('\n')
69
+ .replace(/\n+$/u, '');
70
+ return rendered ? `${rendered}\n` : '';
71
+ }
72
+ print(character) {
73
+ if (this.cursorX >= DEMO_COLUMNS) {
74
+ this.cursorX = 0;
75
+ this.lineFeed();
76
+ }
77
+ this.screen[this.cursorY][this.cursorX] = character;
78
+ this.cursorX += 1;
79
+ }
80
+ lineFeed() {
81
+ if (this.cursorY === DEMO_ROWS - 1) {
82
+ this.history.push(this.screen[0].join(''));
83
+ this.screen = [...this.screen.slice(1), blankRow()];
84
+ }
85
+ else {
86
+ this.cursorY += 1;
87
+ }
88
+ }
89
+ escape(value, index) {
90
+ const next = value[index + 1];
91
+ if (next === '[')
92
+ return this.csi(value, index + 2);
93
+ if (next === ']')
94
+ return this.osc(value, index + 2);
95
+ if (next === '7') {
96
+ this.saveCursor();
97
+ return index + 1;
98
+ }
99
+ if (next === '8') {
100
+ this.restoreCursor();
101
+ return index + 1;
102
+ }
103
+ if (next === 'c') {
104
+ this.screen = blankScreen();
105
+ this.history = [];
106
+ this.cursorX = 0;
107
+ this.cursorY = 0;
108
+ return index + 1;
109
+ }
110
+ throw new Error(`Unknown terminal escape sequence at offset ${index}`);
111
+ }
112
+ osc(value, start) {
113
+ for (let index = start; index < value.length; index += 1) {
114
+ if (value[index] === '\u0007')
115
+ return index;
116
+ if (value[index] === '\u001b' && value[index + 1] === '\\')
117
+ return index + 1;
118
+ }
119
+ throw new Error(`Unterminated terminal OSC sequence at offset ${start - 2}`);
120
+ }
121
+ csi(value, start) {
122
+ let end = start;
123
+ while (end < value.length && !/[\x40-\x7e]/u.test(value[end]))
124
+ end += 1;
125
+ if (end >= value.length)
126
+ throw new Error(`Unterminated terminal CSI sequence at offset ${start - 2}`);
127
+ const body = value.slice(start, end);
128
+ const final = value[end];
129
+ const privateMode = body.startsWith('?');
130
+ const parameters = (privateMode ? body.slice(1) : body)
131
+ .split(';')
132
+ .map((part) => part === '' ? 0 : Number(part));
133
+ if (parameters.some((parameter) => !Number.isInteger(parameter) || parameter < 0)) {
134
+ throw new Error(`Invalid terminal CSI parameters at offset ${start - 2}`);
135
+ }
136
+ this.applyCsi(final, parameters, privateMode);
137
+ return end;
138
+ }
139
+ applyCsi(final, parameters, privateMode) {
140
+ const first = (fallback) => parameters[0] || fallback;
141
+ switch (final) {
142
+ case 'A':
143
+ this.cursorY = clamp(this.cursorY - first(1), 0, DEMO_ROWS - 1);
144
+ return;
145
+ case 'B':
146
+ this.cursorY = clamp(this.cursorY + first(1), 0, DEMO_ROWS - 1);
147
+ return;
148
+ case 'C':
149
+ this.cursorX = clamp(this.cursorX + first(1), 0, DEMO_COLUMNS - 1);
150
+ return;
151
+ case 'D':
152
+ this.cursorX = clamp(this.cursorX - first(1), 0, DEMO_COLUMNS - 1);
153
+ return;
154
+ case 'E':
155
+ this.cursorY = clamp(this.cursorY + first(1), 0, DEMO_ROWS - 1);
156
+ this.cursorX = 0;
157
+ return;
158
+ case 'F':
159
+ this.cursorY = clamp(this.cursorY - first(1), 0, DEMO_ROWS - 1);
160
+ this.cursorX = 0;
161
+ return;
162
+ case 'G':
163
+ this.cursorX = clamp(first(1) - 1, 0, DEMO_COLUMNS - 1);
164
+ return;
165
+ case 'd':
166
+ this.cursorY = clamp(first(1) - 1, 0, DEMO_ROWS - 1);
167
+ return;
168
+ case 'H':
169
+ case 'f':
170
+ this.cursorY = clamp((parameters[0] || 1) - 1, 0, DEMO_ROWS - 1);
171
+ this.cursorX = clamp((parameters[1] || 1) - 1, 0, DEMO_COLUMNS - 1);
172
+ return;
173
+ case 'J':
174
+ this.eraseDisplay(first(0));
175
+ return;
176
+ case 'K':
177
+ this.eraseLine(first(0));
178
+ return;
179
+ case 'P':
180
+ this.deleteCharacters(first(1));
181
+ return;
182
+ case '@':
183
+ this.insertCharacters(first(1));
184
+ return;
185
+ case 'X':
186
+ this.eraseCharacters(first(1));
187
+ return;
188
+ case 'L':
189
+ this.insertLines(first(1));
190
+ return;
191
+ case 'M':
192
+ this.deleteLines(first(1));
193
+ return;
194
+ case 'S':
195
+ for (let count = 0; count < first(1); count += 1)
196
+ this.lineFeed();
197
+ return;
198
+ case 'T':
199
+ for (let count = 0; count < first(1); count += 1)
200
+ this.reverseLineFeed();
201
+ return;
202
+ case 's':
203
+ this.saveCursor();
204
+ return;
205
+ case 'u':
206
+ this.restoreCursor();
207
+ return;
208
+ case 'm': return;
209
+ case 'r': return;
210
+ case 'h':
211
+ case 'l':
212
+ if (!privateMode || parameters.some((parameter) => ![25, 1049, 2004].includes(parameter))) {
213
+ throw new Error(`Unknown terminal mode sequence: ${final}`);
214
+ }
215
+ if (parameters.includes(1049)) {
216
+ if (final === 'h')
217
+ this.enterAlternateScreen();
218
+ else
219
+ this.leaveAlternateScreen();
220
+ }
221
+ return;
222
+ default:
223
+ throw new Error(`Unknown terminal CSI sequence: ${final}`);
224
+ }
225
+ }
226
+ eraseDisplay(mode) {
227
+ if (mode === 2) {
228
+ this.screen = blankScreen();
229
+ this.history = [];
230
+ return;
231
+ }
232
+ if (mode === 0) {
233
+ for (let y = this.cursorY; y < DEMO_ROWS; y += 1) {
234
+ const start = y === this.cursorY ? this.cursorX : 0;
235
+ this.screen[y].fill(' ', start);
236
+ }
237
+ return;
238
+ }
239
+ if (mode === 1) {
240
+ for (let y = 0; y <= this.cursorY; y += 1) {
241
+ const end = y === this.cursorY ? this.cursorX + 1 : DEMO_COLUMNS;
242
+ this.screen[y].fill(' ', 0, end);
243
+ }
244
+ return;
245
+ }
246
+ throw new Error(`Unknown erase-display mode: ${mode}`);
247
+ }
248
+ eraseLine(mode) {
249
+ if (mode === 0)
250
+ this.screen[this.cursorY].fill(' ', this.cursorX);
251
+ else if (mode === 1)
252
+ this.screen[this.cursorY].fill(' ', 0, this.cursorX + 1);
253
+ else if (mode === 2)
254
+ this.screen[this.cursorY].fill(' ');
255
+ else
256
+ throw new Error(`Unknown erase-line mode: ${mode}`);
257
+ }
258
+ deleteCharacters(count) {
259
+ const row = this.screen[this.cursorY];
260
+ row.splice(this.cursorX, count);
261
+ row.push(...Array.from({ length: count }, () => ' '));
262
+ }
263
+ insertCharacters(count) {
264
+ const row = this.screen[this.cursorY];
265
+ row.splice(this.cursorX, 0, ...Array.from({ length: count }, () => ' '));
266
+ row.length = DEMO_COLUMNS;
267
+ }
268
+ eraseCharacters(count) {
269
+ this.screen[this.cursorY].fill(' ', this.cursorX, Math.min(DEMO_COLUMNS, this.cursorX + count));
270
+ }
271
+ insertLines(count) {
272
+ this.screen.splice(this.cursorY, 0, ...Array.from({ length: count }, blankRow));
273
+ this.screen.length = DEMO_ROWS;
274
+ }
275
+ deleteLines(count) {
276
+ this.screen.splice(this.cursorY, count);
277
+ this.screen.push(...Array.from({ length: count }, blankRow));
278
+ this.screen.length = DEMO_ROWS;
279
+ }
280
+ reverseLineFeed() {
281
+ if (this.cursorY === 0)
282
+ this.screen.unshift(blankRow());
283
+ else
284
+ this.cursorY -= 1;
285
+ this.screen.length = DEMO_ROWS;
286
+ }
287
+ saveCursor() {
288
+ this.savedCursor = { x: this.cursorX, y: this.cursorY };
289
+ }
290
+ restoreCursor() {
291
+ this.cursorX = clamp(this.savedCursor.x, 0, DEMO_COLUMNS - 1);
292
+ this.cursorY = clamp(this.savedCursor.y, 0, DEMO_ROWS - 1);
293
+ }
294
+ enterAlternateScreen() {
295
+ if (this.mainScreen)
296
+ return;
297
+ this.mainScreen = { screen: this.screen, x: this.cursorX, y: this.cursorY };
298
+ this.screen = blankScreen();
299
+ this.history = [];
300
+ this.cursorX = 0;
301
+ this.cursorY = 0;
302
+ }
303
+ leaveAlternateScreen() {
304
+ if (!this.mainScreen)
305
+ return;
306
+ this.screen = this.mainScreen.screen;
307
+ this.cursorX = this.mainScreen.x;
308
+ this.cursorY = this.mainScreen.y;
309
+ this.mainScreen = null;
310
+ }
311
+ }
312
+ function normalizeDemoPaths(value) {
313
+ return value
314
+ .replace(QUOTED_TEMP_PROJECT_PATTERN, '$1/tmp/my-awesome-project')
315
+ .replace(QUOTED_RELATIVE_TEMP_PROJECT_PATTERN, '$1/tmp/my-awesome-project')
316
+ .replace(TEMP_PROJECT_PATTERN, '$1/tmp/my-awesome-project');
317
+ }
318
+ function normalizeVisibleTranscript(value) {
319
+ const display = new TerminalDisplay();
320
+ display.feed(normalizeDemoPaths(value));
321
+ return normalizeDemoPaths(display.render());
322
+ }
323
+ function sha256Transcript(value) {
324
+ return crypto.createHash('sha256').update(value, 'utf8').digest('hex');
325
+ }
326
+ function waitFor(output, pattern, timeoutMs) {
327
+ return new Promise((resolve, reject) => {
328
+ const deadline = Date.now() + timeoutMs;
329
+ const check = () => {
330
+ if (pattern.test(output())) {
331
+ resolve();
332
+ return;
333
+ }
334
+ if (Date.now() >= deadline) {
335
+ reject(new Error(`Timed out waiting for terminal output matching ${pattern}`));
336
+ return;
337
+ }
338
+ setTimeout(check, 25);
339
+ };
340
+ check();
341
+ });
342
+ }
343
+ function shellQuote(value) {
344
+ return `'${value.replaceAll("'", "'\\''")}'`;
345
+ }
346
+ function buildDemoPrepareCommand(project) {
347
+ return DEMO_VISIBLE_COMMANDS.prepare.replaceAll(DEMO_PROJECT_PATH, shellQuote(project));
348
+ }
349
+ async function collectDemoTranscript(cwd) {
350
+ const ptyModule = await loadNodePty();
351
+ if (!ptyModule)
352
+ return { status: 'failed', reasonCode: 'DEMO_TRANSCRIPT_UNAVAILABLE', message: '@lydell/node-pty is unavailable' };
353
+ const project = fs.mkdtempSync(path.join(os.tmpdir(), 'agent-infra-'));
354
+ const projectName = path.basename(project);
355
+ const shimDir = fs.mkdtempSync(path.join(os.tmpdir(), 'agent-infra-demo-shim-'));
356
+ const home = fs.mkdtempSync(path.join(os.tmpdir(), 'agent-infra-demo-home-'));
357
+ const globalGitConfig = path.join(home, 'empty-gitconfig');
358
+ const localCli = path.join(cwd, 'dist', 'bin', 'cli.js');
359
+ const basePath = process.env.PATH ?? '';
360
+ let processHandle = null;
361
+ let output = '';
362
+ let exited = null;
363
+ try {
364
+ if (!fs.existsSync(localCli))
365
+ throw new Error(`${localCli} not found; run npm run build first`);
366
+ fs.writeFileSync(globalGitConfig, '');
367
+ for (const name of ['ai', 'agent-infra']) {
368
+ const shim = path.join(shimDir, name);
369
+ const checkpoint = name === 'ai' ? `\nprintf '${CHECKPOINT}'\n` : '';
370
+ fs.writeFileSync(shim, `#!/bin/sh\n"$AGENT_INFRA_DEMO_NODE" "$AGENT_INFRA_DEMO_CLI" "$@"\nstatus=$?${checkpoint}\nexit $status\n`);
371
+ fs.chmodSync(shim, 0o755);
372
+ }
373
+ const treeShim = path.join(shimDir, 'tree');
374
+ fs.writeFileSync(treeShim, `#!/bin/sh\nPATH=${shellQuote(basePath)} command tree "$@"\nstatus=$?\nprintf '${TREE_CHECKPOINT}'\nexit $status\n`);
375
+ fs.chmodSync(treeShim, 0o755);
376
+ const environment = {
377
+ ...process.env,
378
+ HOME: home,
379
+ PATH: `${shimDir}${path.delimiter}${process.env.PATH ?? ''}`,
380
+ TERM: 'xterm-256color',
381
+ LANG: 'C.UTF-8',
382
+ LC_ALL: 'C.UTF-8',
383
+ GIT_CONFIG_GLOBAL: globalGitConfig,
384
+ AGENT_INFRA_DEMO_NODE: process.execPath,
385
+ AGENT_INFRA_DEMO_CLI: localCli,
386
+ AGENT_INFRA_DEMO_PLATFORM: 'linux',
387
+ TERM_PROGRAM: '',
388
+ PS1: 'demo$ ',
389
+ PROMPT: 'demo$ ',
390
+ RPS1: '',
391
+ RPROMPT: '',
392
+ PS2: 'demo> ',
393
+ PROMPT2: 'demo> ',
394
+ PS3: 'demo? ',
395
+ PROMPT3: 'demo? ',
396
+ PS4: '+ '
397
+ };
398
+ processHandle = ptyModule.spawn('zsh', ['-f', '-i'], {
399
+ name: 'xterm-256color', cols: DEMO_COLUMNS, rows: DEMO_ROWS, cwd: path.dirname(project), env: environment
400
+ });
401
+ processHandle.onData((data) => { output += data; });
402
+ processHandle.onExit((event) => { exited = event; });
403
+ await waitFor(() => output, /demo\$ /, DEMO_TIMEOUT_MS);
404
+ const send = async (command, expected) => {
405
+ processHandle.write(`${command}\r`);
406
+ if (expected)
407
+ await waitFor(() => output, expected, DEMO_TIMEOUT_MS);
408
+ else
409
+ await new Promise((resolve) => setTimeout(resolve, 150));
410
+ };
411
+ await send(buildDemoPrepareCommand(projectName));
412
+ await send(DEMO_VISIBLE_COMMANDS.git);
413
+ await send(DEMO_VISIBLE_COMMANDS.init, /Project name/);
414
+ await send('', /Organization/);
415
+ await send('', /Language/);
416
+ await send(DEMO_VISIBLE_COMMANDS.language, /Sandbox engine/);
417
+ await send('', /Platform/);
418
+ await send('', /Agent Client project integrations/);
419
+ await send(DEMO_VISIBLE_COMMANDS.clients, /Template sources/);
420
+ await send('', /Skill sources/);
421
+ await send('', /(?:initialized|success|created)/i);
422
+ await waitFor(() => output, /agent-infra-demo-checkpoint/, DEMO_TIMEOUT_MS);
423
+ await send(DEMO_VISIBLE_COMMANDS.tree, /agent-infra-demo-tree-checkpoint/);
424
+ processHandle.write('\u0004');
425
+ await waitFor(() => exited ? 'exited' : '', /exited/, 5_000);
426
+ if (!output.includes(CHECKPOINT))
427
+ throw new Error('demo transcript checkpoint marker was not emitted');
428
+ if (!output.includes(TREE_CHECKPOINT))
429
+ throw new Error('demo transcript tree checkpoint marker was not emitted');
430
+ if (!/\.agents/.test(output))
431
+ throw new Error('demo transcript tree checkpoint was not emitted');
432
+ const exitEvent = exited;
433
+ if (!exitEvent || exitEvent.exitCode !== 0)
434
+ throw new Error(`demo shell exited with code ${exitEvent?.exitCode ?? 'unknown'}`);
435
+ const transcript = normalizeVisibleTranscript(output);
436
+ if (!transcript.trim())
437
+ throw new Error('demo transcript is empty');
438
+ return { status: 'ok', transcript, sha256: sha256Transcript(transcript) };
439
+ }
440
+ catch (error) {
441
+ try {
442
+ processHandle?.kill('SIGTERM');
443
+ }
444
+ catch { /* best effort cleanup */ }
445
+ return { status: 'failed', reasonCode: 'DEMO_TRANSCRIPT_FAILED', message: error instanceof Error ? error.message : String(error) };
446
+ }
447
+ finally {
448
+ fs.rmSync(project, { recursive: true, force: true });
449
+ fs.rmSync(shimDir, { recursive: true, force: true });
450
+ fs.rmSync(home, { recursive: true, force: true });
451
+ }
452
+ }
453
+ export { buildDemoPrepareCommand, DEMO_COLUMNS, DEMO_PROJECT_PATH, DEMO_ROWS, DEMO_VISIBLE_COMMANDS, collectDemoTranscript, normalizeVisibleTranscript, sha256Transcript };
454
+ //# sourceMappingURL=demo-transcript.js.map
@@ -0,0 +1,28 @@
1
+ import { dispatchHostControlCommand } from '../host-control/command.js';
2
+ import { hostControlServiceStatus, installHostControlService, serveHostControlService, uninstallHostControlService } from '../host-control/service.js';
3
+ import { internalHandlerRoute } from './cli-route-inventory.js';
4
+ export async function hostControl(args) {
5
+ const action = args[0] ?? '';
6
+ if (internalHandlerRoute('host-control', 'serve', action)) {
7
+ const controller = new AbortController();
8
+ process.once('SIGINT', () => controller.abort());
9
+ process.once('SIGTERM', () => controller.abort());
10
+ await serveHostControlService({ dispatch: dispatchHostControlCommand }, controller.signal);
11
+ return;
12
+ }
13
+ if (internalHandlerRoute('host-control', 'status', action)) {
14
+ process.stdout.write(`${JSON.stringify(hostControlServiceStatus())}\n`);
15
+ return;
16
+ }
17
+ if (internalHandlerRoute('host-control', 'install', action)) {
18
+ process.stdout.write(`${JSON.stringify({ status: 'completed', path: installHostControlService() })}\n`);
19
+ return;
20
+ }
21
+ if (internalHandlerRoute('host-control', 'uninstall', action)) {
22
+ process.stdout.write(`${JSON.stringify({ status: 'completed', path: uninstallHostControlService() })}\n`);
23
+ return;
24
+ }
25
+ process.stdout.write(`${JSON.stringify({ status: 'failed', changed: false, error: { code: 'HOST_CONTROL_COMMAND_INVALID', message: 'usage: host-control <serve|status|install|uninstall>' } })}\n`);
26
+ process.exitCode = 1;
27
+ }
28
+ //# sourceMappingURL=host-control.js.map