@miller-tech/uap 2.21.3 → 2.36.4
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.
- package/README.md +22 -10
- package/config/model-profiles/qwen38-coder390.json +46 -0
- package/config/model-profiles/qwen38.json +3 -2
- package/config/model-registry.json +110 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/benchmarks/paired/types.d.ts +2 -2
- package/dist/bin/cli.js +315 -20
- package/dist/bin/cli.js.map +1 -1
- package/dist/cli/attention.d.ts +6 -0
- package/dist/cli/attention.d.ts.map +1 -0
- package/dist/cli/attention.js +115 -0
- package/dist/cli/attention.js.map +1 -0
- package/dist/cli/bench-report.d.ts +82 -0
- package/dist/cli/bench-report.d.ts.map +1 -0
- package/dist/cli/bench-report.js +237 -0
- package/dist/cli/bench-report.js.map +1 -0
- package/dist/cli/clients.d.ts +6 -0
- package/dist/cli/clients.d.ts.map +1 -0
- package/dist/cli/clients.js +142 -0
- package/dist/cli/clients.js.map +1 -0
- package/dist/cli/dashboard-grants.d.ts +26 -0
- package/dist/cli/dashboard-grants.d.ts.map +1 -0
- package/dist/cli/dashboard-grants.js +69 -0
- package/dist/cli/dashboard-grants.js.map +1 -0
- package/dist/cli/dashboard-pace.d.ts +31 -0
- package/dist/cli/dashboard-pace.d.ts.map +1 -0
- package/dist/cli/dashboard-pace.js +42 -0
- package/dist/cli/dashboard-pace.js.map +1 -0
- package/dist/cli/dashboard-session.d.ts +25 -0
- package/dist/cli/dashboard-session.d.ts.map +1 -0
- package/dist/cli/dashboard-session.js +814 -0
- package/dist/cli/dashboard-session.js.map +1 -0
- package/dist/cli/dashboard-types.d.ts +18 -0
- package/dist/cli/dashboard-types.d.ts.map +1 -0
- package/dist/cli/dashboard-types.js +9 -0
- package/dist/cli/dashboard-types.js.map +1 -0
- package/dist/cli/dashboard.d.ts +2 -18
- package/dist/cli/dashboard.d.ts.map +1 -1
- package/dist/cli/dashboard.js +43 -793
- package/dist/cli/dashboard.js.map +1 -1
- package/dist/cli/deliver.d.ts +35 -0
- package/dist/cli/deliver.d.ts.map +1 -1
- package/dist/cli/deliver.js +93 -9
- package/dist/cli/deliver.js.map +1 -1
- package/dist/cli/diff.d.ts +85 -0
- package/dist/cli/diff.d.ts.map +1 -0
- package/dist/cli/diff.js +293 -0
- package/dist/cli/diff.js.map +1 -0
- package/dist/cli/eta.d.ts +35 -0
- package/dist/cli/eta.d.ts.map +1 -0
- package/dist/cli/eta.js +101 -0
- package/dist/cli/eta.js.map +1 -0
- package/dist/cli/handsfree.d.ts +7 -0
- package/dist/cli/handsfree.d.ts.map +1 -1
- package/dist/cli/handsfree.js +27 -0
- package/dist/cli/handsfree.js.map +1 -1
- package/dist/cli/hooks.d.ts.map +1 -1
- package/dist/cli/hooks.js +126 -5
- package/dist/cli/hooks.js.map +1 -1
- package/dist/cli/loops.d.ts +24 -5
- package/dist/cli/loops.d.ts.map +1 -1
- package/dist/cli/loops.js +92 -12
- package/dist/cli/loops.js.map +1 -1
- package/dist/cli/models.d.ts +62 -0
- package/dist/cli/models.d.ts.map +1 -0
- package/dist/cli/models.js +567 -0
- package/dist/cli/models.js.map +1 -0
- package/dist/cli/plan.d.ts +9 -0
- package/dist/cli/plan.d.ts.map +1 -1
- package/dist/cli/plan.js +57 -4
- package/dist/cli/plan.js.map +1 -1
- package/dist/cli/proxy-relay.d.ts +55 -0
- package/dist/cli/proxy-relay.d.ts.map +1 -0
- package/dist/cli/proxy-relay.js +116 -0
- package/dist/cli/proxy-relay.js.map +1 -0
- package/dist/cli/proxy.d.ts +4 -0
- package/dist/cli/proxy.d.ts.map +1 -1
- package/dist/cli/proxy.js +26 -1
- package/dist/cli/proxy.js.map +1 -1
- package/dist/cli/sandbox.d.ts +101 -4
- package/dist/cli/sandbox.d.ts.map +1 -1
- package/dist/cli/sandbox.js +393 -44
- package/dist/cli/sandbox.js.map +1 -1
- package/dist/cli/self.d.ts +13 -0
- package/dist/cli/self.d.ts.map +1 -0
- package/dist/cli/self.js +94 -0
- package/dist/cli/self.js.map +1 -0
- package/dist/cli/systemd-services.d.ts +2 -8
- package/dist/cli/systemd-services.d.ts.map +1 -1
- package/dist/cli/systemd-services.js +5 -20
- package/dist/cli/systemd-services.js.map +1 -1
- package/dist/cli/task.js +1 -1
- package/dist/cli/task.js.map +1 -1
- package/dist/cli/wizard-config.d.ts.map +1 -1
- package/dist/cli/wizard-config.js +31 -2
- package/dist/cli/wizard-config.js.map +1 -1
- package/dist/config/settings-registry.d.ts +1 -1
- package/dist/config/settings-registry.d.ts.map +1 -1
- package/dist/config/settings-registry.js +108 -0
- package/dist/config/settings-registry.js.map +1 -1
- package/dist/coordination/capability-router.js +2 -2
- package/dist/coordination/capability-router.js.map +1 -1
- package/dist/coordination/database.d.ts +13 -0
- package/dist/coordination/database.d.ts.map +1 -1
- package/dist/coordination/database.js +63 -7
- package/dist/coordination/database.js.map +1 -1
- package/dist/coordination/eta-inject.d.ts +32 -0
- package/dist/coordination/eta-inject.d.ts.map +1 -0
- package/dist/coordination/eta-inject.js +64 -0
- package/dist/coordination/eta-inject.js.map +1 -0
- package/dist/coordination/reactor.d.ts.map +1 -1
- package/dist/coordination/reactor.js +14 -0
- package/dist/coordination/reactor.js.map +1 -1
- package/dist/coordination/service.d.ts +18 -8
- package/dist/coordination/service.d.ts.map +1 -1
- package/dist/coordination/service.js +38 -28
- package/dist/coordination/service.js.map +1 -1
- package/dist/dashboard/client-registry.d.ts +163 -0
- package/dist/dashboard/client-registry.d.ts.map +1 -0
- package/dist/dashboard/client-registry.js +549 -0
- package/dist/dashboard/client-registry.js.map +1 -0
- package/dist/dashboard/controls.d.ts.map +1 -1
- package/dist/dashboard/controls.js +33 -4
- package/dist/dashboard/controls.js.map +1 -1
- package/dist/dashboard/data-seeder.d.ts +10 -7
- package/dist/dashboard/data-seeder.d.ts.map +1 -1
- package/dist/dashboard/data-seeder.js +31 -75
- package/dist/dashboard/data-seeder.js.map +1 -1
- package/dist/dashboard/data-service.d.ts +9 -0
- package/dist/dashboard/data-service.d.ts.map +1 -1
- package/dist/dashboard/data-service.js +32 -3
- package/dist/dashboard/data-service.js.map +1 -1
- package/dist/dashboard/placement-routes.d.ts +119 -0
- package/dist/dashboard/placement-routes.d.ts.map +1 -0
- package/dist/dashboard/placement-routes.js +331 -0
- package/dist/dashboard/placement-routes.js.map +1 -0
- package/dist/dashboard/server.d.ts.map +1 -1
- package/dist/dashboard/server.js +408 -2
- package/dist/dashboard/server.js.map +1 -1
- package/dist/delivery/attention.d.ts +130 -0
- package/dist/delivery/attention.d.ts.map +1 -0
- package/dist/delivery/attention.js +341 -0
- package/dist/delivery/attention.js.map +1 -0
- package/dist/delivery/decompose.d.ts +18 -0
- package/dist/delivery/decompose.d.ts.map +1 -1
- package/dist/delivery/decompose.js +22 -1
- package/dist/delivery/decompose.js.map +1 -1
- package/dist/delivery/eta-estimate.d.ts +111 -0
- package/dist/delivery/eta-estimate.d.ts.map +1 -0
- package/dist/delivery/eta-estimate.js +171 -0
- package/dist/delivery/eta-estimate.js.map +1 -0
- package/dist/delivery/eta.d.ts +23 -0
- package/dist/delivery/eta.d.ts.map +1 -0
- package/dist/delivery/eta.js +59 -0
- package/dist/delivery/eta.js.map +1 -0
- package/dist/delivery/orchestrated-mission.d.ts +10 -0
- package/dist/delivery/orchestrated-mission.d.ts.map +1 -1
- package/dist/delivery/orchestrated-mission.js +15 -1
- package/dist/delivery/orchestrated-mission.js.map +1 -1
- package/dist/delivery/plan-check.d.ts +7 -1
- package/dist/delivery/plan-check.d.ts.map +1 -1
- package/dist/delivery/plan-check.js +23 -2
- package/dist/delivery/plan-check.js.map +1 -1
- package/dist/delivery/run-state.d.ts +1 -1
- package/dist/delivery/run-state.d.ts.map +1 -1
- package/dist/delivery/run-state.js +8 -1
- package/dist/delivery/run-state.js.map +1 -1
- package/dist/delivery/task-orchestrator.d.ts +8 -3
- package/dist/delivery/task-orchestrator.d.ts.map +1 -1
- package/dist/delivery/task-orchestrator.js +75 -43
- package/dist/delivery/task-orchestrator.js.map +1 -1
- package/dist/delivery/task-sync.d.ts +21 -0
- package/dist/delivery/task-sync.d.ts.map +1 -1
- package/dist/delivery/task-sync.js +44 -8
- package/dist/delivery/task-sync.js.map +1 -1
- package/dist/delivery/task-workspace.d.ts +3 -3
- package/dist/delivery/task-workspace.js +3 -3
- package/dist/generators/self-card.d.ts +65 -0
- package/dist/generators/self-card.d.ts.map +1 -0
- package/dist/generators/self-card.js +256 -0
- package/dist/generators/self-card.js.map +1 -0
- package/dist/inference/probe.js +1 -1
- package/dist/inference/probe.js.map +1 -1
- package/dist/memory/prepopulate.d.ts.map +1 -1
- package/dist/memory/prepopulate.js +2 -0
- package/dist/memory/prepopulate.js.map +1 -1
- package/dist/models/analytics.d.ts +32 -0
- package/dist/models/analytics.d.ts.map +1 -1
- package/dist/models/analytics.js +68 -5
- package/dist/models/analytics.js.map +1 -1
- package/dist/models/plan-readability.d.ts +55 -0
- package/dist/models/plan-readability.d.ts.map +1 -0
- package/dist/models/plan-readability.js +339 -0
- package/dist/models/plan-readability.js.map +1 -0
- package/dist/placement/admission.d.ts +59 -0
- package/dist/placement/admission.d.ts.map +1 -0
- package/dist/placement/admission.js +197 -0
- package/dist/placement/admission.js.map +1 -0
- package/dist/placement/auto.d.ts +44 -0
- package/dist/placement/auto.d.ts.map +1 -0
- package/dist/placement/auto.js +212 -0
- package/dist/placement/auto.js.map +1 -0
- package/dist/placement/enforce.d.ts +128 -0
- package/dist/placement/enforce.d.ts.map +1 -0
- package/dist/placement/enforce.js +655 -0
- package/dist/placement/enforce.js.map +1 -0
- package/dist/placement/idle.d.ts +50 -0
- package/dist/placement/idle.d.ts.map +1 -0
- package/dist/placement/idle.js +213 -0
- package/dist/placement/idle.js.map +1 -0
- package/dist/placement/ledger.d.ts +323 -0
- package/dist/placement/ledger.d.ts.map +1 -0
- package/dist/placement/ledger.js +263 -0
- package/dist/placement/ledger.js.map +1 -0
- package/dist/placement/preview.d.ts +51 -0
- package/dist/placement/preview.d.ts.map +1 -0
- package/dist/placement/preview.js +61 -0
- package/dist/placement/preview.js.map +1 -0
- package/dist/placement/probes.d.ts +47 -0
- package/dist/placement/probes.d.ts.map +1 -0
- package/dist/placement/probes.js +207 -0
- package/dist/placement/probes.js.map +1 -0
- package/dist/placement/proxy-env.d.ts +21 -0
- package/dist/placement/proxy-env.d.ts.map +1 -0
- package/dist/placement/proxy-env.js +42 -0
- package/dist/placement/proxy-env.js.map +1 -0
- package/dist/placement/registry.d.ts +1038 -0
- package/dist/placement/registry.d.ts.map +1 -0
- package/dist/placement/registry.js +274 -0
- package/dist/placement/registry.js.map +1 -0
- package/dist/policies/liveness.d.ts +6 -8
- package/dist/policies/liveness.d.ts.map +1 -1
- package/dist/policies/liveness.js +6 -25
- package/dist/policies/liveness.js.map +1 -1
- package/dist/policies/sandbox-anchor.d.ts +91 -0
- package/dist/policies/sandbox-anchor.d.ts.map +1 -0
- package/dist/policies/sandbox-anchor.js +187 -0
- package/dist/policies/sandbox-anchor.js.map +1 -0
- package/dist/policies/sandbox-grants.d.ts +131 -0
- package/dist/policies/sandbox-grants.d.ts.map +1 -0
- package/dist/policies/sandbox-grants.js +562 -0
- package/dist/policies/sandbox-grants.js.map +1 -0
- package/dist/state/manifest.d.ts +4 -2
- package/dist/state/manifest.d.ts.map +1 -1
- package/dist/state/manifest.js +32 -16
- package/dist/state/manifest.js.map +1 -1
- package/dist/utils/checkout-root.d.ts +2 -0
- package/dist/utils/checkout-root.d.ts.map +1 -0
- package/dist/utils/checkout-root.js +43 -0
- package/dist/utils/checkout-root.js.map +1 -0
- package/dist/utils/resolve-uap-bin.d.ts +5 -0
- package/dist/utils/resolve-uap-bin.d.ts.map +1 -0
- package/dist/utils/resolve-uap-bin.js +33 -0
- package/dist/utils/resolve-uap-bin.js.map +1 -0
- package/dist/utils/terminal-safe.d.ts +12 -0
- package/dist/utils/terminal-safe.d.ts.map +1 -0
- package/dist/utils/terminal-safe.js +53 -0
- package/dist/utils/terminal-safe.js.map +1 -0
- package/docs/ATTRIBUTION.md +1 -0
- package/docs/DASHBOARD_UPLIFT_SPEC.md +8 -8
- package/docs/INDEX.md +6 -5
- package/docs/architecture/OVERVIEW.md +15 -3
- package/docs/architecture/PROTOCOL.md +7 -1
- package/docs/architecture/adr/0006-operator-directed-model-placement.md +86 -0
- package/docs/architecture/adr/0007-auto-displacement-allowlist-as-standing-consent.md +79 -0
- package/docs/architecture/adr/0008-fleet-clients-link-out.md +92 -0
- package/docs/architecture/adr/0009-completion-triggered-dispatch-and-per-leaf-model-dials.md +71 -0
- package/docs/architecture/adr/0010-attention-queue-and-afk-auto-decider.md +159 -0
- package/docs/architecture/adr/0011-sandbox-grants-and-network-egress-boundary.md +219 -0
- package/docs/architecture/adr/0012-operator-legibility-surfaces.md +175 -0
- package/docs/getting-started/INSTALLATION.md +1 -1
- package/docs/guides/AUTOMATIC_FEATURES.md +8 -0
- package/docs/guides/LOCAL_MODELS.md +1 -1
- package/docs/guides/PROXY.md +2 -1
- package/docs/guides/SANDBOX.md +91 -4
- package/docs/integrations/MCP_ROUTER.md +1 -1
- package/docs/plans/model-performance-proof-options.md +176 -0
- package/docs/reference/API.md +1 -1
- package/docs/reference/CLI.md +169 -4
- package/docs/reference/COMPARISON.md +1 -1
- package/docs/reference/CONFIGURATION.md +12 -3
- package/docs/reference/CONFIGURATION_REFERENCE.md +269 -14
- package/docs/reference/DATABASE_SCHEMA.md +1 -1
- package/docs/reference/FEATURES.md +15 -3
- package/docs/reference/PATTERNS.md +1 -1
- package/docs/reference/PLATFORMS.md +14 -1
- package/docs/specs/operator-model-placement.md +1314 -0
- package/docs/specs/operator-model-placement.review.md +339 -0
- package/package.json +2 -2
- package/scripts/maintenance/publish-npm.sh +23 -11
- package/scripts/version-bump.sh +6 -51
- package/src/policies/enforcers/__pycache__/_common.cpython-311.pyc +0 -0
- package/src/policies/enforcers/__pycache__/expert_review_required.cpython-311.pyc +0 -0
- package/src/policies/enforcers/__pycache__/quality_metrics_gate.cpython-311.pyc +0 -0
- package/src/policies/schemas/policies/mandatory-testing-deployment.md +2 -5
- package/templates/hooks/__pycache__/deliver_autoroute.cpython-311.pyc +0 -0
- package/templates/hooks/session-start.sh +44 -0
- package/tools/agents/UAP/cli.py +14 -3
- package/tools/agents/UAP/paths.py +50 -0
- package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-311.pyc +0 -0
- package/tools/agents/scripts/anthropic_proxy.py +1420 -100
- package/tools/agents/scripts/toolcall_path_normalizer.py +46 -1
- package/tools/agents/tests/test_anthropic_proxy_streaming.py +29 -6
- package/tools/agents/tests/test_doubling_break.py +64 -5
- package/tools/agents/tests/test_error_loop_break.py +10 -4
- package/tools/agents/tests/test_error_loop_ignores_correctives.py +13 -2
- package/tools/agents/tests/test_lockstep_escalation.py +280 -9
- package/tools/agents/tests/test_path_containment.py +94 -0
- package/tools/agents/tests/test_proxy_unix_socket.py +162 -0
- package/tools/agents/tests/test_signature_quality.py +400 -0
- package/tools/agents/tests/test_uap_compliance.py +11 -1
- package/web/dash/core.js +1 -0
- package/web/dash/tab-clients.js +196 -0
- package/web/dash/tab-models.js +387 -8
- package/web/dash/tab-policies.js +87 -4
- package/web/dash/tabs.js +77 -73
- package/web/dashboard.html +6 -0
- package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
- package/src/policies/enforcers/__pycache__/expert_review_required.cpython-312.pyc +0 -0
- package/src/policies/enforcers/__pycache__/quality_metrics_gate.cpython-312.pyc +0 -0
- package/templates/hooks/__pycache__/deliver_autoroute.cpython-312.pyc +0 -0
- package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
- package/web/dash/tab-agents.js +0 -21
- package/web/dash/tab-deliver.js +0 -12
- package/web/dash/tab-memory.js +0 -12
- package/web/dash/tab-orchestration.js +0 -21
- package/web/dash/tab-overview.js +0 -21
- package/web/dash/tab-tasks.js +0 -21
|
@@ -124,18 +124,18 @@ export declare const MetricVectorSchema: z.ZodObject<{
|
|
|
124
124
|
error: z.ZodNullable<z.ZodString>;
|
|
125
125
|
}, "strip", z.ZodTypeAny, {
|
|
126
126
|
error: string | null;
|
|
127
|
+
turns: number | null;
|
|
127
128
|
tokens: number | null;
|
|
128
129
|
latencyMs: number;
|
|
129
|
-
turns: number | null;
|
|
130
130
|
toolCalls: number | null;
|
|
131
131
|
correct: boolean;
|
|
132
132
|
costUsd: number | null;
|
|
133
133
|
wellFormed: boolean | null;
|
|
134
134
|
}, {
|
|
135
135
|
error: string | null;
|
|
136
|
+
turns: number | null;
|
|
136
137
|
tokens: number | null;
|
|
137
138
|
latencyMs: number;
|
|
138
|
-
turns: number | null;
|
|
139
139
|
toolCalls: number | null;
|
|
140
140
|
correct: boolean;
|
|
141
141
|
costUsd: number | null;
|
package/dist/bin/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import { Command, Option } from 'commander';
|
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import { registerConfigCommands } from '../cli/config-command.js';
|
|
5
5
|
import { existsSync, readFileSync } from 'fs';
|
|
6
|
-
import {
|
|
6
|
+
import { execFileSync } from 'child_process';
|
|
7
7
|
import { fileURLToPath } from 'url';
|
|
8
8
|
import { dirname, join } from 'path';
|
|
9
9
|
// Lazy import helpers - commands are loaded on-demand to reduce startup time (~10x faster --help)
|
|
@@ -25,6 +25,7 @@ const lazy = {
|
|
|
25
25
|
model: () => import('../cli/model.js').then((m) => m.registerModelCommands),
|
|
26
26
|
mcpRouter: () => import('../cli/mcp-router.js').then((m) => m.mcpRouterCommand),
|
|
27
27
|
dashboard: () => import('../cli/dashboard.js').then((m) => m.dashboardCommand),
|
|
28
|
+
clients: () => import('../cli/clients.js').then((m) => m.clientsCommand),
|
|
28
29
|
hooks: () => import('../cli/hooks.js'),
|
|
29
30
|
patterns: () => import('../cli/patterns.js').then((m) => m.patternsCommand),
|
|
30
31
|
skill: () => import('../cli/skill.js').then((m) => m.skillCommand),
|
|
@@ -44,8 +45,11 @@ const lazy = {
|
|
|
44
45
|
interaction: () => import('../cli/interaction.js').then((m) => m.interactionCommand),
|
|
45
46
|
orchestratorToggle: () => import('../cli/orchestrator-toggle.js').then((m) => m.orchestratorToggleCommand),
|
|
46
47
|
handsfree: () => import('../cli/handsfree.js').then((m) => m.handsfreeCommand),
|
|
48
|
+
eta: () => import('../cli/eta.js').then((m) => m.etaCommand),
|
|
49
|
+
diff: () => import('../cli/diff.js').then((m) => m.diffCommand),
|
|
47
50
|
proxy: () => import('../cli/proxy.js').then((m) => m.proxyCommand),
|
|
48
51
|
benchPaired: () => import('../cli/bench.js').then((m) => m.benchPairedCommand),
|
|
52
|
+
benchReport: () => import('../cli/bench-report.js').then((m) => m.benchReportCommand),
|
|
49
53
|
tune: () => import('../cli/self-tuning.js').then((m) => m.tuneCommand),
|
|
50
54
|
sandbox: () => import('../cli/sandbox.js').then((m) => m.sandboxCommand),
|
|
51
55
|
design: () => import('../cli/design.js').then((m) => m.designCommand),
|
|
@@ -57,11 +61,14 @@ const lazy = {
|
|
|
57
61
|
doctor: () => import('../cli/doctor.js').then((m) => m.doctorCommand),
|
|
58
62
|
loops: () => import('../cli/loops.js').then((m) => m.loopsCommand),
|
|
59
63
|
inference: () => import('../cli/inference.js').then((m) => m.inferenceHealthCommand),
|
|
64
|
+
models: () => import('../cli/models.js').then((m) => m.modelsCommand),
|
|
60
65
|
review: () => import('../cli/review.js').then((m) => m.reviewCommand),
|
|
61
66
|
principles: () => import('../cli/principles.js').then((m) => m.principlesCommand),
|
|
62
67
|
challenge: () => import('../cli/challenge.js').then((m) => m.challengeCommand),
|
|
63
68
|
fidelity: () => import('../cli/fidelity.js').then((m) => m.fidelityCommand),
|
|
64
69
|
plan: () => import('../cli/plan.js').then((m) => m.planCommand),
|
|
70
|
+
self: () => import('../cli/self.js').then((m) => m.selfCommand),
|
|
71
|
+
attention: () => import('../cli/attention.js').then((m) => m.attentionCommand),
|
|
65
72
|
};
|
|
66
73
|
// Read version from package.json
|
|
67
74
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -109,10 +116,13 @@ program
|
|
|
109
116
|
});
|
|
110
117
|
program
|
|
111
118
|
.command('proxy [subcommand] [value]')
|
|
112
|
-
.description('Reference-counted, session-scoped proxy + dashboard lifecycle: ensure | release | status | start | stop | restart | enable | disable | dashboard [on|off]')
|
|
119
|
+
.description('Reference-counted, session-scoped proxy + dashboard lifecycle: ensure | release | status | start | stop | restart | enable | disable | dashboard [on|off] | connect --socket <path>')
|
|
113
120
|
.option('--client <id>', 'Client/session id (defaults to session env or parent pid)')
|
|
114
121
|
.option('--client-pid <n>', 'Long-lived agent pid for liveness (hooks pass $PPID)')
|
|
115
122
|
.option('--port <n>', 'Proxy port (default 4000 / $PROXY_PORT)')
|
|
123
|
+
.option('--socket <path>', 'connect: proxy AF_UNIX socket (default $UAP_PROXY_SOCKET)')
|
|
124
|
+
.option('--ready-file <path>', 'connect: touch this file once the relay is listening (readiness handshake)')
|
|
125
|
+
.option('--allow-anyone', 'connect: accept that the relay re-serves the 0600 socket on TCP — while it runs, EVERY local user can reach the model path')
|
|
116
126
|
.option('--quiet', 'Suppress output (used by hooks)')
|
|
117
127
|
.option('--if-enabled', 'No-op unless .uap.json proxy.autostart is true (hook-safe)')
|
|
118
128
|
.option('--json', 'Machine-readable status output')
|
|
@@ -132,11 +142,20 @@ program
|
|
|
132
142
|
.command('sandbox')
|
|
133
143
|
.description('Run a command with a kernel-enforced workdir boundary (bubblewrap): only the ' +
|
|
134
144
|
'current dir + scratch are writable, so writes outside fail at the kernel — the ' +
|
|
135
|
-
'boundary --dangerously-skip-permissions cannot bypass.
|
|
145
|
+
'boundary --dangerously-skip-permissions cannot bypass. Optional P4 authorities: ' +
|
|
146
|
+
'`--net off` cuts the network namespace entirely (kernel egress boundary), ' +
|
|
147
|
+
'and per-session writable holes come from the consent ledger ' +
|
|
148
|
+
'(uap sandbox grant <path> --session <id> --reason "..." | grants | revoke <id>). ' +
|
|
149
|
+
'Usage: uap sandbox [--session <id>] [--net shared|off] -- <command> [args...]')
|
|
136
150
|
.argument('[command...]', 'Command to run sandboxed (prefix with -- to pass its flags through)')
|
|
151
|
+
.option('--session <id>', 'Session id the grant ledger is scoped to (default $UAP_SESSION_ID)')
|
|
152
|
+
.option('--net <mode>', 'Network mode: shared (default) or off (kernel egress boundary — no network at all)')
|
|
153
|
+
.option('--ttl <secs>', 'grant: seconds before the grant expires (default 8h, cap 7d)')
|
|
154
|
+
.option('--reason <why>', 'grant: WHY this authority is consented (required)')
|
|
155
|
+
.option('--json', 'grants: machine-readable list')
|
|
137
156
|
.allowUnknownOption(true)
|
|
138
|
-
.action(async (command) => {
|
|
139
|
-
await (await lazy.sandbox())(command || []);
|
|
157
|
+
.action(async (command, options) => {
|
|
158
|
+
await (await lazy.sandbox())(command || [], options);
|
|
140
159
|
});
|
|
141
160
|
program
|
|
142
161
|
.command('generate')
|
|
@@ -468,6 +487,7 @@ program
|
|
|
468
487
|
.argument('[id]', 'list index or fingerprint prefix — show one incident with its escalation handoff')
|
|
469
488
|
.option('--limit <n>', 'how many recent incidents to list', '10')
|
|
470
489
|
.option('--json', 'Emit machine-readable JSON')
|
|
490
|
+
.option('--steer', 'Emit the recurring-hazard digest for session context (silent when no class repeats)')
|
|
471
491
|
.option('--file <path>', 'Ledger path (default: $UAP_LOOP_INCIDENTS or ~/.config/uap/loop-incidents.jsonl)')
|
|
472
492
|
.action(async (id, options) => {
|
|
473
493
|
const cmd = await lazy.loops();
|
|
@@ -498,6 +518,142 @@ program
|
|
|
498
518
|
const cmd = await lazy.inference();
|
|
499
519
|
await cmd(options);
|
|
500
520
|
});
|
|
521
|
+
// Model placement registry (spec: docs/specs/operator-model-placement.md) —
|
|
522
|
+
// `models` (plural) is placement: where a model lives and what it costs.
|
|
523
|
+
// The existing `uap model` (singular) is multi-model routing: which model
|
|
524
|
+
// answers. Both surfaces cross-reference each other in help text.
|
|
525
|
+
program
|
|
526
|
+
.command('models')
|
|
527
|
+
.description('Model placement registry: validate footprints, measure the live backend')
|
|
528
|
+
.addCommand(new Command('validate')
|
|
529
|
+
.description('Cross-check the registry (repo + ~/.uap/model-registry.json) against the capacity policy')
|
|
530
|
+
.option('--repo-path <path>', 'explicit repo registry path (default: <project>/config/model-registry.json)')
|
|
531
|
+
.option('--local-path <path>', 'explicit machine-local registry path (default: ~/.uap/model-registry.json)')
|
|
532
|
+
.action(async (options) => {
|
|
533
|
+
const code = await (await lazy.models())('validate', options);
|
|
534
|
+
if (code)
|
|
535
|
+
process.exitCode = code;
|
|
536
|
+
}))
|
|
537
|
+
.addCommand(new Command('measure')
|
|
538
|
+
.description('Record the live backend\'s measured footprint into the machine-local registry')
|
|
539
|
+
.option('--model <key>', 'registry model key to attribute the measurement to')
|
|
540
|
+
.option('--config <key>', 'registry config key to attribute the measurement to')
|
|
541
|
+
.option('--endpoint <url>', 'inference base URL (default: http://127.0.0.1:8080)')
|
|
542
|
+
.option('--device <key>', 'device key the measurement is valid on (default: first gpu in the registry)')
|
|
543
|
+
.option('--dry-run', 'Print what would be written; write nothing')
|
|
544
|
+
.action(async (options) => {
|
|
545
|
+
const code = await (await lazy.models())('measure', { ...options, dryRun: options.dryRun === true });
|
|
546
|
+
if (code)
|
|
547
|
+
process.exitCode = code;
|
|
548
|
+
}))
|
|
549
|
+
.addCommand(new Command('status')
|
|
550
|
+
.description('Sync and print the placement ledger: devices (probe fact), residents, headroom')
|
|
551
|
+
.option('--repo-path <path>', 'explicit repo registry path')
|
|
552
|
+
.option('--local-path <path>', 'explicit machine-local registry path')
|
|
553
|
+
.option('--ledger-path <path>', 'explicit placement ledger path (default: ~/.uap/placement.json)')
|
|
554
|
+
.action(async (options) => {
|
|
555
|
+
const code = await (await lazy.models())('status', options);
|
|
556
|
+
if (code)
|
|
557
|
+
process.exitCode = code;
|
|
558
|
+
}))
|
|
559
|
+
.addCommand(new Command('pending')
|
|
560
|
+
.description('List parked placement requests awaiting the operator, with ranked options')
|
|
561
|
+
.option('--repo-path <path>', 'explicit repo registry path')
|
|
562
|
+
.option('--local-path <path>', 'explicit machine-local registry path')
|
|
563
|
+
.option('--ledger-path <path>', 'explicit placement ledger path (default: ~/.uap/placement.json)')
|
|
564
|
+
.action(async (options) => {
|
|
565
|
+
const code = await (await lazy.models())('pending', options);
|
|
566
|
+
if (code)
|
|
567
|
+
process.exitCode = code;
|
|
568
|
+
}))
|
|
569
|
+
.addCommand(
|
|
570
|
+
// Args as .argument(), NOT in the name: commander matches the invoked
|
|
571
|
+
// subcommand by NAME, and a name like 'apply <id> <option>' never
|
|
572
|
+
// matches 'apply' (verified live: help listed it, invocation didn't).
|
|
573
|
+
new Command('apply')
|
|
574
|
+
.argument('<placementId>', 'pending placement id (from `uap models pending`)')
|
|
575
|
+
.argument('<option>', '1-based option index (as printed by `uap models pending`)')
|
|
576
|
+
.description('The explicit operator yes: print the impact list, then enforce the placement (rollback on failure)')
|
|
577
|
+
.option('--yes', 'Actually enforce; without it, prints the impact list and the confirm command')
|
|
578
|
+
.option('--repo-path <path>', 'explicit repo registry path')
|
|
579
|
+
.option('--local-path <path>', 'explicit machine-local registry path')
|
|
580
|
+
.option('--ledger-path <path>', 'explicit placement ledger path (default: ~/.uap/placement.json)')
|
|
581
|
+
.action(async (placementId, option, options) => {
|
|
582
|
+
const code = await (await lazy.models())('apply', {
|
|
583
|
+
...options,
|
|
584
|
+
placementId,
|
|
585
|
+
option: Number(option),
|
|
586
|
+
yes: options.yes === true,
|
|
587
|
+
});
|
|
588
|
+
if (code)
|
|
589
|
+
process.exitCode = code;
|
|
590
|
+
}))
|
|
591
|
+
.addCommand(new Command('dismiss')
|
|
592
|
+
.argument('<placementId>', 'pending placement id')
|
|
593
|
+
.description('Refuse a parked placement request; the client falls back on expiry')
|
|
594
|
+
.option('--ledger-path <path>', 'explicit placement ledger path (default: ~/.uap/placement.json)')
|
|
595
|
+
.action(async (placementId, options) => {
|
|
596
|
+
const code = await (await lazy.models())('dismiss', { ...options, placementId });
|
|
597
|
+
if (code)
|
|
598
|
+
process.exitCode = code;
|
|
599
|
+
}))
|
|
600
|
+
.addCommand(new Command('load')
|
|
601
|
+
.argument('<model>', 'registry model key (e.g. qwen3.8-27b)')
|
|
602
|
+
.description('Operator-initiated load: reuse/load-alongside only (displacement needs a pending request)')
|
|
603
|
+
.option('--ledger-path <path>', 'explicit placement ledger path (default: ~/.uap/placement.json)')
|
|
604
|
+
.action(async (model, options) => {
|
|
605
|
+
const code = await (await lazy.models())('load', { ...options, model });
|
|
606
|
+
if (code)
|
|
607
|
+
process.exitCode = code;
|
|
608
|
+
}))
|
|
609
|
+
.addCommand(new Command('unload')
|
|
610
|
+
.argument('<model>', 'registry model key whose live residents should be drained and stopped')
|
|
611
|
+
.description('Drain, stop, verify-free, and refresh for a model\'s live residents')
|
|
612
|
+
.option('--ledger-path <path>', 'explicit placement ledger path (default: ~/.uap/placement.json)')
|
|
613
|
+
.action(async (model, options) => {
|
|
614
|
+
const code = await (await lazy.models())('unload', { ...options, model });
|
|
615
|
+
if (code)
|
|
616
|
+
process.exitCode = code;
|
|
617
|
+
}))
|
|
618
|
+
.addCommand(new Command('units')
|
|
619
|
+
.description('Write Conflicts= drop-ins for same-device registry units (systemd then refuses two residents per device)')
|
|
620
|
+
.option('--repo-path <path>', 'explicit repo registry path')
|
|
621
|
+
.option('--local-path <path>', 'explicit machine-local registry path')
|
|
622
|
+
.action(async (options) => {
|
|
623
|
+
const code = await (await lazy.models())('units', options);
|
|
624
|
+
if (code)
|
|
625
|
+
process.exitCode = code;
|
|
626
|
+
}))
|
|
627
|
+
.addCommand(new Command('auto')
|
|
628
|
+
.description('Auto-load policy: load-alongside always; displacement only for allowlisted models (request-driven, no manual apply). Off until --enable.')
|
|
629
|
+
.option('--enable', 'enable auto-load')
|
|
630
|
+
.option('--disable', 'disable auto-load; every park needs a manual apply again')
|
|
631
|
+
.option('--allow-displace <models>', 'comma-separated registry model keys whose displacement may auto-enforce')
|
|
632
|
+
.option('--disallow-displace <models>', 'comma-separated registry model keys to remove from the displacement allowlist')
|
|
633
|
+
.option('--allow-unload <models>', 'comma-separated registry model keys that may be auto-unloaded once idle (standing consent; needs --yes)')
|
|
634
|
+
.option('--disallow-unload <models>', 'comma-separated registry model keys to remove from the idle-unload allowlist')
|
|
635
|
+
.option('--unload-idle-after-secs <secs>', 'arm idle-unload: no gated use for this many seconds and a listed resident is swept (min 60)')
|
|
636
|
+
.option('--unload-idle-off', 'disarm the idle-unload timer (allowlist is kept)')
|
|
637
|
+
.option('--yes', 'required with --allow-displace / --allow-unload: the standing consent being recorded')
|
|
638
|
+
.option('--policy-path <path>', 'explicit policy file path (testing only: the controller reads ~/.uap/placement-auto.json or UAP_PLACEMENT_AUTO)')
|
|
639
|
+
.action(async (options) => {
|
|
640
|
+
const code = await (await lazy.models())('auto', {
|
|
641
|
+
enable: options.enable === true,
|
|
642
|
+
disable: options.disable === true,
|
|
643
|
+
allowDisplace: options.allowDisplace,
|
|
644
|
+
disallowDisplace: options.disallowDisplace,
|
|
645
|
+
allowUnload: options.allowUnload,
|
|
646
|
+
disallowUnload: options.disallowUnload,
|
|
647
|
+
unloadIdleAfterSecs: options.unloadIdleAfterSecs === undefined
|
|
648
|
+
? undefined
|
|
649
|
+
: Number(options.unloadIdleAfterSecs),
|
|
650
|
+
unloadIdleAfterSecsOff: options.unloadIdleOff === true,
|
|
651
|
+
yes: options.yes === true,
|
|
652
|
+
policyPath: options.policyPath,
|
|
653
|
+
});
|
|
654
|
+
if (code)
|
|
655
|
+
process.exitCode = code;
|
|
656
|
+
}));
|
|
501
657
|
// Quality-metrics gate — complexity/coverage/mutation policing with a ratchet
|
|
502
658
|
program
|
|
503
659
|
.command('quality')
|
|
@@ -895,6 +1051,39 @@ program
|
|
|
895
1051
|
const cmd = await lazy.plan();
|
|
896
1052
|
await cmd(action, { json: Boolean(options.json), file, review: options.review, force: Boolean(options.force) });
|
|
897
1053
|
});
|
|
1054
|
+
// S2 self-knowledge card — UAP's own manual, built offline from shipped docs
|
|
1055
|
+
program
|
|
1056
|
+
.command('self')
|
|
1057
|
+
.description('Self-knowledge card: the version-pinned digest of UAP\'s own commands/features, and offline search over it')
|
|
1058
|
+
.argument('[action]', 'card | query <question> (default: card)')
|
|
1059
|
+
.argument('[question]', 'query: the question to answer from the card')
|
|
1060
|
+
.option('--json', 'Emit JSON')
|
|
1061
|
+
.option('--refresh', 'card: rebuild even when the version pin still matches')
|
|
1062
|
+
.option('--limit <n>', 'query: max results (default 5)')
|
|
1063
|
+
.action(async (action, question, options) => {
|
|
1064
|
+
const cmd = await lazy.self();
|
|
1065
|
+
await cmd(action, question, {
|
|
1066
|
+
json: Boolean(options.json),
|
|
1067
|
+
refresh: Boolean(options.refresh),
|
|
1068
|
+
limit: options.limit !== undefined ? Number(options.limit) : undefined,
|
|
1069
|
+
});
|
|
1070
|
+
});
|
|
1071
|
+
// Attention queue — the ask-instead-of-stop rail
|
|
1072
|
+
program
|
|
1073
|
+
.command('attention')
|
|
1074
|
+
.description('Operator attention queue: items needing your decision, with AFK safe-default adoption')
|
|
1075
|
+
.argument('[action]', 'list | ack <id> | decide <id> <decision> | sweep (default: list)')
|
|
1076
|
+
.argument('[id]', 'ack/decide: the item id')
|
|
1077
|
+
.argument('[decision]', 'decide: your decision text')
|
|
1078
|
+
.option('--status <s>', 'list: pending | acknowledged | decided | auto-decided | escalated (default: pending)')
|
|
1079
|
+
.option('--json', 'Emit JSON')
|
|
1080
|
+
.action(async (action, id, decision, options) => {
|
|
1081
|
+
const cmd = await lazy.attention();
|
|
1082
|
+
await cmd(action, id, decision, {
|
|
1083
|
+
json: Boolean(options.json),
|
|
1084
|
+
status: typeof options.status === 'string' ? options.status : undefined,
|
|
1085
|
+
});
|
|
1086
|
+
});
|
|
898
1087
|
// Paired UAP benchmark — controlled UAP-on vs UAP-off A/B
|
|
899
1088
|
const bench = program
|
|
900
1089
|
.command('bench')
|
|
@@ -920,6 +1109,44 @@ bench
|
|
|
920
1109
|
const cmd = await lazy.benchPaired();
|
|
921
1110
|
await cmd(options);
|
|
922
1111
|
});
|
|
1112
|
+
bench
|
|
1113
|
+
.command('report')
|
|
1114
|
+
.description('Read the latest paired report (or --dir); --compare shows run-to-run delta drift. Deltas always carry their discrimination status')
|
|
1115
|
+
.option('--dir <dir>', 'A specific paired-run dir (default: newest under benchmark-results)')
|
|
1116
|
+
.option('--compare', 'Compare the two newest runs: which deltas held, flipped, narrowed')
|
|
1117
|
+
.option('--full', 'Print the stored report.md instead of the compact delta summary')
|
|
1118
|
+
.option('--json', 'Emit the raw report JSON')
|
|
1119
|
+
.action(async (options) => {
|
|
1120
|
+
const cmd = await lazy.benchReport();
|
|
1121
|
+
await cmd(options);
|
|
1122
|
+
});
|
|
1123
|
+
// Measured pace — the agent's own EWMA ETA over its recorded attempts (P5: S1b)
|
|
1124
|
+
program
|
|
1125
|
+
.command('eta')
|
|
1126
|
+
.description('Measured pace: the EWMA ETA for a (model, taskType, complexity) key, from this project\'s own recorded attempts')
|
|
1127
|
+
.option('-m, --model <id>', 'Model id (default: the active/executor model)')
|
|
1128
|
+
.option('--task-type <t>', "Sample key: task type (default 'orchestrated')")
|
|
1129
|
+
.option('--complexity <c>', 'Sample key: complexity tier (default medium)')
|
|
1130
|
+
.option('--all', 'List every key with history (estimates + too-thin keys)')
|
|
1131
|
+
.option('--limit <n>', 'Sample window size (default 50)')
|
|
1132
|
+
.option('--half-life <n>', 'EWMA half-life in samples (default 10)')
|
|
1133
|
+
.option('--db <path>', 'Pin the analytics DB path (tests, odd layouts)')
|
|
1134
|
+
.option('--json', 'Emit JSON')
|
|
1135
|
+
.action(async (options) => {
|
|
1136
|
+
const cmd = await lazy.eta();
|
|
1137
|
+
await cmd(options);
|
|
1138
|
+
});
|
|
1139
|
+
// Local diff view — what the agent changed around here (P5: S3)
|
|
1140
|
+
program
|
|
1141
|
+
.command('diff')
|
|
1142
|
+
.description('Local diff view: uncommitted + unpushed changes at a glance, with per-file deltas and inspection commands')
|
|
1143
|
+
.option('--base <ref>', 'Base ref for the unpushed view (default: master)')
|
|
1144
|
+
.option('--max <n>', 'Per-section file cap (default 40)')
|
|
1145
|
+
.option('--json', 'Emit the raw facts as JSON')
|
|
1146
|
+
.action(async (options) => {
|
|
1147
|
+
const cmd = await lazy.diff();
|
|
1148
|
+
await cmd(options);
|
|
1149
|
+
});
|
|
923
1150
|
// HALO harness-optimization commands
|
|
924
1151
|
const harness = program
|
|
925
1152
|
.command('harness')
|
|
@@ -1675,6 +1902,40 @@ program
|
|
|
1675
1902
|
.action(async (options) => {
|
|
1676
1903
|
(await lazy.dashboard())('history', options);
|
|
1677
1904
|
}));
|
|
1905
|
+
// Client folder fleet — registry CLI behind the dashboard's Clients tab
|
|
1906
|
+
program
|
|
1907
|
+
.command('clients')
|
|
1908
|
+
.description('Client folder fleet: list, add, remove, scan (feeds the dashboard Clients tab)')
|
|
1909
|
+
.addCommand(new Command('list')
|
|
1910
|
+
.description('Fleet summary for every discovered client (live reads)')
|
|
1911
|
+
.action(async () => {
|
|
1912
|
+
(await lazy.clients())('list', undefined, {});
|
|
1913
|
+
}))
|
|
1914
|
+
.addCommand(new Command('add')
|
|
1915
|
+
.description('Pin a client folder manually')
|
|
1916
|
+
.argument('<path>', 'Path to the client project root')
|
|
1917
|
+
.option('--name <name>', 'Display name (defaults to the folder name)')
|
|
1918
|
+
.option('--port <port>', 'Dashboard port for spawn-on-demand (default: 3861+)')
|
|
1919
|
+
.action(async (path, options) => {
|
|
1920
|
+
(await lazy.clients())('add', path, options);
|
|
1921
|
+
}))
|
|
1922
|
+
.addCommand(new Command('remove')
|
|
1923
|
+
.description('Unpin a manually added client')
|
|
1924
|
+
.argument('<path>', 'Path that was pinned with `add`')
|
|
1925
|
+
.action(async (path) => {
|
|
1926
|
+
(await lazy.clients())('remove', path, {});
|
|
1927
|
+
}))
|
|
1928
|
+
.addCommand(new Command('scan')
|
|
1929
|
+
.description('Show what auto-scan discovers')
|
|
1930
|
+
.action(async () => {
|
|
1931
|
+
(await lazy.clients())('scan', undefined, {});
|
|
1932
|
+
}))
|
|
1933
|
+
.addCommand(new Command('stop')
|
|
1934
|
+
.description("Stop a client's spawned dashboard (pid ownership-verified)")
|
|
1935
|
+
.argument('<path>', 'Path to the client project root')
|
|
1936
|
+
.action(async (path) => {
|
|
1937
|
+
(await lazy.clients())('stop', path, {});
|
|
1938
|
+
}));
|
|
1678
1939
|
// Multi-Model Architecture commands - visible in --help, loaded on demand
|
|
1679
1940
|
{
|
|
1680
1941
|
const modelCmd = program
|
|
@@ -1850,7 +2111,10 @@ uapOmpCmd.addCommand(new Command('dashboard')
|
|
|
1850
2111
|
const uapOmpDir = process.env.HOME + '/.uap/omp';
|
|
1851
2112
|
const dashboardScript = `${uapOmpDir}/commands/uap-dashboard.sh`;
|
|
1852
2113
|
if (existsSync(dashboardScript)) {
|
|
1853
|
-
|
|
2114
|
+
// Argv array, never a shell: the path interpolates into a command
|
|
2115
|
+
// string at the old call site (prepass debt) and a hostile HOME
|
|
2116
|
+
// must not become a shell metacharacter.
|
|
2117
|
+
execFileSync('bash', [dashboardScript], { stdio: 'inherit' });
|
|
1854
2118
|
}
|
|
1855
2119
|
else {
|
|
1856
2120
|
console.error('UAP dashboard not installed. Run: uap-omp install');
|
|
@@ -1864,14 +2128,26 @@ uapOmpCmd.addCommand(new Command('dashboard')
|
|
|
1864
2128
|
// Memory command
|
|
1865
2129
|
uapOmpCmd.addCommand(new Command('memory')
|
|
1866
2130
|
.description('Manage UAP memory for oh-my-pi')
|
|
1867
|
-
.addCommand(new Command('status').description('Show memory status').action(() => {
|
|
2131
|
+
.addCommand(new Command('status').description('Show memory status').action(async () => {
|
|
1868
2132
|
try {
|
|
1869
2133
|
const uapOmpDir = process.env.HOME + '/.uap/omp';
|
|
1870
2134
|
const dbPath = `${uapOmpDir}/memory/short_term.db`;
|
|
1871
2135
|
if (existsSync(dbPath)) {
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
2136
|
+
// The omp memory DB is better-sqlite3's own format: read it with
|
|
2137
|
+
// the library (lazy — keeps `uap --help` fast), never the sqlite3
|
|
2138
|
+
// CLI through a shell. The old call interpolated the path into
|
|
2139
|
+
// `execSync` (prepass debt).
|
|
2140
|
+
const { default: Database } = await import('better-sqlite3');
|
|
2141
|
+
const db = new Database(dbPath, { readonly: true, fileMustExist: true });
|
|
2142
|
+
try {
|
|
2143
|
+
const row = db
|
|
2144
|
+
.prepare('SELECT COUNT(*) as total, COUNT(DISTINCT type) as types FROM memories')
|
|
2145
|
+
.get();
|
|
2146
|
+
console.log(`total: ${row.total}\ntypes: ${row.types}`);
|
|
2147
|
+
}
|
|
2148
|
+
finally {
|
|
2149
|
+
db.close();
|
|
2150
|
+
}
|
|
1875
2151
|
}
|
|
1876
2152
|
else {
|
|
1877
2153
|
console.log('No memory database found. Run: uap-omp install');
|
|
@@ -1886,17 +2162,32 @@ uapOmpCmd.addCommand(new Command('memory')
|
|
|
1886
2162
|
.description('Query memory for relevant context')
|
|
1887
2163
|
.argument('<search>', 'Search term')
|
|
1888
2164
|
.option('-n, --limit <number>', 'Max results', '5')
|
|
1889
|
-
.action((search, options) => {
|
|
2165
|
+
.action(async (search, options) => {
|
|
1890
2166
|
try {
|
|
1891
2167
|
const uapOmpDir = process.env.HOME + '/.uap/omp';
|
|
1892
2168
|
const dbPath = `${uapOmpDir}/memory/short_term.db`;
|
|
1893
2169
|
if (existsSync(dbPath)) {
|
|
1894
|
-
//
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
2170
|
+
// Parameterized LIKE + bound LIMIT: the search term is
|
|
2171
|
+
// user/LLM-controlled and must never reach a shell or be
|
|
2172
|
+
// spliced into SQL text (the old `execSync` call was a real
|
|
2173
|
+
// injection surface — `$()` inside its double quotes executed).
|
|
2174
|
+
// LIKE wildcards in the TERM are escaped too: a literal `%`
|
|
2175
|
+
// search is a literal-% search, not "dump the whole table".
|
|
2176
|
+
const { default: Database } = await import('better-sqlite3');
|
|
2177
|
+
const parsedLimit = parseInt(options.limit, 10);
|
|
2178
|
+
const limit = Number.isFinite(parsedLimit) ? parsedLimit : 5;
|
|
2179
|
+
const db = new Database(dbPath, { readonly: true, fileMustExist: true });
|
|
2180
|
+
try {
|
|
2181
|
+
const rows = db
|
|
2182
|
+
.prepare("SELECT content, type, importance FROM memories WHERE content LIKE ? ESCAPE '\\' ORDER BY importance DESC LIMIT ?")
|
|
2183
|
+
.all(`%${String(search).replace(/[\\%_]/g, (m) => `\\${m}`)}%`, Math.max(1, limit));
|
|
2184
|
+
for (const r of rows) {
|
|
2185
|
+
console.log(`[${r.type}] (i${r.importance}) ${r.content}`);
|
|
2186
|
+
}
|
|
2187
|
+
}
|
|
2188
|
+
finally {
|
|
2189
|
+
db.close();
|
|
2190
|
+
}
|
|
1900
2191
|
}
|
|
1901
2192
|
else {
|
|
1902
2193
|
console.log('No memory database found. Run: uap-omp install');
|
|
@@ -1915,7 +2206,9 @@ uapOmpCmd.addCommand(new Command('worktree')
|
|
|
1915
2206
|
const uapOmpDir = process.env.HOME + '/.uap/omp';
|
|
1916
2207
|
const worktreesFile = `${uapOmpDir}/worktrees.json`;
|
|
1917
2208
|
if (existsSync(worktreesFile)) {
|
|
1918
|
-
|
|
2209
|
+
// Pretty-print it ourselves: no shell, no `cat | jq` dependency
|
|
2210
|
+
// (the old pipe interpolated the path through execSync).
|
|
2211
|
+
console.log(JSON.stringify(JSON.parse(readFileSync(worktreesFile, 'utf-8')), null, 2));
|
|
1919
2212
|
}
|
|
1920
2213
|
else {
|
|
1921
2214
|
console.log('No worktrees tracked. Run: uap-omp install');
|
|
@@ -1948,7 +2241,9 @@ uapOmpCmd.addCommand(new Command('hooks')
|
|
|
1948
2241
|
try {
|
|
1949
2242
|
const scriptPath = join(__dirname, '../../scripts/omp/uap-omp.sh');
|
|
1950
2243
|
if (existsSync(scriptPath)) {
|
|
1951
|
-
|
|
2244
|
+
// Argv array, never a shell (prepass debt: the path used to
|
|
2245
|
+
// interpolate into an execSync command string).
|
|
2246
|
+
execFileSync('bash', [scriptPath, 'install'], { stdio: 'inherit' });
|
|
1952
2247
|
}
|
|
1953
2248
|
else {
|
|
1954
2249
|
console.error('UAP hooks script not found. Please rebuild with: npm run build');
|
|
@@ -1963,7 +2258,7 @@ uapOmpCmd.addCommand(new Command('hooks')
|
|
|
1963
2258
|
try {
|
|
1964
2259
|
const scriptPath = join(__dirname, '../../scripts/omp/uap-omp.sh');
|
|
1965
2260
|
if (existsSync(scriptPath)) {
|
|
1966
|
-
|
|
2261
|
+
execFileSync('bash', [scriptPath, 'status'], { stdio: 'inherit' });
|
|
1967
2262
|
}
|
|
1968
2263
|
else {
|
|
1969
2264
|
console.error('UAP hooks script not found. Please rebuild with: npm run build');
|