windows-development-sandbox 1.11.7 → 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 (121) 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/settings/settings.run.d.ts +3 -0
  18. package/dist/app/features/settings/settings.run.js +16 -2
  19. package/dist/app/kernel/define.d.ts +12 -1
  20. package/dist/app/registry.js +2 -0
  21. package/dist/cli/args.d.ts +0 -3
  22. package/dist/cli/args.js +3 -4
  23. package/dist/cli/commands/index.d.ts +1 -1
  24. package/dist/cli/commands/index.js +1 -1
  25. package/dist/cli/commands/launch/prepare.js +1 -1
  26. package/dist/cli/commands/maintenance/index.d.ts +0 -1
  27. package/dist/cli/commands/maintenance/index.js +0 -1
  28. package/dist/cli/commands/registry.js +1 -2
  29. package/dist/cli/manifest.d.ts +0 -41
  30. package/dist/cli/manifest.js +0 -14
  31. package/dist/cli/menu/pages/apps-page.js +2 -15
  32. package/dist/cli/menu/pages/maintenance-page.d.ts +4 -0
  33. package/dist/cli/menu/pages/maintenance-page.js +51 -8
  34. package/dist/cli/menu/views.js +2 -0
  35. package/dist/core/config/defaults.js +1 -1
  36. package/dist/core/schema/apps.d.ts +9 -0
  37. package/dist/core/schema/apps.js +9 -0
  38. package/dist/core/schema/config.d.ts +1 -0
  39. package/dist/core/schema/config.js +3 -3
  40. package/dist/core/schema/sandbox.d.ts +1 -0
  41. package/dist/core/schema/sandbox.js +11 -3
  42. package/dist/guest/apps/app-installer.js +50 -4
  43. package/dist/guest/apps/index.d.ts +1 -1
  44. package/dist/guest/apps/index.js +1 -1
  45. package/dist/guest/apps/sources.js +1 -1
  46. package/dist/guest/audit/parse.d.ts +32 -2
  47. package/dist/guest/audit/parse.js +43 -5
  48. package/dist/guest/audit/process-audit.d.ts +3 -1
  49. package/dist/guest/audit/process-audit.js +9 -6
  50. package/dist/guest/boot/boot.js +12 -3
  51. package/dist/guest/boot/guide.d.ts +1 -1
  52. package/dist/guest/boot/guide.js +27 -3
  53. package/dist/guest/daemon/sessions.d.ts +7 -0
  54. package/dist/guest/daemon/sessions.js +27 -2
  55. package/dist/guest/entries/daemon.js +2 -1
  56. package/dist/guest/setup/addon-mcp.d.ts +2 -0
  57. package/dist/guest/setup/addon-mcp.js +49 -0
  58. package/dist/guest/setup/agent-addons.d.ts +9 -0
  59. package/dist/guest/setup/agent-addons.js +22 -0
  60. package/dist/guest/setup/headroom.d.ts +7 -0
  61. package/dist/guest/setup/headroom.js +60 -0
  62. package/dist/guest/setup/managed-policy.d.ts +2 -1
  63. package/dist/guest/setup/managed-policy.js +15 -6
  64. package/dist/guest/toolchains/plan.js +8 -3
  65. package/dist/host/audit/attribute.d.ts +46 -0
  66. package/dist/host/audit/attribute.js +76 -0
  67. package/dist/host/audit/collect.d.ts +29 -3
  68. package/dist/host/audit/collect.js +256 -61
  69. package/dist/host/audit/git-commits.d.ts +29 -0
  70. package/dist/host/audit/git-commits.js +157 -0
  71. package/dist/host/audit/index.d.ts +5 -0
  72. package/dist/host/audit/index.js +6 -0
  73. package/dist/host/audit/log.d.ts +44 -7
  74. package/dist/host/audit/log.js +148 -45
  75. package/dist/host/audit/redact.d.ts +2 -0
  76. package/dist/host/audit/redact.js +67 -0
  77. package/dist/runtime/agent.js +110 -15
  78. package/dist/runtime/daemon.js +569 -316
  79. package/dist/runtime/db.js +110 -15
  80. package/dist/runtime/main.js +1011 -672
  81. package/dist/runtime/netproxy.js +110 -15
  82. package/dist/runtime/view.js +110 -15
  83. package/dist/selftest/app.test.js +25 -1
  84. package/dist/selftest/audit.test.js +354 -47
  85. package/dist/selftest/hcs.test.js +35 -0
  86. package/dist/selftest/menu-screens.js +1 -1
  87. package/dist/selftest/menu.test.js +3 -3
  88. package/dist/selftest/support/engine-golden.js +9 -0
  89. package/dist/selftest/support/fixtures.d.ts +1 -0
  90. package/dist/selftest/support/web-preview.js +94 -0
  91. package/dist/selftest/toolchains.test.js +147 -2
  92. package/dist/shared/apps/agent-addons.d.ts +64 -0
  93. package/dist/shared/apps/agent-addons.js +95 -0
  94. package/dist/shared/apps/catalogue.d.ts +33 -2
  95. package/dist/shared/apps/catalogue.js +102 -11
  96. package/dist/shared/apps/index.d.ts +3 -2
  97. package/dist/shared/apps/index.js +3 -2
  98. package/dist/shared/apps/selection.d.ts +2 -0
  99. package/dist/shared/apps/selection.js +7 -0
  100. package/dist/sync/watcher.js +9 -1
  101. package/dist/web/index.html +2 -2
  102. package/dist/web/{main-RQFN4WBY.css → main-UAQPI5XD.css} +1 -1
  103. package/dist/web/{main-K2JMCAZI.js → main-UD4QCXZR.js} +66 -66
  104. package/native/csharp/HcsHost/AssemblyInfo.cs +5 -3
  105. package/native/csharp/HcsHost/Hcs.cs +9 -0
  106. package/native/csharp/HcsHost/Program.cs +26 -1
  107. package/native/csharp/HcsHost/Share.cs +173 -0
  108. package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
  109. package/package.json +1 -1
  110. package/sandbox/addons/ccusage/package-lock.json +111 -0
  111. package/sandbox/addons/ccusage/package.json +7 -0
  112. package/sandbox/addons/context7/package-lock.json +1313 -0
  113. package/sandbox/addons/context7/package.json +7 -0
  114. package/sandbox/addons/headroom/requirements.in +1 -0
  115. package/sandbox/addons/headroom/requirements.txt +2922 -0
  116. package/sandbox/addons/playwright-mcp/package-lock.json +56 -0
  117. package/sandbox/addons/playwright-mcp/package.json +7 -0
  118. package/schemas/config.schema.json +13 -4
  119. package/schemas/sandbox-config.schema.json +2 -2
  120. package/dist/cli/commands/maintenance/audit.d.ts +0 -3
  121. package/dist/cli/commands/maintenance/audit.js +0 -58
@@ -0,0 +1,133 @@
1
+ // The audit feature's work: reads the log on this PC and sums it up (totals, per agent, per session). Much of what is
2
+ // in the log came from the sandbox, so every text is made plain (no control codes) before it leaves here.
3
+ import { plainText } from '../../../core/util/index.js';
4
+ import { AuditLog } from '../../../host/audit/index.js';
5
+ import { implement } from '../../context.js';
6
+ import { listAudit, NO_SESSION } from './audit.def.js';
7
+ /** Most sessions listed. */
8
+ const MAX_SESSIONS = 60;
9
+ const plain = (s) => (s === undefined ? undefined : plainText(s));
10
+ /** A stored event as the feature shows it. */
11
+ export function auditRow(e) {
12
+ const opt = (key, value) => value ? { [key]: plainText(value) } : {};
13
+ return {
14
+ time: e.t,
15
+ kind: e.k,
16
+ what: plain(e.k === 'session' ? (e.ag ?? e.p) : e.p) ?? '',
17
+ ...opt('command', e.c),
18
+ ...opt('parent', e.pp),
19
+ ...opt('action', e.a),
20
+ ...opt('folder', e.w),
21
+ ...opt('project', e.pj),
22
+ ...opt('session', e.s),
23
+ ...opt('agent', e.ag),
24
+ ...(e.s && e.sv ? { linked: e.sv === 't' ? 'only-session' : 'process' } : {}),
25
+ count: e.n ?? 1,
26
+ ...opt('sha', e.h),
27
+ ...opt('author', e.au),
28
+ };
29
+ }
30
+ /** Does an event pass the filters that are not about its kind? */
31
+ function inScope(e, input) {
32
+ const same = (a, b) => a !== undefined && a.toLowerCase() === b.toLowerCase();
33
+ if (input.session !== undefined) {
34
+ if (input.session === NO_SESSION ? e.s !== undefined : !e.s?.startsWith(input.session))
35
+ return false;
36
+ }
37
+ if (input.agent !== undefined && !same(e.ag, input.agent))
38
+ return false;
39
+ if (input.project !== undefined && !same(e.pj, input.project))
40
+ return false;
41
+ return true;
42
+ }
43
+ const tally = () => ({ commands: 0, files: new Set(), commits: 0 });
44
+ function count(t, e) {
45
+ if (e.k === 'proc')
46
+ t.commands += e.n ?? 1;
47
+ if (e.k === 'file')
48
+ t.files.add((e.w ?? '') + '\0' + (e.p ?? ''));
49
+ if (e.k === 'commit')
50
+ t.commits += 1;
51
+ }
52
+ const counts = (t) => ({
53
+ commands: t.commands,
54
+ files: t.files.size,
55
+ commits: t.commits,
56
+ });
57
+ /** The listing for these filters, from a log (the command line, the menu and the web all show this). */
58
+ export function auditListing(log, settings, input, folder, now = Date.now()) {
59
+ // The last n × 24 hours (the day files are UTC days: one more is read, then cut to the hour).
60
+ const since = new Date(now - input.days * 86400000).toISOString();
61
+ const scoped = log.read({ days: input.days + 1, grep: input.grep }).filter((e) => e.t >= since && inScope(e, input));
62
+ const total = tally();
63
+ const unlinked = tally();
64
+ const perSession = new Map();
65
+ for (const e of scoped) {
66
+ count(total, e);
67
+ if (!e.s) {
68
+ count(unlinked, e);
69
+ continue;
70
+ }
71
+ let entry = perSession.get(e.s);
72
+ if (!entry) {
73
+ entry = {
74
+ info: {
75
+ id: plainText(e.s),
76
+ agent: plainText(e.ag ?? (e.k === 'session' ? (e.p ?? '?') : '?')),
77
+ project: plainText(e.pj ?? '?'),
78
+ started: e.t,
79
+ commands: 0,
80
+ files: 0,
81
+ commits: 0,
82
+ },
83
+ t: tally(),
84
+ };
85
+ perSession.set(e.s, entry);
86
+ }
87
+ count(entry.t, e);
88
+ if (e.k === 'session' && e.a === 'end')
89
+ entry.info = { ...entry.info, ended: e.t };
90
+ if (e.k === 'proc' && (e.c || e.p))
91
+ entry.info = { ...entry.info, last: plainText(e.c || e.p || '') };
92
+ }
93
+ const sessions = [...perSession.values()]
94
+ .map(({ info, t }) => ({ ...info, ...counts(t) }))
95
+ .sort((a, b) => b.started.localeCompare(a.started));
96
+ const agents = new Map();
97
+ for (const s of sessions) {
98
+ const a = agents.get(s.agent) ?? { sessions: 0, commands: 0, files: 0, commits: 0 };
99
+ agents.set(s.agent, {
100
+ sessions: a.sessions + 1,
101
+ commands: a.commands + s.commands,
102
+ files: a.files + s.files,
103
+ commits: a.commits + s.commits,
104
+ });
105
+ }
106
+ const matching = input.kind === 'all' ? scoped : scoped.filter((e) => e.k === input.kind);
107
+ return {
108
+ enabled: settings.enabled,
109
+ keepDays: settings.days,
110
+ maxMb: settings.maxMb,
111
+ bytes: log.bytes(),
112
+ folder,
113
+ filter: {
114
+ days: input.days,
115
+ kind: input.kind,
116
+ ...(input.session !== undefined ? { session: input.session } : {}),
117
+ ...(input.agent !== undefined ? { agent: input.agent } : {}),
118
+ ...(input.project !== undefined ? { project: input.project } : {}),
119
+ ...(input.grep !== undefined ? { grep: input.grep } : {}),
120
+ },
121
+ matched: matching.length,
122
+ events: matching.slice(-input.limit).reverse().map(auditRow),
123
+ totals: { events: scoped.length, ...counts(total), sessions: sessions.length },
124
+ agents: [...agents.entries()].map(([agent, a]) => ({ agent, ...a })).sort((a, b) => b.commands - a.commands),
125
+ sessions: sessions.slice(0, MAX_SESSIONS),
126
+ unlinked: counts(unlinked),
127
+ };
128
+ }
129
+ export const listAuditRun = implement(listAudit, (ctx, input) => {
130
+ const settings = ctx.loaded.config.audit;
131
+ const folder = AuditLog.dirFor(ctx.storageRoot, ctx.dataPath);
132
+ return auditListing(new AuditLog(folder, settings), settings, input, folder);
133
+ });
@@ -0,0 +1,2 @@
1
+ export * from './audit.def.js';
2
+ export * from './audit.run.js';
@@ -0,0 +1,3 @@
1
+ // The audit feature: what the agents ran, changed and committed, from the audit log on this PC.
2
+ export * from './audit.def.js';
3
+ export * from './audit.run.js';
@@ -4,6 +4,7 @@ export type { AccountRow, AccountsList, AgentAccounts } from './accounts/account
4
4
  export type { AppRow, AppsList, CustomAppRow } from './apps/apps.def.js';
5
5
  export type { FolderEntry, FolderListing } from './files/files.def.js';
6
6
  export type { LogFileRow, LogFiles, LogTail } from './logs/logs.def.js';
7
+ export type { AuditList, AuditRow, AuditSession } from './audit/audit.def.js';
7
8
  export type { ProjectRow, ProjectsList } from './projects/projects.def.js';
8
9
  export type { SandboxStatus } from './sandbox/sandbox.def.js';
9
10
  export type { SessionRow, SessionsList } from './sessions/sessions.def.js';
@@ -450,6 +451,8 @@ export declare const QUERIES: readonly [QueryDef<import("zod").ZodObject<{}, imp
450
451
  cli: import("zod").ZodBoolean;
451
452
  mesa: import("zod").ZodBoolean;
452
453
  fullGitOnly: import("zod").ZodBoolean;
454
+ plugsInto: import("zod").ZodOptional<import("zod").ZodString>;
455
+ service: import("zod").ZodOptional<import("zod").ZodBoolean>;
453
456
  setting: import("zod").ZodOptional<import("zod").ZodString>;
454
457
  settingField: import("zod").ZodOptional<import("zod").ZodType<import("../kernel/fields.js").Field, unknown, import("zod/v4/core").$ZodTypeInternals<import("../kernel/fields.js").Field, unknown>>>;
455
458
  settingValue: import("zod").ZodOptional<import("zod").ZodUnknown>;
@@ -616,7 +619,100 @@ export declare const QUERIES: readonly [QueryDef<import("zod").ZodObject<{}, imp
616
619
  file: import("zod").ZodString;
617
620
  text: import("zod").ZodString;
618
621
  next: import("zod").ZodNumber;
619
- }, import("zod/v4/core").$strip>, "logs.tail">, QueryDef<import("zod").ZodObject<{}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
622
+ }, import("zod/v4/core").$strip>, "logs.tail">, QueryDef<import("zod").ZodObject<{
623
+ days: import("zod").ZodDefault<import("zod").ZodNumber>;
624
+ kind: import("zod").ZodDefault<import("zod").ZodEnum<{
625
+ file: "file";
626
+ all: "all";
627
+ session: "session";
628
+ commit: "commit";
629
+ proc: "proc";
630
+ guard: "guard";
631
+ }>>;
632
+ session: import("zod").ZodOptional<import("zod").ZodString>;
633
+ agent: import("zod").ZodOptional<import("zod").ZodString>;
634
+ project: import("zod").ZodOptional<import("zod").ZodString>;
635
+ grep: import("zod").ZodOptional<import("zod").ZodString>;
636
+ limit: import("zod").ZodDefault<import("zod").ZodNumber>;
637
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
638
+ enabled: import("zod").ZodBoolean;
639
+ keepDays: import("zod").ZodNumber;
640
+ maxMb: import("zod").ZodNumber;
641
+ bytes: import("zod").ZodNumber;
642
+ folder: import("zod").ZodString;
643
+ filter: import("zod").ZodObject<{
644
+ days: import("zod").ZodNumber;
645
+ kind: import("zod").ZodEnum<{
646
+ file: "file";
647
+ all: "all";
648
+ session: "session";
649
+ commit: "commit";
650
+ proc: "proc";
651
+ guard: "guard";
652
+ }>;
653
+ session: import("zod").ZodOptional<import("zod").ZodString>;
654
+ agent: import("zod").ZodOptional<import("zod").ZodString>;
655
+ project: import("zod").ZodOptional<import("zod").ZodString>;
656
+ grep: import("zod").ZodOptional<import("zod").ZodString>;
657
+ }, import("zod/v4/core").$strip>;
658
+ matched: import("zod").ZodNumber;
659
+ events: import("zod").ZodArray<import("zod").ZodObject<{
660
+ time: import("zod").ZodString;
661
+ kind: import("zod").ZodEnum<{
662
+ file: "file";
663
+ session: "session";
664
+ note: "note";
665
+ commit: "commit";
666
+ proc: "proc";
667
+ guard: "guard";
668
+ }>;
669
+ what: import("zod").ZodString;
670
+ command: import("zod").ZodOptional<import("zod").ZodString>;
671
+ parent: import("zod").ZodOptional<import("zod").ZodString>;
672
+ action: import("zod").ZodOptional<import("zod").ZodString>;
673
+ folder: import("zod").ZodOptional<import("zod").ZodString>;
674
+ project: import("zod").ZodOptional<import("zod").ZodString>;
675
+ session: import("zod").ZodOptional<import("zod").ZodString>;
676
+ agent: import("zod").ZodOptional<import("zod").ZodString>;
677
+ linked: import("zod").ZodOptional<import("zod").ZodEnum<{
678
+ process: "process";
679
+ "only-session": "only-session";
680
+ }>>;
681
+ count: import("zod").ZodNumber;
682
+ sha: import("zod").ZodOptional<import("zod").ZodString>;
683
+ author: import("zod").ZodOptional<import("zod").ZodString>;
684
+ }, import("zod/v4/core").$strip>>;
685
+ totals: import("zod").ZodObject<{
686
+ commands: import("zod").ZodNumber;
687
+ files: import("zod").ZodNumber;
688
+ commits: import("zod").ZodNumber;
689
+ events: import("zod").ZodNumber;
690
+ sessions: import("zod").ZodNumber;
691
+ }, import("zod/v4/core").$strip>;
692
+ agents: import("zod").ZodArray<import("zod").ZodObject<{
693
+ commands: import("zod").ZodNumber;
694
+ files: import("zod").ZodNumber;
695
+ commits: import("zod").ZodNumber;
696
+ agent: import("zod").ZodString;
697
+ sessions: import("zod").ZodNumber;
698
+ }, import("zod/v4/core").$strip>>;
699
+ sessions: import("zod").ZodArray<import("zod").ZodObject<{
700
+ commands: import("zod").ZodNumber;
701
+ files: import("zod").ZodNumber;
702
+ commits: import("zod").ZodNumber;
703
+ id: import("zod").ZodString;
704
+ agent: import("zod").ZodString;
705
+ project: import("zod").ZodString;
706
+ started: import("zod").ZodString;
707
+ ended: import("zod").ZodOptional<import("zod").ZodString>;
708
+ last: import("zod").ZodOptional<import("zod").ZodString>;
709
+ }, import("zod/v4/core").$strip>>;
710
+ unlinked: import("zod").ZodObject<{
711
+ commands: import("zod").ZodNumber;
712
+ files: import("zod").ZodNumber;
713
+ commits: import("zod").ZodNumber;
714
+ }, import("zod/v4/core").$strip>;
715
+ }, import("zod/v4/core").$strip>, "audit.list">, QueryDef<import("zod").ZodObject<{}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
620
716
  managed: import("zod").ZodBoolean;
621
717
  version: import("zod").ZodString;
622
718
  scope: import("zod").ZodNullable<import("zod").ZodEnum<{
@@ -932,6 +1028,8 @@ export declare const VIEWS: readonly [import("../kernel/define.js").ViewDef<{
932
1028
  cli: import("zod").ZodBoolean;
933
1029
  mesa: import("zod").ZodBoolean;
934
1030
  fullGitOnly: import("zod").ZodBoolean;
1031
+ plugsInto: import("zod").ZodOptional<import("zod").ZodString>;
1032
+ service: import("zod").ZodOptional<import("zod").ZodBoolean>;
935
1033
  setting: import("zod").ZodOptional<import("zod").ZodString>;
936
1034
  settingField: import("zod").ZodOptional<import("zod").ZodType<import("../kernel/fields.js").Field, unknown, import("zod/v4/core").$ZodTypeInternals<import("../kernel/fields.js").Field, unknown>>>;
937
1035
  settingValue: import("zod").ZodOptional<import("zod").ZodUnknown>;
@@ -1114,6 +1212,101 @@ export declare const VIEWS: readonly [import("../kernel/define.js").ViewDef<{
1114
1212
  next: import("zod").ZodNumber;
1115
1213
  }, import("zod/v4/core").$strip>, "logs.tail">;
1116
1214
  }, import("./logs/logs.def.js").LogsParams, "logs">, import("../kernel/define.js").ViewDef<{
1215
+ audit: QueryDef<import("zod").ZodObject<{
1216
+ days: import("zod").ZodDefault<import("zod").ZodNumber>;
1217
+ kind: import("zod").ZodDefault<import("zod").ZodEnum<{
1218
+ file: "file";
1219
+ all: "all";
1220
+ session: "session";
1221
+ commit: "commit";
1222
+ proc: "proc";
1223
+ guard: "guard";
1224
+ }>>;
1225
+ session: import("zod").ZodOptional<import("zod").ZodString>;
1226
+ agent: import("zod").ZodOptional<import("zod").ZodString>;
1227
+ project: import("zod").ZodOptional<import("zod").ZodString>;
1228
+ grep: import("zod").ZodOptional<import("zod").ZodString>;
1229
+ limit: import("zod").ZodDefault<import("zod").ZodNumber>;
1230
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
1231
+ enabled: import("zod").ZodBoolean;
1232
+ keepDays: import("zod").ZodNumber;
1233
+ maxMb: import("zod").ZodNumber;
1234
+ bytes: import("zod").ZodNumber;
1235
+ folder: import("zod").ZodString;
1236
+ filter: import("zod").ZodObject<{
1237
+ days: import("zod").ZodNumber;
1238
+ kind: import("zod").ZodEnum<{
1239
+ file: "file";
1240
+ all: "all";
1241
+ session: "session";
1242
+ commit: "commit";
1243
+ proc: "proc";
1244
+ guard: "guard";
1245
+ }>;
1246
+ session: import("zod").ZodOptional<import("zod").ZodString>;
1247
+ agent: import("zod").ZodOptional<import("zod").ZodString>;
1248
+ project: import("zod").ZodOptional<import("zod").ZodString>;
1249
+ grep: import("zod").ZodOptional<import("zod").ZodString>;
1250
+ }, import("zod/v4/core").$strip>;
1251
+ matched: import("zod").ZodNumber;
1252
+ events: import("zod").ZodArray<import("zod").ZodObject<{
1253
+ time: import("zod").ZodString;
1254
+ kind: import("zod").ZodEnum<{
1255
+ file: "file";
1256
+ session: "session";
1257
+ note: "note";
1258
+ commit: "commit";
1259
+ proc: "proc";
1260
+ guard: "guard";
1261
+ }>;
1262
+ what: import("zod").ZodString;
1263
+ command: import("zod").ZodOptional<import("zod").ZodString>;
1264
+ parent: import("zod").ZodOptional<import("zod").ZodString>;
1265
+ action: import("zod").ZodOptional<import("zod").ZodString>;
1266
+ folder: import("zod").ZodOptional<import("zod").ZodString>;
1267
+ project: import("zod").ZodOptional<import("zod").ZodString>;
1268
+ session: import("zod").ZodOptional<import("zod").ZodString>;
1269
+ agent: import("zod").ZodOptional<import("zod").ZodString>;
1270
+ linked: import("zod").ZodOptional<import("zod").ZodEnum<{
1271
+ process: "process";
1272
+ "only-session": "only-session";
1273
+ }>>;
1274
+ count: import("zod").ZodNumber;
1275
+ sha: import("zod").ZodOptional<import("zod").ZodString>;
1276
+ author: import("zod").ZodOptional<import("zod").ZodString>;
1277
+ }, import("zod/v4/core").$strip>>;
1278
+ totals: import("zod").ZodObject<{
1279
+ commands: import("zod").ZodNumber;
1280
+ files: import("zod").ZodNumber;
1281
+ commits: import("zod").ZodNumber;
1282
+ events: import("zod").ZodNumber;
1283
+ sessions: import("zod").ZodNumber;
1284
+ }, import("zod/v4/core").$strip>;
1285
+ agents: import("zod").ZodArray<import("zod").ZodObject<{
1286
+ commands: import("zod").ZodNumber;
1287
+ files: import("zod").ZodNumber;
1288
+ commits: import("zod").ZodNumber;
1289
+ agent: import("zod").ZodString;
1290
+ sessions: import("zod").ZodNumber;
1291
+ }, import("zod/v4/core").$strip>>;
1292
+ sessions: import("zod").ZodArray<import("zod").ZodObject<{
1293
+ commands: import("zod").ZodNumber;
1294
+ files: import("zod").ZodNumber;
1295
+ commits: import("zod").ZodNumber;
1296
+ id: import("zod").ZodString;
1297
+ agent: import("zod").ZodString;
1298
+ project: import("zod").ZodString;
1299
+ started: import("zod").ZodString;
1300
+ ended: import("zod").ZodOptional<import("zod").ZodString>;
1301
+ last: import("zod").ZodOptional<import("zod").ZodString>;
1302
+ }, import("zod/v4/core").$strip>>;
1303
+ unlinked: import("zod").ZodObject<{
1304
+ commands: import("zod").ZodNumber;
1305
+ files: import("zod").ZodNumber;
1306
+ commits: import("zod").ZodNumber;
1307
+ }, import("zod/v4/core").$strip>;
1308
+ }, import("zod/v4/core").$strip>, "audit.list">;
1309
+ }, import("./audit/audit.def.js").AuditParams, "audit">, import("../kernel/define.js").ViewDef<{
1117
1310
  status: QueryDef<import("zod").ZodObject<{}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
1118
1311
  managed: import("zod").ZodBoolean;
1119
1312
  version: import("zod").ZodString;
@@ -9,6 +9,7 @@ import { changeDataFolder, containedOff, containedOn, containedStatus, moveStora
9
9
  import { hideWindow, sandboxStatus, sandboxView, showWindow, stopSandbox } from './sandbox/sandbox.def.js';
10
10
  import { addProject, allProjects, chooseProjects, excludeProject, includeProject, listProjects, projectRoots, projectsView, removeProject, } from './projects/projects.def.js';
11
11
  import { listLogs, logsView, tailLog } from './logs/logs.def.js';
12
+ import { auditView, listAudit } from './audit/audit.def.js';
12
13
  import { listSessions, restartSessions, sessionsView } from './sessions/sessions.def.js';
13
14
  import { vpnLogin, vpnLogout, vpnStatus, vpnView } from './vpn/vpn.def.js';
14
15
  import { githubLogin, githubLogout, githubStatus, githubView } from './github/github.def.js';
@@ -80,6 +81,7 @@ export const QUERIES = [
80
81
  containedStatus,
81
82
  listLogs,
82
83
  tailLog,
84
+ listAudit,
83
85
  updatesStatus,
84
86
  engineStatus,
85
87
  checkEngine,
@@ -100,6 +102,7 @@ export const VIEWS = [
100
102
  dataView,
101
103
  storageView,
102
104
  logsView,
105
+ auditView,
103
106
  updatesView,
104
107
  engineView,
105
108
  webView,
@@ -134,6 +137,7 @@ export function embeddingOf(nav, view) {
134
137
  export const NAV = [
135
138
  { label: 'Agents', view: 'agents' },
136
139
  { label: 'Sessions', view: 'sessions' },
140
+ { label: 'Activity', view: 'audit' },
137
141
  {
138
142
  label: 'Sandbox',
139
143
  children: [
@@ -45,6 +45,9 @@ export declare const getSettingRun: import("../../kernel/define.js").Implementat
45
45
  key: import("zod").ZodString;
46
46
  value: import("zod").ZodUnknown;
47
47
  }, import("zod/v4/core").$strip>, "settings.get">, import("../../../cli/commands/context.js").Context>;
48
+ /** The file of a scope, and the setting a key names in it. */
49
+ /** incoming with every *** that stands where saved has a text replaced by that saved text. Pure. */
50
+ export declare function keepShownSecrets(saved: unknown, incoming: unknown): unknown;
48
51
  export declare const setSettingRun: import("../../kernel/define.js").Implementation<import("../../kernel/define.js").OperationDef<import("zod").ZodObject<{
49
52
  scope: import("zod").ZodDefault<import("zod").ZodEnum<{
50
53
  project: "project";
@@ -4,7 +4,7 @@ import fs from 'node:fs';
4
4
  import path from 'node:path';
5
5
  import _ from 'lodash';
6
6
  import { loadConfig } from '../../../core/config/index.js';
7
- import { redactSecrets } from '../../../core/schema/index.js';
7
+ import { REDACTED, redactSecrets } from '../../../core/schema/index.js';
8
8
  import { fail, safeText, writeJson } from '../../../core/util/index.js';
9
9
  import { hereDir } from '../../../cli/commands/projects/here.js';
10
10
  import { implement } from '../../context.js';
@@ -50,6 +50,18 @@ export const getSettingRun = implement(getSetting, (ctx, input) => {
50
50
  return { key: input.key, value: _.get(redactSecrets(file.userConfig()), key) };
51
51
  });
52
52
  /** The file of a scope, and the setting a key names in it. */
53
+ /** incoming with every *** that stands where saved has a text replaced by that saved text. Pure. */
54
+ export function keepShownSecrets(saved, incoming) {
55
+ if (incoming === REDACTED)
56
+ return typeof saved === 'string' ? saved : incoming;
57
+ if (Array.isArray(incoming))
58
+ return incoming.map((v, i) => keepShownSecrets(Array.isArray(saved) ? saved[i] : undefined, v));
59
+ if (incoming && typeof incoming === 'object') {
60
+ const from = saved && typeof saved === 'object' && !Array.isArray(saved) ? saved : {};
61
+ return Object.fromEntries(Object.entries(incoming).map(([k, v]) => [k, keepShownSecrets(from[k], v)]));
62
+ }
63
+ return incoming;
64
+ }
53
65
  function target(ctx, scope, name) {
54
66
  const file = settingsFiles(ctx)[scope];
55
67
  return { ...findSetting(file, name), file };
@@ -58,7 +70,9 @@ export const setSettingRun = implement(setSetting, (ctx, input) => {
58
70
  const { key, node, file } = target(ctx, input.scope, input.key);
59
71
  if (node.isSection)
60
72
  fail('"' + input.key + '" is a group of settings.', 'Set one of them, e.g. ' + node.leaves(key)[0]?.key.join('.'));
61
- const value = valueFor(node, input.value);
73
+ // A value that comes back with *** where a secret was shown (the web edits a whole map of secrets) keeps what is
74
+ // saved there: *** is how secrets are shown, never a value to save.
75
+ const value = keepShownSecrets(file.valueInFile(key), valueFor(node, input.value));
62
76
  const problem = node.check(value);
63
77
  if (problem !== true) {
64
78
  const typed = typeof input.value === 'string' ? input.value : JSON.stringify(masked(key, input.value));
@@ -103,6 +103,15 @@ export interface ViewTabs<P> {
103
103
  readonly label: string;
104
104
  }[];
105
105
  }
106
+ /**
107
+ * A filter of a view: one parameter picked from fixed values (the audit's kind and period). The web shows a small
108
+ * choice per filter above the page (changing one keeps the view's other parameters); the command line has the query's
109
+ * flags for the same thing, and the menu shows the first value. The first value is the default.
110
+ */
111
+ export interface ViewFilter<P> extends ViewTabs<P> {
112
+ /** What the choice is about ("Period"), for its label. */
113
+ readonly label: string;
114
+ }
106
115
  export interface ViewDef<Q extends QueryMap = QueryMap, P = Record<string, never>, Id extends string = string> {
107
116
  readonly kind: 'view';
108
117
  readonly id: Id;
@@ -115,7 +124,9 @@ export interface ViewDef<Q extends QueryMap = QueryMap, P = Record<string, never
115
124
  readonly pickers?: readonly QueryDef[];
116
125
  /** A parameter switched with tabs above the page (Settings: all projects or this project), first choice default. */
117
126
  readonly tabs?: ViewTabs<P>;
118
- /** Parameters taken from the address as they are (the log shown), besides the tabs' one. */
127
+ /** Parameters picked from fixed values above the page (the audit's kind and period), first value default. */
128
+ readonly filters?: readonly ViewFilter<P>[];
129
+ /** Parameters taken from the address as they are (the log shown), besides the tabs' and filters' ones. */
119
130
  readonly params?: readonly (keyof P & string)[];
120
131
  /** The input of each query for these view parameters (default: each query's defaults). */
121
132
  inputs?(params: P): ViewInputs<Q>;
@@ -9,6 +9,7 @@ import { addProjectRun, allProjectsRun, chooseProjectsRun, excludeProjectRun, in
9
9
  import { checkHealthRun, enableSandboxRun, lastHealthRun, repairHealthRun } from './features/health/index.js';
10
10
  import { hideWindowRun, sandboxStatusRun, showWindowRun, stopSandboxRun } from './features/sandbox/index.js';
11
11
  import { listLogsRun, tailLogRun } from './features/logs/index.js';
12
+ import { listAuditRun } from './features/audit/index.js';
12
13
  import { listSessionsRun, restartSessionsRun } from './features/sessions/index.js';
13
14
  import { exportConfigRun, getSettingRun, importConfigRun, listSettingsRun, resetSettingRun, setSettingRun, } from './features/settings/index.js';
14
15
  import { migrateSettingsRun, runUpdateRun, updatesStatusRun } from './features/updates/index.js';
@@ -69,6 +70,7 @@ export const IMPLEMENTATIONS = [
69
70
  containedOffRun,
70
71
  listLogsRun,
71
72
  tailLogRun,
73
+ listAuditRun,
72
74
  runUpdateRun,
73
75
  migrateSettingsRun,
74
76
  updatesStatusRun,
@@ -42,9 +42,6 @@ export interface CliOptions {
42
42
  all: boolean;
43
43
  /** launch --session <agent>@<folder> (repeatable): several sessions at once, folders made absolute. */
44
44
  sessions: SessionWant[];
45
- /** audit: only events of this kind, and containing this text. */
46
- kind?: string;
47
- grep?: string;
48
45
  /** migrate --dry-run, and --restore <backup folder>. */
49
46
  dryRun: boolean;
50
47
  /** doctor --fix: repair what it finds without asking. */
package/dist/cli/args.js CHANGED
@@ -217,11 +217,10 @@ export function parseCli(argv, wrapper = false) {
217
217
  keepOld: Boolean(o.keepOld),
218
218
  withPaths: Boolean(o.withPaths),
219
219
  all: Boolean(o.all),
220
- sessions: (o.session ?? []).map((s) => parseSessionWant(s)),
220
+ // launch --session is repeatable (a list); `audit --session <id>` is one id, which its definition reads.
221
+ sessions: (Array.isArray(o.session) ? o.session : []).map((s) => parseSessionWant(s)),
221
222
  timeout: o.timeout ?? 600,
222
- days: o.days ?? (name === 'audit' ? 1 : 7),
223
- kind: o.kind,
224
- grep: o.grep,
223
+ days: o.days ?? 7,
225
224
  dryRun: Boolean(o.dryRun),
226
225
  fix: Boolean(o.fix),
227
226
  auto: o.auto === true,
@@ -6,6 +6,6 @@ export { repairCommand } from './repair/index.js';
6
6
  export { contextOrDefaults } from './context.js';
7
7
  export { attach, db, exec } from './sessions/index.js';
8
8
  export { resume } from './resume.js';
9
- export { audit, claudeHost, config, doctor, hostCommand, logs, migrateBeforeCommand, sync, updatesBeforeCommand, watcher, } from './maintenance/index.js';
9
+ export { claudeHost, config, doctor, hostCommand, logs, migrateBeforeCommand, sync, updatesBeforeCommand, watcher, } from './maintenance/index.js';
10
10
  export { agentCommandsCommand, syncAgentCommands } from './agent-commands.js';
11
11
  export { HANDLERS, type Handler } from './registry.js';
@@ -6,6 +6,6 @@ export { repairCommand } from './repair/index.js';
6
6
  export { contextOrDefaults } from './context.js';
7
7
  export { attach, db, exec } from './sessions/index.js';
8
8
  export { resume } from './resume.js';
9
- export { audit, claudeHost, config, doctor, hostCommand, logs, migrateBeforeCommand, sync, updatesBeforeCommand, watcher, } from './maintenance/index.js';
9
+ export { claudeHost, config, doctor, hostCommand, logs, migrateBeforeCommand, sync, updatesBeforeCommand, watcher, } from './maintenance/index.js';
10
10
  export { agentCommandsCommand, syncAgentCommands } from './agent-commands.js';
11
11
  export { HANDLERS } from './registry.js';
@@ -7,7 +7,7 @@ import { RepoGuardStore, readDataSize, saveMarkedProjects } from '../../../host/
7
7
  import { ensureConpty, ensureTerminal } from '../../../host/tools/index.js';
8
8
  import { planView, viewSkipped, saveActiveViews, WorkspaceView } from '../../../host/workspace-view/index.js';
9
9
  import { saveForwards } from '../../../host/network/index.js';
10
- import { saveAuditSettings } from '../../../host/audit/collect.js';
10
+ import { saveAuditSettings } from '../../../host/audit/index.js';
11
11
  import { humanBytes } from '../../../core/disk.js';
12
12
  import { syncBeforeLaunch, watcherRunning } from '../../../sync/index.js';
13
13
  import { errMsg } from '../../../core/util/index.js';
@@ -4,6 +4,5 @@ export * from './config.js';
4
4
  export * from './doctor.js';
5
5
  export * from './host-claude.js';
6
6
  export * from './watch.js';
7
- export * from './audit.js';
8
7
  export * from './migrate.js';
9
8
  export * from './update.js';
@@ -5,6 +5,5 @@ export * from './config.js';
5
5
  export * from './doctor.js';
6
6
  export * from './host-claude.js';
7
7
  export * from './watch.js';
8
- export * from './audit.js';
9
8
  export * from './migrate.js';
10
9
  export * from './update.js';
@@ -8,7 +8,7 @@ import { containedStatus, showStorage } from '../../app/features/storage/index.j
8
8
  import { listProjects } from '../../app/features/projects/index.js';
9
9
  import { definitionHandler } from '../operations/index.js';
10
10
  import { fail } from '../../core/util/index.js';
11
- import { audit, claudeHost, config, doctor, hostCommand, logs, sync, watcher } from './maintenance/index.js';
11
+ import { claudeHost, config, doctor, hostCommand, logs, sync, watcher } from './maintenance/index.js';
12
12
  import { engine } from './engine.js';
13
13
  import { resume } from './resume.js';
14
14
  import { agentCommandsCommand } from './agent-commands.js';
@@ -29,7 +29,6 @@ export const HANDLERS = {
29
29
  projects: definitionHandler(listProjects),
30
30
  sync: sync,
31
31
  logs: logs,
32
- audit: audit,
33
32
  config: config,
34
33
  doctor: doctor,
35
34
  setup: setup,
@@ -499,47 +499,6 @@ declare const COMMAND_LIST: readonly [{
499
499
  readonly group: "Data";
500
500
  readonly args: readonly [];
501
501
  readonly options: readonly [];
502
- }, {
503
- readonly name: "audit";
504
- readonly summary: "what happened in your sandboxes: programs started, files changed, sessions, repo guard (turn it on: sandbox config set audit.enabled true)";
505
- readonly group: "Health";
506
- readonly json: true;
507
- readonly args: readonly [];
508
- readonly options: readonly [{
509
- readonly flag: "--days";
510
- readonly type: "number";
511
- readonly value: "n";
512
- readonly description: "the last n days (default: today)";
513
- readonly default: 1;
514
- }, {
515
- flag: string;
516
- type: "string" | "number" | "boolean" | "list";
517
- description: string;
518
- short?: string | undefined;
519
- value?: string | undefined;
520
- label?: string | undefined;
521
- default?: string | number | undefined;
522
- choices?: string[] | "harnesses" | "sessions" | "accounts" | undefined;
523
- advanced?: boolean | undefined;
524
- when?: string | undefined;
525
- noMenu?: boolean | undefined;
526
- group?: string | undefined;
527
- shownAs?: string | undefined;
528
- }, {
529
- flag: string;
530
- type: "string" | "number" | "boolean" | "list";
531
- description: string;
532
- short?: string | undefined;
533
- value?: string | undefined;
534
- label?: string | undefined;
535
- default?: string | number | undefined;
536
- choices?: string[] | "harnesses" | "sessions" | "accounts" | undefined;
537
- advanced?: boolean | undefined;
538
- when?: string | undefined;
539
- noMenu?: boolean | undefined;
540
- group?: string | undefined;
541
- shownAs?: string | undefined;
542
- }];
543
502
  }, {
544
503
  readonly name: "logs";
545
504
  readonly summary: "print the newest sandbox log";