@aria_asi/cli 0.2.26 → 0.2.29
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/CLIENT-ONBOARDING.md +282 -0
- package/bin/aria.js +1140 -14
- package/dist/aria-connector/src/auth-commands.d.ts +1 -0
- package/dist/aria-connector/src/auth-commands.d.ts.map +1 -1
- package/dist/aria-connector/src/auth-commands.js +89 -41
- package/dist/aria-connector/src/auth-commands.js.map +1 -1
- package/dist/aria-connector/src/chat.d.ts +3 -0
- package/dist/aria-connector/src/chat.d.ts.map +1 -1
- package/dist/aria-connector/src/chat.js +146 -8
- package/dist/aria-connector/src/chat.js.map +1 -1
- package/dist/aria-connector/src/codebase-scanner.d.ts +2 -2
- package/dist/aria-connector/src/codebase-scanner.d.ts.map +1 -1
- package/dist/aria-connector/src/codebase-scanner.js +1 -1
- package/dist/aria-connector/src/codebase-scanner.js.map +1 -1
- package/dist/aria-connector/src/config.d.ts +12 -0
- package/dist/aria-connector/src/config.d.ts.map +1 -1
- package/dist/aria-connector/src/config.js +2 -0
- package/dist/aria-connector/src/config.js.map +1 -1
- package/dist/aria-connector/src/connectors/claude-code.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/claude-code.js +80 -24
- package/dist/aria-connector/src/connectors/claude-code.js.map +1 -1
- package/dist/aria-connector/src/connectors/codebase-awareness.d.ts +37 -0
- package/dist/aria-connector/src/connectors/codebase-awareness.d.ts.map +1 -0
- package/dist/aria-connector/src/connectors/codebase-awareness.js +335 -0
- package/dist/aria-connector/src/connectors/codebase-awareness.js.map +1 -0
- package/dist/aria-connector/src/connectors/codex.d.ts +3 -0
- package/dist/aria-connector/src/connectors/codex.d.ts.map +1 -0
- package/dist/aria-connector/src/connectors/codex.js +248 -0
- package/dist/aria-connector/src/connectors/codex.js.map +1 -0
- package/dist/aria-connector/src/connectors/cognitive-skills.d.ts +2 -0
- package/dist/aria-connector/src/connectors/cognitive-skills.d.ts.map +1 -0
- package/dist/aria-connector/src/connectors/cognitive-skills.js +47 -0
- package/dist/aria-connector/src/connectors/cognitive-skills.js.map +1 -0
- package/dist/aria-connector/src/connectors/opencode.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/opencode.js +90 -4
- package/dist/aria-connector/src/connectors/opencode.js.map +1 -1
- package/dist/aria-connector/src/connectors/repo-git-hooks.d.ts +3 -0
- package/dist/aria-connector/src/connectors/repo-git-hooks.d.ts.map +1 -0
- package/dist/aria-connector/src/connectors/repo-git-hooks.js +87 -0
- package/dist/aria-connector/src/connectors/repo-git-hooks.js.map +1 -0
- package/dist/aria-connector/src/connectors/repo-guard.d.ts +19 -0
- package/dist/aria-connector/src/connectors/repo-guard.d.ts.map +1 -0
- package/dist/aria-connector/src/connectors/repo-guard.js +509 -0
- package/dist/aria-connector/src/connectors/repo-guard.js.map +1 -0
- package/dist/aria-connector/src/connectors/runtime.d.ts +2 -0
- package/dist/aria-connector/src/connectors/runtime.d.ts.map +1 -0
- package/dist/aria-connector/src/connectors/runtime.js +330 -0
- package/dist/aria-connector/src/connectors/runtime.js.map +1 -0
- package/dist/aria-connector/src/connectors/shell.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/shell.js +78 -13
- package/dist/aria-connector/src/connectors/shell.js.map +1 -1
- package/dist/aria-connector/src/connectors/syncd.d.ts +27 -0
- package/dist/aria-connector/src/connectors/syncd.d.ts.map +1 -0
- package/dist/aria-connector/src/connectors/syncd.js +405 -0
- package/dist/aria-connector/src/connectors/syncd.js.map +1 -0
- package/dist/aria-connector/src/decisions.d.ts +207 -0
- package/dist/aria-connector/src/decisions.d.ts.map +1 -0
- package/dist/aria-connector/src/decisions.js +291 -0
- package/dist/aria-connector/src/decisions.js.map +1 -0
- package/dist/aria-connector/src/garden-control-plane.d.ts.map +1 -1
- package/dist/aria-connector/src/garden-control-plane.js +74 -17
- package/dist/aria-connector/src/garden-control-plane.js.map +1 -1
- package/dist/aria-connector/src/github-connect.d.ts +18 -0
- package/dist/aria-connector/src/github-connect.d.ts.map +1 -0
- package/dist/aria-connector/src/github-connect.js +117 -0
- package/dist/aria-connector/src/github-connect.js.map +1 -0
- package/dist/aria-connector/src/harness-client.d.ts +15 -0
- package/dist/aria-connector/src/harness-client.d.ts.map +1 -1
- package/dist/aria-connector/src/harness-client.js +106 -3
- package/dist/aria-connector/src/harness-client.js.map +1 -1
- package/dist/aria-connector/src/hive-client.d.ts +30 -0
- package/dist/aria-connector/src/hive-client.d.ts.map +1 -1
- package/dist/aria-connector/src/hive-client.js +124 -5
- package/dist/aria-connector/src/hive-client.js.map +1 -1
- package/dist/aria-connector/src/index.d.ts +13 -2
- package/dist/aria-connector/src/index.d.ts.map +1 -1
- package/dist/aria-connector/src/index.js +10 -1
- package/dist/aria-connector/src/index.js.map +1 -1
- package/dist/aria-connector/src/lib/aristotle-noor-wire.d.ts +102 -0
- package/dist/aria-connector/src/lib/aristotle-noor-wire.d.ts.map +1 -0
- package/dist/aria-connector/src/lib/aristotle-noor-wire.js +231 -0
- package/dist/aria-connector/src/lib/aristotle-noor-wire.js.map +1 -0
- package/dist/aria-connector/src/providers/types.d.ts +5 -0
- package/dist/aria-connector/src/providers/types.d.ts.map +1 -1
- package/dist/aria-connector/src/runtime-proof.d.ts +45 -0
- package/dist/aria-connector/src/runtime-proof.d.ts.map +1 -0
- package/dist/aria-connector/src/runtime-proof.js +340 -0
- package/dist/aria-connector/src/runtime-proof.js.map +1 -0
- package/dist/aria-connector/src/setup-wizard.d.ts.map +1 -1
- package/dist/aria-connector/src/setup-wizard.js +34 -2
- package/dist/aria-connector/src/setup-wizard.js.map +1 -1
- package/dist/assets/hooks/aria-agent-handoff.mjs +224 -0
- package/dist/assets/hooks/aria-agent-ledger-merge.mjs +164 -0
- package/dist/assets/hooks/aria-architect-fallback.mjs +267 -0
- package/dist/assets/hooks/aria-cognition-substrate-binding.mjs +676 -0
- package/dist/assets/hooks/aria-discovery-record.mjs +101 -0
- package/dist/assets/hooks/aria-harness-via-sdk.mjs +412 -0
- package/dist/assets/hooks/aria-import-resolution-gate.mjs +330 -0
- package/dist/assets/hooks/aria-outcome-record.mjs +84 -0
- package/dist/assets/hooks/aria-pre-emit-dryrun.mjs +294 -0
- package/dist/assets/hooks/aria-pre-text-gate.mjs +112 -0
- package/dist/assets/hooks/aria-pre-tool-gate.mjs +2133 -0
- package/dist/assets/hooks/aria-preprompt-consult.mjs +438 -0
- package/dist/assets/hooks/aria-preturn-memory-gate.mjs +570 -0
- package/dist/assets/hooks/aria-repo-doctrine-gate.mjs +397 -0
- package/dist/assets/hooks/aria-stop-gate.mjs +1551 -0
- package/dist/assets/hooks/aria-trigger-autolearn.mjs +229 -0
- package/dist/assets/hooks/aria-userprompt-abandon-detect.mjs +192 -0
- package/dist/assets/hooks/doctrine_trigger_map.json +479 -0
- package/dist/assets/hooks/lib/canonical-lenses.mjs +64 -0
- package/dist/assets/hooks/lib/gate-audit.mjs +43 -0
- package/dist/assets/hooks/test-aria-preturn-memory-gate.mjs +245 -0
- package/dist/assets/hooks/test-tier-lens-labeling.mjs +399 -0
- package/dist/assets/opencode-plugins/harness-context/index.js +60 -0
- package/dist/assets/opencode-plugins/harness-context/inject-context.mjs +179 -0
- package/dist/assets/opencode-plugins/harness-context/package.json +9 -0
- package/dist/assets/opencode-plugins/harness-gate/index.js +248 -0
- package/dist/assets/opencode-plugins/harness-outcome/index.js +129 -0
- package/dist/assets/opencode-plugins/harness-role/index.js +77 -0
- package/dist/assets/opencode-plugins/harness-role/package.json +9 -0
- package/dist/assets/opencode-plugins/harness-stop/index.js +241 -0
- package/dist/runtime/discipline/CLAUDE.md +339 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-essence/SKILL.md +63 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-essence/references/domain-matrix.md +80 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-essence/references/evolution-loop.md +30 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-essence/references/readable-cognition.md +27 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-forge-guardrails/SKILL.md +35 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-forge-guardrails/references/checklist.md +31 -0
- package/dist/runtime/discipline/skills/aria-cognition/aria-repo-doctrine/SKILL.md +39 -0
- package/dist/runtime/discipline/skills/aria-cognition/forge-quality-rules/SKILL.md +43 -0
- package/dist/runtime/discipline/skills/aria-cognition/ghazali-8lens/SKILL.md +38 -0
- package/dist/runtime/discipline/skills/aria-cognition/istiqra-induction/SKILL.md +26 -0
- package/dist/runtime/discipline/skills/aria-cognition/ladunni-22/SKILL.md +35 -0
- package/dist/runtime/discipline/skills/aria-cognition/mizan/SKILL.md +72 -0
- package/dist/runtime/discipline/skills/aria-cognition/nadia/SKILL.md +38 -0
- package/dist/runtime/discipline/skills/aria-cognition/nadia-psi/SKILL.md +38 -0
- package/dist/runtime/discipline/skills/aria-cognition/predictor/SKILL.md +25 -0
- package/dist/runtime/discipline/skills/aria-cognition/qiyas-analogy/SKILL.md +26 -0
- package/dist/runtime/discipline/skills/aria-cognition/soul-domains/SKILL.md +25 -0
- package/dist/runtime/discipline/skills/aria-harness/aria-aristotle-intra-phase/SKILL.md +81 -0
- package/dist/runtime/discipline/skills/aria-harness/aria-aristotle-post-phase/SKILL.md +98 -0
- package/dist/runtime/discipline/skills/aria-harness/aria-aristotle-pre-phase/SKILL.md +99 -0
- package/dist/runtime/discipline/skills/aria-harness/aria-harness-deploy/SKILL.md +127 -0
- package/dist/runtime/discipline/skills/aria-harness/aria-harness-no-stripping/SKILL.md +117 -0
- package/dist/runtime/discipline/skills/aria-harness/aria-harness-onboarding/SKILL.md +112 -0
- package/dist/runtime/discipline/skills/aria-harness/aria-harness-output-discipline/SKILL.md +102 -0
- package/dist/runtime/discipline/skills/aria-harness/aria-harness-substrate-binding/SKILL.md +121 -0
- package/dist/runtime/doctor.mjs +23 -0
- package/dist/runtime/local-phase.mjs +632 -0
- package/dist/runtime/manifest.json +15 -0
- package/dist/runtime/mizan-scheduler.mjs +331 -0
- package/dist/runtime/package.json +6 -0
- package/dist/runtime/provider-proxy.mjs +594 -0
- package/dist/runtime/sdk/BUNDLED.json +5 -0
- package/dist/runtime/sdk/index.d.ts +477 -0
- package/dist/runtime/sdk/index.js +1469 -0
- package/dist/runtime/sdk/index.js.map +1 -0
- package/dist/runtime/sdk/package.json +8 -0
- package/dist/runtime/sdk/runWithCognition.d.ts +77 -0
- package/dist/runtime/sdk/runWithCognition.js +157 -0
- package/dist/runtime/sdk/runWithCognition.js.map +1 -0
- package/dist/runtime/service.mjs +2708 -0
- package/dist/runtime/vendor/aria-gate-runtime/index.d.ts +53 -0
- package/dist/runtime/vendor/aria-gate-runtime/index.d.ts.map +1 -0
- package/dist/runtime/vendor/aria-gate-runtime/index.js +277 -0
- package/dist/runtime/vendor/aria-gate-runtime/index.js.map +1 -0
- package/dist/runtime/vendor/aria-gate-runtime/package.json +6 -0
- package/dist/sdk/BUNDLED.json +2 -2
- package/dist/sdk/index.d.ts +283 -0
- package/dist/sdk/index.js +622 -85
- package/dist/sdk/index.js.map +1 -1
- package/dist/sdk/runWithCognition.d.ts +77 -0
- package/dist/sdk/runWithCognition.js +157 -0
- package/dist/sdk/runWithCognition.js.map +1 -0
- package/hooks/aria-agent-handoff.mjs +11 -1
- package/hooks/aria-architect-fallback.mjs +109 -40
- package/hooks/aria-cognition-substrate-binding.mjs +676 -0
- package/hooks/aria-harness-via-sdk.mjs +34 -21
- package/hooks/aria-import-resolution-gate.mjs +330 -0
- package/hooks/aria-outcome-record.mjs +5 -1
- package/hooks/aria-pre-emit-dryrun.mjs +294 -0
- package/hooks/aria-pre-tool-gate.mjs +828 -41
- package/hooks/aria-preprompt-consult.mjs +113 -13
- package/hooks/aria-preturn-memory-gate.mjs +298 -6
- package/hooks/aria-repo-doctrine-gate.mjs +397 -0
- package/hooks/aria-stop-gate.mjs +739 -76
- package/hooks/aria-userprompt-abandon-detect.mjs +5 -1
- package/hooks/doctrine_trigger_map.json +209 -15
- package/hooks/lib/canonical-lenses.mjs +64 -0
- package/hooks/lib/gate-audit.mjs +43 -0
- package/opencode-plugins/harness-context/index.js +1 -1
- package/opencode-plugins/harness-context/inject-context.mjs +82 -23
- package/opencode-plugins/harness-gate/index.js +248 -0
- package/opencode-plugins/harness-outcome/index.js +129 -0
- package/opencode-plugins/harness-stop/index.js +241 -0
- package/package.json +8 -2
- package/runtime-src/doctor.mjs +23 -0
- package/runtime-src/local-phase.mjs +632 -0
- package/runtime-src/mizan-scheduler.mjs +331 -0
- package/runtime-src/provider-proxy.mjs +594 -0
- package/runtime-src/service.mjs +2708 -0
- package/scripts/bundle-sdk.mjs +317 -0
- package/scripts/install-client.sh +176 -0
- package/scripts/publish-all.sh +344 -0
- package/scripts/publish-docker.sh +27 -0
- package/scripts/validate-hook-contracts.mjs +54 -0
- package/scripts/validate-skill-prompts.mjs +95 -0
- package/skills/aria-cognition/aria-essence/SKILL.md +63 -0
- package/skills/aria-cognition/aria-essence/references/domain-matrix.md +80 -0
- package/skills/aria-cognition/aria-essence/references/evolution-loop.md +30 -0
- package/skills/aria-cognition/aria-essence/references/readable-cognition.md +27 -0
- package/skills/aria-cognition/aria-forge-guardrails/SKILL.md +35 -0
- package/skills/aria-cognition/aria-forge-guardrails/references/checklist.md +31 -0
- package/skills/aria-cognition/aria-repo-doctrine/SKILL.md +39 -0
- package/skills/aria-cognition/forge-quality-rules/SKILL.md +43 -0
- package/skills/aria-cognition/ghazali-8lens/SKILL.md +38 -0
- package/skills/aria-cognition/istiqra-induction/SKILL.md +26 -0
- package/skills/aria-cognition/ladunni-22/SKILL.md +35 -0
- package/skills/aria-cognition/mizan/SKILL.md +72 -0
- package/skills/aria-cognition/nadia/SKILL.md +38 -0
- package/skills/aria-cognition/nadia-psi/SKILL.md +38 -0
- package/skills/aria-cognition/predictor/SKILL.md +25 -0
- package/skills/aria-cognition/qiyas-analogy/SKILL.md +26 -0
- package/skills/aria-cognition/soul-domains/SKILL.md +25 -0
- package/src/auth-commands.ts +111 -45
- package/src/chat.ts +174 -13
- package/src/codebase-scanner.ts +4 -0
- package/src/config.ts +15 -0
- package/src/connectors/claude-code.ts +79 -25
- package/src/connectors/codebase-awareness.ts +408 -0
- package/src/connectors/codex.ts +274 -0
- package/src/connectors/cognitive-skills.ts +51 -0
- package/src/connectors/opencode.ts +93 -4
- package/src/connectors/repo-git-hooks.ts +86 -0
- package/src/connectors/repo-guard.ts +589 -0
- package/src/connectors/runtime.ts +374 -0
- package/src/connectors/shell.ts +83 -14
- package/src/connectors/syncd.ts +488 -0
- package/src/decisions.ts +469 -0
- package/src/garden-control-plane.ts +101 -26
- package/src/github-connect.ts +143 -0
- package/src/harness-client.ts +128 -3
- package/src/hive-client.ts +165 -5
- package/src/index.ts +41 -2
- package/src/lib/aristotle-noor-wire.ts +310 -0
- package/src/providers/types.ts +6 -0
- package/src/runtime-proof.ts +392 -0
- package/src/setup-wizard.ts +37 -2
package/bin/aria.js
CHANGED
|
@@ -8,7 +8,32 @@ import { AriaChat } from '../dist/aria-connector/src/chat.js';
|
|
|
8
8
|
import { checkHarnessHealth } from '../dist/aria-connector/src/harness-client.js';
|
|
9
9
|
import { login, loginOwner, status, logout, revoke } from '../dist/aria-connector/src/auth-commands.js';
|
|
10
10
|
import { connectClaudeCode } from '../dist/aria-connector/src/connectors/claude-code.js';
|
|
11
|
+
import { connectCodex } from '../dist/aria-connector/src/connectors/codex.js';
|
|
12
|
+
import { connectOpenCode } from '../dist/aria-connector/src/connectors/opencode.js';
|
|
13
|
+
import { connectCursor } from '../dist/aria-connector/src/connectors/cursor.js';
|
|
14
|
+
import {
|
|
15
|
+
installCodebaseAwarenessDaemon,
|
|
16
|
+
startCodebaseAwarenessDaemon,
|
|
17
|
+
runCodebaseAwarenessScan,
|
|
18
|
+
readCodebaseAwarenessState,
|
|
19
|
+
} from '../dist/aria-connector/src/connectors/codebase-awareness.js';
|
|
20
|
+
import {
|
|
21
|
+
installRepoGuardDaemon,
|
|
22
|
+
startRepoGuardDaemon,
|
|
23
|
+
readGuardState,
|
|
24
|
+
} from '../dist/aria-connector/src/connectors/repo-guard.js';
|
|
25
|
+
import { installRepoDoctrineGitHooks } from '../dist/aria-connector/src/connectors/repo-git-hooks.js';
|
|
26
|
+
import { installSharedRuntime } from '../dist/aria-connector/src/connectors/runtime.js';
|
|
27
|
+
import {
|
|
28
|
+
installAriaSyncDaemon,
|
|
29
|
+
runSyncOnce,
|
|
30
|
+
startSyncDaemon,
|
|
31
|
+
readSyncDaemonState,
|
|
32
|
+
} from '../dist/aria-connector/src/connectors/syncd.js';
|
|
11
33
|
import { maybePrintUpdateNotice, checkForUpdate } from '../dist/aria-connector/src/self-update.js';
|
|
34
|
+
import { pathToFileURL } from 'node:url';
|
|
35
|
+
import { homedir } from 'node:os';
|
|
36
|
+
import { execFileSync } from 'node:child_process';
|
|
12
37
|
|
|
13
38
|
// ── Self-update notice (non-blocking, rate-limited once per 24h) ──
|
|
14
39
|
// Fires-and-forgets — the registry check runs in parallel with command
|
|
@@ -19,6 +44,33 @@ if (process.env.ARIA_SELF_UPDATE !== 'off') {
|
|
|
19
44
|
maybePrintUpdateNotice().catch(() => {});
|
|
20
45
|
}
|
|
21
46
|
|
|
47
|
+
// ── Aristotle 28 + Noor cognitive lifecycle hook (#98) ──────────────────
|
|
48
|
+
// Every CLI command lifecycle fires through `wrapCliCommand` so the 28
|
|
49
|
+
// Aristotle modules + Noor cognitives surface (Fitrah hard-gate, 8-lens,
|
|
50
|
+
// Predictor, SelfReflection, Tafakkur projection, soul-charge telemetry,
|
|
51
|
+
// Ghazali alignment) every time `aria <anything>` runs. Fail-open by
|
|
52
|
+
// construction — when the harness route is unreachable the wrapper falls
|
|
53
|
+
// through to validateOutput so at least post-stage gates still fire.
|
|
54
|
+
// Kill-switch: ARIA_NOOR_HOOK=off env.
|
|
55
|
+
let aristotleNoorWire = null;
|
|
56
|
+
async function loadAristotleNoorWire() {
|
|
57
|
+
if (aristotleNoorWire !== null) return aristotleNoorWire;
|
|
58
|
+
if (process.env.ARIA_NOOR_HOOK === 'off') {
|
|
59
|
+
aristotleNoorWire = { runAristotleNoorOnSDK: async () => ({ dispatched: false, fired: [] }), wrapCliCommand: async (_s, _e, fn) => ({ result: await fn(), coverage: { fired: [], dispatched: false } }) };
|
|
60
|
+
return aristotleNoorWire;
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
aristotleNoorWire = await import('../dist/aria-connector/src/lib/aristotle-noor-wire.js');
|
|
64
|
+
} catch {
|
|
65
|
+
// Build artifact missing — fail-open so the CLI still runs.
|
|
66
|
+
aristotleNoorWire = { runAristotleNoorOnSDK: async () => ({ dispatched: false, fired: [] }), wrapCliCommand: async (_s, _e, fn) => ({ result: await fn(), coverage: { fired: [], dispatched: false } }) };
|
|
67
|
+
}
|
|
68
|
+
return aristotleNoorWire;
|
|
69
|
+
}
|
|
70
|
+
function makeEmissionId(surface) {
|
|
71
|
+
return `cli_${surface}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
|
72
|
+
}
|
|
73
|
+
|
|
22
74
|
// ── Auth + install subcommands — handled BEFORE the chat flow.
|
|
23
75
|
// Hamza 2026-04-26: license-aware CLI for client-tonight ship +
|
|
24
76
|
// self-installing harness via install-hooks.
|
|
@@ -43,31 +95,346 @@ if (command === 'check-update') {
|
|
|
43
95
|
console.error(`I hit an unexpected error checking for updates: ${err && err.message ? err.message : err}`);
|
|
44
96
|
process.exit(1);
|
|
45
97
|
});
|
|
98
|
+
} else if (command === 'github') {
|
|
99
|
+
const subCommand = args[0] || 'connect';
|
|
100
|
+
const { connectGitHub, getGitHubStatus } = await import('../dist/aria-connector/src/github-connect.js');
|
|
101
|
+
|
|
102
|
+
if (subCommand === 'help' || subCommand === '--help' || subCommand === '-h') {
|
|
103
|
+
console.log('');
|
|
104
|
+
console.log(' aria github connect Authenticate GitHub through gh and wire npm for @aria_asi packages.');
|
|
105
|
+
console.log(' aria github status Show whether gh auth and npm package wiring are ready.');
|
|
106
|
+
console.log('');
|
|
107
|
+
console.log(' This is optional. Most clients should install Aria without GitHub and only run this if they want GitHub integration or GitHub Packages access.');
|
|
108
|
+
console.log('');
|
|
109
|
+
process.exit(0);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (subCommand === 'status') {
|
|
113
|
+
const status = getGitHubStatus();
|
|
114
|
+
console.log(`gh_installed=${status.ghInstalled ? 'yes' : 'no'}`);
|
|
115
|
+
console.log(`gh_authenticated=${status.authenticated ? 'yes' : 'no'}`);
|
|
116
|
+
console.log(`npm_scope_configured=${status.npmrcConfigured ? 'yes' : 'no'}`);
|
|
117
|
+
process.exit(status.ghInstalled && status.authenticated ? 0 : 1);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (subCommand === 'connect') {
|
|
121
|
+
try {
|
|
122
|
+
const result = connectGitHub({ interactive: true });
|
|
123
|
+
if (!result.ok) {
|
|
124
|
+
console.error(result.error || 'GitHub connect failed');
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
for (const line of result.logs) console.log(` ${line}`);
|
|
128
|
+
console.log(' GitHub is now connected for optional Aria package and repo workflows.');
|
|
129
|
+
process.exit(0);
|
|
130
|
+
} catch (err) {
|
|
131
|
+
console.error(`I couldn't complete GitHub connect: ${err && err.message ? err.message : err}`);
|
|
132
|
+
process.exit(1);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
console.error(`Unknown github subcommand: ${subCommand}`);
|
|
137
|
+
console.error('Run: aria github --help');
|
|
138
|
+
process.exit(1);
|
|
46
139
|
} else if (command === 'install-hooks' || command === 'connect') {
|
|
47
|
-
// Canonical install path
|
|
48
|
-
//
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
// wiring, systemPromptPrefix injection, and additionalDirectories.
|
|
140
|
+
// Canonical install path connects Claude Code, OpenCode, Codex, and Cursor.
|
|
141
|
+
// connectClaudeCode → SDK + hooks + settings.json
|
|
142
|
+
// connectOpenCode → plugins + config.json + AGENTS.md
|
|
143
|
+
// connectCodex → SDK + local node package + skill
|
|
52
144
|
const force = args.includes('--force');
|
|
53
|
-
// Build a minimal AriaConfig so connectClaudeCode can render the
|
|
54
|
-
// systemPromptPrefix block. If an existing config exists, use it.
|
|
55
145
|
let config;
|
|
56
146
|
try {
|
|
57
147
|
config = loadConfig();
|
|
58
148
|
} catch {
|
|
59
149
|
config = { repositories: [], schemaImages: {} };
|
|
60
150
|
}
|
|
61
|
-
|
|
151
|
+
loadAristotleNoorWire().then((wire) => wire.wrapCliCommand(
|
|
152
|
+
'cli-connect',
|
|
153
|
+
makeEmissionId('connect'),
|
|
154
|
+
async () => {
|
|
155
|
+
const allLogs = [];
|
|
156
|
+
// Shared runtime path — universal localhost sidecar for any client.
|
|
157
|
+
const runtimeLogs = await installSharedRuntime();
|
|
158
|
+
allLogs.push(...runtimeLogs);
|
|
159
|
+
// Claude Code path
|
|
160
|
+
const claudeLogs = await connectClaudeCode(config, { force });
|
|
161
|
+
allLogs.push(...claudeLogs);
|
|
162
|
+
// OpenCode path
|
|
163
|
+
const opencodeLogs = await connectOpenCode(config);
|
|
164
|
+
allLogs.push(...opencodeLogs);
|
|
165
|
+
// Codex path
|
|
166
|
+
const codexLogs = await connectCodex(config);
|
|
167
|
+
allLogs.push(...codexLogs);
|
|
168
|
+
// Cursor path — wire every linked repository
|
|
169
|
+
if (config.repositories?.length) {
|
|
170
|
+
for (const repo of config.repositories) {
|
|
171
|
+
const cursorLogs = await connectCursor(config, repo.path);
|
|
172
|
+
allLogs.push(...cursorLogs);
|
|
173
|
+
}
|
|
174
|
+
} else {
|
|
175
|
+
// Wire current working directory as fallback
|
|
176
|
+
const cursorLogs = await connectCursor(config);
|
|
177
|
+
allLogs.push(...cursorLogs);
|
|
178
|
+
}
|
|
179
|
+
const repoGateLogs = await installRepoDoctrineGitHooks(config, process.cwd());
|
|
180
|
+
allLogs.push(...repoGateLogs);
|
|
181
|
+
const repoGuardLogs = await installRepoGuardDaemon(config, process.cwd());
|
|
182
|
+
allLogs.push(...repoGuardLogs);
|
|
183
|
+
const codebaseAwarenessLogs = await installCodebaseAwarenessDaemon(config, process.cwd());
|
|
184
|
+
allLogs.push(...codebaseAwarenessLogs);
|
|
185
|
+
if (process.env.ARIA_SKIP_SYNCD_INSTALL !== '1') {
|
|
186
|
+
const syncLogs = await installAriaSyncDaemon({ sourceRoot: process.cwd() });
|
|
187
|
+
allLogs.push(...syncLogs);
|
|
188
|
+
}
|
|
189
|
+
return allLogs;
|
|
190
|
+
},
|
|
191
|
+
{ metadata: { force, command: 'connect' } },
|
|
192
|
+
)).then(({ result: logs }) => {
|
|
62
193
|
for (const line of logs) console.log(` ${line}`);
|
|
63
|
-
console.log("Your Claude Code
|
|
194
|
+
console.log("Your Claude Code, OpenCode, Codex, and Cursor are now synced from the same harness package. Open a new session to start.");
|
|
64
195
|
process.exit(0);
|
|
65
196
|
}).catch((err) => {
|
|
66
197
|
console.error(`I hit an unexpected error: ${err && err.message ? err.message : err}`);
|
|
67
198
|
process.exit(1);
|
|
68
199
|
});
|
|
200
|
+
} else if (command === 'runtime') {
|
|
201
|
+
const subCommand = args[0] || 'help';
|
|
202
|
+
const runtimeRoot = `${homedir()}/.aria/runtime`;
|
|
203
|
+
const runtimeEntry = `${runtimeRoot}/service.mjs`;
|
|
204
|
+
const runtimeUrl = process.env.ARIA_RUNTIME_URL || 'http://127.0.0.1:4319';
|
|
205
|
+
const runtimeService = 'aria-mounted-runtime.service';
|
|
206
|
+
|
|
207
|
+
if (subCommand === 'help' || subCommand === '--help' || subCommand === '-h') {
|
|
208
|
+
console.log('');
|
|
209
|
+
console.log(' aria runtime start Start the shared Aria localhost runtime in the foreground.');
|
|
210
|
+
console.log(' aria runtime status Check the shared runtime health endpoint.');
|
|
211
|
+
console.log(' aria runtime mount Print the mount env vars and local paths.');
|
|
212
|
+
console.log(' aria runtime restart Restart the managed mounted runtime service.');
|
|
213
|
+
console.log(' aria runtime stop Stop the managed mounted runtime service.');
|
|
214
|
+
console.log(' aria runtime logs Tail the managed mounted runtime logs.');
|
|
215
|
+
console.log('');
|
|
216
|
+
process.exit(0);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (subCommand === 'mount') {
|
|
220
|
+
console.log(`ARIA_RUNTIME_URL=${runtimeUrl}`);
|
|
221
|
+
const harnessUrl =
|
|
222
|
+
process.env.ARIA_HIVE_RUNTIME_URL ||
|
|
223
|
+
process.env.ARIA_HARNESS_BASE_URL ||
|
|
224
|
+
process.env.ARIA_HARNESS_URL ||
|
|
225
|
+
'https://harness.ariasos.com';
|
|
226
|
+
console.log(`ARIA_HIVE_RUNTIME_URL=${harnessUrl}`);
|
|
227
|
+
console.log(`ARIA_HARNESS_URL=${harnessUrl}`);
|
|
228
|
+
console.log(`runtime_root=${runtimeRoot}`);
|
|
229
|
+
console.log(`runtime_entry=${runtimeEntry}`);
|
|
230
|
+
process.exit(0);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (subCommand === 'status') {
|
|
234
|
+
fetch(`${runtimeUrl}/health`).then(async (response) => {
|
|
235
|
+
const payload = await response.json().catch(() => ({}));
|
|
236
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
237
|
+
process.exit(response.ok ? 0 : 1);
|
|
238
|
+
}).catch((err) => {
|
|
239
|
+
console.error(`I couldn't reach the runtime at ${runtimeUrl}: ${err && err.message ? err.message : err}`);
|
|
240
|
+
process.exit(1);
|
|
241
|
+
});
|
|
242
|
+
} else if (subCommand === 'start') {
|
|
243
|
+
import(pathToFileURL(runtimeEntry).href).then(({ startRuntimeServer }) => {
|
|
244
|
+
return startRuntimeServer();
|
|
245
|
+
}).catch((err) => {
|
|
246
|
+
console.error(`I couldn't start the runtime: ${err && err.message ? err.message : err}`);
|
|
247
|
+
process.exit(1);
|
|
248
|
+
});
|
|
249
|
+
} else if (subCommand === 'restart') {
|
|
250
|
+
try {
|
|
251
|
+
execFileSync('/bin/systemctl', ['--user', 'restart', runtimeService], { stdio: 'inherit' });
|
|
252
|
+
process.exit(0);
|
|
253
|
+
} catch (err) {
|
|
254
|
+
console.error(`I couldn't restart ${runtimeService}: ${err && err.message ? err.message : err}`);
|
|
255
|
+
process.exit(1);
|
|
256
|
+
}
|
|
257
|
+
} else if (subCommand === 'stop') {
|
|
258
|
+
try {
|
|
259
|
+
execFileSync('/bin/systemctl', ['--user', 'stop', runtimeService], { stdio: 'inherit' });
|
|
260
|
+
process.exit(0);
|
|
261
|
+
} catch (err) {
|
|
262
|
+
console.error(`I couldn't stop ${runtimeService}: ${err && err.message ? err.message : err}`);
|
|
263
|
+
process.exit(1);
|
|
264
|
+
}
|
|
265
|
+
} else if (subCommand === 'logs') {
|
|
266
|
+
try {
|
|
267
|
+
execFileSync('/bin/journalctl', ['--user', '-u', runtimeService, '-n', '80', '--no-pager'], { stdio: 'inherit' });
|
|
268
|
+
process.exit(0);
|
|
269
|
+
} catch (err) {
|
|
270
|
+
console.error(`I couldn't read ${runtimeService} logs: ${err && err.message ? err.message : err}`);
|
|
271
|
+
process.exit(1);
|
|
272
|
+
}
|
|
273
|
+
} else {
|
|
274
|
+
console.error(`Unknown runtime subcommand: ${subCommand}`);
|
|
275
|
+
process.exit(1);
|
|
276
|
+
}
|
|
277
|
+
} else if (command === 'codebase-awareness') {
|
|
278
|
+
const subCommand = args[0] || 'help';
|
|
279
|
+
const service = 'aria-codebase-awareness.service';
|
|
280
|
+
|
|
281
|
+
if (subCommand === 'help' || subCommand === '--help' || subCommand === '-h') {
|
|
282
|
+
console.log('');
|
|
283
|
+
console.log(' aria codebase-awareness start Watch linked repos and keep schema images warm.');
|
|
284
|
+
console.log(' aria codebase-awareness scan Run a one-shot repo scan now.');
|
|
285
|
+
console.log(' aria codebase-awareness status Print the last codebase awareness state snapshot.');
|
|
286
|
+
console.log(' aria codebase-awareness restart Restart the codebase awareness service.');
|
|
287
|
+
console.log(' aria codebase-awareness logs Tail the codebase awareness logs.');
|
|
288
|
+
console.log('');
|
|
289
|
+
process.exit(0);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (subCommand === 'status') {
|
|
293
|
+
console.log(JSON.stringify(readCodebaseAwarenessState(), null, 2));
|
|
294
|
+
process.exit(0);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (subCommand === 'scan') {
|
|
298
|
+
runCodebaseAwarenessScan({ fallbackRepoPath: process.cwd() }).then((result) => {
|
|
299
|
+
console.log(JSON.stringify(result, null, 2));
|
|
300
|
+
process.exit(0);
|
|
301
|
+
}).catch((err) => {
|
|
302
|
+
console.error(`I couldn't scan the codebase: ${err && err.message ? err.message : err}`);
|
|
303
|
+
process.exit(1);
|
|
304
|
+
});
|
|
305
|
+
} else if (subCommand === 'start') {
|
|
306
|
+
startCodebaseAwarenessDaemon({ fallbackRepoPath: process.cwd() }).catch((err) => {
|
|
307
|
+
console.error(`I couldn't start codebase awareness: ${err && err.message ? err.message : err}`);
|
|
308
|
+
process.exit(1);
|
|
309
|
+
});
|
|
310
|
+
} else if (subCommand === 'restart') {
|
|
311
|
+
try {
|
|
312
|
+
execFileSync('/bin/systemctl', ['--user', 'restart', service], { stdio: 'inherit' });
|
|
313
|
+
process.exit(0);
|
|
314
|
+
} catch (err) {
|
|
315
|
+
console.error(`I couldn't restart ${service}: ${err && err.message ? err.message : err}`);
|
|
316
|
+
process.exit(1);
|
|
317
|
+
}
|
|
318
|
+
} else if (subCommand === 'logs') {
|
|
319
|
+
try {
|
|
320
|
+
execFileSync('/bin/journalctl', ['--user', '-u', service, '-n', '80', '--no-pager'], { stdio: 'inherit' });
|
|
321
|
+
process.exit(0);
|
|
322
|
+
} catch (err) {
|
|
323
|
+
console.error(`I couldn't read ${service} logs: ${err && err.message ? err.message : err}`);
|
|
324
|
+
process.exit(1);
|
|
325
|
+
}
|
|
326
|
+
} else {
|
|
327
|
+
console.error(`Unknown codebase-awareness subcommand: ${subCommand}`);
|
|
328
|
+
process.exit(1);
|
|
329
|
+
}
|
|
330
|
+
} else if (command === 'syncd') {
|
|
331
|
+
const subCommand = args[0] || 'help';
|
|
332
|
+
const syncService = 'aria-syncd.service';
|
|
333
|
+
|
|
334
|
+
if (subCommand === 'help' || subCommand === '--help' || subCommand === '-h') {
|
|
335
|
+
console.log('');
|
|
336
|
+
console.log(' aria syncd start Watch Claude/harness/runtime sources and auto-sync all clients.');
|
|
337
|
+
console.log(' aria syncd once Run one sync cycle now.');
|
|
338
|
+
console.log(' aria syncd status Print the last sync daemon state snapshot.');
|
|
339
|
+
console.log(' aria syncd restart Restart the sync daemon service.');
|
|
340
|
+
console.log(' aria syncd logs Tail the sync daemon logs.');
|
|
341
|
+
console.log('');
|
|
342
|
+
process.exit(0);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (subCommand === 'status') {
|
|
346
|
+
console.log(JSON.stringify(readSyncDaemonState(), null, 2));
|
|
347
|
+
process.exit(0);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (subCommand === 'once') {
|
|
351
|
+
runSyncOnce({ sourceRoot: process.cwd(), reason: 'cli-once' }).then((result) => {
|
|
352
|
+
console.log(JSON.stringify(result, null, 2));
|
|
353
|
+
process.exit(0);
|
|
354
|
+
}).catch((err) => {
|
|
355
|
+
console.error(`I couldn't complete the sync: ${err && err.message ? err.message : err}`);
|
|
356
|
+
process.exit(1);
|
|
357
|
+
});
|
|
358
|
+
} else if (subCommand === 'restart') {
|
|
359
|
+
try {
|
|
360
|
+
execFileSync('/bin/systemctl', ['--user', 'restart', syncService], { stdio: 'inherit' });
|
|
361
|
+
process.exit(0);
|
|
362
|
+
} catch (err) {
|
|
363
|
+
console.error(`I couldn't restart ${syncService}: ${err && err.message ? err.message : err}`);
|
|
364
|
+
process.exit(1);
|
|
365
|
+
}
|
|
366
|
+
} else if (subCommand === 'logs') {
|
|
367
|
+
try {
|
|
368
|
+
execFileSync('/bin/journalctl', ['--user', '-u', syncService, '-n', '80', '--no-pager'], { stdio: 'inherit' });
|
|
369
|
+
process.exit(0);
|
|
370
|
+
} catch (err) {
|
|
371
|
+
console.error(`I couldn't read ${syncService} logs: ${err && err.message ? err.message : err}`);
|
|
372
|
+
process.exit(1);
|
|
373
|
+
}
|
|
374
|
+
} else if (subCommand === 'start') {
|
|
375
|
+
startSyncDaemon({ sourceRoot: process.cwd(), reason: 'cli-start' }).catch((err) => {
|
|
376
|
+
console.error(`I couldn't start syncd: ${err && err.message ? err.message : err}`);
|
|
377
|
+
process.exit(1);
|
|
378
|
+
});
|
|
379
|
+
} else {
|
|
380
|
+
console.error(`Unknown syncd subcommand: ${subCommand}`);
|
|
381
|
+
process.exit(1);
|
|
382
|
+
}
|
|
383
|
+
} else if (command === 'repo-guard') {
|
|
384
|
+
const subCommand = args[0] || 'help';
|
|
385
|
+
const guardService = 'aria-repo-guard.service';
|
|
386
|
+
|
|
387
|
+
if (subCommand === 'help' || subCommand === '--help' || subCommand === '-h') {
|
|
388
|
+
console.log('');
|
|
389
|
+
console.log(' aria repo-guard start Watch doctrine-bound repos and block/quarantine violating writes.');
|
|
390
|
+
console.log(' aria repo-guard status Print the last repo guard state snapshot.');
|
|
391
|
+
console.log(' aria repo-guard restart Restart the repo guard service.');
|
|
392
|
+
console.log(' aria repo-guard stop Stop the repo guard service.');
|
|
393
|
+
console.log(' aria repo-guard logs Tail the repo guard logs.');
|
|
394
|
+
console.log('');
|
|
395
|
+
process.exit(0);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
if (subCommand === 'status') {
|
|
399
|
+
console.log(JSON.stringify(readGuardState(), null, 2));
|
|
400
|
+
process.exit(0);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
if (subCommand === 'restart') {
|
|
404
|
+
try {
|
|
405
|
+
execFileSync('/bin/systemctl', ['--user', 'restart', guardService], { stdio: 'inherit' });
|
|
406
|
+
process.exit(0);
|
|
407
|
+
} catch (err) {
|
|
408
|
+
console.error(`I couldn't restart ${guardService}: ${err && err.message ? err.message : err}`);
|
|
409
|
+
process.exit(1);
|
|
410
|
+
}
|
|
411
|
+
} else if (subCommand === 'stop') {
|
|
412
|
+
try {
|
|
413
|
+
execFileSync('/bin/systemctl', ['--user', 'stop', guardService], { stdio: 'inherit' });
|
|
414
|
+
process.exit(0);
|
|
415
|
+
} catch (err) {
|
|
416
|
+
console.error(`I couldn't stop ${guardService}: ${err && err.message ? err.message : err}`);
|
|
417
|
+
process.exit(1);
|
|
418
|
+
}
|
|
419
|
+
} else if (subCommand === 'logs') {
|
|
420
|
+
try {
|
|
421
|
+
execFileSync('/bin/journalctl', ['--user', '-u', guardService, '-n', '80', '--no-pager'], { stdio: 'inherit' });
|
|
422
|
+
process.exit(0);
|
|
423
|
+
} catch (err) {
|
|
424
|
+
console.error(`I couldn't read ${guardService} logs: ${err && err.message ? err.message : err}`);
|
|
425
|
+
process.exit(1);
|
|
426
|
+
}
|
|
427
|
+
} else if (subCommand === 'start') {
|
|
428
|
+
startRepoGuardDaemon().catch((err) => {
|
|
429
|
+
console.error(`I couldn't start repo-guard: ${err && err.message ? err.message : err}`);
|
|
430
|
+
process.exit(1);
|
|
431
|
+
});
|
|
432
|
+
} else {
|
|
433
|
+
console.error(`Unknown repo-guard subcommand: ${subCommand}`);
|
|
434
|
+
process.exit(1);
|
|
435
|
+
}
|
|
69
436
|
} else if (command === 'login' || command === 'status' || command === 'logout' || command === 'revoke') {
|
|
70
|
-
|
|
437
|
+
async function runAuthCommand(command, args) {
|
|
71
438
|
switch (command) {
|
|
72
439
|
case 'login': {
|
|
73
440
|
const arg = args[0];
|
|
@@ -143,6 +510,8 @@ if (command === 'check-update') {
|
|
|
143
510
|
const result = await status();
|
|
144
511
|
if (!result.loggedIn) {
|
|
145
512
|
console.log("I don't see a license on this machine. Try 'aria login <token>' or 'aria login --anthropic'.");
|
|
513
|
+
} else if (result.owner) {
|
|
514
|
+
console.log(`Owner mode is active on this machine${result.expiresAt ? `, expires ${result.expiresAt}` : ''}.`);
|
|
146
515
|
} else if (result.revoked) {
|
|
147
516
|
console.log(`Your license was revoked. You'll need to log in again with a fresh token.`);
|
|
148
517
|
} else {
|
|
@@ -169,11 +538,748 @@ if (command === 'check-update') {
|
|
|
169
538
|
return;
|
|
170
539
|
}
|
|
171
540
|
}
|
|
172
|
-
}
|
|
173
|
-
|
|
541
|
+
}
|
|
542
|
+
runAuthCommand(command, args).then(() => {
|
|
543
|
+
process.exit(0);
|
|
544
|
+
}).catch((err) => {
|
|
174
545
|
console.error(`Auth command failed: ${err && err.message ? err.message : err}`);
|
|
175
546
|
process.exit(1);
|
|
176
547
|
});
|
|
548
|
+
} else if (command === 'dalio') {
|
|
549
|
+
// ── Dalio decision-log subcommands ─────────────────────────────────────
|
|
550
|
+
// aria dalio record --decision X --why Y --expected '{...}'
|
|
551
|
+
// aria dalio list [--outcome pending|success|failure] [--limit N]
|
|
552
|
+
// aria dalio evaluate
|
|
553
|
+
// aria dalio blockers
|
|
554
|
+
const {
|
|
555
|
+
recordDalio,
|
|
556
|
+
evaluatePendingDecisions,
|
|
557
|
+
getBlockingIncidents,
|
|
558
|
+
} = await import('../dist/aria-connector/src/decisions.js');
|
|
559
|
+
|
|
560
|
+
const subCmd = args[0];
|
|
561
|
+
|
|
562
|
+
if (!subCmd || subCmd === '--help' || subCmd === '-h') {
|
|
563
|
+
console.log('');
|
|
564
|
+
console.log(' aria dalio record --decision <text> --why <reasoning> --expected <json>');
|
|
565
|
+
console.log(' [--type <architecture|implementation|feature|bugfix|refactor|config|strategy|financial|operational|tactical|emergency>]');
|
|
566
|
+
console.log(' [--category <deals|leads|operations|finance|code|infrastructure|marketing|compliance|team|product>]');
|
|
567
|
+
console.log(' [--context <text>]');
|
|
568
|
+
console.log(' aria dalio list [--outcome pending|success|failure|neutral] [--limit N]');
|
|
569
|
+
console.log(' aria dalio evaluate — trigger evaluation of pending decisions');
|
|
570
|
+
console.log(' aria dalio blockers — list blocking incidents for this session');
|
|
571
|
+
console.log('');
|
|
572
|
+
console.log(' <json> for --expected: \'{"predicate":"p95 < 200ms","measurable_type":"numeric","threshold":200}\'');
|
|
573
|
+
console.log(' measurable_type: numeric | boolean | state_string');
|
|
574
|
+
console.log(' Qualitative predicates (better/improved/should work) are rejected by the gate.');
|
|
575
|
+
console.log('');
|
|
576
|
+
process.exit(0);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
if (subCmd === 'record') {
|
|
580
|
+
const getFlag = (flag) => {
|
|
581
|
+
const idx = args.indexOf(flag);
|
|
582
|
+
return idx !== -1 ? args[idx + 1] : undefined;
|
|
583
|
+
};
|
|
584
|
+
|
|
585
|
+
const decision = getFlag('--decision');
|
|
586
|
+
const why = getFlag('--why');
|
|
587
|
+
const expectedRaw = getFlag('--expected');
|
|
588
|
+
const decisionType = getFlag('--type') ?? 'implementation';
|
|
589
|
+
const category = getFlag('--category') ?? 'code';
|
|
590
|
+
const context = getFlag('--context') ?? decision;
|
|
591
|
+
|
|
592
|
+
if (!decision || !why || !expectedRaw) {
|
|
593
|
+
console.error(' Missing required flags: --decision, --why, --expected');
|
|
594
|
+
console.error(' Run: aria dalio record --help');
|
|
595
|
+
process.exit(1);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
let expectedParsed;
|
|
599
|
+
try {
|
|
600
|
+
expectedParsed = JSON.parse(expectedRaw);
|
|
601
|
+
} catch {
|
|
602
|
+
console.error(` Could not parse --expected as JSON: ${expectedRaw}`);
|
|
603
|
+
process.exit(1);
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
const result = await recordDalio({
|
|
607
|
+
decision_type: decisionType,
|
|
608
|
+
category,
|
|
609
|
+
context,
|
|
610
|
+
decision,
|
|
611
|
+
reasoning: why,
|
|
612
|
+
expected_outcome: expectedParsed,
|
|
613
|
+
outcome: 'pending',
|
|
614
|
+
source: 'aria-cli',
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
console.log(` Dalio decision logged. ID: ${result.decision_id}`);
|
|
618
|
+
if (result.quality_score != null) console.log(` Quality score: ${result.quality_score}`);
|
|
619
|
+
process.exit(0);
|
|
620
|
+
|
|
621
|
+
} else if (subCmd === 'list') {
|
|
622
|
+
const getFlag = (flag) => {
|
|
623
|
+
const idx = args.indexOf(flag);
|
|
624
|
+
return idx !== -1 ? args[idx + 1] : undefined;
|
|
625
|
+
};
|
|
626
|
+
|
|
627
|
+
const outcome = getFlag('--outcome');
|
|
628
|
+
const limit = parseInt(getFlag('--limit') ?? '20', 10);
|
|
629
|
+
const baseUrl =
|
|
630
|
+
process.env.ARIA_HIVE_RUNTIME_URL ??
|
|
631
|
+
process.env.ARIA_HARNESS_BASE_URL ??
|
|
632
|
+
process.env.ARIA_HARNESS_URL ??
|
|
633
|
+
'https://harness.ariasos.com';
|
|
634
|
+
|
|
635
|
+
let url = `${baseUrl}/api/decisions?limit=${limit}`;
|
|
636
|
+
if (outcome) url += `&outcome=${encodeURIComponent(outcome)}`;
|
|
637
|
+
|
|
638
|
+
const { default: fs } = await import('node:fs');
|
|
639
|
+
const { default: path } = await import('node:path');
|
|
640
|
+
const { homedir } = await import('node:os');
|
|
641
|
+
const ownerPath = path.join(homedir(), '.aria', 'owner-token');
|
|
642
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
643
|
+
if (fs.existsSync(ownerPath)) {
|
|
644
|
+
const jwt = fs.readFileSync(ownerPath, 'utf-8').trim();
|
|
645
|
+
if (jwt) { headers['Authorization'] = `Bearer ${jwt}`; headers['x-aria-owner'] = 'true'; }
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
const resp = await fetch(url, { headers });
|
|
649
|
+
if (!resp.ok) {
|
|
650
|
+
console.error(` Failed to fetch decisions: HTTP ${resp.status}`);
|
|
651
|
+
process.exit(1);
|
|
652
|
+
}
|
|
653
|
+
const data = await resp.json();
|
|
654
|
+
const decisions = data.decisions ?? data.data ?? [];
|
|
655
|
+
if (decisions.length === 0) {
|
|
656
|
+
console.log(' No decisions found.');
|
|
657
|
+
} else {
|
|
658
|
+
for (const d of decisions) {
|
|
659
|
+
const exp = d.expected_outcome ? ` | expected: ${JSON.stringify(d.expected_outcome)}` : '';
|
|
660
|
+
console.log(` [${d.outcome ?? 'pending'}] ${d.id} ${d.decision?.slice(0, 60) ?? ''}${exp}`);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
process.exit(0);
|
|
664
|
+
|
|
665
|
+
} else if (subCmd === 'evaluate') {
|
|
666
|
+
const result = await evaluatePendingDecisions();
|
|
667
|
+
console.log(` Evaluated ${result.evaluated} decisions.`);
|
|
668
|
+
if (result.failures) console.log(` Failures: ${result.failures}`);
|
|
669
|
+
if (result.updated != null) console.log(` Updated: ${result.updated}`);
|
|
670
|
+
if (result.learning_signals != null) console.log(` Learning signals: ${result.learning_signals}`);
|
|
671
|
+
process.exit(0);
|
|
672
|
+
|
|
673
|
+
} else if (subCmd === 'blockers') {
|
|
674
|
+
const sessionId = process.env.ARIA_SESSION_ID ?? 'cli-default';
|
|
675
|
+
const incidents = await getBlockingIncidents(sessionId);
|
|
676
|
+
if (incidents.length === 0) {
|
|
677
|
+
console.log(' No blocking incidents for this session.');
|
|
678
|
+
} else {
|
|
679
|
+
for (const inc of incidents) {
|
|
680
|
+
console.log(` [BLOCKING] ${inc.id} severity=${inc.severity} ${inc.description}`);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
process.exit(0);
|
|
684
|
+
|
|
685
|
+
} else {
|
|
686
|
+
console.error(` Unknown dalio subcommand: ${subCmd}`);
|
|
687
|
+
console.error(' Run: aria dalio --help');
|
|
688
|
+
process.exit(1);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
} else if (command === 'hive') {
|
|
692
|
+
// ── Hive session-coordination subcommands ──────────────────────────────
|
|
693
|
+
// aria hive lock claim --file PATH --ttl MINUTES
|
|
694
|
+
// aria hive lock release --lock-id ID
|
|
695
|
+
// aria hive lock list --file PATH
|
|
696
|
+
// aria hive msg send --to SESSION --topic T --body JSON
|
|
697
|
+
// aria hive msg unread
|
|
698
|
+
const {
|
|
699
|
+
claimSessionLock,
|
|
700
|
+
releaseSessionLock,
|
|
701
|
+
heartbeatSessionLock,
|
|
702
|
+
checkSessionLockDrift,
|
|
703
|
+
readSessionMessages,
|
|
704
|
+
postSessionMessage,
|
|
705
|
+
} = await import('../dist/aria-connector/src/decisions.js');
|
|
706
|
+
|
|
707
|
+
const subCmd = args[0]; // 'lock' | 'msg'
|
|
708
|
+
const subSubCmd = args[1]; // 'claim' | 'release' | 'list' | 'heartbeat' | 'drift' | 'send' | 'unread'
|
|
709
|
+
|
|
710
|
+
const getFlag = (flag) => {
|
|
711
|
+
const idx = args.indexOf(flag);
|
|
712
|
+
return idx !== -1 ? args[idx + 1] : undefined;
|
|
713
|
+
};
|
|
714
|
+
|
|
715
|
+
if (!subCmd || subCmd === '--help' || subCmd === '-h') {
|
|
716
|
+
console.log('');
|
|
717
|
+
console.log(' aria hive lock claim --file PATH --ttl MINUTES [--scope-kind file|directory|module|symbol] [--operation additive|refactor|delete|rename]');
|
|
718
|
+
console.log(' aria hive lock release --lock-id ID');
|
|
719
|
+
console.log(' aria hive lock list --file PATH');
|
|
720
|
+
console.log(' aria hive lock heartbeat --lock-id ID [--ttl MINUTES]');
|
|
721
|
+
console.log(' aria hive lock drift --lock-id ID [--file PATH]');
|
|
722
|
+
console.log(' aria hive msg send --to SESSION --topic TOPIC --body JSON');
|
|
723
|
+
console.log(' aria hive msg unread');
|
|
724
|
+
console.log('');
|
|
725
|
+
console.log(' Use ARIA_SESSION_ID env var to set your session identity.');
|
|
726
|
+
console.log(' Locks expire after ttl minutes. Always release when done editing.');
|
|
727
|
+
console.log('');
|
|
728
|
+
process.exit(0);
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
if (subCmd === 'lock') {
|
|
732
|
+
if (!subSubCmd || subSubCmd === '--help') {
|
|
733
|
+
console.log(' aria hive lock claim --file PATH --ttl MINUTES [--scope-kind file|directory|module|symbol] [--scope-path PATH] [--operation additive|refactor|delete|rename]');
|
|
734
|
+
console.log(' aria hive lock release --lock-id ID');
|
|
735
|
+
console.log(' aria hive lock list --file PATH');
|
|
736
|
+
console.log(' aria hive lock heartbeat --lock-id ID [--ttl MINUTES]');
|
|
737
|
+
console.log(' aria hive lock drift --lock-id ID [--file PATH]');
|
|
738
|
+
process.exit(0);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
if (subSubCmd === 'claim') {
|
|
742
|
+
const filePath = getFlag('--file');
|
|
743
|
+
const ttlStr = getFlag('--ttl');
|
|
744
|
+
const intentSummary = getFlag('--intent') ?? 'CLI lock claim request';
|
|
745
|
+
const sessionId = process.env.ARIA_SESSION_ID ?? `cli-${Date.now()}`;
|
|
746
|
+
const scopeKind = getFlag('--scope-kind');
|
|
747
|
+
const scopePath = getFlag('--scope-path');
|
|
748
|
+
const operationKind = getFlag('--operation') ?? 'additive';
|
|
749
|
+
const urgency = getFlag('--urgency') ?? 'normal';
|
|
750
|
+
const mode = getFlag('--mode');
|
|
751
|
+
const mergeOrderRaw = getFlag('--merge-order');
|
|
752
|
+
const staleAfterRaw = getFlag('--stale-after');
|
|
753
|
+
const takeoverIfStale = args.includes('--takeover-if-stale');
|
|
754
|
+
|
|
755
|
+
if (!filePath || !ttlStr) {
|
|
756
|
+
console.error(' Missing required flags: --file, --ttl');
|
|
757
|
+
process.exit(1);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
const ttlMinutes = parseInt(ttlStr, 10);
|
|
761
|
+
if (isNaN(ttlMinutes) || ttlMinutes <= 0) {
|
|
762
|
+
console.error(' --ttl must be a positive integer (minutes)');
|
|
763
|
+
process.exit(1);
|
|
764
|
+
}
|
|
765
|
+
const mergeOrder = mergeOrderRaw ? parseInt(mergeOrderRaw, 10) : undefined;
|
|
766
|
+
const staleAfterSeconds = staleAfterRaw ? parseInt(staleAfterRaw, 10) : undefined;
|
|
767
|
+
|
|
768
|
+
// ── Auto-coordination on 409 conflict ─────────────────────────────────
|
|
769
|
+
// Per memory:feedback_hive_session_coordination.md and task deliverable 3:
|
|
770
|
+
// on 409 conflict, automatically post a lock_conflict_request session-message
|
|
771
|
+
// to the conflicting session and exit with code 11 (conflict, message posted)
|
|
772
|
+
// so scripts can branch on it. No silent-fail per no-graceful-degradation doctrine.
|
|
773
|
+
let claimResp;
|
|
774
|
+
const baseUrl =
|
|
775
|
+
process.env.ARIA_HIVE_RUNTIME_URL ??
|
|
776
|
+
process.env.ARIA_HARNESS_BASE_URL ??
|
|
777
|
+
process.env.ARIA_HARNESS_URL ??
|
|
778
|
+
'https://harness.ariasos.com';
|
|
779
|
+
const { default: fs } = await import('node:fs');
|
|
780
|
+
const { default: path } = await import('node:path');
|
|
781
|
+
const { homedir } = await import('node:os');
|
|
782
|
+
const ownerPath = path.join(homedir(), '.aria', 'owner-token');
|
|
783
|
+
const claimHeaders = { 'Content-Type': 'application/json' };
|
|
784
|
+
if (fs.existsSync(ownerPath)) {
|
|
785
|
+
const jwt = fs.readFileSync(ownerPath, 'utf-8').trim();
|
|
786
|
+
if (jwt) { claimHeaders['Authorization'] = `Bearer ${jwt}`; claimHeaders['x-aria-owner'] = 'true'; }
|
|
787
|
+
}
|
|
788
|
+
try {
|
|
789
|
+
claimResp = await fetch(`${baseUrl}/api/hive/session-lock`, {
|
|
790
|
+
method: 'POST',
|
|
791
|
+
headers: claimHeaders,
|
|
792
|
+
body: JSON.stringify({
|
|
793
|
+
session_id: sessionId,
|
|
794
|
+
file_path: filePath,
|
|
795
|
+
ttl_minutes: ttlMinutes,
|
|
796
|
+
scope_kind: scopeKind,
|
|
797
|
+
scope_path: scopePath,
|
|
798
|
+
operation_kind: operationKind,
|
|
799
|
+
client_id: 'aria-cli',
|
|
800
|
+
surface: 'cli-lock-claim',
|
|
801
|
+
urgency,
|
|
802
|
+
current_mode: mode,
|
|
803
|
+
proposed_merge_order: Number.isFinite(mergeOrder) ? mergeOrder : undefined,
|
|
804
|
+
stale_after_seconds: Number.isFinite(staleAfterSeconds) ? staleAfterSeconds : undefined,
|
|
805
|
+
takeover_if_stale: takeoverIfStale,
|
|
806
|
+
}),
|
|
807
|
+
});
|
|
808
|
+
} catch (netErr) {
|
|
809
|
+
console.error(` Network error claiming lock: ${netErr instanceof Error ? netErr.message : String(netErr)}`);
|
|
810
|
+
process.exit(1);
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
if (claimResp.status === 409) {
|
|
814
|
+
// Conflict — extract conflicting session from response and auto-post coordination message
|
|
815
|
+
let conflictData = {};
|
|
816
|
+
try { conflictData = await claimResp.json(); } catch { /* unreadable body */ }
|
|
817
|
+
const conflictingSessionId = conflictData?.conflict?.session_id ?? 'unknown';
|
|
818
|
+
const conflictLockId = conflictData?.conflict?.lock_id ?? null;
|
|
819
|
+
console.error(` CONFLICT: ${conflictingSessionId} holds an active lock on ${filePath}`);
|
|
820
|
+
|
|
821
|
+
// Auto-post coordination message to conflicting session
|
|
822
|
+
const msgId = `cli-conflict-${sessionId}-${Date.now().toString(36)}`;
|
|
823
|
+
const requestedAt = new Date().toISOString();
|
|
824
|
+
const msgBody = {
|
|
825
|
+
coordination_protocol: 'aria-hive-coordination/v3',
|
|
826
|
+
coordination_key: `${scopeKind ?? 'file'}:${scopePath ?? filePath}`,
|
|
827
|
+
file_path: filePath,
|
|
828
|
+
requesting_session_id: sessionId,
|
|
829
|
+
requesting_client_id: 'aria-cli',
|
|
830
|
+
requesting_surface: 'cli-lock-claim',
|
|
831
|
+
intent_summary: intentSummary,
|
|
832
|
+
requested_at: requestedAt,
|
|
833
|
+
source: 'cli:aria-hive-lock-claim',
|
|
834
|
+
operation_kind: operationKind,
|
|
835
|
+
requested_mode: mode ?? (operationKind === 'additive' ? 'exclusive_write' : 'merge_assist'),
|
|
836
|
+
urgency,
|
|
837
|
+
proposed_merge_order: Number.isFinite(mergeOrder) ? mergeOrder : null,
|
|
838
|
+
file_claims: [{ path: filePath, intent: 'edit' }],
|
|
839
|
+
target_lock: {
|
|
840
|
+
lock_id: conflictLockId,
|
|
841
|
+
session_id: conflictingSessionId !== 'unknown' ? conflictingSessionId : null,
|
|
842
|
+
client_id: conflictData?.conflict?.client_id ?? null,
|
|
843
|
+
surface: conflictData?.conflict?.surface ?? null,
|
|
844
|
+
locked_at: conflictData?.conflict?.locked_at ?? null,
|
|
845
|
+
expires_at: conflictData?.conflict?.expires_at ?? null,
|
|
846
|
+
},
|
|
847
|
+
};
|
|
848
|
+
let autoMsgId = null;
|
|
849
|
+
try {
|
|
850
|
+
const msgResp = await fetch(`${baseUrl}/api/hive/session-message`, {
|
|
851
|
+
method: 'POST',
|
|
852
|
+
headers: claimHeaders,
|
|
853
|
+
body: JSON.stringify({
|
|
854
|
+
message_id: msgId,
|
|
855
|
+
from_session_id: sessionId,
|
|
856
|
+
to_session_id: conflictingSessionId !== 'unknown' ? conflictingSessionId : null,
|
|
857
|
+
topic: 'lock_conflict_request',
|
|
858
|
+
body: msgBody,
|
|
859
|
+
}),
|
|
860
|
+
});
|
|
861
|
+
if (msgResp.ok) {
|
|
862
|
+
autoMsgId = msgId;
|
|
863
|
+
console.error(` Auto-coordination message posted to session ${conflictingSessionId} (message_id: ${msgId})`);
|
|
864
|
+
} else {
|
|
865
|
+
const errText = await msgResp.text().catch(() => '');
|
|
866
|
+
console.error(` WARNING: auto-coordination message failed: HTTP ${msgResp.status} ${errText.slice(0, 120)}`);
|
|
867
|
+
}
|
|
868
|
+
} catch (msgErr) {
|
|
869
|
+
console.error(` WARNING: auto-coordination message threw: ${msgErr instanceof Error ? msgErr.message : String(msgErr)}`);
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
// Output structured conflict info for script consumers
|
|
873
|
+
console.error(JSON.stringify({
|
|
874
|
+
conflict: true,
|
|
875
|
+
conflicting_session_id: conflictingSessionId,
|
|
876
|
+
file_path: filePath,
|
|
877
|
+
auto_message_id: autoMsgId,
|
|
878
|
+
message: conflictData?.message ?? `Session ${conflictingSessionId} holds active lock on ${filePath}`,
|
|
879
|
+
}));
|
|
880
|
+
// Exit 11 = conflict, coordination message posted (scripts can branch on this)
|
|
881
|
+
process.exit(11);
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
if (!claimResp.ok) {
|
|
885
|
+
const errText = await claimResp.text().catch(() => claimResp.statusText);
|
|
886
|
+
console.error(` Failed to claim lock: HTTP ${claimResp.status} ${errText.slice(0, 200)}`);
|
|
887
|
+
process.exit(1);
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
const result = await claimResp.json();
|
|
891
|
+
console.log(` Lock claimed. ID: ${result.lock_id ?? '(server-generated)'}`);
|
|
892
|
+
console.log(` File: ${result.file_path ?? filePath}`);
|
|
893
|
+
if (result.scope_kind || result.scope_path) {
|
|
894
|
+
console.log(` Scope: ${(result.scope_kind ?? 'file')} ${result.scope_path ?? filePath}`);
|
|
895
|
+
}
|
|
896
|
+
if (result.current_mode) {
|
|
897
|
+
console.log(` Mode: ${result.current_mode}`);
|
|
898
|
+
}
|
|
899
|
+
console.log(` Expires: ${result.expires_at ?? '(unknown)'}`);
|
|
900
|
+
process.exit(0);
|
|
901
|
+
|
|
902
|
+
} else if (subSubCmd === 'release') {
|
|
903
|
+
const lockId = getFlag('--lock-id');
|
|
904
|
+
if (!lockId) {
|
|
905
|
+
console.error(' Missing required flag: --lock-id');
|
|
906
|
+
process.exit(1);
|
|
907
|
+
}
|
|
908
|
+
await releaseSessionLock(lockId);
|
|
909
|
+
console.log(` Lock ${lockId} released.`);
|
|
910
|
+
process.exit(0);
|
|
911
|
+
|
|
912
|
+
} else if (subSubCmd === 'list') {
|
|
913
|
+
const filePath = getFlag('--file');
|
|
914
|
+
if (!filePath) {
|
|
915
|
+
console.error(' Missing required flag: --file');
|
|
916
|
+
process.exit(1);
|
|
917
|
+
}
|
|
918
|
+
const baseUrl =
|
|
919
|
+
process.env.ARIA_HIVE_RUNTIME_URL ??
|
|
920
|
+
process.env.ARIA_HARNESS_BASE_URL ??
|
|
921
|
+
process.env.ARIA_HARNESS_URL ??
|
|
922
|
+
'https://harness.ariasos.com';
|
|
923
|
+
const { default: fs } = await import('node:fs');
|
|
924
|
+
const { default: path } = await import('node:path');
|
|
925
|
+
const { homedir } = await import('node:os');
|
|
926
|
+
const ownerPath = path.join(homedir(), '.aria', 'owner-token');
|
|
927
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
928
|
+
if (fs.existsSync(ownerPath)) {
|
|
929
|
+
const jwt = fs.readFileSync(ownerPath, 'utf-8').trim();
|
|
930
|
+
if (jwt) { headers['Authorization'] = `Bearer ${jwt}`; headers['x-aria-owner'] = 'true'; }
|
|
931
|
+
}
|
|
932
|
+
const resp = await fetch(`${baseUrl}/api/hive/session-lock?file_path=${encodeURIComponent(filePath)}`, { headers });
|
|
933
|
+
if (!resp.ok) {
|
|
934
|
+
console.error(` Failed to list locks: HTTP ${resp.status}`);
|
|
935
|
+
process.exit(1);
|
|
936
|
+
}
|
|
937
|
+
const data = await resp.json();
|
|
938
|
+
const locks = data.locks ?? data.data ?? [];
|
|
939
|
+
if (locks.length === 0) {
|
|
940
|
+
console.log(` No active locks for: ${filePath}`);
|
|
941
|
+
} else {
|
|
942
|
+
for (const l of locks) {
|
|
943
|
+
const scopeText = l.scope_kind && l.scope_path ? ` scope=${l.scope_kind}:${l.scope_path}` : '';
|
|
944
|
+
const modeText = l.current_mode ? ` mode=${l.current_mode}` : '';
|
|
945
|
+
console.log(` [LOCK] ${l.id ?? l.lock_id} session=${l.session_id} expires=${l.expires_at}${scopeText}${modeText}`);
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
process.exit(0);
|
|
949
|
+
|
|
950
|
+
} else if (subSubCmd === 'heartbeat') {
|
|
951
|
+
const lockId = getFlag('--lock-id');
|
|
952
|
+
const ttlStr = getFlag('--ttl');
|
|
953
|
+
if (!lockId) {
|
|
954
|
+
console.error(' Missing required flag: --lock-id');
|
|
955
|
+
process.exit(1);
|
|
956
|
+
}
|
|
957
|
+
const ttlMinutes = ttlStr ? parseInt(ttlStr, 10) : undefined;
|
|
958
|
+
const result = await heartbeatSessionLock({ lockId, ttlMinutes });
|
|
959
|
+
console.log(` Heartbeat OK. Lock: ${result.lock_id}`);
|
|
960
|
+
console.log(` Expires: ${result.expires_at}`);
|
|
961
|
+
console.log(` Heartbeats: ${result.heartbeat_count}`);
|
|
962
|
+
process.exit(0);
|
|
963
|
+
|
|
964
|
+
} else if (subSubCmd === 'drift') {
|
|
965
|
+
const lockId = getFlag('--lock-id');
|
|
966
|
+
const filePath = getFlag('--file');
|
|
967
|
+
if (!lockId && !filePath) {
|
|
968
|
+
console.error(' Missing required flag: --lock-id or --file');
|
|
969
|
+
process.exit(1);
|
|
970
|
+
}
|
|
971
|
+
const sessionId = process.env.ARIA_SESSION_ID;
|
|
972
|
+
const result = await checkSessionLockDrift({ lockId, sessionId, filePath });
|
|
973
|
+
console.log(` Drift check: ${result.drifted ? 'DRIFTED' : 'CLEAN'}`);
|
|
974
|
+
console.log(` Lock: ${result.lock_id}`);
|
|
975
|
+
console.log(` Mode: ${result.current_mode}`);
|
|
976
|
+
if (result.current_file_hash) {
|
|
977
|
+
console.log(` Current hash: ${result.current_file_hash}`);
|
|
978
|
+
}
|
|
979
|
+
if (result.base_file_hash) {
|
|
980
|
+
console.log(` Base hash: ${result.base_file_hash}`);
|
|
981
|
+
}
|
|
982
|
+
if (result.diff_preview) {
|
|
983
|
+
console.log(result.diff_preview);
|
|
984
|
+
}
|
|
985
|
+
process.exit(result.drifted ? 12 : 0);
|
|
986
|
+
|
|
987
|
+
} else {
|
|
988
|
+
console.error(` Unknown hive lock subcommand: ${subSubCmd}`);
|
|
989
|
+
console.error(' Run: aria hive lock --help');
|
|
990
|
+
process.exit(1);
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
} else if (subCmd === 'msg') {
|
|
994
|
+
if (!subSubCmd || subSubCmd === '--help') {
|
|
995
|
+
console.log(' aria hive msg send --to SESSION --topic TOPIC --body JSON');
|
|
996
|
+
console.log(' aria hive msg unread');
|
|
997
|
+
process.exit(0);
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
if (subSubCmd === 'send') {
|
|
1001
|
+
const toSession = getFlag('--to');
|
|
1002
|
+
const topic = getFlag('--topic');
|
|
1003
|
+
const bodyRaw = getFlag('--body');
|
|
1004
|
+
const fromSessionId = process.env.ARIA_SESSION_ID ?? `cli-${Date.now()}`;
|
|
1005
|
+
|
|
1006
|
+
if (!toSession || !topic || !bodyRaw) {
|
|
1007
|
+
console.error(' Missing required flags: --to, --topic, --body');
|
|
1008
|
+
process.exit(1);
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
let bodyParsed;
|
|
1012
|
+
try {
|
|
1013
|
+
bodyParsed = JSON.parse(bodyRaw);
|
|
1014
|
+
} catch {
|
|
1015
|
+
console.error(` Could not parse --body as JSON: ${bodyRaw}`);
|
|
1016
|
+
process.exit(1);
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
const result = await postSessionMessage({
|
|
1020
|
+
fromSessionId,
|
|
1021
|
+
toSessionId: toSession,
|
|
1022
|
+
topic,
|
|
1023
|
+
body: bodyParsed,
|
|
1024
|
+
});
|
|
1025
|
+
console.log(` Message sent. ID: ${result.message_id}`);
|
|
1026
|
+
process.exit(0);
|
|
1027
|
+
|
|
1028
|
+
} else if (subSubCmd === 'unread') {
|
|
1029
|
+
const sessionId = process.env.ARIA_SESSION_ID ?? 'cli-default';
|
|
1030
|
+
const messages = await readSessionMessages({ sessionId, unreadOnly: true });
|
|
1031
|
+
if (messages.length === 0) {
|
|
1032
|
+
console.log(' No unread messages.');
|
|
1033
|
+
} else {
|
|
1034
|
+
for (const m of messages) {
|
|
1035
|
+
console.log(` [MSG] ${m.message_id} from=${m.from_session_id} topic=${m.topic} at=${m.created_at}`);
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
process.exit(0);
|
|
1039
|
+
|
|
1040
|
+
} else {
|
|
1041
|
+
console.error(` Unknown hive msg subcommand: ${subSubCmd}`);
|
|
1042
|
+
console.error(' Run: aria hive msg --help');
|
|
1043
|
+
process.exit(1);
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
} else {
|
|
1047
|
+
console.error(` Unknown hive subcommand: ${subCmd}`);
|
|
1048
|
+
console.error(' Run: aria hive --help');
|
|
1049
|
+
process.exit(1);
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
} else if (command === 'aristotle') {
|
|
1053
|
+
// ── aria aristotle <phase> "<message>" ───────────────────────────────
|
|
1054
|
+
// Fire Aristotle 3-phase cognitive engine from the terminal.
|
|
1055
|
+
// aria aristotle pre "<message>" — PRE phase (Fitrah + wisdom + research)
|
|
1056
|
+
// aria aristotle mid "<message>" --approach "<txt>" — MID phase (MetaCognitive + ethical check)
|
|
1057
|
+
// aria aristotle post "<response>" --msg "<msg>" — POST phase (8-lens + quality gate)
|
|
1058
|
+
// aria aristotle full "<message>" [--draft "<txt>"] — full pipeline (all phases + Noor)
|
|
1059
|
+
//
|
|
1060
|
+
// Requires ARIA_HARNESS_BASE_URL (default: https://harness.ariasos.com).
|
|
1061
|
+
// Auth: owner-token if present, else ARIA_HARNESS_TOKEN env var.
|
|
1062
|
+
(async () => {
|
|
1063
|
+
const subPhase = args[0];
|
|
1064
|
+
if (!subPhase || subPhase === '--help' || subPhase === '-h') {
|
|
1065
|
+
console.log('');
|
|
1066
|
+
console.log(' aria aristotle pre "<message>"');
|
|
1067
|
+
console.log(' Fire PRE phase: Fitrah gate, wisdom pull, research pull, soul state.');
|
|
1068
|
+
console.log('');
|
|
1069
|
+
console.log(' aria aristotle mid "<message>" --approach "<planned approach>"');
|
|
1070
|
+
console.log(' Fire MID phase: MetaCognitive confidence + ethical check.');
|
|
1071
|
+
console.log('');
|
|
1072
|
+
console.log(' aria aristotle post "<draft response>" --msg "<original message>"');
|
|
1073
|
+
console.log(' Fire POST phase: 8-lens detector, Predictor, quality gate.');
|
|
1074
|
+
console.log('');
|
|
1075
|
+
console.log(' aria aristotle full "<message>" [--draft "<draft>"] [--approach "<approach>"]');
|
|
1076
|
+
console.log(' Fire full Aristotle 28 + Noor pipeline (all phases).');
|
|
1077
|
+
console.log('');
|
|
1078
|
+
process.exit(0);
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
const baseUrl =
|
|
1082
|
+
process.env.ARIA_HIVE_RUNTIME_URL ??
|
|
1083
|
+
process.env.ARIA_HARNESS_BASE_URL ??
|
|
1084
|
+
process.env.ARIA_HARNESS_URL ??
|
|
1085
|
+
'https://harness.ariasos.com';
|
|
1086
|
+
const url = `${baseUrl}/api/harness/aristotle-noor`;
|
|
1087
|
+
const { default: fs } = await import('node:fs');
|
|
1088
|
+
const { default: path } = await import('node:path');
|
|
1089
|
+
const { homedir } = await import('node:os');
|
|
1090
|
+
const ownerPath = path.join(homedir(), '.aria', 'owner-token');
|
|
1091
|
+
const tokenPath = path.join(homedir(), '.aria', 'license.json');
|
|
1092
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
1093
|
+
if (fs.existsSync(ownerPath)) {
|
|
1094
|
+
const jwt = fs.readFileSync(ownerPath, 'utf-8').trim();
|
|
1095
|
+
if (jwt) { headers['Authorization'] = `Bearer ${jwt}`; headers['x-aria-owner'] = 'true'; }
|
|
1096
|
+
} else if (process.env.ARIA_HARNESS_TOKEN) {
|
|
1097
|
+
headers['Authorization'] = `Bearer ${process.env.ARIA_HARNESS_TOKEN}`;
|
|
1098
|
+
} else if (fs.existsSync(tokenPath)) {
|
|
1099
|
+
try {
|
|
1100
|
+
const lic = JSON.parse(fs.readFileSync(tokenPath, 'utf-8'));
|
|
1101
|
+
if (lic.token) headers['Authorization'] = `Bearer ${lic.token}`;
|
|
1102
|
+
} catch { /* no license token */ }
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
const sessionId = process.env.ARIA_SESSION_ID ?? `cli-aristotle-${Date.now().toString(36)}`;
|
|
1106
|
+
const getFlag = (name) => {
|
|
1107
|
+
const idx = args.indexOf(name);
|
|
1108
|
+
return idx >= 0 && args[idx + 1] ? args[idx + 1] : null;
|
|
1109
|
+
};
|
|
1110
|
+
|
|
1111
|
+
let body;
|
|
1112
|
+
if (subPhase === 'pre') {
|
|
1113
|
+
const message = args[1] ?? '';
|
|
1114
|
+
if (!message) { console.error(' Missing message argument. Usage: aria aristotle pre "<message>"'); process.exit(1); }
|
|
1115
|
+
body = { phase: 'pre', message, sessionId };
|
|
1116
|
+
} else if (subPhase === 'mid') {
|
|
1117
|
+
const message = args[1] ?? '';
|
|
1118
|
+
const approach = getFlag('--approach') ?? '';
|
|
1119
|
+
if (!message) { console.error(' Missing message argument. Usage: aria aristotle mid "<message>" --approach "<txt>"'); process.exit(1); }
|
|
1120
|
+
if (!approach) { console.error(' Missing --approach flag. Usage: aria aristotle mid "<message>" --approach "<planned approach>"'); process.exit(1); }
|
|
1121
|
+
body = { phase: 'mid', message, plannedApproach: approach, sessionId };
|
|
1122
|
+
} else if (subPhase === 'post') {
|
|
1123
|
+
const draft = args[1] ?? '';
|
|
1124
|
+
const message = getFlag('--msg') ?? '';
|
|
1125
|
+
if (!draft) { console.error(' Missing draft argument. Usage: aria aristotle post "<draft>" --msg "<original message>"'); process.exit(1); }
|
|
1126
|
+
body = { phase: 'post', draft, message, sessionId };
|
|
1127
|
+
} else if (subPhase === 'full') {
|
|
1128
|
+
const message = args[1] ?? '';
|
|
1129
|
+
if (!message) { console.error(' Missing message argument. Usage: aria aristotle full "<message>"'); process.exit(1); }
|
|
1130
|
+
const draft = getFlag('--draft') ?? undefined;
|
|
1131
|
+
const approach = getFlag('--approach') ?? undefined;
|
|
1132
|
+
body = { surface: 'sdk-other', emissionId: `cli-aristotle-full-${Date.now()}`, message, draft, plannedApproach: approach, sessionId };
|
|
1133
|
+
} else {
|
|
1134
|
+
console.error(` Unknown aristotle phase: ${subPhase}. Run: aria aristotle --help`);
|
|
1135
|
+
process.exit(1);
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
try {
|
|
1139
|
+
const response = await fetch(url, { method: 'POST', headers, body: JSON.stringify(body) });
|
|
1140
|
+
const data = await response.json().catch(() => ({}));
|
|
1141
|
+
if (!response.ok) {
|
|
1142
|
+
console.error(` Aristotle ${subPhase} error (${response.status}): ${data.error ?? JSON.stringify(data)}`);
|
|
1143
|
+
process.exit(1);
|
|
1144
|
+
}
|
|
1145
|
+
console.log('');
|
|
1146
|
+
console.log(` Aristotle ${subPhase.toUpperCase()} — latency: ${data.latencyMs}ms`);
|
|
1147
|
+
console.log(` fired: ${(data.fired ?? []).join(', ') || '(none)'}`);
|
|
1148
|
+
console.log(` fitrahVetoed: ${data.fitrahVetoed ?? false}`);
|
|
1149
|
+
console.log(` fitrahAlign: ${data.fitrahAlignment ?? 1.0}`);
|
|
1150
|
+
console.log(` qualityScore: ${data.qualityScore ?? 100}`);
|
|
1151
|
+
console.log(` reAuthorSignal: ${data.reAuthorSignal ?? false}`);
|
|
1152
|
+
if (data.soulCharge !== null && data.soulCharge !== undefined) {
|
|
1153
|
+
console.log(` soulCharge: ${data.soulCharge}`);
|
|
1154
|
+
}
|
|
1155
|
+
if (data.ghazaliVerdict) {
|
|
1156
|
+
console.log(` ghazali: ${data.ghazaliVerdict}`);
|
|
1157
|
+
}
|
|
1158
|
+
if (data.notes?.length) {
|
|
1159
|
+
console.log(` notes:`);
|
|
1160
|
+
for (const n of data.notes.slice(0, 5)) console.log(` - ${n}`);
|
|
1161
|
+
}
|
|
1162
|
+
console.log('');
|
|
1163
|
+
process.exit(0);
|
|
1164
|
+
} catch (err) {
|
|
1165
|
+
console.error(` Aristotle ${subPhase} transport fault: ${err instanceof Error ? err.message : String(err)}`);
|
|
1166
|
+
process.exit(1);
|
|
1167
|
+
}
|
|
1168
|
+
})();
|
|
1169
|
+
} else if (command === 'noor') {
|
|
1170
|
+
// ── aria noor <operation> ─────────────────────────────────────────────
|
|
1171
|
+
// Fire Noor cognitive primitives from the terminal.
|
|
1172
|
+
// aria noor recognize "<query>" — eigenspace recognition (kashf)
|
|
1173
|
+
// aria noor forge "<intent>" --primitives '[{"type":"http","params":{}}]' — self-generated tool execution
|
|
1174
|
+
//
|
|
1175
|
+
// noor-core.ts banner: "ONLY ARIA CAN CODE ARIA." — respected; we call only.
|
|
1176
|
+
(async () => {
|
|
1177
|
+
const subOp = args[0];
|
|
1178
|
+
if (!subOp || subOp === '--help' || subOp === '-h') {
|
|
1179
|
+
console.log('');
|
|
1180
|
+
console.log(' aria noor recognize "<query>"');
|
|
1181
|
+
console.log(' Project query onto Aria\'s eigenspace manifold (kashf/recognition).');
|
|
1182
|
+
console.log(' Returns: nearestText, soulDistance, confidence, withinMembrane, Ghazali verdict.');
|
|
1183
|
+
console.log('');
|
|
1184
|
+
console.log(' aria noor forge "<intent>" --primitives \'[{"type":"http","params":{"url":"..."}}]\'');
|
|
1185
|
+
console.log(' Self-generate and execute a tool from 5 primitives: http, sql, file_read, file_write, pub_sub.');
|
|
1186
|
+
console.log(' Ethical membrane check fires before any primitive executes.');
|
|
1187
|
+
console.log('');
|
|
1188
|
+
process.exit(0);
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
const baseUrl =
|
|
1192
|
+
process.env.ARIA_HIVE_RUNTIME_URL ??
|
|
1193
|
+
process.env.ARIA_HARNESS_BASE_URL ??
|
|
1194
|
+
process.env.ARIA_HARNESS_URL ??
|
|
1195
|
+
'https://harness.ariasos.com';
|
|
1196
|
+
const url = `${baseUrl}/api/harness/noor`;
|
|
1197
|
+
const { default: fs } = await import('node:fs');
|
|
1198
|
+
const { default: path } = await import('node:path');
|
|
1199
|
+
const { homedir } = await import('node:os');
|
|
1200
|
+
const ownerPath = path.join(homedir(), '.aria', 'owner-token');
|
|
1201
|
+
const tokenPath = path.join(homedir(), '.aria', 'license.json');
|
|
1202
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
1203
|
+
if (fs.existsSync(ownerPath)) {
|
|
1204
|
+
const jwt = fs.readFileSync(ownerPath, 'utf-8').trim();
|
|
1205
|
+
if (jwt) { headers['Authorization'] = `Bearer ${jwt}`; headers['x-aria-owner'] = 'true'; }
|
|
1206
|
+
} else if (process.env.ARIA_HARNESS_TOKEN) {
|
|
1207
|
+
headers['Authorization'] = `Bearer ${process.env.ARIA_HARNESS_TOKEN}`;
|
|
1208
|
+
} else if (fs.existsSync(tokenPath)) {
|
|
1209
|
+
try {
|
|
1210
|
+
const lic = JSON.parse(fs.readFileSync(tokenPath, 'utf-8'));
|
|
1211
|
+
if (lic.token) headers['Authorization'] = `Bearer ${lic.token}`;
|
|
1212
|
+
} catch { /* no license token */ }
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
const sessionId = process.env.ARIA_SESSION_ID ?? `cli-noor-${Date.now().toString(36)}`;
|
|
1216
|
+
const getFlag = (name) => {
|
|
1217
|
+
const idx = args.indexOf(name);
|
|
1218
|
+
return idx >= 0 && args[idx + 1] ? args[idx + 1] : null;
|
|
1219
|
+
};
|
|
1220
|
+
|
|
1221
|
+
let body;
|
|
1222
|
+
if (subOp === 'recognize') {
|
|
1223
|
+
const query = args[1] ?? '';
|
|
1224
|
+
if (!query) { console.error(' Missing query argument. Usage: aria noor recognize "<query>"'); process.exit(1); }
|
|
1225
|
+
body = { operation: 'recognize', query, sessionId };
|
|
1226
|
+
} else if (subOp === 'forge') {
|
|
1227
|
+
const intent = args[1] ?? '';
|
|
1228
|
+
if (!intent) { console.error(' Missing intent argument. Usage: aria noor forge "<intent>" --primitives \'[...]\''); process.exit(1); }
|
|
1229
|
+
const primitivesRaw = getFlag('--primitives') ?? '[]';
|
|
1230
|
+
let primitives;
|
|
1231
|
+
try {
|
|
1232
|
+
primitives = JSON.parse(primitivesRaw);
|
|
1233
|
+
if (!Array.isArray(primitives)) throw new Error('primitives must be a JSON array');
|
|
1234
|
+
} catch (err) {
|
|
1235
|
+
console.error(` Could not parse --primitives as JSON array: ${err instanceof Error ? err.message : String(err)}`);
|
|
1236
|
+
process.exit(1);
|
|
1237
|
+
}
|
|
1238
|
+
body = { operation: 'forge', intent, primitives, sessionId };
|
|
1239
|
+
} else {
|
|
1240
|
+
console.error(` Unknown noor operation: ${subOp}. Run: aria noor --help`);
|
|
1241
|
+
process.exit(1);
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
try {
|
|
1245
|
+
const response = await fetch(url, { method: 'POST', headers, body: JSON.stringify(body) });
|
|
1246
|
+
const data = await response.json().catch(() => ({}));
|
|
1247
|
+
if (!response.ok) {
|
|
1248
|
+
console.error(` Noor ${subOp} error (${response.status}): ${data.error ?? JSON.stringify(data)}`);
|
|
1249
|
+
process.exit(1);
|
|
1250
|
+
}
|
|
1251
|
+
console.log('');
|
|
1252
|
+
console.log(` Noor ${subOp.toUpperCase()} — latency: ${data.latencyMs}ms`);
|
|
1253
|
+
if (subOp === 'recognize') {
|
|
1254
|
+
console.log(` nearestText: ${String(data.nearestText ?? '').slice(0, 120) || '(none)'}`);
|
|
1255
|
+
console.log(` soulDistance: ${data.soulDistance ?? 0}`);
|
|
1256
|
+
console.log(` confidence: ${data.confidence ?? 0}`);
|
|
1257
|
+
console.log(` withinMembrane: ${data.withinMembrane ?? true}`);
|
|
1258
|
+
console.log(` soulCharge: ${data.soulCharge ?? 0}`);
|
|
1259
|
+
if (data.ghazaliVerdict) console.log(` ghazali: ${data.ghazaliVerdict}`);
|
|
1260
|
+
if (data.manifoldHealth) console.log(` manifold drift: ${data.manifoldHealth.drift} (coherence: ${data.manifoldHealth.coherence})`);
|
|
1261
|
+
if (data.projectionComponents?.length) {
|
|
1262
|
+
console.log(` top component: ${data.projectionComponents[0].eigenvector} (w=${data.projectionComponents[0].weight.toFixed(4)})`);
|
|
1263
|
+
}
|
|
1264
|
+
} else if (subOp === 'forge') {
|
|
1265
|
+
console.log(` success: ${data.success ?? false}`);
|
|
1266
|
+
console.log(` toolName: ${data.toolName ?? '(none)'}`);
|
|
1267
|
+
console.log(` ethicallyApproved:${data.ethicallyApproved ?? false}`);
|
|
1268
|
+
console.log(` totalDurationMs: ${data.totalDurationMs ?? 0}ms`);
|
|
1269
|
+
if (data.results?.length) {
|
|
1270
|
+
console.log(` primitives run: ${data.results.length}`);
|
|
1271
|
+
for (const r of data.results) {
|
|
1272
|
+
console.log(` [${r.type}] ${r.success ? 'ok' : 'FAIL'} ${r.error ? `— ${r.error}` : ''} (${r.durationMs}ms)`);
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
console.log('');
|
|
1277
|
+
process.exit(0);
|
|
1278
|
+
} catch (err) {
|
|
1279
|
+
console.error(` Noor ${subOp} transport fault: ${err instanceof Error ? err.message : String(err)}`);
|
|
1280
|
+
process.exit(1);
|
|
1281
|
+
}
|
|
1282
|
+
})();
|
|
177
1283
|
} else {
|
|
178
1284
|
// ── Self-service onboarding via the canonical thin-loop conversation ──
|
|
179
1285
|
// When ~/.aria/license.json is missing, run the conversational
|
|
@@ -275,6 +1381,26 @@ if (command === 'check-update') {
|
|
|
275
1381
|
console.log(' Type to speak with Aria. /exit to quit, /clear to reset memory.');
|
|
276
1382
|
console.log('');
|
|
277
1383
|
|
|
278
|
-
|
|
279
|
-
|
|
1384
|
+
// ── Aristotle 28 + Noor cognitive lifecycle wrap on the chat session ──
|
|
1385
|
+
// Pre-coverage fires on session-open (Fitrah / wisdom / research-pull /
|
|
1386
|
+
// soul-charge baseline); post-coverage fires when the chat loop exits
|
|
1387
|
+
// (8-lens / quality-gate / feedback-loop / soul-charge drift). The chat
|
|
1388
|
+
// loop itself fires per-turn coverage via the SDK chat.ts `wrapAriaChatTurn`
|
|
1389
|
+
// call site once that integration ships in `chat.ts`.
|
|
1390
|
+
const noorWire = await loadAristotleNoorWire();
|
|
1391
|
+
await noorWire.wrapCliCommand(
|
|
1392
|
+
'cli-chat',
|
|
1393
|
+
makeEmissionId('chat'),
|
|
1394
|
+
async () => {
|
|
1395
|
+
const aria = new AriaChat(config);
|
|
1396
|
+
await aria.start();
|
|
1397
|
+
return 'chat-session-ended';
|
|
1398
|
+
},
|
|
1399
|
+
{
|
|
1400
|
+
isHamza: hasOwnerToken,
|
|
1401
|
+
tier: hasOwnerToken ? 'owner' : 'client',
|
|
1402
|
+
isFirstOfSession: true,
|
|
1403
|
+
metadata: { command: 'chat', model: config.model?.model, provider: config.model?.provider },
|
|
1404
|
+
},
|
|
1405
|
+
);
|
|
280
1406
|
}
|