@namzu/cli 11.0.0 → 12.0.1

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 (134) hide show
  1. package/README.md +390 -46
  2. package/dist/cli.d.ts +15 -0
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +132 -4
  5. package/dist/cli.js.map +1 -1
  6. package/dist/commands/acp.d.ts +29 -0
  7. package/dist/commands/acp.d.ts.map +1 -0
  8. package/dist/commands/acp.js +156 -0
  9. package/dist/commands/acp.js.map +1 -0
  10. package/dist/commands/doctor.d.ts +12 -1
  11. package/dist/commands/doctor.d.ts.map +1 -1
  12. package/dist/commands/doctor.js +18 -2
  13. package/dist/commands/doctor.js.map +1 -1
  14. package/dist/commands/drain.d.ts +2 -2
  15. package/dist/commands/drain.d.ts.map +1 -1
  16. package/dist/commands/drain.js +31 -8
  17. package/dist/commands/drain.js.map +1 -1
  18. package/dist/commands/run-flags.d.ts.map +1 -1
  19. package/dist/commands/run-flags.js +33 -0
  20. package/dist/commands/run-flags.js.map +1 -1
  21. package/dist/commands/run-stream.d.ts +3 -3
  22. package/dist/commands/run-stream.d.ts.map +1 -1
  23. package/dist/commands/run-stream.js +27 -10
  24. package/dist/commands/run-stream.js.map +1 -1
  25. package/dist/commands/run.d.ts.map +1 -1
  26. package/dist/commands/run.js +50 -4
  27. package/dist/commands/run.js.map +1 -1
  28. package/dist/commands/types.d.ts +10 -0
  29. package/dist/commands/types.d.ts.map +1 -1
  30. package/dist/config/load.d.ts +64 -0
  31. package/dist/config/load.d.ts.map +1 -1
  32. package/dist/config/load.js +137 -20
  33. package/dist/config/load.js.map +1 -1
  34. package/dist/config/schema.d.ts +51 -0
  35. package/dist/config/schema.d.ts.map +1 -1
  36. package/dist/config/schema.js.map +1 -1
  37. package/dist/context/capabilities.d.ts +88 -0
  38. package/dist/context/capabilities.d.ts.map +1 -0
  39. package/dist/context/capabilities.js +160 -0
  40. package/dist/context/capabilities.js.map +1 -0
  41. package/dist/context/sandbox.d.ts +13 -0
  42. package/dist/context/sandbox.d.ts.map +1 -1
  43. package/dist/context/sandbox.js +15 -0
  44. package/dist/context/sandbox.js.map +1 -1
  45. package/dist/doctor/checks/index.d.ts +6 -1
  46. package/dist/doctor/checks/index.d.ts.map +1 -1
  47. package/dist/doctor/checks/index.js +45 -2
  48. package/dist/doctor/checks/index.js.map +1 -1
  49. package/dist/doctor/checks/invariants.d.ts +23 -0
  50. package/dist/doctor/checks/invariants.d.ts.map +1 -0
  51. package/dist/doctor/checks/invariants.js +79 -0
  52. package/dist/doctor/checks/invariants.js.map +1 -0
  53. package/dist/doctor/checks/logging.d.ts +10 -0
  54. package/dist/doctor/checks/logging.d.ts.map +1 -0
  55. package/dist/doctor/checks/logging.js +69 -0
  56. package/dist/doctor/checks/logging.js.map +1 -0
  57. package/dist/doctor/checks/session-export.d.ts +21 -0
  58. package/dist/doctor/checks/session-export.d.ts.map +1 -0
  59. package/dist/doctor/checks/session-export.js +62 -0
  60. package/dist/doctor/checks/session-export.js.map +1 -0
  61. package/dist/doctor/checks/telemetry.d.ts +15 -28
  62. package/dist/doctor/checks/telemetry.d.ts.map +1 -1
  63. package/dist/doctor/checks/telemetry.js +34 -54
  64. package/dist/doctor/checks/telemetry.js.map +1 -1
  65. package/dist/doctor/checks/vault.d.ts +4 -20
  66. package/dist/doctor/checks/vault.d.ts.map +1 -1
  67. package/dist/doctor/checks/vault.js +58 -19
  68. package/dist/doctor/checks/vault.js.map +1 -1
  69. package/dist/doctor/registry.d.ts.map +1 -1
  70. package/dist/doctor/registry.js +13 -6
  71. package/dist/doctor/registry.js.map +1 -1
  72. package/dist/index.d.ts +3 -2
  73. package/dist/index.d.ts.map +1 -1
  74. package/dist/index.js +3 -2
  75. package/dist/index.js.map +1 -1
  76. package/dist/integrations/files/attachment-store.d.ts +44 -0
  77. package/dist/integrations/files/attachment-store.d.ts.map +1 -0
  78. package/dist/integrations/files/attachment-store.js +86 -0
  79. package/dist/integrations/files/attachment-store.js.map +1 -0
  80. package/dist/integrations/providers/credential-provider.d.ts +39 -0
  81. package/dist/integrations/providers/credential-provider.d.ts.map +1 -0
  82. package/dist/integrations/providers/credential-provider.js +74 -0
  83. package/dist/integrations/providers/credential-provider.js.map +1 -0
  84. package/dist/integrations/providers/discover.d.ts.map +1 -1
  85. package/dist/integrations/providers/discover.js +15 -3
  86. package/dist/integrations/providers/discover.js.map +1 -1
  87. package/dist/integrations/providers/oauth.d.ts.map +1 -1
  88. package/dist/integrations/providers/oauth.js +24 -1
  89. package/dist/integrations/providers/oauth.js.map +1 -1
  90. package/dist/integrations/sessions/store.d.ts +2 -2
  91. package/dist/integrations/sessions/store.d.ts.map +1 -1
  92. package/dist/integrations/sessions/store.js +21 -9
  93. package/dist/integrations/sessions/store.js.map +1 -1
  94. package/dist/integrations/subagents/runtime.d.ts +3 -3
  95. package/dist/integrations/subagents/runtime.d.ts.map +1 -1
  96. package/dist/integrations/subagents/runtime.js +12 -12
  97. package/dist/integrations/subagents/runtime.js.map +1 -1
  98. package/dist/integrations/telemetry/session-export.d.ts +99 -0
  99. package/dist/integrations/telemetry/session-export.d.ts.map +1 -0
  100. package/dist/integrations/telemetry/session-export.js +119 -0
  101. package/dist/integrations/telemetry/session-export.js.map +1 -0
  102. package/dist/logging.d.ts +79 -0
  103. package/dist/logging.d.ts.map +1 -0
  104. package/dist/logging.js +67 -0
  105. package/dist/logging.js.map +1 -0
  106. package/dist/permissions/rules.d.ts +3 -3
  107. package/dist/permissions/rules.d.ts.map +1 -1
  108. package/dist/permissions/rules.js +1 -1
  109. package/dist/permissions/rules.js.map +1 -1
  110. package/dist/skills/store.d.ts +1 -1
  111. package/dist/skills/store.js +1 -1
  112. package/dist/tui/App.d.ts.map +1 -1
  113. package/dist/tui/App.js +92 -6
  114. package/dist/tui/App.js.map +1 -1
  115. package/dist/tui/StatusBar.d.ts +1 -1
  116. package/dist/tui/StatusBar.d.ts.map +1 -1
  117. package/dist/tui/agent.d.ts +54 -24
  118. package/dist/tui/agent.d.ts.map +1 -1
  119. package/dist/tui/agent.js +330 -127
  120. package/dist/tui/agent.js.map +1 -1
  121. package/dist/tui/index.d.ts.map +1 -1
  122. package/dist/tui/index.js +17 -6
  123. package/dist/tui/index.js.map +1 -1
  124. package/dist/tui/log-pane.d.ts +48 -0
  125. package/dist/tui/log-pane.d.ts.map +1 -0
  126. package/dist/tui/log-pane.js +106 -0
  127. package/dist/tui/log-pane.js.map +1 -0
  128. package/dist/tui/slashCommands.d.ts +134 -11
  129. package/dist/tui/slashCommands.d.ts.map +1 -1
  130. package/dist/tui/slashCommands.js +169 -15
  131. package/dist/tui/slashCommands.js.map +1 -1
  132. package/dist/tui/types.d.ts +11 -2
  133. package/dist/tui/types.d.ts.map +1 -1
  134. package/package.json +8 -6
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Log level + format resolution for the CLI's five entry points that used
3
+ * to force the SDK logger's level to `silent` via `configureLogger` and
4
+ * never turn it back on: `tui/index.tsx`, `commands/run.ts`,
5
+ * `commands/drain.ts` and `commands/run-stream.ts` (twice — `run-stream`
6
+ * itself and `providers-json`). LOG-05.
7
+ *
8
+ * Kept out of `config/load.ts`'s cascade on purpose. That system merges
9
+ * four sources for `format`/`quiet`/`permissions`/`sandbox`, all of them
10
+ * either boolean or a closed enum with a config-file counterpart.
11
+ * `NAMZU_LOG_LEVEL` has no config-file counterpart in this increment and is
12
+ * not boolean-shaped — it names a level directly, string-valued, the same
13
+ * way `--verbose`/`--quiet` do. Precedence here is exactly what the design
14
+ * specifies and nothing more: an explicit flag beats the environment beats
15
+ * the default that used to be silence.
16
+ */
17
+ import type { LevelFilter, LogSink } from '@namzu/sdk';
18
+ export type LogFormat = 'pretty' | 'json';
19
+ /** What every entry point installs as its process sink, resolved once per
20
+ * invocation in `cli.ts#getContext()` and threaded through
21
+ * `CommandContext`/`TuiContext`. */
22
+ export interface ResolvedLogging {
23
+ readonly level: LevelFilter;
24
+ readonly format: LogFormat;
25
+ }
26
+ export interface LogLevelFlags {
27
+ /** `-v, --verbose` as Commander parsed it — `undefined` unless given. */
28
+ readonly verbose?: boolean;
29
+ /**
30
+ * `-q, --quiet` as Commander parsed it — `undefined` unless given.
31
+ * Reuses the CLI's existing global flag rather than minting a second
32
+ * "quiet" that means something different depending which one you typed.
33
+ */
34
+ readonly quiet?: boolean;
35
+ }
36
+ /**
37
+ * `--verbose` -> `debug`, `--quiet` -> `warn`, otherwise `NAMZU_LOG_LEVEL`
38
+ * if it names a real level, otherwise `info` — the floor that used to be
39
+ * silence.
40
+ *
41
+ * `cli.ts` declares `--verbose` and `--quiet` as a `.conflicts()`-paired
42
+ * pair of Commander options, so through the CLI itself at most one of
43
+ * `flags.verbose` / `flags.quiet` is ever true at once. The `verbose`-first
44
+ * check below is what a caller that builds `LogLevelFlags` by hand — every
45
+ * test in `logging.test.ts` — gets instead of relying on that invariant.
46
+ */
47
+ export declare function resolveLogLevel(flags: LogLevelFlags, env?: NodeJS.ProcessEnv): LevelFilter;
48
+ export interface LogFormatFlags {
49
+ /**
50
+ * `--log-format <pretty|json>`. Commander's `.choices(['pretty','json'])`
51
+ * already rejects anything else at parse time, so `undefined` is the
52
+ * only other value `cli.ts` can hand this. Re-checked below anyway
53
+ * because a caller building this by hand (every test in
54
+ * `logging.test.ts`) is not bound by what Commander would have refused.
55
+ */
56
+ readonly logFormat?: string;
57
+ }
58
+ export declare function resolveLogFormat(flags: LogFormatFlags, env?: NodeJS.ProcessEnv): LogFormat;
59
+ /**
60
+ * The sink `run`/`drain` install, chosen by `--log-format`/
61
+ * `NAMZU_LOG_FORMAT`. `run-stream` does NOT use this — its stderr is a
62
+ * machine-read NDJSON channel regardless of the format flag, the same way
63
+ * its stdout protocol is unaffected by anything the operator passes. See
64
+ * `commands/run-stream.ts`.
65
+ */
66
+ export declare function createStderrSink(format: LogFormat): LogSink;
67
+ /**
68
+ * Falls back to the same resolution `cli.ts#getContext()` would have
69
+ * produced with no flags and the live environment, for a `ctx`/`TuiContext`
70
+ * a test built by hand without a `logging` field — a fixture omitting a
71
+ * field it does not care about must not crash the handler it exercises.
72
+ * Every production `ctx` carries `logging`; only a test double hits the
73
+ * fallback, and `test-setup.ts` defaults `NAMZU_LOG_LEVEL` to `silent` so
74
+ * that fallback stays quiet unless a test deliberately overrides it.
75
+ */
76
+ export declare function contextLogging(ctx: {
77
+ readonly logging?: ResolvedLogging;
78
+ }): ResolvedLogging;
79
+ //# sourceMappingURL=logging.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../src/logging.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAGtD,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAA;AAEzC;;qCAEqC;AACrC,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAA;IAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAA;CAC1B;AAQD,MAAM,WAAW,aAAa;IAC7B,yEAAyE;IACzE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CACxB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC9B,KAAK,EAAE,aAAa,EACpB,GAAG,GAAE,MAAM,CAAC,UAAwB,GAClC,WAAW,CAIb;AAED,MAAM,WAAW,cAAc;IAC9B;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,wBAAgB,gBAAgB,CAC/B,KAAK,EAAE,cAAc,EACrB,GAAG,GAAE,MAAM,CAAC,UAAwB,GAClC,SAAS,CAGX;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAE3D;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE;IAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,CAAA;CAAE,GAAG,eAAe,CAE3F"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Log level + format resolution for the CLI's five entry points that used
3
+ * to force the SDK logger's level to `silent` via `configureLogger` and
4
+ * never turn it back on: `tui/index.tsx`, `commands/run.ts`,
5
+ * `commands/drain.ts` and `commands/run-stream.ts` (twice — `run-stream`
6
+ * itself and `providers-json`). LOG-05.
7
+ *
8
+ * Kept out of `config/load.ts`'s cascade on purpose. That system merges
9
+ * four sources for `format`/`quiet`/`permissions`/`sandbox`, all of them
10
+ * either boolean or a closed enum with a config-file counterpart.
11
+ * `NAMZU_LOG_LEVEL` has no config-file counterpart in this increment and is
12
+ * not boolean-shaped — it names a level directly, string-valued, the same
13
+ * way `--verbose`/`--quiet` do. Precedence here is exactly what the design
14
+ * specifies and nothing more: an explicit flag beats the environment beats
15
+ * the default that used to be silence.
16
+ */
17
+ import { jsonLinesSink, prettySink } from '@namzu/sdk';
18
+ const LEVEL_FILTERS = new Set(['debug', 'info', 'warn', 'error', 'silent']);
19
+ function isLevelFilter(value) {
20
+ return value !== undefined && LEVEL_FILTERS.has(value);
21
+ }
22
+ /**
23
+ * `--verbose` -> `debug`, `--quiet` -> `warn`, otherwise `NAMZU_LOG_LEVEL`
24
+ * if it names a real level, otherwise `info` — the floor that used to be
25
+ * silence.
26
+ *
27
+ * `cli.ts` declares `--verbose` and `--quiet` as a `.conflicts()`-paired
28
+ * pair of Commander options, so through the CLI itself at most one of
29
+ * `flags.verbose` / `flags.quiet` is ever true at once. The `verbose`-first
30
+ * check below is what a caller that builds `LogLevelFlags` by hand — every
31
+ * test in `logging.test.ts` — gets instead of relying on that invariant.
32
+ */
33
+ export function resolveLogLevel(flags, env = process.env) {
34
+ if (flags.verbose)
35
+ return 'debug';
36
+ if (flags.quiet)
37
+ return 'warn';
38
+ return isLevelFilter(env.NAMZU_LOG_LEVEL) ? env.NAMZU_LOG_LEVEL : 'info';
39
+ }
40
+ export function resolveLogFormat(flags, env = process.env) {
41
+ if (flags.logFormat === 'pretty' || flags.logFormat === 'json')
42
+ return flags.logFormat;
43
+ return env.NAMZU_LOG_FORMAT === 'json' ? 'json' : 'pretty';
44
+ }
45
+ /**
46
+ * The sink `run`/`drain` install, chosen by `--log-format`/
47
+ * `NAMZU_LOG_FORMAT`. `run-stream` does NOT use this — its stderr is a
48
+ * machine-read NDJSON channel regardless of the format flag, the same way
49
+ * its stdout protocol is unaffected by anything the operator passes. See
50
+ * `commands/run-stream.ts`.
51
+ */
52
+ export function createStderrSink(format) {
53
+ return format === 'json' ? jsonLinesSink(process.stderr) : prettySink(process.stderr);
54
+ }
55
+ /**
56
+ * Falls back to the same resolution `cli.ts#getContext()` would have
57
+ * produced with no flags and the live environment, for a `ctx`/`TuiContext`
58
+ * a test built by hand without a `logging` field — a fixture omitting a
59
+ * field it does not care about must not crash the handler it exercises.
60
+ * Every production `ctx` carries `logging`; only a test double hits the
61
+ * fallback, and `test-setup.ts` defaults `NAMZU_LOG_LEVEL` to `silent` so
62
+ * that fallback stays quiet unless a test deliberately overrides it.
63
+ */
64
+ export function contextLogging(ctx) {
65
+ return ctx.logging ?? { level: resolveLogLevel({}), format: resolveLogFormat({}) };
66
+ }
67
+ //# sourceMappingURL=logging.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logging.js","sourceRoot":"","sources":["../src/logging.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAYtD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAA;AAEnF,SAAS,aAAa,CAAC,KAAyB;IAC/C,OAAO,KAAK,KAAK,SAAS,IAAI,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;AACvD,CAAC;AAaD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,eAAe,CAC9B,KAAoB,EACpB,MAAyB,OAAO,CAAC,GAAG;IAEpC,IAAI,KAAK,CAAC,OAAO;QAAE,OAAO,OAAO,CAAA;IACjC,IAAI,KAAK,CAAC,KAAK;QAAE,OAAO,MAAM,CAAA;IAC9B,OAAO,aAAa,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,CAAA;AACzE,CAAC;AAaD,MAAM,UAAU,gBAAgB,CAC/B,KAAqB,EACrB,MAAyB,OAAO,CAAC,GAAG;IAEpC,IAAI,KAAK,CAAC,SAAS,KAAK,QAAQ,IAAI,KAAK,CAAC,SAAS,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC,SAAS,CAAA;IACtF,OAAO,GAAG,CAAC,gBAAgB,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAA;AAC3D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAiB;IACjD,OAAO,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;AACtF,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,GAA2C;IACzE,OAAO,GAAG,CAAC,OAAO,IAAI,EAAE,KAAK,EAAE,eAAe,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,CAAC,EAAE,CAAA;AACnF,CAAC"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Operator-authored tool permissions, compiled to the kernel's rule vocabulary.
3
3
  *
4
- * The kernel already has the engine — `VerificationRule[]` with an
4
+ * The kernel already has the engine — `AuthorizationRule[]` with an
5
5
  * allow/deny/review decision, evaluated first-match-wins. What was missing was
6
6
  * any way for a person to author those rules: the CLI passed `rules: []`, so a
7
7
  * gate with seven rule types ran with none of them and every decision fell back
@@ -10,7 +10,7 @@
10
10
  * The whole surface is pure: config in, rules out. The gate stays the only
11
11
  * thing that decides anything, which is what keeps this testable without a run.
12
12
  */
13
- import type { VerificationRule } from '@namzu/sdk';
13
+ import type { AuthorizationRule } from '@namzu/sdk';
14
14
  /** What the operator wants to happen when a rule matches. */
15
15
  export type PermissionEffect = 'allow' | 'ask' | 'deny';
16
16
  export declare function isPermissionEffect(value: unknown): value is PermissionEffect;
@@ -30,7 +30,7 @@ export interface CompileDiagnostic {
30
30
  readonly message: string;
31
31
  }
32
32
  export interface CompiledPermissions {
33
- readonly rules: readonly VerificationRule[];
33
+ readonly rules: readonly AuthorizationRule[];
34
34
  /**
35
35
  * What was wrong with the config, for the caller to print.
36
36
  *
@@ -1 +1 @@
1
- {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/permissions/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAElD,6DAA6D;AAC7D,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAA;AAIvD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAE5E;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GAAG,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAA;AAE1F,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAA;AAExE,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,KAAK,EAAE,SAAS,gBAAgB,EAAE,CAAA;IAC3C;;;;;;;OAOG;IACH,QAAQ,CAAC,WAAW,EAAE,SAAS,iBAAiB,EAAE,CAAA;CAClD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAQ7D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,wBAAgB,iBAAiB,CAChC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE,OAAO,GAAG,MAAe,GACjC,MAAM,CASR;AAMD,oEAAoE;AACpE,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAKtE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAU1D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,iBAAiB,GAAG,SAAS,GAAG,mBAAmB,CAgD7F"}
1
+ {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/permissions/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEnD,6DAA6D;AAC7D,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAA;AAIvD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAE5E;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GAAG,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAA;AAE1F,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAA;AAExE,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,KAAK,EAAE,SAAS,iBAAiB,EAAE,CAAA;IAC5C;;;;;;;OAOG;IACH,QAAQ,CAAC,WAAW,EAAE,SAAS,iBAAiB,EAAE,CAAA;CAClD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAQ7D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,wBAAgB,iBAAiB,CAChC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,QAAQ,GAAE,OAAO,GAAG,MAAe,GACjC,MAAM,CASR;AAMD,oEAAoE;AACpE,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAKtE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAU1D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,iBAAiB,GAAG,SAAS,GAAG,mBAAmB,CAgD7F"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Operator-authored tool permissions, compiled to the kernel's rule vocabulary.
3
3
  *
4
- * The kernel already has the engine — `VerificationRule[]` with an
4
+ * The kernel already has the engine — `AuthorizationRule[]` with an
5
5
  * allow/deny/review decision, evaluated first-match-wins. What was missing was
6
6
  * any way for a person to author those rules: the CLI passed `rules: []`, so a
7
7
  * gate with seven rule types ran with none of them and every decision fell back
@@ -1 +1 @@
1
- {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../src/permissions/rules.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../src/permissions/rules.ts"],"names":[],"mappings":"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"}
@@ -48,7 +48,7 @@ interface ParsedSkill {
48
48
  * ## Absent frontmatter is fine; broken frontmatter is not
49
49
  *
50
50
  * These were the same case here and are not the same thing. A file with no
51
- * frontmatter is a documented, supported shape (`docs/cli/skills.md`): the body
51
+ * frontmatter is a documented, supported shape: the body
52
52
  * is the skill. A file that opens a fence and then fails to parse is an author
53
53
  * who tried to write metadata and got it wrong, and answering that with "no
54
54
  * metadata, carry on" put the broken YAML into the body — and from there
@@ -34,7 +34,7 @@ export function projectSkillsDir(cwd = process.cwd()) {
34
34
  * ## Absent frontmatter is fine; broken frontmatter is not
35
35
  *
36
36
  * These were the same case here and are not the same thing. A file with no
37
- * frontmatter is a documented, supported shape (`docs/cli/skills.md`): the body
37
+ * frontmatter is a documented, supported shape: the body
38
38
  * is the skill. A file that opens a fence and then fails to parse is an author
39
39
  * who tried to write metadata and got it wrong, and answering that with "no
40
40
  * metadata, carry on" put the broken YAML into the body — and from there
@@ -1 +1 @@
1
- {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/tui/App.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAmEH,OAAO,KAAK,EAAqB,UAAU,EAAE,MAAM,YAAY,CAAA;AAE/D,MAAM,WAAW,QAAQ;IACxB,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAA;CACxB;AAqCD,wBAAgB,GAAG,CAAC,EAAE,GAAG,EAAE,EAAE,QAAQ,2CAknDpC"}
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/tui/App.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAmFH,OAAO,KAAK,EAAqB,UAAU,EAAE,MAAM,YAAY,CAAA;AAE/D,MAAM,WAAW,QAAQ;IACxB,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAA;CACxB;AAqCD,wBAAgB,GAAG,CAAC,EAAE,GAAG,EAAE,EAAE,QAAQ,2CAqsDpC"}
package/dist/tui/App.js CHANGED
@@ -1,6 +1,19 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * TUI root. Composes the banner, transcript, composer, status bar, and
4
+ * the first-run provider picker overlay.
5
+ *
6
+ * Session lifecycle:
7
+ * 1. Mount → probeAgentSession() (readPreferences + discoverProviders).
8
+ * 2. If a v2 preferences file exists → createAgentSession(prefs, detected) → ready.
9
+ * 3. If preferences missing OR v1 (legacy) → show <Picker/>.
10
+ * After picker submit, writePreferences + hydrate session.
11
+ * 4. If discovery returned zero providers → show <Picker/> in
12
+ * empty-state mode (explains where to put credentials).
13
+ */
14
+ import { DiskMessageFeedbackStore, HostCommandRegistry, kernelHostCommands, } from '@namzu/sdk';
2
15
  import { Box, Text, useApp, useInput } from 'ink';
3
- import { relative } from 'node:path';
16
+ import { join, relative } from 'node:path';
4
17
  import { useCallback, useEffect, useRef, useState } from 'react';
5
18
  import { beginSubscriptionLogin, clearStoredSubscriptionCredential, credentialsPath, primaryProvider, readStoredSubscriptionCredential, writePreferences, } from '../integrations/providers/index.js';
6
19
  import { describeLoginOutcome, describeLoginStart, describeLogout } from './login-prompt.js';
@@ -26,7 +39,7 @@ import { appendMessages, listRecent, loadConversation, openSessions, startConver
26
39
  import { createAgentSession, probeAgentSession, } from './agent.js';
27
40
  import { ResumePicker } from './ResumePicker.js';
28
41
  import { discoverUserCommands } from '../user-commands/store.js';
29
- import { SLASH_COMMANDS, runSlash } from './slashCommands.js';
42
+ import { hostCommandNames, kernelCommandDescriptors, mergeHostCommands, renderOutcome, runSlash, } from './slashCommands.js';
30
43
  import { splitCompleteBlocks } from './stream-blocks.js';
31
44
  import { theme } from './theme.js';
32
45
  /**
@@ -41,6 +54,14 @@ import { theme } from './theme.js';
41
54
  const LIVE_FURNITURE_ROWS = 10;
42
55
  export function App({ ctx }) {
43
56
  const { exit } = useApp();
57
+ /**
58
+ * The last assistant message id the run reported, for `/feedback`.
59
+ *
60
+ * A ref rather than state: nothing renders it, and making it state would
61
+ * re-render the transcript on every delta — the exact cost the `pending`
62
+ * buffering two hundred lines down exists to avoid.
63
+ */
64
+ const lastAssistantMessage = useRef(null);
44
65
  const [messages, setMessages] = useState([]);
45
66
  const [history, setHistory] = useState([]);
46
67
  const [state, setState] = useState('idle');
@@ -253,7 +274,7 @@ export function App({ ctx }) {
253
274
  sessionsRef.current = sessions;
254
275
  scopeRef.current = {
255
276
  sessionId,
256
- threadId: sessions.threadId,
277
+ topicId: sessions.topicId,
257
278
  projectId: sessions.projectId,
258
279
  tenantId: sessions.tenantId,
259
280
  };
@@ -283,7 +304,7 @@ export function App({ ctx }) {
283
304
  // Builtins are reserved: a `help.md` must not take over `/help`.
284
305
  // Passing the names here is what lets the loader tell its author
285
306
  // the file is shadowed instead of leaving it silently unused.
286
- reserved: SLASH_COMMANDS.map((c) => c.name),
307
+ reserved: hostCommandNames(),
287
308
  }));
288
309
  setCurrentProvider(primaryProvider(prefs).id);
289
310
  if (s.hasProvider) {
@@ -547,7 +568,15 @@ export function App({ ctx }) {
547
568
  liveRows: LIVE_FURNITURE_ROWS + window.rows,
548
569
  })
549
570
  : 0;
571
+ // One merged vocabulary for the session: this host's own commands plus
572
+ // whatever the kernel's registry reports. Built here so `/help`, the
573
+ // autocomplete and the dispatcher all answer from the same list — three
574
+ // places that used to read one hardcoded array and would otherwise
575
+ // disagree the moment a capability added a command.
576
+ const hostCommands = mergeHostCommands(kernelCommandDescriptors());
550
577
  const slashCtx = {
578
+ builtins: hostCommands,
579
+ lastAssistantMessageId: () => lastAssistantMessage.current?.messageId ?? null,
551
580
  // Called when `/tools` renders, not read here — the same shape, and the
552
581
  // same reason, as `neverPrompted` below.
553
582
  availableTools: () => session?.toolNames() ?? [],
@@ -573,7 +602,6 @@ export function App({ ctx }) {
573
602
  approvalLatched: () => session?.approvalLatched() ?? false,
574
603
  neverPrompted: () => session?.promptExemptTools() ?? [],
575
604
  },
576
- agentIds: session?.agentIds ?? [],
577
605
  instructionFiles: session?.instructionFiles ?? [],
578
606
  userCommands,
579
607
  };
@@ -758,6 +786,9 @@ export function App({ ctx }) {
758
786
  switch (event.kind) {
759
787
  case 'delta': {
760
788
  setState('thinking');
789
+ if (event.messageId && event.runId) {
790
+ lastAssistantMessage.current = { runId: event.runId, messageId: event.messageId };
791
+ }
761
792
  st.text += event.text;
762
793
  // Held, not appended. Appending each delta is what produced text
763
794
  // that types itself out — nothing animates it, but a few
@@ -989,7 +1020,7 @@ export function App({ ctx }) {
989
1020
  // including the queue — so a command-driven turn is not a second way
990
1021
  // to run one.
991
1022
  let outgoing = value;
992
- const slash = runSlash(value, slashCtx);
1023
+ const slash = runSlash(value, slashCtx, hostCommands);
993
1024
  if (slash) {
994
1025
  switch (slash.kind) {
995
1026
  case 'message':
@@ -1167,6 +1198,61 @@ export function App({ ctx }) {
1167
1198
  break;
1168
1199
  case 'none':
1169
1200
  return;
1201
+ case 'host-command': {
1202
+ // Dispatched through the kernel's registry, built with what
1203
+ // THIS session can answer from. The descriptors used for
1204
+ // the merge above carry no store — they are names — so the
1205
+ // registry is rebuilt here with the live one.
1206
+ const registry = new HostCommandRegistry();
1207
+ registry.register(kernelHostCommands({ allowedAgentIds: session?.agentIds ?? [] }));
1208
+ void (async () => {
1209
+ const outcome = await registry.dispatch(`/${slash.name} ${slash.args.join(' ')}`.trim());
1210
+ pushMessage('system', outcome
1211
+ ? renderOutcome(outcome)
1212
+ : `/${slash.name} is registered but this session cannot run it.`);
1213
+ })();
1214
+ return;
1215
+ }
1216
+ case 'feedback': {
1217
+ const target = lastAssistantMessage.current;
1218
+ // Written under the same `<cwd>/.namzu` root the runs live
1219
+ // in, so a rating and the transcript it judges are one
1220
+ // directory apart and travel together.
1221
+ if (!target) {
1222
+ pushMessage('system', 'Nothing to rate yet.');
1223
+ return;
1224
+ }
1225
+ const store = new DiskMessageFeedbackStore({
1226
+ rootDir: join(ctx.cwd, '.namzu', 'feedback'),
1227
+ runsDir: join(ctx.cwd, '.namzu', 'runs'),
1228
+ });
1229
+ const runId = target.runId;
1230
+ const messageId = slash.messageId;
1231
+ // Fire-and-forget: this switch is synchronous, and the
1232
+ // transcript reports the outcome either way rather than
1233
+ // blocking a keystroke on a disk write.
1234
+ void (async () => {
1235
+ try {
1236
+ // A first rating expects nothing; a second replaces the
1237
+ // first, which is what a rater changing their mind does.
1238
+ // Read-then-write rather than blind overwrite, so two
1239
+ // raters on one message still collide loudly.
1240
+ const current = (await store.listMessageFeedback({ runId })).find((r) => r.messageId === messageId);
1241
+ const record = await store.putMessageFeedback({
1242
+ runId,
1243
+ messageId,
1244
+ rating: slash.rating,
1245
+ ...(slash.note ? { note: slash.note } : {}),
1246
+ expectedVersion: current?.ownerVersion ?? 0,
1247
+ });
1248
+ pushMessage('system', `Recorded ${record.rating} for ${record.messageId}.`);
1249
+ }
1250
+ catch (err) {
1251
+ pushMessage('system', `Could not record feedback: ${err instanceof Error ? err.message : String(err)}`);
1252
+ }
1253
+ })();
1254
+ return;
1255
+ }
1170
1256
  default: {
1171
1257
  // Exhaustive on purpose. Without it a `SlashAction` kind added
1172
1258
  // and not handled here falls out of the switch into the send