@pleri/olam-cli 0.1.7

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 (196) hide show
  1. package/dist/__tests__/auth-status.test.d.ts +2 -0
  2. package/dist/__tests__/auth-status.test.d.ts.map +1 -0
  3. package/dist/__tests__/auth-status.test.js +290 -0
  4. package/dist/__tests__/auth-status.test.js.map +1 -0
  5. package/dist/__tests__/auth-upgrade.test.d.ts +9 -0
  6. package/dist/__tests__/auth-upgrade.test.d.ts.map +1 -0
  7. package/dist/__tests__/auth-upgrade.test.js +161 -0
  8. package/dist/__tests__/auth-upgrade.test.js.map +1 -0
  9. package/dist/__tests__/create-app-urls.test.d.ts +2 -0
  10. package/dist/__tests__/create-app-urls.test.d.ts.map +1 -0
  11. package/dist/__tests__/create-app-urls.test.js +102 -0
  12. package/dist/__tests__/create-app-urls.test.js.map +1 -0
  13. package/dist/__tests__/enter.test.d.ts +2 -0
  14. package/dist/__tests__/enter.test.d.ts.map +1 -0
  15. package/dist/__tests__/enter.test.js +90 -0
  16. package/dist/__tests__/enter.test.js.map +1 -0
  17. package/dist/__tests__/host-cp-gh-token.test.d.ts +9 -0
  18. package/dist/__tests__/host-cp-gh-token.test.d.ts.map +1 -0
  19. package/dist/__tests__/host-cp-gh-token.test.js +119 -0
  20. package/dist/__tests__/host-cp-gh-token.test.js.map +1 -0
  21. package/dist/__tests__/host-cp.test.d.ts +9 -0
  22. package/dist/__tests__/host-cp.test.d.ts.map +1 -0
  23. package/dist/__tests__/host-cp.test.js +254 -0
  24. package/dist/__tests__/host-cp.test.js.map +1 -0
  25. package/dist/__tests__/keys.test.d.ts +9 -0
  26. package/dist/__tests__/keys.test.d.ts.map +1 -0
  27. package/dist/__tests__/keys.test.js +145 -0
  28. package/dist/__tests__/keys.test.js.map +1 -0
  29. package/dist/__tests__/logs.test.d.ts +9 -0
  30. package/dist/__tests__/logs.test.d.ts.map +1 -0
  31. package/dist/__tests__/logs.test.js +124 -0
  32. package/dist/__tests__/logs.test.js.map +1 -0
  33. package/dist/__tests__/ps.test.d.ts +2 -0
  34. package/dist/__tests__/ps.test.d.ts.map +1 -0
  35. package/dist/__tests__/ps.test.js +172 -0
  36. package/dist/__tests__/ps.test.js.map +1 -0
  37. package/dist/__tests__/status-app-urls.test.d.ts +2 -0
  38. package/dist/__tests__/status-app-urls.test.d.ts.map +1 -0
  39. package/dist/__tests__/status-app-urls.test.js +125 -0
  40. package/dist/__tests__/status-app-urls.test.js.map +1 -0
  41. package/dist/__tests__/upgrade.test.d.ts +9 -0
  42. package/dist/__tests__/upgrade.test.d.ts.map +1 -0
  43. package/dist/__tests__/upgrade.test.js +262 -0
  44. package/dist/__tests__/upgrade.test.js.map +1 -0
  45. package/dist/commands/__tests__/carry-uncommitted.test.d.ts +14 -0
  46. package/dist/commands/__tests__/carry-uncommitted.test.d.ts.map +1 -0
  47. package/dist/commands/__tests__/carry-uncommitted.test.js +83 -0
  48. package/dist/commands/__tests__/carry-uncommitted.test.js.map +1 -0
  49. package/dist/commands/__tests__/openHostCpUrl.test.d.ts +2 -0
  50. package/dist/commands/__tests__/openHostCpUrl.test.d.ts.map +1 -0
  51. package/dist/commands/__tests__/openHostCpUrl.test.js +63 -0
  52. package/dist/commands/__tests__/openHostCpUrl.test.js.map +1 -0
  53. package/dist/commands/__tests__/refresh.test.d.ts +13 -0
  54. package/dist/commands/__tests__/refresh.test.d.ts.map +1 -0
  55. package/dist/commands/__tests__/refresh.test.js +170 -0
  56. package/dist/commands/__tests__/refresh.test.js.map +1 -0
  57. package/dist/commands/auth-status.d.ts +43 -0
  58. package/dist/commands/auth-status.d.ts.map +1 -0
  59. package/dist/commands/auth-status.js +208 -0
  60. package/dist/commands/auth-status.js.map +1 -0
  61. package/dist/commands/auth-upgrade.d.ts +47 -0
  62. package/dist/commands/auth-upgrade.d.ts.map +1 -0
  63. package/dist/commands/auth-upgrade.js +277 -0
  64. package/dist/commands/auth-upgrade.js.map +1 -0
  65. package/dist/commands/auth.d.ts +16 -0
  66. package/dist/commands/auth.d.ts.map +1 -0
  67. package/dist/commands/auth.js +283 -0
  68. package/dist/commands/auth.js.map +1 -0
  69. package/dist/commands/create.d.ts +8 -0
  70. package/dist/commands/create.d.ts.map +1 -0
  71. package/dist/commands/create.js +512 -0
  72. package/dist/commands/create.js.map +1 -0
  73. package/dist/commands/crystallize.d.ts +8 -0
  74. package/dist/commands/crystallize.d.ts.map +1 -0
  75. package/dist/commands/crystallize.js +101 -0
  76. package/dist/commands/crystallize.js.map +1 -0
  77. package/dist/commands/destroy.d.ts +6 -0
  78. package/dist/commands/destroy.d.ts.map +1 -0
  79. package/dist/commands/destroy.js +54 -0
  80. package/dist/commands/destroy.js.map +1 -0
  81. package/dist/commands/dispatch.d.ts +9 -0
  82. package/dist/commands/dispatch.d.ts.map +1 -0
  83. package/dist/commands/dispatch.js +94 -0
  84. package/dist/commands/dispatch.js.map +1 -0
  85. package/dist/commands/enter.d.ts +63 -0
  86. package/dist/commands/enter.d.ts.map +1 -0
  87. package/dist/commands/enter.js +206 -0
  88. package/dist/commands/enter.js.map +1 -0
  89. package/dist/commands/host-cp.d.ts +191 -0
  90. package/dist/commands/host-cp.d.ts.map +1 -0
  91. package/dist/commands/host-cp.js +797 -0
  92. package/dist/commands/host-cp.js.map +1 -0
  93. package/dist/commands/init.d.ts +9 -0
  94. package/dist/commands/init.d.ts.map +1 -0
  95. package/dist/commands/init.js +143 -0
  96. package/dist/commands/init.js.map +1 -0
  97. package/dist/commands/install.d.ts +22 -0
  98. package/dist/commands/install.d.ts.map +1 -0
  99. package/dist/commands/install.js +203 -0
  100. package/dist/commands/install.js.map +1 -0
  101. package/dist/commands/keys.d.ts +26 -0
  102. package/dist/commands/keys.d.ts.map +1 -0
  103. package/dist/commands/keys.js +151 -0
  104. package/dist/commands/keys.js.map +1 -0
  105. package/dist/commands/lanes.d.ts +18 -0
  106. package/dist/commands/lanes.d.ts.map +1 -0
  107. package/dist/commands/lanes.js +122 -0
  108. package/dist/commands/lanes.js.map +1 -0
  109. package/dist/commands/list.d.ts +6 -0
  110. package/dist/commands/list.d.ts.map +1 -0
  111. package/dist/commands/list.js +39 -0
  112. package/dist/commands/list.js.map +1 -0
  113. package/dist/commands/logs.d.ts +38 -0
  114. package/dist/commands/logs.d.ts.map +1 -0
  115. package/dist/commands/logs.js +177 -0
  116. package/dist/commands/logs.js.map +1 -0
  117. package/dist/commands/observe.d.ts +9 -0
  118. package/dist/commands/observe.d.ts.map +1 -0
  119. package/dist/commands/observe.js +34 -0
  120. package/dist/commands/observe.js.map +1 -0
  121. package/dist/commands/policy-check.d.ts +14 -0
  122. package/dist/commands/policy-check.d.ts.map +1 -0
  123. package/dist/commands/policy-check.js +76 -0
  124. package/dist/commands/policy-check.js.map +1 -0
  125. package/dist/commands/pr.d.ts +17 -0
  126. package/dist/commands/pr.d.ts.map +1 -0
  127. package/dist/commands/pr.js +148 -0
  128. package/dist/commands/pr.js.map +1 -0
  129. package/dist/commands/ps.d.ts +25 -0
  130. package/dist/commands/ps.d.ts.map +1 -0
  131. package/dist/commands/ps.js +164 -0
  132. package/dist/commands/ps.js.map +1 -0
  133. package/dist/commands/refresh-helpers.d.ts +25 -0
  134. package/dist/commands/refresh-helpers.d.ts.map +1 -0
  135. package/dist/commands/refresh-helpers.js +56 -0
  136. package/dist/commands/refresh-helpers.js.map +1 -0
  137. package/dist/commands/refresh.d.ts +23 -0
  138. package/dist/commands/refresh.d.ts.map +1 -0
  139. package/dist/commands/refresh.js +237 -0
  140. package/dist/commands/refresh.js.map +1 -0
  141. package/dist/commands/status.d.ts +6 -0
  142. package/dist/commands/status.d.ts.map +1 -0
  143. package/dist/commands/status.js +51 -0
  144. package/dist/commands/status.js.map +1 -0
  145. package/dist/commands/upgrade.d.ts +67 -0
  146. package/dist/commands/upgrade.d.ts.map +1 -0
  147. package/dist/commands/upgrade.js +358 -0
  148. package/dist/commands/upgrade.js.map +1 -0
  149. package/dist/commands/workspace.d.ts +23 -0
  150. package/dist/commands/workspace.d.ts.map +1 -0
  151. package/dist/commands/workspace.js +198 -0
  152. package/dist/commands/workspace.js.map +1 -0
  153. package/dist/commands/world-snapshot.d.ts +18 -0
  154. package/dist/commands/world-snapshot.d.ts.map +1 -0
  155. package/dist/commands/world-snapshot.js +327 -0
  156. package/dist/commands/world-snapshot.js.map +1 -0
  157. package/dist/context.d.ts +26 -0
  158. package/dist/context.d.ts.map +1 -0
  159. package/dist/context.js +51 -0
  160. package/dist/context.js.map +1 -0
  161. package/dist/index.d.ts +9 -0
  162. package/dist/index.d.ts.map +1 -0
  163. package/dist/index.js +18007 -0
  164. package/dist/index.js.map +1 -0
  165. package/dist/mcp-server.js +32236 -0
  166. package/dist/output.d.ts +10 -0
  167. package/dist/output.d.ts.map +1 -0
  168. package/dist/output.js +31 -0
  169. package/dist/output.js.map +1 -0
  170. package/host-cp/compose.yaml +126 -0
  171. package/host-cp/src/auth-secret-hint.mjs +45 -0
  172. package/host-cp/src/auth.mjs +155 -0
  173. package/host-cp/src/compose-worlds-sources.mjs +170 -0
  174. package/host-cp/src/container-secret-fetcher.mjs +163 -0
  175. package/host-cp/src/docker-events.mjs +184 -0
  176. package/host-cp/src/local-worlds-source.mjs +83 -0
  177. package/host-cp/src/plan-orchestrator.mjs +829 -0
  178. package/host-cp/src/plan-progress.mjs +282 -0
  179. package/host-cp/src/pr-cache.mjs +201 -0
  180. package/host-cp/src/pr-merge-poller.mjs +154 -0
  181. package/host-cp/src/process-poller.mjs +250 -0
  182. package/host-cp/src/proxy.mjs +245 -0
  183. package/host-cp/src/pylon-worlds-source.mjs +68 -0
  184. package/host-cp/src/redact.mjs +67 -0
  185. package/host-cp/src/secret-cache.mjs +104 -0
  186. package/host-cp/src/server.mjs +2215 -0
  187. package/host-cp/src/sse-gate.mjs +117 -0
  188. package/host-cp/src/version-status.mjs +209 -0
  189. package/host-cp/src/workspace-catalog.mjs +149 -0
  190. package/host-cp/src/world-names-store.mjs +176 -0
  191. package/host-cp/src/world-pr-state.mjs +97 -0
  192. package/host-cp/src/world-progress.mjs +322 -0
  193. package/host-cp/src/world-tunnel-manager.mjs +288 -0
  194. package/host-cp/src/worlds-db-source.mjs +191 -0
  195. package/host-cp/src/worlds-source.mjs +59 -0
  196. package/package.json +38 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crystallize.js","sourceRoot":"","sources":["../../src/commands/crystallize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * olam destroy <world> — Tear down a world and clean up resources.
3
+ */
4
+ import type { Command } from 'commander';
5
+ export declare function registerDestroy(program: Command): void;
6
+ //# sourceMappingURL=destroy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"destroy.d.ts","sourceRoot":"","sources":["../../src/commands/destroy.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzC,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA8CtD"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * olam destroy <world> — Tear down a world and clean up resources.
3
+ */
4
+ import ora from 'ora';
5
+ import { loadContext } from '../context.js';
6
+ import { printError, printSuccess } from '../output.js';
7
+ import { findHostCpContainer, callHostCpRegistry } from './host-cp.js';
8
+ export function registerDestroy(program) {
9
+ program
10
+ .command('destroy')
11
+ .description('Destroy a world and clean up resources')
12
+ .argument('<world>', 'World ID')
13
+ .option('--skip-crystallize', 'Skip thought crystallization')
14
+ .action(async (worldId, opts) => {
15
+ const { ctx, error } = await loadContext();
16
+ if (!ctx) {
17
+ printError(error?.message ?? 'Olam is not configured. Run `olam init` first.');
18
+ process.exitCode = 1;
19
+ return;
20
+ }
21
+ const world = ctx.worldManager.getWorld(worldId);
22
+ if (!world) {
23
+ printError(`World "${worldId}" not found. Run \`olam list\` to see worlds.`);
24
+ process.exitCode = 1;
25
+ return;
26
+ }
27
+ const spinner = ora(`Destroying ${world.name}...`).start();
28
+ try {
29
+ await ctx.worldManager.destroyWorld(worldId, {
30
+ skipCrystallize: opts.skipCrystallize,
31
+ });
32
+ spinner.succeed(`Destroyed ${world.name} (${worldId})`);
33
+ // Auto-deregister from host CP if it's running. Best-effort —
34
+ // a failed deregister leaves a stale registry entry that
35
+ // resolves to a 502 the next time the SPA tries to fetch the
36
+ // world's data, which is non-fatal but ugly.
37
+ try {
38
+ const hostCp = await findHostCpContainer();
39
+ if (hostCp && hostCp.state === 'running') {
40
+ await callHostCpRegistry('DELETE', { id: worldId });
41
+ }
42
+ }
43
+ catch {
44
+ // Docker unreachable / host-cp probe failed — silently skip.
45
+ }
46
+ }
47
+ catch (err) {
48
+ spinner.fail('Failed to destroy world');
49
+ printError(err instanceof Error ? err.message : String(err));
50
+ process.exitCode = 1;
51
+ }
52
+ });
53
+ }
54
+ //# sourceMappingURL=destroy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"destroy.js","sourceRoot":"","sources":["../../src/commands/destroy.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvE,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC9C,OAAO;SACJ,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,wCAAwC,CAAC;SACrD,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC;SAC/B,MAAM,CAAC,oBAAoB,EAAE,8BAA8B,CAAC;SAC5D,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,IAAmC,EAAE,EAAE;QACrE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,MAAM,WAAW,EAAE,CAAC;QAC3C,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,UAAU,CAAC,KAAK,EAAE,OAAO,IAAI,gDAAgD,CAAC,CAAC;YAC/E,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACjD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,UAAU,CAAC,UAAU,OAAO,+CAA+C,CAAC,CAAC;YAC7E,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAAG,GAAG,CAAC,cAAc,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC;QAE3D,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,YAAY,CAAC,YAAY,CAAC,OAAO,EAAE;gBAC3C,eAAe,EAAE,IAAI,CAAC,eAAe;aACtC,CAAC,CAAC;YACH,OAAO,CAAC,OAAO,CAAC,aAAa,KAAK,CAAC,IAAI,KAAK,OAAO,GAAG,CAAC,CAAC;YACxD,8DAA8D;YAC9D,yDAAyD;YACzD,6DAA6D;YAC7D,6CAA6C;YAC7C,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,mBAAmB,EAAE,CAAC;gBAC3C,IAAI,MAAM,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;oBACzC,MAAM,kBAAkB,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;gBACtD,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,6DAA6D;YAC/D,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;YACxC,UAAU,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAC7D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * olam dispatch <world> <prompt> — Send a task to a running world.
3
+ *
4
+ * Mirrors the MCP server's olam_dispatch tool, delegating to the
5
+ * same container API for persistent Claude session dispatch.
6
+ */
7
+ import type { Command } from 'commander';
8
+ export declare function registerDispatch(program: Command): void;
9
+ //# sourceMappingURL=dispatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../src/commands/dispatch.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOzC,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6GvD"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * olam dispatch <world> <prompt> — Send a task to a running world.
3
+ *
4
+ * Mirrors the MCP server's olam_dispatch tool, delegating to the
5
+ * same container API for persistent Claude session dispatch.
6
+ */
7
+ import ora from 'ora';
8
+ import pc from 'picocolors';
9
+ import { loadContext } from '../context.js';
10
+ import { printError, printInfo, printHeader } from '../output.js';
11
+ import { DEEP_MODE_SUFFIX, COMPLEX_PROMPT_RE } from '@olam/core/src/orchestrator/dispatch.js';
12
+ export function registerDispatch(program) {
13
+ program
14
+ .command('dispatch')
15
+ .description('Send a prompt to a world for execution')
16
+ .argument('<world>', 'World ID')
17
+ .argument('<prompt>', 'Task prompt')
18
+ .option('--mode <mode>', 'Execution mode: deep, fast, auto', 'auto')
19
+ .option('--max-turns <n>', 'Maximum turns', parseInt)
20
+ .action(async (worldId, prompt, opts) => {
21
+ const { ctx, error } = await loadContext();
22
+ if (!ctx) {
23
+ printError(error?.message ?? 'Olam is not configured. Run `olam init` first.');
24
+ process.exitCode = 1;
25
+ return;
26
+ }
27
+ const worldMeta = ctx.worldManager.getWorld(worldId);
28
+ if (!worldMeta) {
29
+ printError(`World "${worldId}" not found. Run \`olam list\` to see worlds.`);
30
+ process.exitCode = 1;
31
+ return;
32
+ }
33
+ if (worldMeta.status !== 'running') {
34
+ printError(`World "${worldId}" is ${worldMeta.status}. Only running worlds accept dispatches.`);
35
+ process.exitCode = 1;
36
+ return;
37
+ }
38
+ const spinner = ora('Dispatching...').start();
39
+ try {
40
+ const computeWorld = await ctx.computeProvider.getWorld(worldId);
41
+ if (!computeWorld) {
42
+ spinner.fail('Compute world not found');
43
+ printError('The world may have been destroyed externally.');
44
+ process.exitCode = 1;
45
+ return;
46
+ }
47
+ // Start Claude session if needed
48
+ await computeWorld.exec('curl -s -X POST http://localhost:8080/api/claude/start');
49
+ // Enhance prompt based on mode (shared regex with MCP server)
50
+ let finalPrompt = prompt;
51
+ if (opts.mode === 'deep') {
52
+ finalPrompt += DEEP_MODE_SUFFIX;
53
+ }
54
+ else if (opts.mode === 'auto') {
55
+ const isComplex = prompt.length > 100 ||
56
+ COMPLEX_PROMPT_RE.test(prompt);
57
+ if (isComplex) {
58
+ finalPrompt += DEEP_MODE_SUFFIX;
59
+ }
60
+ }
61
+ // Write intent node (mirrors MCP server's world-dispatch.ts)
62
+ const intentPayloadFile = '/tmp/olam-dispatch-intent.json';
63
+ await computeWorld.exec(`cat > ${intentPayloadFile} << 'OLAM_EOF'\n${JSON.stringify({
64
+ tool_name: '__intent__',
65
+ tool_input: { prompt: finalPrompt },
66
+ hook_event_name: 'intent',
67
+ })}\nOLAM_EOF`);
68
+ await computeWorld.exec(`curl -s -X POST -H "Content-Type: application/json" -d @${intentPayloadFile} http://localhost:8080/hooks/thought`);
69
+ // Send prompt via temp file to avoid shell injection
70
+ const dispatchPayloadFile = '/tmp/olam-dispatch.json';
71
+ await computeWorld.exec(`cat > ${dispatchPayloadFile} << 'OLAM_EOF'\n${JSON.stringify({ prompt: finalPrompt })}\nOLAM_EOF`);
72
+ const result = await computeWorld.exec(`curl -s -X POST -H "Content-Type: application/json" -d @${dispatchPayloadFile} http://localhost:8080/dispatch`);
73
+ if (result.exitCode !== 0) {
74
+ throw new Error(result.stderr || 'Dispatch POST failed');
75
+ }
76
+ spinner.succeed('Dispatch sent');
77
+ const dashboardPort = 19080 + worldMeta.portOffset;
78
+ const terminalPort = 17681 + worldMeta.portOffset;
79
+ printHeader('Dispatch');
80
+ printInfo('World', `${worldMeta.name} (${worldId})`);
81
+ printInfo('Mode', opts.mode);
82
+ printInfo('Dashboard', `http://localhost:${dashboardPort}`);
83
+ printInfo('Terminal', `http://localhost:${terminalPort}`);
84
+ const containerName = `olam-${worldId}-devbox`;
85
+ console.log(`\n${pc.dim(`Watch live: docker exec -it ${containerName} tmux attach -t claude-main -r`)}`);
86
+ }
87
+ catch (err) {
88
+ spinner.fail('Dispatch failed');
89
+ printError(err instanceof Error ? err.message : String(err));
90
+ process.exitCode = 1;
91
+ }
92
+ });
93
+ }
94
+ //# sourceMappingURL=dispatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../src/commands/dispatch.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAE9F,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC/C,OAAO;SACJ,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,wCAAwC,CAAC;SACrD,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC;SAC/B,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC;SACnC,MAAM,CAAC,eAAe,EAAE,kCAAkC,EAAE,MAAM,CAAC;SACnE,MAAM,CAAC,iBAAiB,EAAE,eAAe,EAAE,QAAQ,CAAC;SACpD,MAAM,CAAC,KAAK,EACX,OAAe,EACf,MAAc,EACd,IAAyC,EACzC,EAAE;QACF,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,MAAM,WAAW,EAAE,CAAC;QAC3C,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,UAAU,CAAC,KAAK,EAAE,OAAO,IAAI,gDAAgD,CAAC,CAAC;YAC/E,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QAED,MAAM,SAAS,GAAG,GAAG,CAAC,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACrD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,UAAU,CAAC,UAAU,OAAO,+CAA+C,CAAC,CAAC;YAC7E,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QAED,IAAI,SAAS,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACnC,UAAU,CAAC,UAAU,OAAO,QAAQ,SAAS,CAAC,MAAM,0CAA0C,CAAC,CAAC;YAChG,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAAG,GAAG,CAAC,gBAAgB,CAAC,CAAC,KAAK,EAAE,CAAC;QAE9C,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,MAAM,GAAG,CAAC,eAAe,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACjE,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,OAAO,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;gBACxC,UAAU,CAAC,+CAA+C,CAAC,CAAC;gBAC5D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;gBACrB,OAAO;YACT,CAAC;YAED,iCAAiC;YACjC,MAAM,YAAY,CAAC,IAAI,CACrB,wDAAwD,CACzD,CAAC;YAEF,8DAA8D;YAC9D,IAAI,WAAW,GAAG,MAAM,CAAC;YAEzB,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBACzB,WAAW,IAAI,gBAAgB,CAAC;YAClC,CAAC;iBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAChC,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,GAAG,GAAG;oBACnC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACjC,IAAI,SAAS,EAAE,CAAC;oBACd,WAAW,IAAI,gBAAgB,CAAC;gBAClC,CAAC;YACH,CAAC;YAED,6DAA6D;YAC7D,MAAM,iBAAiB,GAAG,gCAAgC,CAAC;YAC3D,MAAM,YAAY,CAAC,IAAI,CACrB,SAAS,iBAAiB,mBAAmB,IAAI,CAAC,SAAS,CAAC;gBAC1D,SAAS,EAAE,YAAY;gBACvB,UAAU,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE;gBACnC,eAAe,EAAE,QAAQ;aAC1B,CAAC,YAAY,CACf,CAAC;YACF,MAAM,YAAY,CAAC,IAAI,CACrB,2DAA2D,iBAAiB,sCAAsC,CACnH,CAAC;YAEF,qDAAqD;YACrD,MAAM,mBAAmB,GAAG,yBAAyB,CAAC;YACtD,MAAM,YAAY,CAAC,IAAI,CACrB,SAAS,mBAAmB,mBAAmB,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,YAAY,CACnG,CAAC;YACF,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,IAAI,CACpC,2DAA2D,mBAAmB,iCAAiC,CAChH,CAAC;YAEF,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,IAAI,sBAAsB,CAAC,CAAC;YAC3D,CAAC;YAED,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;YAEjC,MAAM,aAAa,GAAG,KAAK,GAAG,SAAS,CAAC,UAAU,CAAC;YACnD,MAAM,YAAY,GAAG,KAAK,GAAG,SAAS,CAAC,UAAU,CAAC;YAElD,WAAW,CAAC,UAAU,CAAC,CAAC;YACxB,SAAS,CAAC,OAAO,EAAE,GAAG,SAAS,CAAC,IAAI,KAAK,OAAO,GAAG,CAAC,CAAC;YACrD,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAC7B,SAAS,CAAC,WAAW,EAAE,oBAAoB,aAAa,EAAE,CAAC,CAAC;YAC5D,SAAS,CAAC,UAAU,EAAE,oBAAoB,YAAY,EAAE,CAAC,CAAC;YAE1D,MAAM,aAAa,GAAG,QAAQ,OAAO,SAAS,CAAC;YAC/C,OAAO,CAAC,GAAG,CACT,KAAK,EAAE,CAAC,GAAG,CAAC,+BAA+B,aAAa,gCAAgC,CAAC,EAAE,CAC5F,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAChC,UAAU,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAC7D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * olam enter <world> — Open terminal into a world's Claude session.
3
+ *
4
+ * Two modes:
5
+ *
6
+ * 1. **Default** (no --start-claude): print the shell command the operator
7
+ * can run to attach an interactive terminal to the world. Optionally
8
+ * `--exec` runs that command in-process instead of printing it.
9
+ *
10
+ * 2. **--start-claude** (Phase C/C4): open a tmux session inside the world,
11
+ * pre-fill the Claude prompt with `--task <text>` if supplied, then
12
+ * attach. Task text is delivered to tmux's paste buffer via STDIN
13
+ * (`docker exec -i ... tmux load-buffer -`) and pasted with
14
+ * `tmux paste-buffer` — LITERAL bytes, no shell evaluation. T17
15
+ * mitigation. See {@link buildStartClaudeCommands} for the contract.
16
+ */
17
+ import type { Command } from 'commander';
18
+ export interface StartClaudeStep {
19
+ /** Human-readable description (operator-facing). */
20
+ readonly description: string;
21
+ /**
22
+ * The shell command to execute.
23
+ *
24
+ * SECURITY INVARIANT: this string is composed from defensively-validated
25
+ * identifiers (containerName, sessionName via {@link SAFE_IDENT}). It
26
+ * NEVER includes user-supplied free-form text — the only free-form input
27
+ * (`task`) rides via {@link stdin} and is delivered to tmux's
28
+ * `load-buffer -` STDIN, not argv.
29
+ */
30
+ readonly command: string;
31
+ /**
32
+ * Optional STDIN payload. Set ONLY for the `tmux load-buffer -` step.
33
+ * The contents are written to the tmux paste buffer LITERALLY, with
34
+ * NO shell expansion. Shell metacharacters (`;`, `|`, `$(...)`, etc.)
35
+ * appear in Claude's input verbatim.
36
+ */
37
+ readonly stdin?: string;
38
+ }
39
+ /**
40
+ * Build the `olam enter --start-claude` command sequence.
41
+ *
42
+ * SECURITY INVARIANT (T17 mitigation, mirroring C4 spec):
43
+ *
44
+ * When `task` is supplied, the task text is delivered to tmux's paste-buffer
45
+ * via STDIN of `docker exec -i <c> tmux load-buffer -`. It is NEVER passed
46
+ * as a shell argument and NEVER interpolated into any command-line position.
47
+ * `tmux paste-buffer` writes buffer contents literally — without shell
48
+ * evaluation — so a `task` like `"Fix bug; rm -rf /tmp"` arrives in Claude's
49
+ * prompt area as literal text. The user reviews then presses Enter manually
50
+ * (no newline is appended by this builder).
51
+ *
52
+ * Mirrors the same trust class as `BootstrapStep` (bootstrap-runner.ts) and
53
+ * `SupervisedRepo.start` (tmux-supervisor.ts). Do not change without
54
+ * security review — replacing the stdin path with `tmux send-keys
55
+ * "$task"` (or any shell-interpolated form) re-opens the T17 RCE.
56
+ *
57
+ * @throws Error if `containerName` or `sessionName` fail the defensive
58
+ * regex guard (these become unquoted argv tokens in the returned
59
+ * commands; metachar injection there bypasses the stdin contract).
60
+ */
61
+ export declare function buildStartClaudeCommands(containerName: string, sessionName: string, task: string | undefined): StartClaudeStep[];
62
+ export declare function registerEnter(program: Command): void;
63
+ //# sourceMappingURL=enter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enter.d.ts","sourceRoot":"","sources":["../../src/commands/enter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUzC,MAAM,WAAW,eAAe;IAC9B,oDAAoD;IACpD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;;;;;;OAQG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,wBAAwB,CACtC,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GAAG,SAAS,GACvB,eAAe,EAAE,CAsEnB;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuIpD"}
@@ -0,0 +1,206 @@
1
+ /**
2
+ * olam enter <world> — Open terminal into a world's Claude session.
3
+ *
4
+ * Two modes:
5
+ *
6
+ * 1. **Default** (no --start-claude): print the shell command the operator
7
+ * can run to attach an interactive terminal to the world. Optionally
8
+ * `--exec` runs that command in-process instead of printing it.
9
+ *
10
+ * 2. **--start-claude** (Phase C/C4): open a tmux session inside the world,
11
+ * pre-fill the Claude prompt with `--task <text>` if supplied, then
12
+ * attach. Task text is delivered to tmux's paste buffer via STDIN
13
+ * (`docker exec -i ... tmux load-buffer -`) and pasted with
14
+ * `tmux paste-buffer` — LITERAL bytes, no shell evaluation. T17
15
+ * mitigation. See {@link buildStartClaudeCommands} for the contract.
16
+ */
17
+ import { execSync } from 'node:child_process';
18
+ import pc from 'picocolors';
19
+ import { loadContext } from '../context.js';
20
+ import { printError } from '../output.js';
21
+ /** Same SAFE_IDENT contract as world/tmux-supervisor.ts and
22
+ * world/bootstrap-runner.ts — caller-side schema validates upstream;
23
+ * we re-check defensively at this seam. */
24
+ const SAFE_IDENT = /^[a-z0-9][a-z0-9-]{0,63}$/;
25
+ /**
26
+ * Build the `olam enter --start-claude` command sequence.
27
+ *
28
+ * SECURITY INVARIANT (T17 mitigation, mirroring C4 spec):
29
+ *
30
+ * When `task` is supplied, the task text is delivered to tmux's paste-buffer
31
+ * via STDIN of `docker exec -i <c> tmux load-buffer -`. It is NEVER passed
32
+ * as a shell argument and NEVER interpolated into any command-line position.
33
+ * `tmux paste-buffer` writes buffer contents literally — without shell
34
+ * evaluation — so a `task` like `"Fix bug; rm -rf /tmp"` arrives in Claude's
35
+ * prompt area as literal text. The user reviews then presses Enter manually
36
+ * (no newline is appended by this builder).
37
+ *
38
+ * Mirrors the same trust class as `BootstrapStep` (bootstrap-runner.ts) and
39
+ * `SupervisedRepo.start` (tmux-supervisor.ts). Do not change without
40
+ * security review — replacing the stdin path with `tmux send-keys
41
+ * "$task"` (or any shell-interpolated form) re-opens the T17 RCE.
42
+ *
43
+ * @throws Error if `containerName` or `sessionName` fail the defensive
44
+ * regex guard (these become unquoted argv tokens in the returned
45
+ * commands; metachar injection there bypasses the stdin contract).
46
+ */
47
+ export function buildStartClaudeCommands(containerName, sessionName, task) {
48
+ if (!SAFE_IDENT.test(containerName)) {
49
+ throw new Error(`containerName "${containerName}" must match ${SAFE_IDENT} (defensive guard)`);
50
+ }
51
+ if (!SAFE_IDENT.test(sessionName)) {
52
+ throw new Error(`sessionName "${sessionName}" must match ${SAFE_IDENT} (defensive guard)`);
53
+ }
54
+ if (task !== undefined && task.includes('\0')) {
55
+ // CP3 audit ADV-C4-001 closure: tmux paste-buffer's behavior on embedded
56
+ // NUL is implementation-defined (older tmux truncates at first NUL,
57
+ // silently submitting only the prefix). Reject early with a clear error.
58
+ throw new Error('task contains a NUL byte; tmux paste-buffer truncates on NUL — re-encode or remove the byte');
59
+ }
60
+ const steps = [];
61
+ // 1a. Open or attach to the per-world tmux session. With `-A`, if the
62
+ // session already exists (e.g. C1's supervisor opened it with repo
63
+ // windows), the -n/-cmd args are IGNORED — so step 1b ensures the
64
+ // `claude` window exists idempotently regardless of attach-vs-create.
65
+ steps.push({
66
+ description: 'Open or attach to per-world tmux session',
67
+ command: `docker exec ${containerName} tmux new-session -A -d ` +
68
+ `-s ${sessionName} -n claude 'claude'`,
69
+ });
70
+ // 1b. Idempotently ensure the claude window exists. CP3 audit ADV-C4-002
71
+ // closure: -A attach on an existing session without a `claude` window
72
+ // would silently no-op step 1's window arg, then step 3's paste-buffer
73
+ // target would fail mid-flight with the buffer already loaded.
74
+ steps.push({
75
+ description: 'Ensure claude window exists in the session',
76
+ command: `docker exec ${containerName} sh -c ` +
77
+ `"tmux new-window -t ${sessionName} -n claude 'claude' 2>/dev/null || true"`,
78
+ });
79
+ // 2. (Conditional) Deliver task text to the paste buffer via STDIN.
80
+ // NOTE — this is the load-bearing security primitive: task text is
81
+ // NEVER part of the argv. tmux load-buffer reads from stdin in
82
+ // literal-byte mode.
83
+ if (task !== undefined && task.length > 0) {
84
+ steps.push({
85
+ description: 'Load task text into tmux paste buffer via STDIN (literal — no shell eval)',
86
+ command: `docker exec -i ${containerName} tmux load-buffer -`,
87
+ stdin: task,
88
+ });
89
+ steps.push({
90
+ description: 'Paste buffer into the claude window (no Enter — user reviews then submits)',
91
+ command: `docker exec ${containerName} tmux paste-buffer ` +
92
+ `-t ${sessionName}:claude`,
93
+ });
94
+ }
95
+ // 3. Attach an interactive terminal so the operator sees the session.
96
+ steps.push({
97
+ description: 'Attach interactive terminal to the session',
98
+ command: `docker exec -it ${containerName} tmux attach -t ${sessionName}`,
99
+ });
100
+ return steps;
101
+ }
102
+ export function registerEnter(program) {
103
+ program
104
+ .command('enter')
105
+ .description('Open terminal to a world')
106
+ .argument('<world>', 'World ID')
107
+ .option('--exec', 'Execute the command directly instead of printing it')
108
+ .option('--start-claude', 'Open a Claude session inside the world via tmux (literal-paste task contract)')
109
+ .option('--task <text>', 'Optional task text to pre-fill Claude with (delivered via tmux load-buffer; never shell-evaluated)')
110
+ .action(async (worldId, opts) => {
111
+ const { ctx, error } = await loadContext();
112
+ if (!ctx) {
113
+ printError(error?.message ?? 'Olam is not configured. Run `olam init` first.');
114
+ process.exitCode = 1;
115
+ return;
116
+ }
117
+ const computeWorld = await ctx.computeProvider.getWorld(worldId);
118
+ if (!computeWorld) {
119
+ printError(`World "${worldId}" not found.`);
120
+ process.exitCode = 1;
121
+ return;
122
+ }
123
+ const connectionInfo = await computeWorld.getConnectionInfo();
124
+ // --start-claude path: tmux session with literal-paste task contract.
125
+ if (opts.startClaude) {
126
+ if (computeWorld.provider !== 'docker') {
127
+ printError(`--start-claude is only supported on the docker provider today (got "${computeWorld.provider}")`);
128
+ process.exitCode = 1;
129
+ return;
130
+ }
131
+ const containerName = connectionInfo.containerId;
132
+ const sessionName = `olam-${worldId}`;
133
+ let steps;
134
+ try {
135
+ steps = buildStartClaudeCommands(containerName, sessionName, opts.task);
136
+ }
137
+ catch (err) {
138
+ printError(err instanceof Error ? err.message : String(err));
139
+ process.exitCode = 1;
140
+ return;
141
+ }
142
+ if (opts.exec) {
143
+ for (const step of steps) {
144
+ try {
145
+ execSync(step.command, {
146
+ stdio: step.stdin !== undefined
147
+ ? ['pipe', 'inherit', 'inherit']
148
+ : 'inherit',
149
+ input: step.stdin,
150
+ });
151
+ }
152
+ catch (err) {
153
+ printError(`Step "${step.description}" failed: ` +
154
+ (err instanceof Error ? err.message : String(err)));
155
+ process.exitCode = 1;
156
+ return;
157
+ }
158
+ }
159
+ return;
160
+ }
161
+ console.log('Run these commands in order to enter the world:\n');
162
+ // CP3 audit ADV-C4-004 closure: do NOT apply pc.bold to commands in
163
+ // --start-claude print mode — these lines are meant to be copy-pasted
164
+ // into a shell or saved to a script. With FORCE_COLOR=1 set in the
165
+ // operator's env, pc.bold injects ANSI escapes that break the saved
166
+ // script ("command not found: \e[1mdocker"). Plain text only.
167
+ for (const step of steps) {
168
+ console.log(` ${pc.dim(`# ${step.description}`)}`);
169
+ if (step.stdin !== undefined) {
170
+ // Print form: shell-quote the task and pipe via printf. Same
171
+ // security boundary — outer single-quotes neutralize all shell
172
+ // metacharacters inside the payload.
173
+ const escaped = step.stdin.replace(/'/g, "'\\''");
174
+ console.log(` printf '%s' '${escaped}' | ${step.command}`);
175
+ }
176
+ else {
177
+ console.log(` ${step.command}`);
178
+ }
179
+ }
180
+ return;
181
+ }
182
+ // Legacy default path — unchanged.
183
+ const { getEnterCommand } = await import('@olam/core/src/orchestrator/enter.js');
184
+ const result = getEnterCommand(worldId, connectionInfo.containerId, computeWorld.provider, connectionInfo.ssh?.host);
185
+ if (!result.command) {
186
+ printError(result.instructions);
187
+ process.exitCode = 1;
188
+ return;
189
+ }
190
+ if (opts.exec) {
191
+ try {
192
+ execSync(result.command, { stdio: 'inherit' });
193
+ }
194
+ catch (err) {
195
+ printError(err instanceof Error ? err.message : `Command failed: ${result.command}`);
196
+ process.exitCode = 1;
197
+ }
198
+ return;
199
+ }
200
+ console.log('Run this command to enter the world:\n');
201
+ console.log(` ${pc.bold(result.command)}`);
202
+ const containerName = `olam-${worldId}-devbox`;
203
+ console.log(`\n${pc.dim(`Observe dispatch: docker exec -it ${containerName} tmux attach -t olam-dispatch -r`)}`);
204
+ });
205
+ }
206
+ //# sourceMappingURL=enter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enter.js","sourceRoot":"","sources":["../../src/commands/enter.ts"],"names":[],"mappings":"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"}