heyspex 0.1.0 → 0.2.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.
- package/.claude-plugin/marketplace.json +14 -0
- package/README.md +21 -0
- package/bin/hs.mjs +1089 -104
- package/bin/spexcode.mjs +262 -0
- package/dev-factory/engine/worktree.mjs +740 -0
- package/dev-factory/lib/code-repo-root.mjs +67 -0
- package/dev-factory/lib/context-budget.mjs +84 -0
- package/dev-factory/lib/epic-detect.mjs +190 -0
- package/dev-factory/lib/fleet-queue-file.mjs +846 -0
- package/dev-factory/lib/fleet-queue.mjs +426 -0
- package/dev-factory/lib/fleet-state.mjs +14 -18
- package/dev-factory/lib/model-catalog.mjs +338 -0
- package/dev-factory/lib/seat-context.mjs +199 -0
- package/dev-factory/lib/spec-io.mjs +93 -0
- package/dev-factory/lib/sufficiency-score.mjs +8 -2
- package/dev-factory/lib/worktree-allocator.mjs +744 -0
- package/dev-factory/model-catalog.json +222 -0
- package/dist/cli/hs-check.mjs +1127 -103
- package/dist/cli/hs-claim.mjs +981 -63
- package/dist/cli/hs-connect.mjs +10059 -1729
- package/dist/cli/hs-defer.mjs +5507 -3072
- package/dist/cli/hs-dev.mjs +576 -0
- package/dist/cli/hs-env.mjs +416 -302
- package/dist/cli/hs-index-rebuild.mjs +7334 -0
- package/dist/cli/hs-index-reconcile.mjs +8138 -0
- package/dist/cli/hs-init.mjs +2840 -149
- package/dist/cli/hs-install.mjs +7214 -594
- package/dist/cli/hs-join.mjs +10640 -2421
- package/dist/cli/hs-vault-pull.mjs +8157 -6370
- package/dist/cli/hs-vault-push.mjs +6433 -0
- package/dist/cli/hs-vault.mjs +4029 -1555
- package/dist/cli/hs-workspace.mjs +2702 -538
- package/dist/cli-templates/customer-vault/specs/entity-model.md +594 -601
- package/dist/cli-templates/customer-vault/specs/protocols/canonical-frontmatter-templates.md +110 -177
- package/dist/cli-templates/customer-vault/specs/protocols/destructive-action-checklist.md +122 -0
- package/dist/cli-templates/customer-vault/specs/protocols/memory-protocol.md +13 -15
- package/dist/cli-templates/customer-vault/specs/protocols/session-close-protocol.md +91 -0
- package/dist/cli-templates/customer-vault/specs/protocols/spec-hierarchy.md +150 -168
- package/dist/cli-templates/customer-vault/specs/protocols/spec-summary-authoring.md +83 -0
- package/dist/cli-templates/harness-commands/claude/hs-auto.md +36 -0
- package/dist/cli-templates/harness-commands/claude/hs-backfill.md +28 -0
- package/dist/cli-templates/harness-commands/claude/hs-capture.md +62 -0
- package/dist/cli-templates/harness-commands/claude/hs-defer.md +29 -0
- package/dist/cli-templates/harness-commands/claude/hs-dev.md +20 -0
- package/dist/cli-templates/harness-commands/claude/hs-doctor.md +32 -0
- package/dist/cli-templates/harness-commands/claude/hs-ground.md +30 -0
- package/dist/cli-templates/harness-commands/claude/hs-handoff.md +33 -0
- package/dist/cli-templates/harness-commands/claude/hs-log.md +27 -0
- package/dist/cli-templates/harness-commands/claude/hs-next.md +29 -0
- package/dist/cli-templates/harness-commands/claude/hs-promote.md +70 -0
- package/dist/cli-templates/harness-commands/claude/hs-push.md +35 -0
- package/dist/cli-templates/harness-commands/claude/hs-qc.md +27 -0
- package/dist/cli-templates/harness-commands/claude/hs-res.md +63 -0
- package/dist/cli-templates/harness-commands/claude/hs-resolve.md +23 -0
- package/dist/cli-templates/harness-commands/claude/hs-review.md +23 -0
- package/dist/cli-templates/harness-commands/claude/hs-view.md +28 -0
- package/dist/cli-templates/harness-commands/claude/kill-ports.md +32 -0
- package/dist/cli-templates/harness-commands/claude/prototype.md +91 -0
- package/dist/cli-templates/harness-commands/cursor/hs-auto.md +40 -0
- package/dist/cli-templates/harness-commands/cursor/hs-backfill.md +31 -0
- package/dist/cli-templates/harness-commands/cursor/hs-capture.md +65 -0
- package/dist/cli-templates/harness-commands/cursor/hs-defer.md +32 -0
- package/dist/cli-templates/harness-commands/cursor/hs-dev.md +24 -0
- package/dist/cli-templates/harness-commands/cursor/hs-doctor.md +36 -0
- package/dist/cli-templates/harness-commands/cursor/hs-ground.md +33 -0
- package/dist/cli-templates/harness-commands/cursor/hs-handoff.md +37 -0
- package/dist/cli-templates/harness-commands/cursor/hs-log.md +31 -0
- package/dist/cli-templates/harness-commands/cursor/hs-next.md +32 -0
- package/dist/cli-templates/harness-commands/cursor/hs-promote.md +73 -0
- package/dist/cli-templates/harness-commands/cursor/hs-push.md +38 -0
- package/dist/cli-templates/harness-commands/cursor/hs-qc.md +30 -0
- package/dist/cli-templates/harness-commands/cursor/hs-res.md +67 -0
- package/dist/cli-templates/harness-commands/cursor/hs-resolve.md +26 -0
- package/dist/cli-templates/harness-commands/cursor/hs-review.md +26 -0
- package/dist/cli-templates/harness-commands/cursor/hs-view.md +32 -0
- package/dist/cli-templates/harness-commands/cursor/kill-ports.md +35 -0
- package/dist/cli-templates/harness-commands/cursor/prototype.md +95 -0
- package/docs/copilot-plugin-install.md +162 -0
- package/docs/driving-heyspex-from-copilot.md +165 -0
- package/docs/mcp-client-config.md +259 -6
- package/package.json +249 -124
- package/plugins/heyspex/.claude-plugin/plugin.json +12 -0
- package/plugins/heyspex/.cursor-plugin/plugin.json +15 -0
- package/plugins/heyspex/.mcp.json +12 -0
- package/plugins/heyspex/README.md +309 -0
- package/plugins/heyspex/bin/launch-mcp.mjs +95 -0
- package/plugins/heyspex/bin/run-hook.mjs +80 -0
- package/plugins/heyspex/hooks/cursor-hooks.json +308 -0
- package/plugins/heyspex/hooks/hooks.json +418 -0
- package/plugins/heyspex/mcp.json +13 -0
- package/scripts/check-mcp-freshness.mjs +17 -9
- package/scripts/claude-hooks/_env-vault-events.mjs +68 -0
- package/scripts/claude-hooks/_guardrail-events.mjs +96 -0
- package/scripts/claude-hooks/_guardrail-loader.mjs +494 -0
- package/scripts/claude-hooks/_intent-classifier-router.mjs +456 -0
- package/scripts/claude-hooks/_intent-classifier-semantic.mjs +356 -0
- package/scripts/claude-hooks/_run.mjs +413 -0
- package/scripts/claude-hooks/_transcript-text.mjs +60 -0
- package/scripts/claude-hooks/_vault-retrieval.mjs +322 -0
- package/scripts/claude-hooks/agent-spawn-delegation-gate.mjs +133 -0
- package/scripts/claude-hooks/capture-execution-gate.mjs +51 -0
- package/scripts/claude-hooks/capture-workflow-gate.mjs +11 -0
- package/scripts/claude-hooks/check-auto-memory-budget.mjs +396 -0
- package/scripts/claude-hooks/check-claude-md-budget.mjs +327 -0
- package/scripts/claude-hooks/check-mcp-freshness-hook.mjs +14 -0
- package/scripts/claude-hooks/claim-before-code-gate.mjs +11 -0
- package/scripts/claude-hooks/claim-liveness-shared.mjs +577 -0
- package/scripts/claude-hooks/close-terminal-on-ship.mjs +64 -0
- package/scripts/claude-hooks/coo-denylist-gate.mjs +11 -0
- package/scripts/claude-hooks/coo-guard-check.mjs +11 -0
- package/scripts/claude-hooks/deep-research-cost-gate.mjs +11 -0
- package/scripts/claude-hooks/dev-server-task-reminder.mjs +15 -0
- package/scripts/claude-hooks/diagnose-capture-reminder.mjs +11 -0
- package/scripts/claude-hooks/directive-obligation-gate.mjs +11 -0
- package/scripts/claude-hooks/emit-claim-status.mjs +41 -0
- package/scripts/claude-hooks/enforce-session-sequence.mjs +11 -0
- package/scripts/claude-hooks/enforce-vault-naming.mjs +11 -0
- package/scripts/claude-hooks/env-vault-guard.mjs +11 -0
- package/scripts/claude-hooks/epic-milestone-phrasing-gate.mjs +11 -0
- package/scripts/claude-hooks/git-identity-guard.mjs +11 -0
- package/scripts/claude-hooks/git-reflog-audit.mjs +15 -0
- package/scripts/claude-hooks/git-stash-gate.mjs +11 -0
- package/scripts/claude-hooks/guard-auto-memory-writes.mjs +137 -0
- package/scripts/claude-hooks/id-display-format-gate.mjs +11 -0
- package/scripts/claude-hooks/inject-communication-style.mjs +86 -0
- package/scripts/claude-hooks/inject-coo-seat.mjs +78 -0
- package/scripts/claude-hooks/inject-dev-server-awareness.mjs +11 -0
- package/scripts/claude-hooks/inject-doctrine.mjs +13 -0
- package/scripts/claude-hooks/inject-vault-context.mjs +14 -0
- package/scripts/claude-hooks/intent-classifier-trigger.mjs +279 -0
- package/scripts/claude-hooks/log-session-activity.mjs +341 -0
- package/scripts/claude-hooks/naughty-list-gate.mjs +11 -0
- package/scripts/claude-hooks/notify-status-flip.mjs +72 -0
- package/scripts/claude-hooks/plan-exit-ingest-gate.mjs +170 -0
- package/scripts/claude-hooks/plan-ingest-close-reminder.mjs +66 -0
- package/scripts/claude-hooks/plan-review-gate.mjs +11 -0
- package/scripts/claude-hooks/preflight-reminder.mjs +262 -0
- package/scripts/claude-hooks/protected-action-intent.mjs +221 -0
- package/scripts/claude-hooks/research-method-guard.mjs +398 -0
- package/scripts/claude-hooks/research-protocol-gate.mjs +11 -0
- package/scripts/claude-hooks/session-end.mjs +451 -0
- package/scripts/claude-hooks/settings-write-gate.mjs +11 -0
- package/scripts/claude-hooks/settlement-check-gate.mjs +39 -0
- package/scripts/claude-hooks/status-flip-detect.mjs +17 -0
- package/scripts/claude-hooks/terminal-close-shared.mjs +426 -0
- package/scripts/claude-hooks/terminal-close-watcher.mjs +122 -0
- package/scripts/claude-hooks/vault-mirror-catchup.mjs +11 -0
- package/scripts/claude-hooks/vault-write-tier-guard.mjs +11 -0
- package/scripts/claude-hooks/wip-checkpoint.mjs +302 -0
- package/scripts/cursor-hooks/manifest.mjs +281 -0
- package/scripts/dev-server-status.mjs +34 -13
- package/scripts/dev-server-stop.mjs +313 -0
- package/scripts/heyspex-mode.mjs +288 -0
- package/scripts/hs-auto-resolve.mjs +240 -0
- package/scripts/hs-auto-source.mjs +398 -0
- package/scripts/hs-auto.mjs +134 -0
- package/scripts/hs-capture-cli.mjs +326 -0
- package/scripts/hs-classifier.mjs +136 -0
- package/scripts/hs-companion.mjs +88 -0
- package/scripts/hs-gateway.mjs +115 -0
- package/scripts/hs-mode.mjs +125 -0
- package/scripts/hs-next.mjs +441 -0
- package/scripts/hs-settings.mjs +338 -0
- package/scripts/hs-view.mjs +496 -0
- package/scripts/hs-worktree.mjs +201 -0
- package/scripts/install-claude-code-hooks.mjs +272 -0
- package/scripts/install-cursor-hooks.mjs +471 -0
- package/scripts/lib/agent-env-markers.mjs +38 -0
- package/scripts/lib/console-url-resolver.mjs +199 -61
- package/scripts/lib/customer-kit.mjs +1203 -0
- package/scripts/lib/dev-mode.mjs +249 -32
- package/scripts/lib/directive-obligations.mjs +349 -0
- package/scripts/lib/heyspex-home.mjs +72 -0
- package/scripts/lib/hook-dispositions.mjs +210 -0
- package/scripts/lib/hook-vault-header.mjs +30 -0
- package/scripts/lib/hs-command.mjs +277 -0
- package/scripts/lib/hs-companion-settings.mjs +472 -0
- package/scripts/lib/hs-source-branch.mjs +196 -0
- package/scripts/lib/hs-source-commit.mjs +59 -5
- package/scripts/lib/hs-source-identity.mjs +526 -0
- package/scripts/lib/hs-source-log.mjs +13 -22
- package/scripts/lib/hs-source-preflight.mjs +18 -4
- package/scripts/lib/hs-source-push.mjs +386 -307
- package/scripts/lib/hs-worktree-args.mjs +115 -0
- package/scripts/lib/shared-path-helpers.mjs +134 -0
- package/scripts/lib/standalone-doctor.mjs +540 -3
- package/scripts/lib/subagent-git-lock.mjs +109 -0
- package/scripts/lib/template-pin.mjs +34 -0
- package/scripts/lib/window-placement.mjs +109 -0
- package/scripts/provenance-lib.mjs +91 -0
- package/scripts/stamp-provenance-on-edit.mjs +222 -0
- package/scripts/wip-ledger-health.mjs +653 -0
- package/spexharness/doctrine/baseline/SPEXCODE-DOCTRINE.baseline.json +29 -0
- package/spexharness/src/adapters/audit.mjs +197 -0
- package/spexharness/src/adapters/claude-code.mjs +449 -0
- package/spexharness/src/adapters/copilot.mjs +236 -0
- package/spexharness/src/adapters/detect-harness.mjs +34 -0
- package/spexharness/src/chat/tui/ansi.mjs +448 -0
- package/spexharness/src/chat/tui/palette.mjs +22 -0
- package/spexharness/src/chat/tui/select.mjs +208 -0
- package/spexharness/src/config-root.mjs +54 -0
- package/spexharness/src/context-budget.mjs +141 -0
- package/spexharness/src/dev-server-control.mjs +389 -0
- package/spexharness/src/doctrine/behaviour.mjs +371 -0
- package/spexharness/src/doctrine/corpus.mjs +733 -0
- package/spexharness/src/doctrine/inject.mjs +338 -0
- package/spexharness/src/doctrine/merge.mjs +184 -0
- package/spexharness/src/doctrine/sources.mjs +252 -0
- package/spexharness/src/doctrine/synthesize.mjs +401 -0
- package/spexharness/src/doctrine/vault-source.mjs +574 -0
- package/spexharness/src/doctrine/writer.mjs +176 -0
- package/spexharness/src/events.mjs +84 -0
- package/spexharness/src/gates/_shell-write-targets.mjs +77 -0
- package/spexharness/src/gates/capture-workflow-gate.mjs +202 -0
- package/spexharness/src/gates/claim-before-code-gate.decide.mjs +33 -0
- package/spexharness/src/gates/claim-before-code-gate.mjs +129 -0
- package/spexharness/src/gates/deep-research-cost-gate.mjs +275 -0
- package/spexharness/src/gates/diagnose-capture-reminder.mjs +112 -0
- package/spexharness/src/gates/directive-obligation-gate.decide.mjs +132 -0
- package/spexharness/src/gates/directive-obligation-gate.mjs +183 -0
- package/spexharness/src/gates/enforce-session-sequence.mjs +895 -0
- package/spexharness/src/gates/enforce-vault-naming.mjs +215 -0
- package/spexharness/src/gates/epic-milestone-phrasing-gate.mjs +233 -0
- package/spexharness/src/gates/git-identity-guard.decide.mjs +436 -0
- package/spexharness/src/gates/git-identity-guard.mjs +61 -0
- package/spexharness/src/gates/git-reflog-audit.mjs +151 -0
- package/spexharness/src/gates/git-stash-gate.decide.mjs +361 -0
- package/spexharness/src/gates/git-stash-gate.mjs +159 -0
- package/spexharness/src/gates/id-display-format-gate.mjs +190 -0
- package/spexharness/src/gates/inject-doctrine-gate.mjs +89 -0
- package/spexharness/src/gates/inject-vault-context.mjs +239 -0
- package/spexharness/src/gates/naughty-list-gate.mjs +213 -0
- package/spexharness/src/gates/plan-review-gate.mjs +233 -0
- package/spexharness/src/gates/preflight-reminder-gate.mjs +265 -0
- package/spexharness/src/gates/research-protocol-gate.mjs +175 -0
- package/spexharness/src/gates/settings-write-gate.decide.mjs +96 -0
- package/spexharness/src/gates/settings-write-gate.mjs +104 -0
- package/spexharness/src/gates/vault-mirror-catchup.mjs +124 -0
- package/spexharness/src/gates/vault-write-tier-guard.decide.mjs +125 -0
- package/spexharness/src/gates/vault-write-tier-guard.mjs +42 -0
- package/spexharness/src/git-reflog-audit.mjs +294 -0
- package/spexharness/src/intent-classifier.mjs +196 -0
- package/spexharness/src/intent-directive.mjs +626 -0
- package/spexharness/src/profile/learn.mjs +551 -0
- package/spexharness/src/profile/proposals.mjs +357 -0
- package/spexharness/src/profile/vault-inclusion.mjs +386 -0
- package/spexharness/src/redact.mjs +151 -0
- package/spexharness/src/rule-table.mjs +849 -0
- package/spexharness/src/seat-context.mjs +122 -0
- package/spexharness/src/session-bootstrap.mjs +512 -0
- package/spexharness/src/session-record.mjs +815 -0
- package/spexharness/src/token-inventory.mjs +207 -0
- package/vendor/heyspex-mcp/account-switch.mjs +96 -0
- package/vendor/heyspex-mcp/alignment-gate.mjs +315 -1
- package/vendor/heyspex-mcp/blocker-resolver.mjs +37 -2
- package/vendor/heyspex-mcp/breakdown-ladder.mjs +119 -4
- package/vendor/heyspex-mcp/breakdown-source.mjs +271 -0
- package/vendor/heyspex-mcp/breakdown-writer.mjs +23 -3
- package/vendor/heyspex-mcp/capture-buffer-patches.mjs +77 -8
- package/vendor/heyspex-mcp/capture-channel.mjs +55 -5
- package/vendor/heyspex-mcp/capture-console-client.mjs +117 -3
- package/vendor/heyspex-mcp/capture-focus.mjs +1061 -31
- package/vendor/heyspex-mcp/capture-outbox.mjs +15 -5
- package/vendor/heyspex-mcp/capture-sources.mjs +195 -0
- package/vendor/heyspex-mcp/capture-tools.mjs +1264 -0
- package/vendor/heyspex-mcp/claim-tools.mjs +1147 -0
- package/vendor/heyspex-mcp/cli-verbs.mjs +2074 -0
- package/vendor/heyspex-mcp/cli.mjs +207 -15524
- package/vendor/heyspex-mcp/close-branch-report.mjs +102 -0
- package/vendor/heyspex-mcp/cloud-tool-surface.mjs +128 -0
- package/vendor/heyspex-mcp/cloud-vault-writes.mjs +602 -0
- package/vendor/heyspex-mcp/config-seed.yaml +15 -0
- package/vendor/heyspex-mcp/config-settings.mjs +290 -7
- package/vendor/heyspex-mcp/console-fetch.mjs +822 -17
- package/vendor/heyspex-mcp/console-transport.mjs +172 -0
- package/vendor/heyspex-mcp/credentials.mjs +585 -0
- package/vendor/heyspex-mcp/defer-spec.mjs +44 -4
- package/vendor/heyspex-mcp/deferred-reclaim.mjs +29 -3
- package/vendor/heyspex-mcp/design-handlers.mjs +31 -0
- package/vendor/heyspex-mcp/design-tools.mjs +4 -1
- package/vendor/heyspex-mcp/dev-factory-bridge.mjs +4 -4
- package/vendor/heyspex-mcp/dev-mode-core.mjs +45 -0
- package/vendor/heyspex-mcp/dev-tools.mjs +131 -0
- package/vendor/heyspex-mcp/diagnose-handlers.mjs +54 -0
- package/vendor/heyspex-mcp/events-tools.mjs +207 -0
- package/vendor/heyspex-mcp/filing-tools.mjs +723 -0
- package/vendor/heyspex-mcp/fleet-handlers.mjs +37 -0
- package/vendor/heyspex-mcp/fleet-queue-tools.mjs +71 -15
- package/vendor/heyspex-mcp/focus-tools.mjs +190 -0
- package/vendor/heyspex-mcp/folder-trust-store.mjs +60 -0
- package/vendor/heyspex-mcp/http-transport.mjs +302 -0
- package/vendor/heyspex-mcp/list-tools.mjs +257 -0
- package/vendor/heyspex-mcp/login-handoff.mjs +15 -1
- package/vendor/heyspex-mcp/mcp-config.mjs +107 -0
- package/vendor/heyspex-mcp/memory-tools.mjs +523 -0
- package/vendor/heyspex-mcp/mvp-mode.mjs +53 -6
- package/vendor/heyspex-mcp/obligation-backstop.mjs +103 -0
- package/vendor/heyspex-mcp/occupied-keys.mjs +142 -0
- package/vendor/heyspex-mcp/on-deck-brief.mjs +3377 -0
- package/vendor/heyspex-mcp/on-deck-scheduler.mjs +1708 -0
- package/vendor/heyspex-mcp/package-root.mjs +32 -0
- package/vendor/heyspex-mcp/peer-presence.mjs +8 -1
- package/vendor/heyspex-mcp/plan-ground.mjs +621 -652
- package/vendor/heyspex-mcp/plan-push.mjs +908 -22
- package/vendor/heyspex-mcp/plan-review.mjs +124 -30
- package/vendor/heyspex-mcp/preflight-gate.mjs +0 -0
- package/vendor/heyspex-mcp/procedure-handlers.mjs +327 -0
- package/vendor/heyspex-mcp/procedure-tools.mjs +1181 -970
- package/vendor/heyspex-mcp/promote-capture.mjs +388 -69
- package/vendor/heyspex-mcp/promote-diagnose.mjs +74 -0
- package/vendor/heyspex-mcp/promote-research-to-diagnose.mjs +9 -2
- package/vendor/heyspex-mcp/promote-research.mjs +666 -53
- package/vendor/heyspex-mcp/promotion-helpers.mjs +251 -0
- package/vendor/heyspex-mcp/prompts.mjs +1460 -0
- package/vendor/heyspex-mcp/read-path.mjs +191 -15
- package/vendor/heyspex-mcp/receipt-shape.mjs +146 -0
- package/vendor/heyspex-mcp/recipe-handlers.mjs +117 -0
- package/vendor/heyspex-mcp/regen-tasks.mjs +210 -3
- package/vendor/heyspex-mcp/register-spec.mjs +266 -54
- package/vendor/heyspex-mcp/request-context.mjs +83 -0
- package/vendor/heyspex-mcp/research-focus.mjs +207 -4
- package/vendor/heyspex-mcp/research-handlers.mjs +625 -0
- package/vendor/heyspex-mcp/research-tools.mjs +4 -4
- package/vendor/heyspex-mcp/response-budget.mjs +348 -0
- package/vendor/heyspex-mcp/review-focus.mjs +25 -1
- package/vendor/heyspex-mcp/roadmap-default.mjs +70 -0
- package/vendor/heyspex-mcp/search-specs.mjs +280 -0
- package/vendor/heyspex-mcp/seat-block-ledger.mjs +113 -0
- package/vendor/heyspex-mcp/seat-identity.mjs +2 -6
- package/vendor/heyspex-mcp/session-owner.mjs +109 -0
- package/vendor/heyspex-mcp/session-tools.mjs +162 -0
- package/vendor/heyspex-mcp/settings-registry.mjs +232 -0
- package/vendor/heyspex-mcp/settings-tools.mjs +85 -12
- package/vendor/heyspex-mcp/spec-edit-tools.mjs +453 -0
- package/vendor/heyspex-mcp/spec-id-lib.mjs +93 -17
- package/vendor/heyspex-mcp/split-research.mjs +304 -56
- package/vendor/heyspex-mcp/stdio-rpc.mjs +22 -0
- package/vendor/heyspex-mcp/submit-for-review.mjs +150 -7
- package/vendor/heyspex-mcp/summary-contract.mjs +105 -0
- package/vendor/heyspex-mcp/summary-write-tools.mjs +228 -0
- package/vendor/heyspex-mcp/symptom-query.mjs +146 -0
- package/vendor/heyspex-mcp/test-helpers.mjs +123 -1
- package/vendor/heyspex-mcp/tool-catalog.mjs +2819 -0
- package/vendor/heyspex-mcp/tool-dispatch.mjs +657 -0
- package/vendor/heyspex-mcp/tool-helpers.mjs +325 -0
- package/vendor/heyspex-mcp/validate-linkage.mjs +414 -27
- package/vendor/heyspex-mcp/vault-io.mjs +720 -0
- package/vendor/heyspex-mcp/vault-less-endpoints.mjs +52 -0
- package/vendor/heyspex-mcp/vault-resolve.mjs +554 -68
- package/vendor/heyspex-mcp/verify-reproduction.mjs +270 -30
- package/vendor/heyspex-mcp/whoami.mjs +92 -0
- package/vendor/heyspex-mcp/write-outbox.mjs +512 -0
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// HeySpex Intent Classifier — SEMANTIC layer.
|
|
3
|
+
//
|
|
4
|
+
// The Intent Classifier has two layers ([[HS-UJVA-EPIC-KKMO-autonomous-skill-routing-context]]):
|
|
5
|
+
// 1. LEXICAL (fast path) — the per-rule regex patterns in the guardrail registry.
|
|
6
|
+
// A regex hit fires instantly and never waits on this module.
|
|
7
|
+
// 2. SEMANTIC — on a regex MISS, resolve intent WITHOUT a second, separate model.
|
|
8
|
+
// DEFAULT (mode: self_check, [[HS-M4PN-TASK]]): the router deterministically
|
|
9
|
+
// injects a SELF-CHECK instruction and lets the agent already running the session
|
|
10
|
+
// judge intent as part of its own turn — no network, no fleet machine, works for
|
|
11
|
+
// every user. The self-check block is built in _intent-classifier-router.mjs;
|
|
12
|
+
// this module is the OPT-IN model fallback for anyone who still wants it.
|
|
13
|
+
// Why the semantic layer exists at all (regex alone is not enough):
|
|
14
|
+
// [[intent-classifier-injected-content]] — 9/10 paraphrased improvement-idea
|
|
15
|
+
// phrasings missed before the patterns were broadened, and paraphrase drift
|
|
16
|
+
// never ends.
|
|
17
|
+
//
|
|
18
|
+
// OPT-IN MODEL FALLBACK (mode: model): classifyIntent() below classifies the prompt
|
|
19
|
+
// with a fast LOCAL model (Ollama) and returns { behavior, confidence } so the caller
|
|
20
|
+
// can fire above a threshold. This is the ORIGINAL mechanism, now DEMOTED to an
|
|
21
|
+
// explicit opt-in — it is NEVER on the default path, so no reachable endpoint is
|
|
22
|
+
// required for the semantic layer to function ([[HS-M4PN-TASK]] AC2).
|
|
23
|
+
//
|
|
24
|
+
// HARD FAIL-SAFE CONTRACT (hook house rules): this module NEVER throws, NEVER
|
|
25
|
+
// hangs past its timeout, and on ANY problem (endpoint down, timeout, bad JSON,
|
|
26
|
+
// unexpected shape) returns { behavior: null, confidence: 0 } so the calling hook
|
|
27
|
+
// proceeds exactly as if the semantic layer did not exist. Dependency-free:
|
|
28
|
+
// Node stdlib + global fetch only (hooks run on a fresh clone with no npm install).
|
|
29
|
+
//
|
|
30
|
+
// Config (.heyspex/config.yaml → agent_behaviors.intent_classifier.*), all optional.
|
|
31
|
+
// The file is read from the VAULT root (the loader's `defaultConfigRoot()`), not this
|
|
32
|
+
// checkout — [[HS-4C76-9W86-DIAG-heyspex-config-yaml-has-no-single-home]]:
|
|
33
|
+
// semantic_enabled: true|false (default true — turns Layer 2 on/off entirely)
|
|
34
|
+
// mode: self_check|model (default self_check — deterministic injection;
|
|
35
|
+
// `model` opts into the Ollama fallback below)
|
|
36
|
+
// endpoint: Ollama base URL (default http://192.168.1.252:11434 — mode:model only)
|
|
37
|
+
// model: model name (default qwen3:8b — mode:model only)
|
|
38
|
+
// timeout_ms: request budget (default 2500 — the hook's overall budget is 5s)
|
|
39
|
+
// min_confidence: fire threshold (default 0.7 — consumed by the calling hook)
|
|
40
|
+
// Env overrides (kill switch first):
|
|
41
|
+
// HEYSPEX_INTENT_SEMANTIC_OFF=1 hard off (disables Layer 2 entirely)
|
|
42
|
+
// HEYSPEX_INTENT_SEMANTIC_MODE=self_check|model
|
|
43
|
+
// HEYSPEX_INTENT_ENDPOINT / HEYSPEX_INTENT_MODEL /
|
|
44
|
+
// HEYSPEX_INTENT_TIMEOUT_MS / HEYSPEX_INTENT_MIN_CONFIDENCE
|
|
45
|
+
//
|
|
46
|
+
// Self-test without a session (exercises the opt-in model fallback):
|
|
47
|
+
// node scripts/claude-hooks/_intent-classifier-semantic.mjs --ping
|
|
48
|
+
// node scripts/claude-hooks/_intent-classifier-semantic.mjs --classify "some prompt"
|
|
49
|
+
|
|
50
|
+
import fs from 'node:fs';
|
|
51
|
+
import path from 'node:path';
|
|
52
|
+
import { fileURLToPath } from 'node:url';
|
|
53
|
+
|
|
54
|
+
import { readConfigLeafRaw } from './_guardrail-loader.mjs';
|
|
55
|
+
import { defaultConfigRoot } from '../../spexharness/src/config-root.mjs';
|
|
56
|
+
|
|
57
|
+
// The CODE checkout — where `.heyspex/intent-classifier-history.jsonl` (an event
|
|
58
|
+
// log, a code-repo artifact) is appended. NOT where config.yaml is read from: the
|
|
59
|
+
// config reads below default to the vault root via `defaultConfigRoot()`
|
|
60
|
+
// ([[HS-4C76-9W86-DIAG-heyspex-config-yaml-has-no-single-home]]).
|
|
61
|
+
export const DEFAULT_REPO_ROOT = path.resolve(
|
|
62
|
+
path.dirname(fileURLToPath(import.meta.url)),
|
|
63
|
+
'..',
|
|
64
|
+
'..',
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
// Semantic-layer modes ([[HS-M4PN-TASK]]):
|
|
68
|
+
// 'self_check' — DEFAULT. On a regex miss the router injects a deterministic
|
|
69
|
+
// self-check instruction; the session's own agent judges intent.
|
|
70
|
+
// No network, no fleet machine.
|
|
71
|
+
// 'model' — OPT-IN fallback. classifyIntent() calls the local Ollama endpoint.
|
|
72
|
+
export const SEMANTIC_MODES = Object.freeze(['self_check', 'model']);
|
|
73
|
+
|
|
74
|
+
export const DEFAULTS = Object.freeze({
|
|
75
|
+
semanticEnabled: true,
|
|
76
|
+
semanticMode: 'self_check',
|
|
77
|
+
endpoint: 'http://192.168.1.252:11434',
|
|
78
|
+
model: 'qwen3:8b',
|
|
79
|
+
timeoutMs: 2500,
|
|
80
|
+
minConfidence: 0.7,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// The behavior catalog the classifier chooses from. Descriptions are the actual
|
|
84
|
+
// classification instructions, so keep them about the USER'S INTENT, not the
|
|
85
|
+
// system's response. Any hook can pass its own list; this shared catalog keeps
|
|
86
|
+
// capture-trigger and research-trigger consistent if both adopt the semantic layer.
|
|
87
|
+
export const KNOWN_BEHAVIORS = Object.freeze([
|
|
88
|
+
{
|
|
89
|
+
key: 'capture_on_idea',
|
|
90
|
+
description:
|
|
91
|
+
'The user is sharing a raw idea, suggestion, observation, or improvement thought — a brain-dump about something that could exist or be better — rather than giving a direct work order, asking a question about existing work, or continuing work already in progress.',
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
key: 'research_before_decision',
|
|
95
|
+
description:
|
|
96
|
+
'The user is declining to make a design or architecture decision themselves and is asking for research, best practices, or an expert recommendation instead (e.g. "not a decision I should have to make", "don\'t reinvent the wheel").',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
key: 'settings_intent',
|
|
100
|
+
description:
|
|
101
|
+
'The user wants to READ or CHANGE a HeySpex workflow setting / agent behavior — enable or disable a behavior (auto-capture, the research trigger, the intent classifier), turn something on or off, set/lower/raise a threshold or value (confidence, timeout), or ask what a setting is currently. About the configuration itself, NOT a request to do the underlying work. (e.g. "turn off auto-capture", "lower the classifier confidence to 0.6", "is auto-capture on", "make it stop capturing everything").',
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
key: 'defer_intent',
|
|
105
|
+
description:
|
|
106
|
+
'The user wants to DEFER, POSTPONE, or SCHEDULE a follow-up to a later time — "come back to this later", "remind me in a week", "park/table this until X is done", "schedule this for next week", "not now — later, after the migration". About WHEN to revisit something, not a request to do it now.',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
key: 'handoff_intent',
|
|
110
|
+
description:
|
|
111
|
+
'The user asks for a hand-off prompt, doc, notes or resume context for the NEXT agent or session ("give me a handoff prompt for the next agent", "hand this off", "what should the next session know"). About producing the hand-off artifact, NOT about loading one (a lane code like GQ5R or `hs handoff load`) and not ordinary work.',
|
|
112
|
+
},
|
|
113
|
+
]);
|
|
114
|
+
|
|
115
|
+
function num(raw, fallback) {
|
|
116
|
+
const n = Number(raw);
|
|
117
|
+
return Number.isFinite(n) && n > 0 ? n : fallback;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function clamp01(n) {
|
|
121
|
+
const v = Number(n);
|
|
122
|
+
if (!Number.isFinite(v)) return 0;
|
|
123
|
+
return Math.max(0, Math.min(1, v));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Resolve the semantic-layer config: env override → .heyspex/config.yaml →
|
|
128
|
+
* shipped defaults. FAIL-SAFE: any unreadable value falls back to its default.
|
|
129
|
+
* `repoRoot` is the directory holding `.heyspex/config.yaml` — defaults to the
|
|
130
|
+
* vault root; an explicit argument (tests, fixtures) always wins.
|
|
131
|
+
*/
|
|
132
|
+
export function readIntentClassifierConfig(repoRoot = defaultConfigRoot()) {
|
|
133
|
+
const cfg = { ...DEFAULTS };
|
|
134
|
+
try {
|
|
135
|
+
if (process.env.HEYSPEX_INTENT_SEMANTIC_OFF === '1') cfg.semanticEnabled = false;
|
|
136
|
+
else {
|
|
137
|
+
const enabled = readConfigLeafRaw('agent_behaviors.intent_classifier.semantic_enabled', repoRoot);
|
|
138
|
+
if (enabled !== undefined) cfg.semanticEnabled = enabled.trim().toLowerCase() !== 'false';
|
|
139
|
+
}
|
|
140
|
+
// Mode: env override → config → default 'self_check'. Any unrecognized value
|
|
141
|
+
// falls back to the deterministic default rather than silently enabling the model.
|
|
142
|
+
const modeRaw =
|
|
143
|
+
process.env.HEYSPEX_INTENT_SEMANTIC_MODE ||
|
|
144
|
+
unquote(readConfigLeafRaw('agent_behaviors.intent_classifier.mode', repoRoot));
|
|
145
|
+
if (typeof modeRaw === 'string') {
|
|
146
|
+
const m = modeRaw.trim().toLowerCase();
|
|
147
|
+
if (SEMANTIC_MODES.includes(m)) cfg.semanticMode = m;
|
|
148
|
+
}
|
|
149
|
+
const endpoint =
|
|
150
|
+
process.env.HEYSPEX_INTENT_ENDPOINT ||
|
|
151
|
+
unquote(readConfigLeafRaw('agent_behaviors.intent_classifier.endpoint', repoRoot));
|
|
152
|
+
if (endpoint && /^https?:\/\//.test(endpoint)) cfg.endpoint = endpoint.replace(/\/+$/, '');
|
|
153
|
+
const model =
|
|
154
|
+
process.env.HEYSPEX_INTENT_MODEL ||
|
|
155
|
+
unquote(readConfigLeafRaw('agent_behaviors.intent_classifier.model', repoRoot));
|
|
156
|
+
if (model) cfg.model = model;
|
|
157
|
+
cfg.timeoutMs = num(
|
|
158
|
+
process.env.HEYSPEX_INTENT_TIMEOUT_MS ??
|
|
159
|
+
readConfigLeafRaw('agent_behaviors.intent_classifier.timeout_ms', repoRoot),
|
|
160
|
+
DEFAULTS.timeoutMs,
|
|
161
|
+
);
|
|
162
|
+
const minConf = Number(
|
|
163
|
+
process.env.HEYSPEX_INTENT_MIN_CONFIDENCE ??
|
|
164
|
+
readConfigLeafRaw('agent_behaviors.intent_classifier.min_confidence', repoRoot),
|
|
165
|
+
);
|
|
166
|
+
if (Number.isFinite(minConf) && minConf > 0 && minConf <= 1) cfg.minConfidence = minConf;
|
|
167
|
+
} catch {
|
|
168
|
+
return { ...DEFAULTS };
|
|
169
|
+
}
|
|
170
|
+
return cfg;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function unquote(raw) {
|
|
174
|
+
if (typeof raw !== 'string') return undefined;
|
|
175
|
+
const v = raw.trim();
|
|
176
|
+
const m = v.match(/^"(.*)"$/) || v.match(/^'(.*)'$/);
|
|
177
|
+
return m ? m[1] : v || undefined;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function buildSystemPrompt(behaviors) {
|
|
181
|
+
const rows = behaviors
|
|
182
|
+
.map((b) => `- ${b.key}: ${b.description}`)
|
|
183
|
+
.join('\n');
|
|
184
|
+
return (
|
|
185
|
+
'You classify ONE user message from a coding-agent session into exactly one behavior key, or "none" ' +
|
|
186
|
+
'when no behavior applies. Behaviors:\n' +
|
|
187
|
+
rows +
|
|
188
|
+
'\n- none: a direct work order, a question about existing work, a bug report to fix now, small talk, or anything else.\n' +
|
|
189
|
+
'Reply with STRICT JSON only, no prose: {"behavior":"<one key above or none>","confidence":<number 0..1>}'
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Classify a prompt into one of the given behaviors via the local Ollama endpoint.
|
|
195
|
+
*
|
|
196
|
+
* @param {string} prompt the user's message
|
|
197
|
+
* @param {{key:string, description:string}[]} behaviors candidate behaviors (defaults to KNOWN_BEHAVIORS)
|
|
198
|
+
* @param {object} [opts] { endpoint, model, timeoutMs, repoRoot } — omitted values come from config
|
|
199
|
+
* @returns {Promise<{behavior: string|null, confidence: number, latencyMs?: number, error?: string}>}
|
|
200
|
+
* behavior is null when nothing matched OR anything failed (fail-safe).
|
|
201
|
+
*/
|
|
202
|
+
export async function classifyIntent(prompt, behaviors = KNOWN_BEHAVIORS, opts = {}) {
|
|
203
|
+
const none = { behavior: null, confidence: 0 };
|
|
204
|
+
try {
|
|
205
|
+
if (typeof prompt !== 'string' || !prompt.trim()) return none;
|
|
206
|
+
const list = Array.isArray(behaviors) && behaviors.length ? behaviors : KNOWN_BEHAVIORS;
|
|
207
|
+
const cfg = readIntentClassifierConfig(opts.repoRoot ?? defaultConfigRoot());
|
|
208
|
+
const endpoint = opts.endpoint ?? cfg.endpoint;
|
|
209
|
+
const model = opts.model ?? cfg.model;
|
|
210
|
+
const timeoutMs = num(opts.timeoutMs, cfg.timeoutMs);
|
|
211
|
+
|
|
212
|
+
// Very short prompts carry no classifiable intent; very long ones are truncated
|
|
213
|
+
// to keep the local model inside the latency budget.
|
|
214
|
+
const text = prompt.trim().slice(0, 2000);
|
|
215
|
+
if (text.length < 12) return none;
|
|
216
|
+
|
|
217
|
+
// Optional call counter (proof/observability): when HEYSPEX_INTENT_CALL_LOG names
|
|
218
|
+
// a file, append one byte per model call so a test can assert exactly ≤1 call per
|
|
219
|
+
// prompt. Fail-safe: never let instrumentation break the classifier.
|
|
220
|
+
if (process.env.HEYSPEX_INTENT_CALL_LOG) {
|
|
221
|
+
try {
|
|
222
|
+
fs.appendFileSync(process.env.HEYSPEX_INTENT_CALL_LOG, `${new Date().toISOString()} ${model}\n`);
|
|
223
|
+
} catch {
|
|
224
|
+
/* ignore */
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const controller = new AbortController();
|
|
229
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
230
|
+
const t0 = Date.now();
|
|
231
|
+
let res;
|
|
232
|
+
try {
|
|
233
|
+
res = await fetch(`${endpoint}/api/chat`, {
|
|
234
|
+
method: 'POST',
|
|
235
|
+
headers: { 'content-type': 'application/json' },
|
|
236
|
+
signal: controller.signal,
|
|
237
|
+
body: JSON.stringify({
|
|
238
|
+
model,
|
|
239
|
+
stream: false,
|
|
240
|
+
format: 'json',
|
|
241
|
+
think: false, // qwen3: skip the reasoning preamble; harmless no-op elsewhere
|
|
242
|
+
keep_alive: '30m', // keep the classifier warm between prompts
|
|
243
|
+
options: { temperature: 0, num_predict: 120 },
|
|
244
|
+
messages: [
|
|
245
|
+
{ role: 'system', content: buildSystemPrompt(list) },
|
|
246
|
+
{ role: 'user', content: text },
|
|
247
|
+
],
|
|
248
|
+
}),
|
|
249
|
+
});
|
|
250
|
+
} finally {
|
|
251
|
+
clearTimeout(timer);
|
|
252
|
+
}
|
|
253
|
+
const latencyMs = Date.now() - t0;
|
|
254
|
+
if (!res || !res.ok) return { ...none, latencyMs, error: `http_${res?.status ?? 'no_response'}` };
|
|
255
|
+
|
|
256
|
+
const payload = await res.json().catch(() => null);
|
|
257
|
+
const content = payload?.message?.content;
|
|
258
|
+
if (typeof content !== 'string' || !content.trim()) return { ...none, latencyMs, error: 'empty_response' };
|
|
259
|
+
|
|
260
|
+
let parsed;
|
|
261
|
+
try {
|
|
262
|
+
parsed = JSON.parse(content);
|
|
263
|
+
} catch {
|
|
264
|
+
// Defensive: some models wrap JSON in text — try the first {...} span.
|
|
265
|
+
const m = content.match(/\{[\s\S]*\}/);
|
|
266
|
+
if (!m) return { ...none, latencyMs, error: 'unparseable_response' };
|
|
267
|
+
try {
|
|
268
|
+
parsed = JSON.parse(m[0]);
|
|
269
|
+
} catch {
|
|
270
|
+
return { ...none, latencyMs, error: 'unparseable_response' };
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const rawBehavior = typeof parsed?.behavior === 'string' ? parsed.behavior.trim() : '';
|
|
275
|
+
const confidence = clamp01(parsed?.confidence);
|
|
276
|
+
const valid = list.some((b) => b.key === rawBehavior);
|
|
277
|
+
if (!valid || rawBehavior === 'none') return { behavior: null, confidence, latencyMs };
|
|
278
|
+
return { behavior: rawBehavior, confidence, latencyMs };
|
|
279
|
+
} catch (err) {
|
|
280
|
+
const error = err?.name === 'AbortError' ? 'timeout' : 'unreachable';
|
|
281
|
+
return { ...none, error };
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Append one classifier-decision row to .heyspex/intent-classifier-history.jsonl.
|
|
287
|
+
* Called by the hooks for FIRES (either layer), semantic NEAR-MISSES (matched
|
|
288
|
+
* behavior below threshold), and semantic ERRORS — never for the ordinary
|
|
289
|
+
* regex-miss/no-match case, so the log stays small. FAIL-SAFE: never throws.
|
|
290
|
+
*/
|
|
291
|
+
export function appendClassifierEvent(row, repoRoot = DEFAULT_REPO_ROOT) {
|
|
292
|
+
try {
|
|
293
|
+
const full = {
|
|
294
|
+
timestamp: new Date().toISOString(),
|
|
295
|
+
event_kind: 'intent_classifier.decision',
|
|
296
|
+
...row,
|
|
297
|
+
};
|
|
298
|
+
fs.appendFileSync(
|
|
299
|
+
path.join(repoRoot, '.heyspex', 'intent-classifier-history.jsonl'),
|
|
300
|
+
JSON.stringify(full) + '\n',
|
|
301
|
+
);
|
|
302
|
+
return true;
|
|
303
|
+
} catch {
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// ── self-test CLI (no session required) ─────────────────────────────────────
|
|
309
|
+
|
|
310
|
+
async function ping() {
|
|
311
|
+
const cfg = readIntentClassifierConfig();
|
|
312
|
+
const out = { config: cfg, reachable: false, version: null, classify: null };
|
|
313
|
+
try {
|
|
314
|
+
const controller = new AbortController();
|
|
315
|
+
const timer = setTimeout(() => controller.abort(), cfg.timeoutMs);
|
|
316
|
+
const res = await fetch(`${cfg.endpoint}/api/version`, { signal: controller.signal });
|
|
317
|
+
clearTimeout(timer);
|
|
318
|
+
if (res.ok) {
|
|
319
|
+
out.reachable = true;
|
|
320
|
+
out.version = (await res.json().catch(() => null))?.version ?? null;
|
|
321
|
+
}
|
|
322
|
+
} catch {
|
|
323
|
+
/* stays unreachable */
|
|
324
|
+
}
|
|
325
|
+
if (out.reachable) {
|
|
326
|
+
out.classify = await classifyIntent(
|
|
327
|
+
"it'd be smart to let the app notice ideas on its own",
|
|
328
|
+
KNOWN_BEHAVIORS,
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
process.stdout.write(JSON.stringify(out, null, 2) + '\n');
|
|
332
|
+
process.exit(out.reachable && out.classify?.behavior === 'capture_on_idea' ? 0 : 1);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
async function classifyCli(text) {
|
|
336
|
+
const result = await classifyIntent(text, KNOWN_BEHAVIORS);
|
|
337
|
+
process.stdout.write(JSON.stringify(result, null, 2) + '\n');
|
|
338
|
+
process.exit(0);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
const isMain = process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url);
|
|
342
|
+
if (isMain) {
|
|
343
|
+
if (process.argv.includes('--ping')) {
|
|
344
|
+
ping();
|
|
345
|
+
} else {
|
|
346
|
+
const idx = process.argv.indexOf('--classify');
|
|
347
|
+
if (idx !== -1 && process.argv[idx + 1]) {
|
|
348
|
+
classifyCli(process.argv[idx + 1]);
|
|
349
|
+
} else if (process.argv.length > 2) {
|
|
350
|
+
process.stdout.write(
|
|
351
|
+
'Usage: node _intent-classifier-semantic.mjs --ping | --classify "<text>"\n',
|
|
352
|
+
);
|
|
353
|
+
process.exit(2);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|