windows-development-sandbox 1.11.6 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/README.md +12 -6
  2. package/config.example.json +4 -3
  3. package/dist/app/features/apps/apps-rows.d.ts +4 -1
  4. package/dist/app/features/apps/apps-rows.js +7 -2
  5. package/dist/app/features/apps/apps.def.d.ts +19 -0
  6. package/dist/app/features/apps/apps.def.js +49 -12
  7. package/dist/app/features/apps/apps.run.d.ts +2 -0
  8. package/dist/app/features/apps/apps.run.js +1 -1
  9. package/dist/app/features/audit/audit.def.d.ts +341 -0
  10. package/dist/app/features/audit/audit.def.js +454 -0
  11. package/dist/app/features/audit/audit.run.d.ts +107 -0
  12. package/dist/app/features/audit/audit.run.js +133 -0
  13. package/dist/app/features/audit/index.d.ts +2 -0
  14. package/dist/app/features/audit/index.js +3 -0
  15. package/dist/app/features/defs.d.ts +194 -1
  16. package/dist/app/features/defs.js +4 -0
  17. package/dist/app/features/projects/projects.def.js +1 -1
  18. package/dist/app/features/settings/settings.run.d.ts +3 -0
  19. package/dist/app/features/settings/settings.run.js +16 -2
  20. package/dist/app/features/updates/update-lines.d.ts +1 -1
  21. package/dist/app/features/updates/update-lines.js +3 -7
  22. package/dist/app/features/updates/updates.def.js +1 -1
  23. package/dist/app/kernel/define.d.ts +12 -1
  24. package/dist/app/registry.js +2 -0
  25. package/dist/cli/args.d.ts +0 -3
  26. package/dist/cli/args.js +3 -4
  27. package/dist/cli/commands/index.d.ts +1 -1
  28. package/dist/cli/commands/index.js +1 -1
  29. package/dist/cli/commands/launch/prepare.js +1 -1
  30. package/dist/cli/commands/maintenance/index.d.ts +0 -1
  31. package/dist/cli/commands/maintenance/index.js +0 -1
  32. package/dist/cli/commands/registry.js +1 -2
  33. package/dist/cli/manifest.d.ts +0 -41
  34. package/dist/cli/manifest.js +0 -14
  35. package/dist/cli/menu/pages/apps-page.js +2 -15
  36. package/dist/cli/menu/pages/maintenance-page.d.ts +4 -0
  37. package/dist/cli/menu/pages/maintenance-page.js +51 -8
  38. package/dist/cli/menu/views.js +2 -0
  39. package/dist/core/config/defaults.js +1 -1
  40. package/dist/core/schema/apps.d.ts +9 -0
  41. package/dist/core/schema/apps.js +9 -0
  42. package/dist/core/schema/config.d.ts +1 -0
  43. package/dist/core/schema/config.js +3 -3
  44. package/dist/core/schema/sandbox.d.ts +1 -0
  45. package/dist/core/schema/sandbox.js +11 -3
  46. package/dist/guest/apps/app-installer.js +50 -4
  47. package/dist/guest/apps/index.d.ts +1 -1
  48. package/dist/guest/apps/index.js +1 -1
  49. package/dist/guest/apps/sources.js +1 -1
  50. package/dist/guest/audit/parse.d.ts +32 -2
  51. package/dist/guest/audit/parse.js +43 -5
  52. package/dist/guest/audit/process-audit.d.ts +3 -1
  53. package/dist/guest/audit/process-audit.js +9 -6
  54. package/dist/guest/boot/boot.js +12 -3
  55. package/dist/guest/boot/guide.d.ts +1 -1
  56. package/dist/guest/boot/guide.js +27 -3
  57. package/dist/guest/daemon/sessions.d.ts +7 -0
  58. package/dist/guest/daemon/sessions.js +27 -2
  59. package/dist/guest/entries/daemon.js +2 -1
  60. package/dist/guest/setup/addon-mcp.d.ts +2 -0
  61. package/dist/guest/setup/addon-mcp.js +49 -0
  62. package/dist/guest/setup/agent-addons.d.ts +9 -0
  63. package/dist/guest/setup/agent-addons.js +22 -0
  64. package/dist/guest/setup/headroom.d.ts +7 -0
  65. package/dist/guest/setup/headroom.js +60 -0
  66. package/dist/guest/setup/managed-policy.d.ts +2 -1
  67. package/dist/guest/setup/managed-policy.js +15 -6
  68. package/dist/guest/toolchains/plan.js +8 -3
  69. package/dist/host/audit/attribute.d.ts +46 -0
  70. package/dist/host/audit/attribute.js +76 -0
  71. package/dist/host/audit/collect.d.ts +29 -3
  72. package/dist/host/audit/collect.js +256 -61
  73. package/dist/host/audit/git-commits.d.ts +29 -0
  74. package/dist/host/audit/git-commits.js +157 -0
  75. package/dist/host/audit/index.d.ts +5 -0
  76. package/dist/host/audit/index.js +6 -0
  77. package/dist/host/audit/log.d.ts +44 -7
  78. package/dist/host/audit/log.js +148 -45
  79. package/dist/host/audit/redact.d.ts +2 -0
  80. package/dist/host/audit/redact.js +67 -0
  81. package/dist/host/update/decision.d.ts +3 -2
  82. package/dist/host/update/decision.js +2 -3
  83. package/dist/host/update/updater.d.ts +4 -1
  84. package/dist/host/update/updater.js +11 -6
  85. package/dist/runtime/agent.js +110 -15
  86. package/dist/runtime/daemon.js +569 -316
  87. package/dist/runtime/db.js +110 -15
  88. package/dist/runtime/main.js +1011 -672
  89. package/dist/runtime/netproxy.js +110 -15
  90. package/dist/runtime/view.js +110 -15
  91. package/dist/selftest/app.test.js +25 -1
  92. package/dist/selftest/audit.test.js +354 -47
  93. package/dist/selftest/hcs.test.js +35 -0
  94. package/dist/selftest/menu-screens.js +1 -1
  95. package/dist/selftest/menu.test.js +3 -3
  96. package/dist/selftest/support/engine-golden.js +9 -0
  97. package/dist/selftest/support/fixtures.d.ts +1 -0
  98. package/dist/selftest/support/web-preview.js +94 -0
  99. package/dist/selftest/toolchains.test.js +147 -2
  100. package/dist/selftest/update-service.test.js +0 -7
  101. package/dist/selftest/update.test.js +4 -4
  102. package/dist/shared/apps/agent-addons.d.ts +64 -0
  103. package/dist/shared/apps/agent-addons.js +95 -0
  104. package/dist/shared/apps/catalogue.d.ts +33 -2
  105. package/dist/shared/apps/catalogue.js +102 -11
  106. package/dist/shared/apps/index.d.ts +3 -2
  107. package/dist/shared/apps/index.js +3 -2
  108. package/dist/shared/apps/selection.d.ts +2 -0
  109. package/dist/shared/apps/selection.js +7 -0
  110. package/dist/sync/watcher.js +9 -1
  111. package/dist/web/index.html +2 -2
  112. package/dist/web/{main-RQFN4WBY.css → main-UAQPI5XD.css} +1 -1
  113. package/dist/web/{main-QL7KHCEE.js → main-UD4QCXZR.js} +66 -66
  114. package/native/csharp/HcsHost/AssemblyInfo.cs +5 -3
  115. package/native/csharp/HcsHost/Hcs.cs +9 -0
  116. package/native/csharp/HcsHost/Program.cs +26 -1
  117. package/native/csharp/HcsHost/Share.cs +173 -0
  118. package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
  119. package/package.json +1 -1
  120. package/sandbox/addons/ccusage/package-lock.json +111 -0
  121. package/sandbox/addons/ccusage/package.json +7 -0
  122. package/sandbox/addons/context7/package-lock.json +1313 -0
  123. package/sandbox/addons/context7/package.json +7 -0
  124. package/sandbox/addons/headroom/requirements.in +1 -0
  125. package/sandbox/addons/headroom/requirements.txt +2922 -0
  126. package/sandbox/addons/playwright-mcp/package-lock.json +56 -0
  127. package/sandbox/addons/playwright-mcp/package.json +7 -0
  128. package/schemas/config.schema.json +13 -4
  129. package/schemas/sandbox-config.schema.json +2 -2
  130. package/dist/cli/commands/maintenance/audit.d.ts +0 -3
  131. package/dist/cli/commands/maintenance/audit.js +0 -58
@@ -60,14 +60,14 @@ export class Updater {
60
60
  const force = options.force ?? false;
61
61
  // The gates that need no network run first, so a skipped check costs nothing.
62
62
  const early = decideUpdate({ ...base, latest: null, sandboxRunning: options.sandboxRunning, force });
63
- if (early.kind === 'skip' && (early.reason === 'too-soon' || early.reason === 'sandbox-running'))
63
+ if (early.kind === 'skip' && early.reason === 'too-soon')
64
64
  return { kind: 'skipped', reason: early.reason, current };
65
65
  const latest = await this.source.latest();
66
66
  this.state.update((s) => ({ ...s, lastCheck: this.now().toISOString() }));
67
67
  const decision = decideUpdate({ ...base, latest, sandboxRunning: options.sandboxRunning, force });
68
68
  if (decision.kind === 'skip')
69
69
  return { kind: 'skipped', reason: decision.reason, current };
70
- return this.install(decision.release, current, node);
70
+ return this.install(decision.release, current, node, options.sandboxRunning);
71
71
  }
72
72
  /** Points the shims back at the version the last successful update replaced. Returns that version. */
73
73
  rollback() {
@@ -90,7 +90,7 @@ export class Updater {
90
90
  this.state.update((s) => ({ ...s, previous: current }));
91
91
  return target;
92
92
  }
93
- async install(release, current, node) {
93
+ async install(release, current, node, sandboxRunning) {
94
94
  const version = release.version;
95
95
  const archive = path.join(this.layout.root, 'staging', version + '.tgz');
96
96
  const work = this.layout.versionDir(version) + '.staging';
@@ -139,7 +139,7 @@ export class Updater {
139
139
  // A leftover download is replaced by the next one.
140
140
  }
141
141
  }
142
- this.finish(version, current);
142
+ this.finish(version, current, sandboxRunning);
143
143
  return { kind: 'installed', version, previous: current };
144
144
  }
145
145
  /** The commands a version's package.json declares, or null when it cannot be read. */
@@ -277,10 +277,15 @@ export class Updater {
277
277
  '): ' +
278
278
  (errorLine(run.stderr || run.stdout || run.error?.message || '') || 'no output'));
279
279
  }
280
- /** Records the update, keeps the replaced version for a rollback and removes the rest. */
281
- finish(version, previous) {
280
+ /**
281
+ * Records the update, keeps the replaced version for a rollback and removes the rest, but only when no sandbox runs:
282
+ * its helpers on this PC may still run an older version from its folder.
283
+ */
284
+ finish(version, previous, sandboxRunning) {
282
285
  const at = this.now().toISOString();
283
286
  this.state.update((s) => ({ ...s, previous, lastResult: { version, ok: true, at } }));
287
+ if (sandboxRunning)
288
+ return;
284
289
  for (const old of this.layout.installedVersions())
285
290
  if (old !== version && old !== previous) {
286
291
  try {
@@ -25541,14 +25541,19 @@ var NetworkSchema = external_exports.strictObject({
25541
25541
  });
25542
25542
  var AuditSchema = external_exports.strictObject({
25543
25543
  enabled: external_exports.boolean().describe(
25544
- "Keep an audit log on this PC of what happened in your sandboxes: programs started (with their command lines), files changed in the project, sessions, and what the repo guard caught. The sandbox cannot change it. Read it with sandbox audit."
25544
+ "Keep an audit log on this PC of what your agents did: programs started (with their command lines, secrets hidden), files changed in the projects, git commits, sessions, and what the repo guard caught, each linked to the agent session that did it where that can be known. The sandbox cannot change it. Read it with sandbox audit or on the Activity page."
25545
+ ),
25546
+ days: external_exports.number().int().min(1).max(365).describe(
25547
+ "Days the audit log is kept (1 to 30; a larger number keeps 30); older days are deleted when a sandbox starts and once a day."
25545
25548
  ),
25546
- days: external_exports.number().int().min(1).max(365).describe("Days the audit log is kept."),
25547
25549
  maxMb: external_exports.number().int().min(5).max(5e3).describe("Most space the audit log may take, in MB (older days go first). Days before today are compressed."),
25548
25550
  processes: external_exports.boolean().describe(
25549
25551
  "Record every program started in the sandbox with its command line (Windows process auditing; repeated runs are counted, not listed)."
25550
25552
  ),
25551
- files: external_exports.boolean().describe("Record the files changed in the project while the sandbox runs.")
25553
+ files: external_exports.boolean().describe("Record the files changed in the projects while the sandbox runs."),
25554
+ commits: external_exports.boolean().describe(
25555
+ "Record the git commits made in the projects while the sandbox runs (read from each project's .git folder on this PC)."
25556
+ )
25552
25557
  });
25553
25558
  var WorkspaceFilterSchema = external_exports.strictObject({
25554
25559
  enabled: external_exports.boolean().describe(
@@ -25751,7 +25756,100 @@ var ToolchainsSchema = external_exports.strictObject({
25751
25756
 
25752
25757
  // src/shared/apps/catalogue.ts
25753
25758
  var gh = (github, asset) => ({ github, asset });
25759
+ var RTK_VERSION = "1.0.1";
25760
+ var RTK_URL = "https://github.com/rtk-ai/rtk/releases/download/v" + RTK_VERSION + "/rtk-oss-x86_64-pc-windows-msvc.zip";
25761
+ var RTK_SHA256 = "0e53e2eca471e15fbd3636e64e6bc0b182cbc278ed0339c80450a2dd03f4cd6b";
25762
+ var HEADROOM_VERSION = "0.41.0";
25763
+ var CCUSAGE_VERSION = "20.0.36";
25764
+ var PLAYWRIGHT_MCP_VERSION = "0.0.83";
25765
+ var CONTEXT7_MCP_VERSION = "4.4.2";
25754
25766
  var APPS = [
25767
+ // ---- agent add-ons
25768
+ {
25769
+ id: "rtk",
25770
+ name: "rtk (Rust Token Killer)",
25771
+ category: "agents",
25772
+ about: "Compacts the output of shell commands (git, tests, builds, ls ...) before the agent reads it, so it uses fewer tokens. Claude Code's Bash commands go through it on their own.",
25773
+ size: "6 MB",
25774
+ source: { url: RTK_URL, sha256: RTK_SHA256 },
25775
+ exe: "rtk.exe",
25776
+ cli: true,
25777
+ plugsInto: "Claude Code through a hook in the sandbox's managed settings; other agents are told to use it",
25778
+ userOnly: true
25779
+ },
25780
+ {
25781
+ id: "headroom",
25782
+ name: "Headroom",
25783
+ category: "agents",
25784
+ about: "Compresses what Claude Code sends to the model (tool output, logs, files) so it uses fewer tokens: a local proxy on 127.0.0.1:8787 that sits in Claude Code's API path, offline apart from forwarding to api.anthropic.com.",
25785
+ size: "150 MB",
25786
+ source: { locked: "uv", package: "headroom-ai", version: HEADROOM_VERSION },
25787
+ exe: "headroom.exe",
25788
+ service: true,
25789
+ plugsInto: "Claude Code: the sandbox starts the proxy and points Claude Code at it (managed settings)",
25790
+ userOnly: true
25791
+ },
25792
+ {
25793
+ id: "ccusage",
25794
+ name: "ccusage",
25795
+ category: "agents",
25796
+ about: "Reports the agents' token use and cost by day, month or session from their logs in the sandbox (`ccusage daily`; add --offline to skip fetching prices).",
25797
+ size: "5 MB",
25798
+ source: { locked: "npm", package: "ccusage", version: CCUSAGE_VERSION },
25799
+ exe: "ccusage.cmd",
25800
+ cli: true,
25801
+ plugsInto: "Reads Claude Code's session logs in the sandbox; changes nothing",
25802
+ userOnly: true
25803
+ },
25804
+ {
25805
+ id: "playwright-mcp",
25806
+ name: "Playwright MCP",
25807
+ category: "agents",
25808
+ about: "Lets Claude Code drive a browser (Microsoft Edge, already in the sandbox) to open pages, click, fill forms and take screenshots: the MCP server of microsoft/playwright-mcp.",
25809
+ size: "20 MB",
25810
+ source: { locked: "npm", package: "@playwright/mcp", version: PLAYWRIGHT_MCP_VERSION },
25811
+ exe: "playwright-mcp.cmd",
25812
+ service: true,
25813
+ mcp: { name: "sbx-playwright", script: "node_modules/@playwright/mcp/cli.js", args: ["--browser", "msedge"] },
25814
+ plugsInto: "Claude Code as the MCP server sbx-playwright (the sandbox's Claude settings)",
25815
+ userOnly: true
25816
+ },
25817
+ {
25818
+ id: "context7",
25819
+ name: "Context7 MCP",
25820
+ category: "agents",
25821
+ about: "Up-to-date documentation and code examples for libraries, looked up by Claude Code while it works (upstash/context7). The library names and questions go to Upstash's context7.com.",
25822
+ size: "55 MB",
25823
+ source: { locked: "npm", package: "@upstash/context7-mcp", version: CONTEXT7_MCP_VERSION },
25824
+ exe: "context7-mcp.cmd",
25825
+ service: true,
25826
+ mcp: { name: "sbx-context7", script: "node_modules/@upstash/context7-mcp/dist/index.js" },
25827
+ plugsInto: "Claude Code as the MCP server sbx-context7 (the sandbox's Claude settings)",
25828
+ userOnly: true
25829
+ },
25830
+ {
25831
+ id: "claude-mem",
25832
+ name: "claude-mem",
25833
+ category: "agents",
25834
+ about: "Persistent memory for Claude Code (a plugin you install on this PC): its database is brought into the sandbox.",
25835
+ size: "",
25836
+ source: { resolve: "setting" },
25837
+ exe: "",
25838
+ setting: "claudeProfile.syncClaudeMem",
25839
+ plugsInto: "Claude Code, with your Claude settings copied from this PC",
25840
+ userOnly: true
25841
+ },
25842
+ {
25843
+ id: "rea",
25844
+ name: "REA (Reverse Engineer Anything)",
25845
+ category: "agents",
25846
+ about: "Agent-driven reverse engineering (MCP server and CLI, by morluto). Run `rea setup` once to add it to Claude Code and Codex. Native binaries need Ghidra; needs Node 22.19+.",
25847
+ size: "8 MB",
25848
+ source: { npm: "rea-agents" },
25849
+ exe: "rea.cmd",
25850
+ cli: true,
25851
+ plugsInto: "Claude Code and Codex as an MCP server, after `rea setup`"
25852
+ },
25755
25853
  // ---- editors
25756
25854
  {
25757
25855
  id: "vscode",
@@ -26213,16 +26311,6 @@ var APPS = [
26213
26311
  cli: true
26214
26312
  },
26215
26313
  // ---- reverse engineering
26216
- {
26217
- id: "rea",
26218
- name: "REA (Reverse Engineer Anything)",
26219
- category: "reversing",
26220
- about: "Agent-driven reverse engineering (MCP server and CLI, by morluto). Run `rea setup` once to add it to Claude Code and Codex. Native binaries need Ghidra; needs Node 22.19+.",
26221
- size: "8 MB",
26222
- source: { npm: "rea-agents" },
26223
- exe: "rea.cmd",
26224
- cli: true
26225
- },
26226
26314
  {
26227
26315
  id: "ghidra",
26228
26316
  name: "Ghidra",
@@ -26502,6 +26590,8 @@ var APPS = [
26502
26590
  // src/core/schema/apps.ts
26503
26591
  var CATALOGUE_IDS = APPS.filter((a) => !a.setting).map((a) => a.id);
26504
26592
  var AppIdSchema = external_exports.enum(CATALOGUE_IDS);
26593
+ var PROJECT_IDS = APPS.filter((a) => !a.setting && !a.userOnly).map((a) => a.id);
26594
+ var ProjectAppIdSchema = external_exports.enum(PROJECT_IDS);
26505
26595
  var CustomAppIdSchema = external_exports.string().regex(/^[a-z0-9][a-z0-9-]{0,40}$/, "lower-case letters, digits and - only");
26506
26596
  var compiles = (pattern) => {
26507
26597
  try {
@@ -26525,6 +26615,11 @@ var CustomAppSchema = external_exports.strictObject({
26525
26615
  }).refine((a) => a.github && a.asset ? !a.url : Boolean(a.url) && !a.github && !a.asset, {
26526
26616
  message: "give github + asset, or url (not both)"
26527
26617
  });
26618
+ var ProjectAppsSchema = external_exports.strictObject({
26619
+ install: external_exports.array(ProjectAppIdSchema).describe(
26620
+ "Apps from the catalogue this project adds to yours (agent add-ons such as rtk, Headroom and the MCP servers are set in your own settings only)."
26621
+ )
26622
+ });
26528
26623
  var AppsSchema = external_exports.strictObject({
26529
26624
  install: external_exports.array(AppIdSchema).describe(
26530
26625
  "Apps from the catalogue to install in every sandbox (the Apps screen in the menu lists them by category). Each is downloaded once and kept."
@@ -26689,8 +26784,8 @@ var LocalOverridesSchema = external_exports.strictObject({
26689
26784
  attach: AttachSchema.partial(),
26690
26785
  personalization: toggle("Copy your desktop look into the sandbox.").partial(),
26691
26786
  // Catalogue apps only (a vetted list): your own programs (apps.custom) download anything, so a repo cannot add
26692
- // them.
26693
- apps: AppsSchema.pick({ install: true }).partial(),
26787
+ // them, nor agent add-ons that are yours only (rtk hooks every agent command, Headroom sits in its API path).
26788
+ apps: ProjectAppsSchema.partial(),
26694
26789
  claudeProfile: ClaudeProfileSchema.pick({
26695
26790
  enabled: true,
26696
26791
  overwrite: true,