@pleri/olam-cli 0.1.175 → 0.1.182

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 (130) hide show
  1. package/README.md +19 -0
  2. package/bin/olam.cjs +22 -0
  3. package/dist/commands/auth.d.ts.map +1 -1
  4. package/dist/commands/auth.js +67 -19
  5. package/dist/commands/auth.js.map +1 -1
  6. package/dist/commands/config.d.ts.map +1 -1
  7. package/dist/commands/config.js +93 -0
  8. package/dist/commands/config.js.map +1 -1
  9. package/dist/commands/destroy.d.ts +41 -0
  10. package/dist/commands/destroy.d.ts.map +1 -1
  11. package/dist/commands/destroy.js +81 -33
  12. package/dist/commands/destroy.js.map +1 -1
  13. package/dist/commands/dispatch-resolve.d.ts +54 -0
  14. package/dist/commands/dispatch-resolve.d.ts.map +1 -0
  15. package/dist/commands/dispatch-resolve.js +105 -0
  16. package/dist/commands/dispatch-resolve.js.map +1 -0
  17. package/dist/commands/dispatch.d.ts.map +1 -1
  18. package/dist/commands/dispatch.js +40 -9
  19. package/dist/commands/dispatch.js.map +1 -1
  20. package/dist/commands/flywheel/index.d.ts.map +1 -1
  21. package/dist/commands/flywheel/index.js +4 -0
  22. package/dist/commands/flywheel/index.js.map +1 -1
  23. package/dist/commands/flywheel/install-sessionstart-hook.d.ts +64 -0
  24. package/dist/commands/flywheel/install-sessionstart-hook.d.ts.map +1 -0
  25. package/dist/commands/flywheel/install-sessionstart-hook.js +197 -0
  26. package/dist/commands/flywheel/install-sessionstart-hook.js.map +1 -0
  27. package/dist/commands/flywheel/k5-validate.d.ts +31 -0
  28. package/dist/commands/flywheel/k5-validate.d.ts.map +1 -1
  29. package/dist/commands/flywheel/k5-validate.js +80 -19
  30. package/dist/commands/flywheel/k5-validate.js.map +1 -1
  31. package/dist/commands/flywheel/session-start.d.ts +26 -0
  32. package/dist/commands/flywheel/session-start.d.ts.map +1 -0
  33. package/dist/commands/flywheel/session-start.js +119 -0
  34. package/dist/commands/flywheel/session-start.js.map +1 -0
  35. package/dist/commands/host-cp.d.ts +0 -3
  36. package/dist/commands/host-cp.d.ts.map +1 -1
  37. package/dist/commands/host-cp.js +27 -2
  38. package/dist/commands/host-cp.js.map +1 -1
  39. package/dist/commands/kg-classify.d.ts.map +1 -1
  40. package/dist/commands/kg-classify.js +20 -0
  41. package/dist/commands/kg-classify.js.map +1 -1
  42. package/dist/commands/kg-doctor.d.ts +67 -6
  43. package/dist/commands/kg-doctor.d.ts.map +1 -1
  44. package/dist/commands/kg-doctor.js +126 -46
  45. package/dist/commands/kg-doctor.js.map +1 -1
  46. package/dist/commands/list.d.ts +27 -0
  47. package/dist/commands/list.d.ts.map +1 -1
  48. package/dist/commands/list.js +67 -19
  49. package/dist/commands/list.js.map +1 -1
  50. package/dist/commands/memory/status.d.ts +18 -0
  51. package/dist/commands/memory/status.d.ts.map +1 -1
  52. package/dist/commands/memory/status.js +38 -2
  53. package/dist/commands/memory/status.js.map +1 -1
  54. package/dist/commands/memory-service-container.d.ts +44 -0
  55. package/dist/commands/memory-service-container.d.ts.map +1 -1
  56. package/dist/commands/memory-service-container.js +49 -0
  57. package/dist/commands/memory-service-container.js.map +1 -1
  58. package/dist/commands/ps.d.ts +32 -0
  59. package/dist/commands/ps.d.ts.map +1 -1
  60. package/dist/commands/ps.js +34 -0
  61. package/dist/commands/ps.js.map +1 -1
  62. package/dist/commands/runbooks.d.ts +32 -0
  63. package/dist/commands/runbooks.d.ts.map +1 -1
  64. package/dist/commands/runbooks.js +79 -22
  65. package/dist/commands/runbooks.js.map +1 -1
  66. package/dist/commands/skills-source.d.ts.map +1 -1
  67. package/dist/commands/skills-source.js +77 -2
  68. package/dist/commands/skills-source.js.map +1 -1
  69. package/dist/commands/upgrade-history.d.ts +0 -2
  70. package/dist/commands/upgrade-history.d.ts.map +1 -1
  71. package/dist/commands/upgrade-history.js +0 -6
  72. package/dist/commands/upgrade-history.js.map +1 -1
  73. package/dist/commands/upgrade-lock.d.ts +0 -9
  74. package/dist/commands/upgrade-lock.d.ts.map +1 -1
  75. package/dist/commands/upgrade-lock.js +1 -1
  76. package/dist/commands/upgrade-lock.js.map +1 -1
  77. package/dist/commands/world-snapshot.d.ts +13 -0
  78. package/dist/commands/world-snapshot.d.ts.map +1 -1
  79. package/dist/commands/world-snapshot.js +81 -1
  80. package/dist/commands/world-snapshot.js.map +1 -1
  81. package/dist/commands/yolo.d.ts +95 -0
  82. package/dist/commands/yolo.d.ts.map +1 -0
  83. package/dist/commands/yolo.js +377 -0
  84. package/dist/commands/yolo.js.map +1 -0
  85. package/dist/image-digests.json +8 -8
  86. package/dist/index.js +3990 -2445
  87. package/dist/index.js.map +1 -1
  88. package/dist/lib/anthropic-base-url-file.d.ts +37 -0
  89. package/dist/lib/anthropic-base-url-file.d.ts.map +1 -0
  90. package/dist/lib/anthropic-base-url-file.js +46 -0
  91. package/dist/lib/anthropic-base-url-file.js.map +1 -0
  92. package/dist/lib/auth-remote.d.ts +9 -17
  93. package/dist/lib/auth-remote.d.ts.map +1 -1
  94. package/dist/lib/auth-remote.js +25 -20
  95. package/dist/lib/auth-remote.js.map +1 -1
  96. package/dist/lib/cf-access-token.d.ts +32 -0
  97. package/dist/lib/cf-access-token.d.ts.map +1 -0
  98. package/dist/lib/cf-access-token.js +52 -0
  99. package/dist/lib/cf-access-token.js.map +1 -0
  100. package/dist/lib/config.d.ts +17 -3
  101. package/dist/lib/config.d.ts.map +1 -1
  102. package/dist/lib/config.js +28 -4
  103. package/dist/lib/config.js.map +1 -1
  104. package/dist/lib/kubectl-context.d.ts +49 -0
  105. package/dist/lib/kubectl-context.d.ts.map +1 -1
  106. package/dist/lib/kubectl-context.js +64 -2
  107. package/dist/lib/kubectl-context.js.map +1 -1
  108. package/dist/lib/upgrade-kubernetes.d.ts +7 -0
  109. package/dist/lib/upgrade-kubernetes.d.ts.map +1 -1
  110. package/dist/lib/upgrade-kubernetes.js +35 -8
  111. package/dist/lib/upgrade-kubernetes.js.map +1 -1
  112. package/dist/mcp-server.js +1470 -991
  113. package/hermes-bundle/version.json +1 -1
  114. package/host-cp/k8s/manifests/45-pvc.yaml +6 -2
  115. package/host-cp/k8s/manifests/50-deployment.yaml +1 -1
  116. package/host-cp/k8s/manifests/auth-service/50-deployment.yaml +1 -1
  117. package/host-cp/k8s/manifests/kg-service/50-deployment.yaml +1 -1
  118. package/host-cp/k8s/manifests/mcp-auth-service/50-deployment.yaml +1 -1
  119. package/host-cp/k8s/manifests/memory-service/50-deployment.yaml +1 -1
  120. package/host-cp/observability/trace-summary.mjs +267 -0
  121. package/host-cp/src/bootstrap-selective.mjs +58 -0
  122. package/host-cp/src/host-stream.mjs +52 -0
  123. package/host-cp/src/plan-chat-service.mjs +51 -0
  124. package/host-cp/src/redirect.mjs +159 -0
  125. package/host-cp/src/resolver.mjs +121 -0
  126. package/host-cp/src/router.mjs +168 -0
  127. package/host-cp/src/serve-only-config.mjs +85 -0
  128. package/host-cp/src/server.mjs +375 -205
  129. package/host-cp/src/world-services.mjs +136 -0
  130. package/package.json +1 -1
@@ -8,6 +8,14 @@
8
8
  import pc from 'picocolors';
9
9
  import { classify, KgServiceUnreachableError } from '@olam/core/src/kg/kg-service-client.js';
10
10
  import { printError, printInfo } from '../output.js';
11
+ /** Compact token-count formatting (mirrors `kg savings`' `~`-prefix convention). */
12
+ function formatSavedTokens(n) {
13
+ if (n >= 1_000_000)
14
+ return `~${(n / 1_000_000).toFixed(1)}M`;
15
+ if (n >= 1_000)
16
+ return `~${Math.round(n / 1000)}k`;
17
+ return `~${n}`;
18
+ }
11
19
  export function registerKgClassifyCommand(kg) {
12
20
  kg.command('classify <question>')
13
21
  .description('Route a question to kg | grep | both via the 4-layer classifier (kg-service required)')
@@ -36,6 +44,18 @@ export function registerKgClassifyCommand(kg) {
36
44
  if (result.candidate_symbols.length > 0) {
37
45
  printInfo('symbols', result.candidate_symbols.join(', '));
38
46
  }
47
+ // Hit-signal metadata enriched by the server. `nodes_matched` is the
48
+ // count of distinct symbol/exemplar matches the route resolved to —
49
+ // the "matched signals" an operator wants to see at a glance. Only
50
+ // meaningful (and only emitted) when the route is not grep.
51
+ if (result.route !== 'grep') {
52
+ if (result.nodes_matched != null) {
53
+ printInfo('matched signals', String(result.nodes_matched));
54
+ }
55
+ if (result.savings && result.savings.saved_tokens_est > 0) {
56
+ printInfo('est. savings', `${formatSavedTokens(result.savings.saved_tokens_est)} tokens`);
57
+ }
58
+ }
39
59
  }
40
60
  catch (err) {
41
61
  if (err instanceof KgServiceUnreachableError) {
@@ -1 +1 @@
1
- {"version":3,"file":"kg-classify.js","sourceRoot":"","sources":["../../src/commands/kg-classify.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,QAAQ,EAAE,yBAAyB,EAAE,MAAM,wCAAwC,CAAC;AAC7F,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAOrD,MAAM,UAAU,yBAAyB,CAAC,EAAW;IACnD,EAAE,CAAC,OAAO,CAAC,qBAAqB,CAAC;SAC9B,WAAW,CAAC,uFAAuF,CAAC;SACpG,MAAM,CAAC,oBAAoB,EAAE,uDAAuD,CAAC;SACrF,MAAM,CAAC,QAAQ,EAAE,gDAAgD,CAAC;SAClE,MAAM,CAAC,KAAK,EAAE,QAAgB,EAAE,IAAuB,EAAE,EAAE;QAC1D,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;YAC1E,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;gBAC7D,OAAO;YACT,CAAC;YACD,4BAA4B;YAC5B,MAAM,QAAQ,GACZ,MAAM,CAAC,KAAK,KAAK,IAAI;gBACnB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;gBACf,CAAC,CAAC,MAAM,CAAC,KAAK,KAAK,MAAM;oBACvB,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;oBACpB,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC1B,SAAS,CAAC,OAAO,EAAE,GAAG,QAAQ,YAAY,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,OAAO,KAAK,CAAC,CAAC;YACrF,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;YACnD,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YACnC,IAAI,MAAM,CAAC,UAAU;gBAAE,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;YAClE,IAAI,MAAM,CAAC,SAAS;gBAAE,SAAS,CAAC,WAAW,EAAE,GAAG,MAAM,CAAC,SAAU,SAAS,MAAM,CAAC,OAAO,IAAI,GAAG,GAAG,CAAC,CAAC;YACpG,IAAI,MAAM,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,yBAAyB,EAAE,CAAC;gBAC7C,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBACxB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;gBACrB,OAAO;YACT,CAAC;YACD,UAAU,CAAC,oBAAoB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACnF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"kg-classify.js","sourceRoot":"","sources":["../../src/commands/kg-classify.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,QAAQ,EAAE,yBAAyB,EAAE,MAAM,wCAAwC,CAAC;AAC7F,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAOrD,oFAAoF;AACpF,SAAS,iBAAiB,CAAC,CAAS;IAClC,IAAI,CAAC,IAAI,SAAS;QAAE,OAAO,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAC7D,IAAI,CAAC,IAAI,KAAK;QAAE,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC;IACnD,OAAO,IAAI,CAAC,EAAE,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,EAAW;IACnD,EAAE,CAAC,OAAO,CAAC,qBAAqB,CAAC;SAC9B,WAAW,CAAC,uFAAuF,CAAC;SACpG,MAAM,CAAC,oBAAoB,EAAE,uDAAuD,CAAC;SACrF,MAAM,CAAC,QAAQ,EAAE,gDAAgD,CAAC;SAClE,MAAM,CAAC,KAAK,EAAE,QAAgB,EAAE,IAAuB,EAAE,EAAE;QAC1D,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;YAC1E,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;gBAC7D,OAAO;YACT,CAAC;YACD,4BAA4B;YAC5B,MAAM,QAAQ,GACZ,MAAM,CAAC,KAAK,KAAK,IAAI;gBACnB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;gBACf,CAAC,CAAC,MAAM,CAAC,KAAK,KAAK,MAAM;oBACvB,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;oBACpB,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC1B,SAAS,CAAC,OAAO,EAAE,GAAG,QAAQ,YAAY,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,OAAO,KAAK,CAAC,CAAC;YACrF,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;YACnD,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YACnC,IAAI,MAAM,CAAC,UAAU;gBAAE,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;YAClE,IAAI,MAAM,CAAC,SAAS;gBAAE,SAAS,CAAC,WAAW,EAAE,GAAG,MAAM,CAAC,SAAU,SAAS,MAAM,CAAC,OAAO,IAAI,GAAG,GAAG,CAAC,CAAC;YACpG,IAAI,MAAM,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAC5D,CAAC;YACD,qEAAqE;YACrE,oEAAoE;YACpE,mEAAmE;YACnE,4DAA4D;YAC5D,IAAI,MAAM,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;gBAC5B,IAAI,MAAM,CAAC,aAAa,IAAI,IAAI,EAAE,CAAC;oBACjC,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC;gBAC7D,CAAC;gBACD,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,gBAAgB,GAAG,CAAC,EAAE,CAAC;oBAC1D,SAAS,CAAC,cAAc,EAAE,GAAG,iBAAiB,CAAC,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;gBAC5F,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,yBAAyB,EAAE,CAAC;gBAC7C,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBACxB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;gBACrB,OAAO;YACT,CAAC;YACD,UAAU,CAAC,oBAAoB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACnF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -1,15 +1,76 @@
1
1
  /**
2
2
  * `olam kg doctor` — diagnostic table for the kg-service container.
3
3
  *
4
- * 4 probes:
5
- * 1. Container state (running / stopped / missing)
6
- * 2. /health responds with ready=true
7
- * 3. /status lists at least one workspace (advisory; warn if empty)
8
- * 4. /classify round-trip works end-to-end (synthetic probe)
4
+ * Probes (in order):
5
+ * 1. container — Container state (running / stopped / missing)
6
+ * 2. health — /health responds with ready=true (+ version + uptime)
7
+ * 3. workspaces — /status lists at least one workspace (advisory; warn if empty)
8
+ * 4. classify — /classify round-trip works end-to-end (synthetic probe)
9
+ * 5. savings — cumulative KG-hit tally (advisory; "is the hook firing?")
9
10
  *
10
- * Exit 0 on all-green; non-zero on first failure with remedy hint.
11
+ * Exit 0 on all-green; non-zero on the first hard failure with a remedy hint.
12
+ * Advisory warnings (empty workspaces, zero hits) never flip the exit code.
11
13
  * --json emits a machine-readable structure for monitoring pipelines.
14
+ *
15
+ * The probe walk is a pure, injectable function (`runKgDoctor`) so it can be
16
+ * unit-tested without a live container — mirrors the `runKgStatus` /
17
+ * `runDoctor` testability pattern used elsewhere in the CLI.
12
18
  */
13
19
  import type { Command } from 'commander';
20
+ import { type ClassifyResponse, type HealthResponse, type SavingsResponse, type StatusResponse } from '@olam/core/src/kg/kg-service-client.js';
21
+ interface KgDoctorOptions {
22
+ readonly json?: boolean;
23
+ }
24
+ interface ProbeResult {
25
+ readonly name: string;
26
+ readonly status: 'ok' | 'warn' | 'fail';
27
+ readonly detail?: string;
28
+ readonly remedy?: string;
29
+ }
30
+ /**
31
+ * Minimal surface of `KgServiceContainerController` the probe walk needs.
32
+ * Declaring it as an interface lets tests inject a fake without spawning
33
+ * `docker inspect`.
34
+ */
35
+ export interface KgDoctorContainerProbe {
36
+ status(): {
37
+ state: 'running' | 'stopped' | 'missing';
38
+ port: number;
39
+ };
40
+ imageMissingEverywhere(): boolean;
41
+ }
42
+ /**
43
+ * Injectable dependencies for `runKgDoctor`. Defaults wire the real
44
+ * kg-service HTTP client + container controller; tests pass fakes.
45
+ */
46
+ export interface KgDoctorDeps {
47
+ readonly controller?: KgDoctorContainerProbe;
48
+ readonly health?: (opts?: {
49
+ timeoutMs?: number;
50
+ }) => Promise<HealthResponse>;
51
+ readonly status?: (opts?: {
52
+ timeoutMs?: number;
53
+ }) => Promise<StatusResponse>;
54
+ readonly classify?: (req: {
55
+ q: string;
56
+ workspace?: string;
57
+ }, opts?: {
58
+ timeoutMs?: number;
59
+ }) => Promise<ClassifyResponse>;
60
+ readonly savings?: (opts?: {
61
+ timeoutMs?: number;
62
+ }) => Promise<SavingsResponse>;
63
+ }
64
+ export interface KgDoctorResult {
65
+ readonly exitCode: number;
66
+ readonly probes: ReadonlyArray<ProbeResult>;
67
+ }
68
+ /**
69
+ * Pure, injectable probe walk. Renders to the configured output when not in
70
+ * JSON mode and returns the structured result + exit code. Tests drive this
71
+ * directly with fake deps; the commander action is a thin wrapper.
72
+ */
73
+ export declare function runKgDoctor(opts: KgDoctorOptions, deps?: KgDoctorDeps): Promise<KgDoctorResult>;
14
74
  export declare function registerKgDoctorCommand(kg: Command): void;
75
+ export {};
15
76
  //# sourceMappingURL=kg-doctor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"kg-doctor.d.ts","sourceRoot":"","sources":["../../src/commands/kg-doctor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6IzC,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAsCzD"}
1
+ {"version":3,"file":"kg-doctor.d.ts","sourceRoot":"","sources":["../../src/commands/kg-doctor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGzC,OAAO,EAML,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,MAAM,wCAAwC,CAAC;AAGhD,UAAU,eAAe;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,UAAU,WAAW;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACrC,MAAM,IAAI;QAAE,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACrE,sBAAsB,IAAI,OAAO,CAAC;CACnC;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,sBAAsB,CAAC;IAC7C,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7E,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7E,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAClB,GAAG,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,EACtC,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KAC1B,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;CAChF;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;CAC7C;AAoLD;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,eAAe,EACrB,IAAI,GAAE,YAAiB,GACtB,OAAO,CAAC,cAAc,CAAC,CAmCzB;AAED,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,CAUzD"}
@@ -1,22 +1,56 @@
1
1
  /**
2
2
  * `olam kg doctor` — diagnostic table for the kg-service container.
3
3
  *
4
- * 4 probes:
5
- * 1. Container state (running / stopped / missing)
6
- * 2. /health responds with ready=true
7
- * 3. /status lists at least one workspace (advisory; warn if empty)
8
- * 4. /classify round-trip works end-to-end (synthetic probe)
4
+ * Probes (in order):
5
+ * 1. container — Container state (running / stopped / missing)
6
+ * 2. health — /health responds with ready=true (+ version + uptime)
7
+ * 3. workspaces — /status lists at least one workspace (advisory; warn if empty)
8
+ * 4. classify — /classify round-trip works end-to-end (synthetic probe)
9
+ * 5. savings — cumulative KG-hit tally (advisory; "is the hook firing?")
9
10
  *
10
- * Exit 0 on all-green; non-zero on first failure with remedy hint.
11
+ * Exit 0 on all-green; non-zero on the first hard failure with a remedy hint.
12
+ * Advisory warnings (empty workspaces, zero hits) never flip the exit code.
11
13
  * --json emits a machine-readable structure for monitoring pipelines.
14
+ *
15
+ * The probe walk is a pure, injectable function (`runKgDoctor`) so it can be
16
+ * unit-tested without a live container — mirrors the `runKgStatus` /
17
+ * `runDoctor` testability pattern used elsewhere in the CLI.
12
18
  */
13
19
  import pc from 'picocolors';
14
20
  import { KgServiceContainerController } from './kg-service-container.js';
15
- import { classify, health, KgServiceUnreachableError, status, } from '@olam/core/src/kg/kg-service-client.js';
21
+ import { classify as classifyImpl, health as healthImpl, KgServiceUnreachableError, savings as savingsImpl, status as statusImpl, } from '@olam/core/src/kg/kg-service-client.js';
16
22
  import { printError, printHeader, printInfo, printSuccess, printWarning } from '../output.js';
17
- async function runProbes() {
23
+ /** Compact human-readable uptime (e.g. "3m", "2h 5m", "1d 4h"). */
24
+ function formatUptime(seconds) {
25
+ if (!Number.isFinite(seconds) || seconds < 0)
26
+ return '?';
27
+ const total = Math.floor(seconds);
28
+ if (total < 60)
29
+ return `${total}s`;
30
+ const minutes = Math.floor(total / 60);
31
+ if (minutes < 60)
32
+ return `${minutes}m`;
33
+ const hours = Math.floor(minutes / 60);
34
+ if (hours < 24)
35
+ return `${hours}h ${minutes % 60}m`;
36
+ const days = Math.floor(hours / 24);
37
+ return `${days}d ${hours % 24}h`;
38
+ }
39
+ /** Compact token-count formatting that mirrors `kg savings`' `~`-prefix convention. */
40
+ function formatSavedTokens(n) {
41
+ if (n >= 1_000_000)
42
+ return `~${(n / 1_000_000).toFixed(1)}M`;
43
+ if (n >= 1_000)
44
+ return `~${Math.round(n / 1000)}k`;
45
+ return `~${n}`;
46
+ }
47
+ async function runProbes(deps) {
18
48
  const results = [];
19
- const controller = new KgServiceContainerController();
49
+ const controller = deps.controller ?? new KgServiceContainerController();
50
+ const health = deps.health ?? healthImpl;
51
+ const status = deps.status ?? statusImpl;
52
+ const classify = deps.classify ?? classifyImpl;
53
+ const savings = deps.savings ?? savingsImpl;
20
54
  // Probe 1: container state
21
55
  const state = controller.status();
22
56
  if (state.state === 'running') {
@@ -54,7 +88,10 @@ async function runProbes() {
54
88
  try {
55
89
  const h = await health({ timeoutMs: 2_000 });
56
90
  if (h.ready) {
57
- results.push({ name: 'health', status: 'ok', detail: `ready · v${h.version}` });
91
+ // Surface uptime when the server reports it (added by /health in the
92
+ // current server.py; older builds omit uptime_s — degrade gracefully).
93
+ const uptime = h.uptime_s != null ? ` · up ${formatUptime(h.uptime_s)}` : '';
94
+ results.push({ name: 'health', status: 'ok', detail: `ready · v${h.version}${uptime}` });
58
95
  }
59
96
  else {
60
97
  results.push({
@@ -135,48 +172,91 @@ async function runProbes() {
135
172
  });
136
173
  }
137
174
  }
175
+ // Probe 5: /savings (cumulative KG-hit tally).
176
+ //
177
+ // Advisory-only — answers the operator's real question "is the KG-first
178
+ // hook actually firing on my grep/find calls?". Zero hits is a soft WARN
179
+ // (not a failure): a freshly-booted service legitimately has no tally yet.
180
+ // A non-zero tally is the felt signal that the substrate is doing work.
181
+ try {
182
+ const sv = await savings({ timeoutMs: 2_000 });
183
+ if (sv.total_hits === 0) {
184
+ results.push({
185
+ name: 'savings',
186
+ status: 'warn',
187
+ detail: 'no KG hits logged yet',
188
+ remedy: 'Run a few grep/find Bash calls in a world to exercise the KG-first hook',
189
+ });
190
+ }
191
+ else {
192
+ results.push({
193
+ name: 'savings',
194
+ status: 'ok',
195
+ detail: `${sv.total_hits} hits · ${formatSavedTokens(sv.total_saved_tokens_est)} tokens saved (est)`,
196
+ });
197
+ }
198
+ }
199
+ catch {
200
+ // Older kg-service builds predate the /savings endpoint. Treat an
201
+ // unreachable/absent endpoint as advisory — never fail doctor on it.
202
+ results.push({
203
+ name: 'savings',
204
+ status: 'warn',
205
+ detail: 'savings tally unavailable (older kg-service build?)',
206
+ });
207
+ }
138
208
  return results;
139
209
  }
210
+ /**
211
+ * Pure, injectable probe walk. Renders to the configured output when not in
212
+ * JSON mode and returns the structured result + exit code. Tests drive this
213
+ * directly with fake deps; the commander action is a thin wrapper.
214
+ */
215
+ export async function runKgDoctor(opts, deps = {}) {
216
+ const probes = await runProbes(deps);
217
+ if (opts.json) {
218
+ process.stdout.write(JSON.stringify({ probes }, null, 2) + '\n');
219
+ }
220
+ else {
221
+ printHeader('kg-service doctor');
222
+ for (const p of probes) {
223
+ const badge = p.status === 'ok'
224
+ ? pc.green('✓')
225
+ : p.status === 'warn'
226
+ ? pc.yellow('⊘')
227
+ : pc.red('✗');
228
+ const label = `${badge} ${p.name}`;
229
+ const detail = p.detail ?? '';
230
+ printInfo(label, detail);
231
+ if (p.remedy) {
232
+ process.stderr.write(` ${pc.dim('remedy:')} ${p.remedy}\n`);
233
+ }
234
+ }
235
+ }
236
+ // Exit code: non-zero if any probe FAILED; warn alone is acceptable.
237
+ const hasFail = probes.some((p) => p.status === 'fail');
238
+ if (hasFail) {
239
+ if (!opts.json)
240
+ printError('one or more probes failed');
241
+ return { exitCode: 1, probes };
242
+ }
243
+ if (probes.every((p) => p.status === 'ok')) {
244
+ if (!opts.json)
245
+ printSuccess('all probes green');
246
+ }
247
+ else if (!opts.json) {
248
+ printWarning('mostly green, with advisory warnings');
249
+ }
250
+ return { exitCode: 0, probes };
251
+ }
140
252
  export function registerKgDoctorCommand(kg) {
141
253
  kg.command('doctor')
142
- .description('Diagnostic table for kg-service (container + /health + workspaces + classify round-trip)')
254
+ .description('Diagnostic table for kg-service (container + /health + workspaces + classify round-trip + savings tally)')
143
255
  .option('--json', 'Emit machine-readable JSON instead of the formatted table')
144
256
  .action(async (opts) => {
145
- const probes = await runProbes();
146
- if (opts.json) {
147
- process.stdout.write(JSON.stringify({ probes }, null, 2) + '\n');
148
- }
149
- else {
150
- printHeader('kg-service doctor');
151
- for (const p of probes) {
152
- const badge = p.status === 'ok'
153
- ? pc.green('✓')
154
- : p.status === 'warn'
155
- ? pc.yellow('⊘')
156
- : pc.red('✗');
157
- const label = `${badge} ${p.name}`;
158
- const detail = p.detail ?? '';
159
- printInfo(label, detail);
160
- if (p.remedy) {
161
- process.stderr.write(` ${pc.dim('remedy:')} ${p.remedy}\n`);
162
- }
163
- }
164
- }
165
- // Exit code: non-zero if any fail; warn alone is acceptable.
166
- const hasFail = probes.some((p) => p.status === 'fail');
167
- if (hasFail) {
168
- if (!opts.json)
169
- printError('one or more probes failed');
170
- process.exitCode = 1;
171
- }
172
- else if (probes.every((p) => p.status === 'ok')) {
173
- if (!opts.json)
174
- printSuccess('all probes green');
175
- }
176
- else {
177
- if (!opts.json)
178
- printWarning('mostly green, with advisory warnings');
179
- }
257
+ const r = await runKgDoctor(opts);
258
+ if (r.exitCode !== 0)
259
+ process.exitCode = r.exitCode;
180
260
  });
181
261
  }
182
262
  //# sourceMappingURL=kg-doctor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"kg-doctor.js","sourceRoot":"","sources":["../../src/commands/kg-doctor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,4BAA4B,EAAE,MAAM,2BAA2B,CAAC;AACzE,OAAO,EACL,QAAQ,EACR,MAAM,EACN,yBAAyB,EACzB,MAAM,GACP,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAa9F,KAAK,UAAU,SAAS;IACtB,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,MAAM,UAAU,GAAG,IAAI,4BAA4B,EAAE,CAAC;IAEtD,2BAA2B;IAC3B,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC;IAClC,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACzF,CAAC;SAAM,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QACrC,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,WAAW;YACjB,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,oBAAoB;SAC7B,CAAC,CAAC;QACH,OAAO,OAAO,CAAC,CAAC,kDAAkD;IACpE,CAAC;SAAM,CAAC;QACN,IAAI,UAAU,CAAC,sBAAsB,EAAE,EAAE,CAAC;YACxC,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,WAAW;gBACjB,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,4BAA4B;gBACpC,MAAM,EAAE,sEAAsE;aAC/E,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,WAAW;gBACjB,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,SAAS;gBACjB,MAAM,EAAE,oBAAoB;aAC7B,CAAC,CAAC;QACL,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,mBAAmB;IACnB,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7C,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAClF,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,QAAQ;gBACd,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,8CAA8C;gBACtD,MAAM,EAAE,+BAA+B;aACxC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;YACxD,MAAM,EAAE,qCAAqC;SAC9C,CAAC,CAAC;QACH,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,2CAA2C;IAC3C,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7C,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,YAAY;gBAClB,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,yBAAyB;gBACjC,MAAM,EAAE,sCAAsC;aAC/C,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,YAAY;gBAClB,MAAM,EAAE,IAAI;gBACZ,MAAM,EAAE,GAAG,CAAC,CAAC,UAAU,CAAC,MAAM,aAAa,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;aACxF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,YAAY;YAClB,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACzD,CAAC,CAAC;IACL,CAAC;IAED,gCAAgC;IAChC,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,QAAQ,CAAC,EAAE,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;QACtE,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC;YACjC,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE,IAAI;gBACZ,MAAM,EAAE,mBAAmB,CAAC,CAAC,OAAO,cAAc,CAAC,CAAC,KAAK,EAAE;aAC5D,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,2BAA2B;aACpC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,yBAAyB,EAAE,CAAC;YAC7C,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,wBAAwB;gBAChC,MAAM,EAAE,oBAAoB;aAC7B,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aACzD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,EAAW;IACjD,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,0FAA0F,CAAC;SACvG,MAAM,CAAC,QAAQ,EAAE,2DAA2D,CAAC;SAC7E,MAAM,CAAC,KAAK,EAAE,IAAqB,EAAE,EAAE;QACtC,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;QAEjC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QACnE,CAAC;aAAM,CAAC;YACN,WAAW,CAAC,mBAAmB,CAAC,CAAC;YACjC,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;gBACvB,MAAM,KAAK,GACT,CAAC,CAAC,MAAM,KAAK,IAAI;oBACf,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC;oBACf,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM;wBACnB,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC;wBAChB,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACpB,MAAM,KAAK,GAAG,GAAG,KAAK,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;gBACpC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC;gBAC9B,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;gBACzB,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;oBACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC;gBACnE,CAAC;YACH,CAAC;QACH,CAAC;QAED,6DAA6D;QAC7D,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;QACxD,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC,IAAI,CAAC,IAAI;gBAAE,UAAU,CAAC,2BAA2B,CAAC,CAAC;YACxD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC;aAAM,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,EAAE,CAAC;YAClD,IAAI,CAAC,IAAI,CAAC,IAAI;gBAAE,YAAY,CAAC,kBAAkB,CAAC,CAAC;QACnD,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,IAAI;gBAAE,YAAY,CAAC,sCAAsC,CAAC,CAAC;QACvE,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"kg-doctor.js","sourceRoot":"","sources":["../../src/commands/kg-doctor.ts"],"names":[],"mappings":"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"}
@@ -2,5 +2,32 @@
2
2
  * olam list — List all active worlds.
3
3
  */
4
4
  import type { Command } from 'commander';
5
+ /** Lifecycle statuses accepted by `--status`. Mirrors WorldLifecycleStatus. */
6
+ declare const VALID_STATUSES: readonly ["creating", "running", "paused", "crystallizing", "destroyed", "error"];
7
+ type ValidStatus = (typeof VALID_STATUSES)[number];
8
+ /** Minimal world shape this command renders. Structurally compatible with WorldMetadata. */
9
+ interface ListableWorld {
10
+ readonly id: string;
11
+ readonly name: string;
12
+ readonly status: string;
13
+ readonly repos: readonly string[];
14
+ readonly totalCostUsd: number;
15
+ readonly createdAt: string;
16
+ }
17
+ export interface ListOptions {
18
+ readonly json?: boolean;
19
+ }
20
+ /**
21
+ * Pure renderer for `olam list`. Returns the lines to print so the
22
+ * formatting + JSON contract is unit-testable without touching the
23
+ * world registry or process I/O.
24
+ */
25
+ export declare function renderWorldList(worlds: readonly ListableWorld[], opts?: ListOptions): string;
26
+ /** Normalise + validate a `--status` value. Returns null when unset. */
27
+ export declare function parseStatusFilter(raw: string | undefined): {
28
+ status: ValidStatus | null;
29
+ error?: string;
30
+ };
5
31
  export declare function registerList(program: Command): void;
32
+ export {};
6
33
  //# sourceMappingURL=list.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuCnD"}
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,+EAA+E;AAC/E,QAAA,MAAM,cAAc,mFAOV,CAAC;AAEX,KAAK,WAAW,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD,4FAA4F;AAC5F,UAAU,aAAa;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,aAAa,EAAE,EAChC,IAAI,GAAE,WAAgB,GACrB,MAAM,CAuCR;AAED,wEAAwE;AACxE,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG;IAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAUzG;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6BnD"}
@@ -4,36 +4,84 @@
4
4
  import pc from 'picocolors';
5
5
  import { loadContext } from '../context.js';
6
6
  import { printError, formatAge } from '../output.js';
7
+ /** Lifecycle statuses accepted by `--status`. Mirrors WorldLifecycleStatus. */
8
+ const VALID_STATUSES = [
9
+ 'creating',
10
+ 'running',
11
+ 'paused',
12
+ 'crystallizing',
13
+ 'destroyed',
14
+ 'error',
15
+ ];
16
+ /**
17
+ * Pure renderer for `olam list`. Returns the lines to print so the
18
+ * formatting + JSON contract is unit-testable without touching the
19
+ * world registry or process I/O.
20
+ */
21
+ export function renderWorldList(worlds, opts = {}) {
22
+ if (opts.json) {
23
+ return JSON.stringify(worlds.map((w) => ({
24
+ id: w.id,
25
+ name: w.name,
26
+ status: w.status,
27
+ repos: [...w.repos],
28
+ totalCostUsd: w.totalCostUsd,
29
+ createdAt: w.createdAt,
30
+ })));
31
+ }
32
+ if (worlds.length === 0) {
33
+ return pc.dim('No worlds. Create one with `olam create --name my-world`.');
34
+ }
35
+ const lines = [`${pc.bold(String(worlds.length))} world(s)\n`];
36
+ for (const w of worlds) {
37
+ const statusColor = w.status === 'running'
38
+ ? pc.green(w.status)
39
+ : w.status === 'error'
40
+ ? pc.red(w.status)
41
+ : pc.yellow(w.status);
42
+ const age = formatAge(w.createdAt);
43
+ const cost = `$${w.totalCostUsd.toFixed(2)}`;
44
+ lines.push(` ${pc.bold(w.name)} ${pc.dim(`(${w.id})`)}`);
45
+ lines.push(` ${statusColor} ${pc.dim('|')} ${w.repos.join(', ')} ${pc.dim('|')} ${cost} ${pc.dim('|')} ${age}`);
46
+ lines.push('');
47
+ }
48
+ return lines.join('\n');
49
+ }
50
+ /** Normalise + validate a `--status` value. Returns null when unset. */
51
+ export function parseStatusFilter(raw) {
52
+ if (raw === undefined)
53
+ return { status: null };
54
+ const normalised = raw.trim().toLowerCase();
55
+ if (VALID_STATUSES.includes(normalised)) {
56
+ return { status: normalised };
57
+ }
58
+ return {
59
+ status: null,
60
+ error: `Unknown status "${raw}". Valid values: ${VALID_STATUSES.join(', ')}.`,
61
+ };
62
+ }
7
63
  export function registerList(program) {
8
64
  program
9
65
  .command('list')
10
66
  .alias('ls')
11
67
  .description('List active worlds')
12
- .action(async () => {
68
+ .option('--json', 'Emit machine-readable JSON instead of the text table', false)
69
+ .option('--status <status>', `Only show worlds with this lifecycle status (${VALID_STATUSES.join(', ')})`)
70
+ .action(async (raw) => {
71
+ const { status, error: statusError } = parseStatusFilter(raw.status);
72
+ if (statusError) {
73
+ printError(statusError);
74
+ process.exitCode = 1;
75
+ return;
76
+ }
13
77
  const { ctx, error } = await loadContext();
14
78
  if (!ctx) {
15
79
  printError(error?.message ?? 'Olam is not configured. Run `olam init` first.');
16
80
  process.exitCode = 1;
17
81
  return;
18
82
  }
19
- const worlds = ctx.worldManager.listWorlds();
20
- if (worlds.length === 0) {
21
- console.log(pc.dim('No worlds. Create one with `olam create --name my-world`.'));
22
- return;
23
- }
24
- console.log(`${pc.bold(String(worlds.length))} world(s)\n`);
25
- for (const w of worlds) {
26
- const statusColor = w.status === 'running'
27
- ? pc.green(w.status)
28
- : w.status === 'error'
29
- ? pc.red(w.status)
30
- : pc.yellow(w.status);
31
- const age = formatAge(w.createdAt);
32
- const cost = `$${w.totalCostUsd.toFixed(2)}`;
33
- console.log(` ${pc.bold(w.name)} ${pc.dim(`(${w.id})`)}`);
34
- console.log(` ${statusColor} ${pc.dim('|')} ${w.repos.join(', ')} ${pc.dim('|')} ${cost} ${pc.dim('|')} ${age}`);
35
- console.log();
36
- }
83
+ const worlds = ctx.worldManager.listWorlds(status ? { status } : undefined);
84
+ console.log(renderWorldList(worlds, { json: raw.json === true }));
37
85
  });
38
86
  }
39
87
  //# sourceMappingURL=list.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAErD,MAAM,UAAU,YAAY,CAAC,OAAgB;IAC3C,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,KAAK,CAAC,IAAI,CAAC;SACX,WAAW,CAAC,oBAAoB,CAAC;SACjC,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,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,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC,UAAU,EAAE,CAAC;QAE7C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAC,CAAC;YACjF,OAAO;QACT,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,CAAC;QAE5D,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,KAAK,SAAS;gBACxC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;gBACpB,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,OAAO;oBACpB,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;oBAClB,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAE1B,MAAM,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YACnC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YAE7C,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YAC3D,OAAO,CAAC,GAAG,CACT,OAAO,WAAW,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAC7G,CAAC;YACF,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"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"}
@@ -7,9 +7,18 @@
7
7
  * reports container lifecycle (`running | stopped | missing`) instead of
8
8
  * pid/alive.
9
9
  *
10
+ * Enrichment (additive, backward-compatible): a single `docker inspect` call
11
+ * augments the dump with container runtime metadata — `uptime` (from
12
+ * `State.StartedAt`), `restarts` (`RestartCount`, with a crash-loop warning
13
+ * past a threshold), and `health` (Docker `State.Health.Status`, or `none`
14
+ * for images without a HEALTHCHECK). All new fields are display-only and
15
+ * additive in both human + `--json` modes; existing field names/types and the
16
+ * exit-code contract (anchored on `state` + `livez`) are unchanged.
17
+ *
10
18
  * Plan reference: docs/plans/memory-service-as-docker-peripheral/phase-b-tasks.md B3
11
19
  */
12
20
  import type { Command } from 'commander';
21
+ import { type MemoryServiceHealth } from '../memory-service-container.js';
13
22
  interface MemoryStatus {
14
23
  state: 'running' | 'stopped' | 'missing';
15
24
  containerId: string | null;
@@ -17,6 +26,15 @@ interface MemoryStatus {
17
26
  secretSet: boolean;
18
27
  port: number;
19
28
  legacyPidfilePresent: boolean;
29
+ /**
30
+ * Container runtime metadata (Phase B+ enrichment). Best-effort: `null`
31
+ * fields mean the data was unavailable (e.g. container missing, or a parse
32
+ * miss on `docker inspect`). These fields are display-only — they never
33
+ * affect the exit code, which stays anchored on `state` + `livez`.
34
+ */
35
+ startedAt: string | null;
36
+ restartCount: number | null;
37
+ health: MemoryServiceHealth;
20
38
  }
21
39
  export declare function collectMemoryStatus(): Promise<MemoryStatus>;
22
40
  export declare function runMemoryStatus(opts?: {
@@ -1 +1 @@
1
- {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/commands/memory/status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWzC,UAAU,YAAY;IACpB,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IACzC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,IAAI,GAAG,aAAa,GAAG,cAAc,GAAG,SAAS,CAAC;IACzD,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB,EAAE,OAAO,CAAC;CAC/B;AAgBD,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,YAAY,CAAC,CAajE;AAED,wBAAsB,eAAe,CAAC,IAAI,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CA+CpF;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CASvD"}
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/commands/memory/status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASzC,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,gCAAgC,CAAC;AAExC,UAAU,YAAY;IACpB,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IACzC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,IAAI,GAAG,aAAa,GAAG,cAAc,GAAG,SAAS,CAAC;IACzD,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB,EAAE,OAAO,CAAC;IAC9B;;;;;OAKG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,mBAAmB,CAAC;CAC7B;AAwBD,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,YAAY,CAAC,CAmBjE;AAED,wBAAsB,eAAe,CAAC,IAAI,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAgEpF;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CASvD"}