@aria_asi/cli 0.2.30 → 0.2.31
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/dist/aria-connector/src/connectors/claude-code.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/claude-code.js +88 -20
- package/dist/aria-connector/src/connectors/claude-code.js.map +1 -1
- package/dist/aria-connector/src/connectors/codex.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/codex.js +526 -2
- package/dist/aria-connector/src/connectors/codex.js.map +1 -1
- package/dist/aria-connector/src/connectors/doctrine-trigger-map.d.ts +7 -0
- package/dist/aria-connector/src/connectors/doctrine-trigger-map.d.ts.map +1 -0
- package/dist/aria-connector/src/connectors/doctrine-trigger-map.js +87 -0
- package/dist/aria-connector/src/connectors/doctrine-trigger-map.js.map +1 -0
- package/dist/aria-connector/src/connectors/must-read.d.ts +4 -0
- package/dist/aria-connector/src/connectors/must-read.d.ts.map +1 -0
- package/dist/aria-connector/src/connectors/must-read.js +111 -0
- package/dist/aria-connector/src/connectors/must-read.js.map +1 -0
- package/dist/aria-connector/src/connectors/opencode.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/opencode.js +2 -0
- package/dist/aria-connector/src/connectors/opencode.js.map +1 -1
- package/dist/aria-connector/src/connectors/runtime.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/runtime.js +231 -19
- package/dist/aria-connector/src/connectors/runtime.js.map +1 -1
- package/dist/aria-connector/src/connectors/shell.d.ts.map +1 -1
- package/dist/aria-connector/src/connectors/shell.js +76 -3
- package/dist/aria-connector/src/connectors/shell.js.map +1 -1
- package/dist/assets/hooks/aria-cognition-substrate-binding.mjs +52 -25
- package/dist/assets/hooks/aria-harness-via-sdk.mjs +126 -12
- package/dist/assets/hooks/aria-pre-tool-gate.mjs +185 -76
- package/dist/assets/hooks/aria-preturn-memory-gate.mjs +63 -14
- package/dist/assets/hooks/aria-repo-doctrine-gate.mjs +2 -0
- package/dist/assets/hooks/aria-stop-gate.mjs +225 -52
- package/dist/assets/hooks/lib/canonical-lenses.mjs +6 -5
- package/dist/assets/hooks/lib/gate-loop-state.mjs +50 -0
- package/dist/assets/hooks/lib/hook-message-window.mjs +121 -0
- package/dist/assets/hooks/test-tier-lens-labeling.mjs +26 -58
- package/dist/assets/opencode-plugins/harness-gate/index.js +23 -1
- package/dist/assets/opencode-plugins/harness-stop/index.js +93 -4
- package/dist/runtime/auth-middleware.mjs +251 -0
- package/dist/runtime/codex-bridge.mjs +644 -0
- package/dist/runtime/discipline/CLAUDE.md +12 -0
- package/dist/runtime/discipline/doctrine_trigger_map.json +479 -0
- package/dist/runtime/doctrine_trigger_map.json +479 -0
- package/dist/runtime/fleet-engine.mjs +231 -0
- package/dist/runtime/harness-daemon.mjs +433 -0
- package/dist/runtime/manifest.json +1 -1
- package/dist/runtime/metering.mjs +100 -0
- package/dist/runtime/onboarding-engine.mjs +89 -0
- package/dist/runtime/plugin-engine.mjs +196 -0
- package/dist/runtime/sdk/BUNDLED.json +1 -1
- package/dist/runtime/sdk/index.d.ts +7 -0
- package/dist/runtime/sdk/index.js +120 -14
- package/dist/runtime/sdk/index.js.map +1 -1
- package/dist/runtime/service.mjs +1094 -47
- package/dist/runtime/workflow-engine.mjs +322 -0
- package/dist/sdk/BUNDLED.json +1 -1
- package/dist/sdk/index.d.ts +7 -0
- package/dist/sdk/index.js +120 -14
- package/dist/sdk/index.js.map +1 -1
- package/hooks/aria-cognition-substrate-binding.mjs +52 -25
- package/hooks/aria-harness-via-sdk.mjs +126 -12
- package/hooks/aria-pre-tool-gate.mjs +185 -76
- package/hooks/aria-preturn-memory-gate.mjs +63 -14
- package/hooks/aria-repo-doctrine-gate.mjs +2 -0
- package/hooks/aria-stop-gate.mjs +225 -52
- package/hooks/lib/canonical-lenses.mjs +6 -5
- package/hooks/lib/gate-loop-state.mjs +50 -0
- package/hooks/lib/hook-message-window.mjs +121 -0
- package/hooks/test-tier-lens-labeling.mjs +26 -58
- package/opencode-plugins/harness-gate/index.js +23 -1
- package/opencode-plugins/harness-stop/index.js +93 -4
- package/package.json +1 -1
- package/runtime-src/auth-middleware.mjs +251 -0
- package/runtime-src/codex-bridge.mjs +644 -0
- package/runtime-src/fleet-engine.mjs +231 -0
- package/runtime-src/harness-daemon.mjs +433 -0
- package/runtime-src/metering.mjs +100 -0
- package/runtime-src/onboarding-engine.mjs +89 -0
- package/runtime-src/plugin-engine.mjs +196 -0
- package/runtime-src/service.mjs +1094 -47
- package/runtime-src/workflow-engine.mjs +322 -0
- package/scripts/bundle-sdk.mjs +5 -0
- package/src/connectors/claude-code.ts +98 -20
- package/src/connectors/codex.ts +534 -1
- package/src/connectors/doctrine-trigger-map.ts +112 -0
- package/src/connectors/must-read.ts +113 -0
- package/src/connectors/opencode.ts +3 -0
- package/src/connectors/runtime.ts +241 -21
- package/src/connectors/shell.ts +78 -3
- package/dist/cli-0.2.0.tgz +0 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
export type MustReadSurface = 'claude' | 'codex' | 'opencode';
|
|
2
|
+
|
|
3
|
+
function surfaceRoot(surface: MustReadSurface): string {
|
|
4
|
+
if (surface === 'claude') return '~/.claude';
|
|
5
|
+
if (surface === 'codex') return '~/.codex';
|
|
6
|
+
return '~/.aria';
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function doctrineMapPath(surface: MustReadSurface): string {
|
|
10
|
+
if (surface === 'claude') return '~/.claude/hooks/doctrine_trigger_map.json';
|
|
11
|
+
if (surface === 'codex') return '~/.codex/doctrine_trigger_map.json';
|
|
12
|
+
return '~/.opencode/doctrine_trigger_map.json';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function surfaceSpecificFiles(surface: MustReadSurface): string[] {
|
|
16
|
+
if (surface === 'claude') {
|
|
17
|
+
return [
|
|
18
|
+
'~/.claude/hooks/aria-harness-via-sdk.mjs',
|
|
19
|
+
'~/.claude/hooks/aria-preprompt-consult.mjs',
|
|
20
|
+
'~/.claude/hooks/aria-pre-tool-gate.mjs',
|
|
21
|
+
'~/.claude/hooks/aria-preturn-memory-gate.mjs',
|
|
22
|
+
'~/.claude/hooks/aria-cognition-substrate-binding.mjs',
|
|
23
|
+
'~/.claude/hooks/aria-stop-gate.mjs',
|
|
24
|
+
'~/.claude/hooks/aria-pre-text-gate.mjs',
|
|
25
|
+
];
|
|
26
|
+
}
|
|
27
|
+
if (surface === 'codex') {
|
|
28
|
+
return [
|
|
29
|
+
'~/.codex/AGENTS.md',
|
|
30
|
+
'~/.codex/config.toml',
|
|
31
|
+
'~/.aria/wrappers/codex',
|
|
32
|
+
'~/.aria/runtime/service.mjs',
|
|
33
|
+
'~/.codex/skills/aria-http-harness-client/SKILL.md',
|
|
34
|
+
'~/.codex/skills/aria-cognition/aria-repo-doctrine/SKILL.md',
|
|
35
|
+
'~/.codex/skills/aria-cognition/ghazali-8lens/SKILL.md',
|
|
36
|
+
'~/.codex/skills/aria-cognition/mizan/SKILL.md',
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
return [
|
|
40
|
+
'~/.aria/AGENTS.md',
|
|
41
|
+
'~/.aria/runtime/discipline/skills/aria-harness/aria-harness-onboarding/SKILL.md',
|
|
42
|
+
'~/.aria/runtime/discipline/skills/aria-cognition/aria-repo-doctrine/SKILL.md',
|
|
43
|
+
'~/.aria/runtime/discipline/skills/aria-cognition/ghazali-8lens/SKILL.md',
|
|
44
|
+
'~/.aria/runtime/discipline/skills/aria-cognition/mizan/SKILL.md',
|
|
45
|
+
];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function buildMustReadGuide(surface: MustReadSurface): string {
|
|
49
|
+
const root = surfaceRoot(surface);
|
|
50
|
+
const coreFiles = [
|
|
51
|
+
`${root}/ARIA_MUST_READ.md`,
|
|
52
|
+
'~/.aria/runtime/discipline/CLAUDE.md',
|
|
53
|
+
'~/.aria/runtime/discipline/skills/aria-harness/aria-harness-onboarding/SKILL.md',
|
|
54
|
+
'~/.aria/runtime/discipline/skills/aria-harness/aria-harness-substrate-binding/SKILL.md',
|
|
55
|
+
doctrineMapPath(surface),
|
|
56
|
+
];
|
|
57
|
+
const orderedFiles = [...coreFiles, ...surfaceSpecificFiles(surface)];
|
|
58
|
+
|
|
59
|
+
return `# Aria Agent Must-Read Order
|
|
60
|
+
|
|
61
|
+
This file exists because weaker models and long sessions drift unless the reading order is explicit.
|
|
62
|
+
Read these files in order before the first non-trivial action, and re-open the relevant gate file whenever a block fires.
|
|
63
|
+
|
|
64
|
+
## Required Read Order
|
|
65
|
+
|
|
66
|
+
${orderedFiles.map((filePath, index) => `${index + 1}. \`${filePath}\``).join('\n')}
|
|
67
|
+
|
|
68
|
+
## What Each File Teaches
|
|
69
|
+
|
|
70
|
+
1. \`${root}/ARIA_MUST_READ.md\`
|
|
71
|
+
The cross-surface reading order, recovery rules, and what to re-open after compaction or a block.
|
|
72
|
+
|
|
73
|
+
2. \`~/.aria/runtime/discipline/CLAUDE.md\`
|
|
74
|
+
The full harness doctrine: L1/L2/L3, cognition requirements, deploy verify contract, drift triggers, and anti-loop rules.
|
|
75
|
+
|
|
76
|
+
3. \`~/.aria/runtime/discipline/skills/aria-harness/aria-harness-onboarding/SKILL.md\`
|
|
77
|
+
The harness model in practical terms: packet, bind, and live gates.
|
|
78
|
+
|
|
79
|
+
4. \`~/.aria/runtime/discipline/skills/aria-harness/aria-harness-substrate-binding/SKILL.md\`
|
|
80
|
+
The cognition contract and anchor discipline. Re-open this whenever cognition or stop-gate fails.
|
|
81
|
+
|
|
82
|
+
5. \`${doctrineMapPath(surface)}\`
|
|
83
|
+
The live doctrine trigger map. This is what the runtime and stop gates actually match against.
|
|
84
|
+
|
|
85
|
+
## Surface-Specific Re-Open Rules
|
|
86
|
+
|
|
87
|
+
- If a pre-tool or write block fires:
|
|
88
|
+
Re-open the pre-tool surface file for this client plus \`aria-harness-substrate-binding\`.
|
|
89
|
+
|
|
90
|
+
- If an output or stop-gate block fires:
|
|
91
|
+
Re-open \`~/.aria/runtime/discipline/CLAUDE.md\`, the doctrine trigger map, and the substrate-binding skill before re-authoring.
|
|
92
|
+
|
|
93
|
+
- If transcript compaction or ledger deadlock happens:
|
|
94
|
+
Re-open items 1 through 4 first, then inspect the exact current hook or runtime file causing the block. Do not guess from stale memory.
|
|
95
|
+
|
|
96
|
+
- If the model starts repeating itself:
|
|
97
|
+
Stop, re-open this file, and repair from the gate evidence instead of restating intent.
|
|
98
|
+
|
|
99
|
+
## Non-Negotiables
|
|
100
|
+
|
|
101
|
+
- Do not rename canonical cognition meaning into generic aliases.
|
|
102
|
+
- Do not say "good enough", "should work", or make unverified completion claims.
|
|
103
|
+
- Do not treat skills as optional flavor text; they are the reading order and repair guide.
|
|
104
|
+
- Do not proceed after a gate block without re-opening the file that owns that gate.
|
|
105
|
+
`;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function mustReadIntro(surface: MustReadSurface): string {
|
|
109
|
+
const root = surfaceRoot(surface);
|
|
110
|
+
return `## Must Read Order
|
|
111
|
+
Read \`${root}/ARIA_MUST_READ.md\` before the first non-trivial action and re-open it after any gate block, compaction, or repeated drift.
|
|
112
|
+
`;
|
|
113
|
+
}
|
|
@@ -16,6 +16,8 @@ import * as path from 'path';
|
|
|
16
16
|
import { fileURLToPath } from 'node:url';
|
|
17
17
|
import type { AriaConfig } from '../config.js';
|
|
18
18
|
import { connectShell } from './shell.js';
|
|
19
|
+
import { syncDoctrineTriggerMap } from './doctrine-trigger-map.js';
|
|
20
|
+
import { buildMustReadGuide, mustReadIntro } from './must-read.js';
|
|
19
21
|
|
|
20
22
|
// ── Bundled OpenCode plugins ────────────────────────────────────────────────
|
|
21
23
|
//
|
|
@@ -139,6 +141,7 @@ export async function connectOpenCode(config: AriaConfig): Promise<string[]> {
|
|
|
139
141
|
copyPluginDir(srcDir, dstDir, logs);
|
|
140
142
|
installedPaths.push(dstDir);
|
|
141
143
|
}
|
|
144
|
+
syncDoctrineTriggerMap(logs);
|
|
142
145
|
|
|
143
146
|
// ── Wire ~/.opencode/config.json ──────────────────────────────────────────
|
|
144
147
|
const configPath = path.join(opencodeDir, 'config.json');
|
|
@@ -7,12 +7,14 @@ import {
|
|
|
7
7
|
chmodSync,
|
|
8
8
|
rmSync,
|
|
9
9
|
writeFileSync,
|
|
10
|
+
readFileSync,
|
|
10
11
|
} from 'fs';
|
|
11
12
|
import { execFileSync } from 'child_process';
|
|
12
13
|
import { homedir } from 'os';
|
|
13
14
|
import * as path from 'path';
|
|
14
15
|
import { fileURLToPath } from 'node:url';
|
|
15
16
|
import { loadConfig, saveConfig } from '../config.js';
|
|
17
|
+
import { syncDoctrineTriggerMap } from './doctrine-trigger-map.js';
|
|
16
18
|
|
|
17
19
|
function packageRuntimeDir(): string {
|
|
18
20
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -50,6 +52,39 @@ function writeWrapper(binPath: string, targetScript: string): void {
|
|
|
50
52
|
try { chmodSync(binPath, 0o755); } catch {}
|
|
51
53
|
}
|
|
52
54
|
|
|
55
|
+
function trimUrl(value: string): string {
|
|
56
|
+
return value.trim().replace(/\/+$/, '');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function isLocalHarnessDaemonUrl(value: string): boolean {
|
|
60
|
+
const normalized = trimUrl(value);
|
|
61
|
+
return normalized === 'http://127.0.0.1:8790' || normalized === 'http://localhost:8790';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function canonicalUpstreamHarnessUrl(): string {
|
|
65
|
+
const localSoulCandidates = existsSync('/etc/rancher/k3s/k3s.yaml')
|
|
66
|
+
? ['http://127.0.0.1:30080', 'http://192.168.4.25:30080']
|
|
67
|
+
: [];
|
|
68
|
+
const candidates = [
|
|
69
|
+
process.env.ARIA_UPSTREAM_HARNESS_URL || '',
|
|
70
|
+
process.env.ARIA_HIVE_UPSTREAM_URL || '',
|
|
71
|
+
...localSoulCandidates,
|
|
72
|
+
process.env.ARIA_SOUL_URL || '',
|
|
73
|
+
process.env.ARIAS_SOUL_URL || '',
|
|
74
|
+
process.env.ARIA_SOUL_BASE_URL || '',
|
|
75
|
+
...(process.env.ARIA_HARNESS_FALLBACK_URLS || '').split(','),
|
|
76
|
+
'https://harness.ariasos.com',
|
|
77
|
+
]
|
|
78
|
+
.map((entry) => trimUrl(String(entry || '')))
|
|
79
|
+
.filter(Boolean);
|
|
80
|
+
|
|
81
|
+
for (const candidate of candidates) {
|
|
82
|
+
if (!isLocalHarnessDaemonUrl(candidate)) return candidate;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return 'https://harness.ariasos.com';
|
|
86
|
+
}
|
|
87
|
+
|
|
53
88
|
function writeRuntimeEnv(runtimeDst: string): string {
|
|
54
89
|
const envPath = path.join(runtimeDst, 'runtime.env');
|
|
55
90
|
const config = loadConfig();
|
|
@@ -59,24 +94,46 @@ function writeRuntimeEnv(runtimeDst: string): string {
|
|
|
59
94
|
const deepModel = runtimeProfiles.deepModel || 'deepseek-v4-pro';
|
|
60
95
|
const xaiFallbackModel = runtimeProfiles.xaiFallbackModel || 'grok-4-2-reasoning';
|
|
61
96
|
const nimFallbackModel = runtimeProfiles.nimFallbackModel || 'qwen/qwen3.5-122b-a10b';
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
process.env.
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
process.env.
|
|
69
|
-
|
|
70
|
-
|
|
97
|
+
const localHarnessUrl = 'http://127.0.0.1:8790';
|
|
98
|
+
const upstreamHarnessUrl = canonicalUpstreamHarnessUrl();
|
|
99
|
+
const harnessFallbackUrls = [
|
|
100
|
+
process.env.ARIA_HARNESS_FALLBACK_URLS || '',
|
|
101
|
+
process.env.ARIA_SOUL_URL || '',
|
|
102
|
+
process.env.ARIAS_SOUL_URL || '',
|
|
103
|
+
process.env.ARIA_SOUL_BASE_URL || '',
|
|
104
|
+
upstreamHarnessUrl,
|
|
105
|
+
'http://127.0.0.1:30080',
|
|
106
|
+
'http://192.168.4.25:30080',
|
|
107
|
+
'https://arias-soul-6zp3gtk2ca-uc.a.run.app',
|
|
108
|
+
'https://harness.ariasos.com',
|
|
109
|
+
]
|
|
110
|
+
.flatMap((entry) => String(entry || '').split(','))
|
|
111
|
+
.map((entry) => trimUrl(String(entry || '')))
|
|
112
|
+
.filter((entry) => entry && !isLocalHarnessDaemonUrl(entry));
|
|
113
|
+
const forgeServiceUrl = `${localHarnessUrl}/api/forge/psi`;
|
|
114
|
+
const upstreamForgeServiceUrl =
|
|
115
|
+
process.env.ARIA_UPSTREAM_FORGE_SERVICE_URL ||
|
|
116
|
+
process.env.ARIA_FORGE_UPSTREAM_URL ||
|
|
117
|
+
`${upstreamHarnessUrl}/api/forge/psi`;
|
|
71
118
|
writeFileSync(
|
|
72
119
|
envPath,
|
|
73
120
|
[
|
|
74
121
|
'ARIA_RUNTIME_HOST=127.0.0.1',
|
|
75
122
|
'ARIA_RUNTIME_PORT=4319',
|
|
76
123
|
'ARIA_RUNTIME_URL=http://127.0.0.1:4319',
|
|
77
|
-
|
|
78
|
-
|
|
124
|
+
'ARIA_HARNESS_DAEMON_HOST=127.0.0.1',
|
|
125
|
+
'ARIA_HARNESS_DAEMON_PORT=8790',
|
|
126
|
+
`ARIA_HARNESS_DAEMON_URL=${localHarnessUrl}`,
|
|
127
|
+
'ARIA_CODEX_BRIDGE_HOST=127.0.0.1',
|
|
128
|
+
'ARIA_CODEX_BRIDGE_PORT=4320',
|
|
129
|
+
'ARIA_CODEX_DOWNSTREAM_PORT=4321',
|
|
130
|
+
`ARIA_HIVE_RUNTIME_URL=${localHarnessUrl}`,
|
|
131
|
+
`ARIA_HARNESS_BASE_URL=${localHarnessUrl}`,
|
|
132
|
+
`ARIA_HARNESS_URL=${localHarnessUrl}`,
|
|
133
|
+
`ARIA_UPSTREAM_HARNESS_URL=${upstreamHarnessUrl}`,
|
|
134
|
+
`ARIA_HARNESS_FALLBACK_URLS=${Array.from(new Set(harnessFallbackUrls)).join(',')}`,
|
|
79
135
|
`ARIA_FORGE_SERVICE_URL=${forgeServiceUrl}`,
|
|
136
|
+
`ARIA_UPSTREAM_FORGE_SERVICE_URL=${upstreamForgeServiceUrl}`,
|
|
80
137
|
'ARIA_QDRANT_URL=http://127.0.0.1:6333',
|
|
81
138
|
'ARIA_QDRANT_COLLECTION=aria_garden_memory',
|
|
82
139
|
`ARIA_RUNTIME_DEFAULT_PROVIDER=${defaultProvider}`,
|
|
@@ -230,7 +287,8 @@ function installSystemdUserService(ariaDir: string, logs: string[]): void {
|
|
|
230
287
|
const unit = [
|
|
231
288
|
'[Unit]',
|
|
232
289
|
'Description=Aria Mounted Runtime',
|
|
233
|
-
'After=network.target',
|
|
290
|
+
'After=network.target aria-harnessd.service',
|
|
291
|
+
'Requires=aria-harnessd.service',
|
|
234
292
|
'',
|
|
235
293
|
'[Service]',
|
|
236
294
|
'Type=simple',
|
|
@@ -256,13 +314,154 @@ function installSystemdUserService(ariaDir: string, logs: string[]): void {
|
|
|
256
314
|
}
|
|
257
315
|
}
|
|
258
316
|
|
|
317
|
+
function installHarnessDaemonSystemdUserService(ariaDir: string, logs: string[]): void {
|
|
318
|
+
const systemctlPath = '/bin/systemctl';
|
|
319
|
+
if (process.platform !== 'linux' || !existsSync(systemctlPath)) {
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
const serviceDir = path.join(homedir(), '.config', 'systemd', 'user');
|
|
324
|
+
const servicePath = path.join(serviceDir, 'aria-harnessd.service');
|
|
325
|
+
mkdirSync(serviceDir, { recursive: true, mode: 0o755 });
|
|
326
|
+
|
|
327
|
+
const unit = [
|
|
328
|
+
'[Unit]',
|
|
329
|
+
'Description=Aria Local Harness Daemon',
|
|
330
|
+
'After=network.target',
|
|
331
|
+
'',
|
|
332
|
+
'[Service]',
|
|
333
|
+
'Type=simple',
|
|
334
|
+
`EnvironmentFile=-${path.join(ariaDir, 'runtime', 'runtime.env')}`,
|
|
335
|
+
`ExecStart=${path.join(ariaDir, 'bin', 'aria-harnessd')}`,
|
|
336
|
+
'Restart=always',
|
|
337
|
+
'RestartSec=2',
|
|
338
|
+
'',
|
|
339
|
+
'[Install]',
|
|
340
|
+
'WantedBy=default.target',
|
|
341
|
+
'',
|
|
342
|
+
].join('\n');
|
|
343
|
+
|
|
344
|
+
writeFileSync(servicePath, unit, { mode: 0o644 });
|
|
345
|
+
logs.push(`Installed systemd user unit → ${servicePath}`);
|
|
346
|
+
|
|
347
|
+
try {
|
|
348
|
+
execFileSync(systemctlPath, ['--user', 'daemon-reload'], { stdio: 'ignore' });
|
|
349
|
+
execFileSync(systemctlPath, ['--user', 'enable', '--now', 'aria-harnessd.service'], { stdio: 'ignore' });
|
|
350
|
+
logs.push('Enabled and started systemd user service: aria-harnessd.service');
|
|
351
|
+
} catch (error) {
|
|
352
|
+
logs.push(`⚠ local harness daemon installed but not activated: ${error instanceof Error ? error.message : String(error)}`);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function retireLegacySoulPortForwardServices(logs: string[]): void {
|
|
357
|
+
const systemctlPath = '/bin/systemctl';
|
|
358
|
+
if (process.platform !== 'linux' || !existsSync(systemctlPath)) {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
const serviceDir = path.join(homedir(), '.config', 'systemd', 'user');
|
|
363
|
+
const legacyUnits = ['aria-soul-portforward.service', 'aria-soul-forward.service'];
|
|
364
|
+
const dependencyNeedles = new Set(legacyUnits);
|
|
365
|
+
|
|
366
|
+
if (existsSync(serviceDir)) {
|
|
367
|
+
for (const name of readdirSync(serviceDir)) {
|
|
368
|
+
if (!name.endsWith('.service')) continue;
|
|
369
|
+
const unitPath = path.join(serviceDir, name);
|
|
370
|
+
if (!statSync(unitPath).isFile()) continue;
|
|
371
|
+
let current = '';
|
|
372
|
+
try {
|
|
373
|
+
current = readFileSync(unitPath, 'utf8');
|
|
374
|
+
} catch {
|
|
375
|
+
continue;
|
|
376
|
+
}
|
|
377
|
+
let next = current;
|
|
378
|
+
for (const needle of dependencyNeedles) {
|
|
379
|
+
next = next.replaceAll(needle, 'aria-harnessd.service');
|
|
380
|
+
}
|
|
381
|
+
if (next !== current) {
|
|
382
|
+
writeFileSync(unitPath, next, { mode: 0o644 });
|
|
383
|
+
logs.push(`Rebound legacy 8790 dependency → ${unitPath}`);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
for (const unit of legacyUnits) {
|
|
389
|
+
const unitPath = path.join(serviceDir, unit);
|
|
390
|
+
const backupPath = `${unitPath}.legacy-disabled.bak`;
|
|
391
|
+
const disabledPath = `${unitPath}.disabled`;
|
|
392
|
+
try {
|
|
393
|
+
if (existsSync(unitPath) && statSync(unitPath).isFile() && !existsSync(backupPath)) {
|
|
394
|
+
copyFileSync(unitPath, backupPath);
|
|
395
|
+
logs.push(`Backed up legacy 8790 unit → ${backupPath}`);
|
|
396
|
+
}
|
|
397
|
+
} catch {}
|
|
398
|
+
try {
|
|
399
|
+
if (existsSync(unitPath) && statSync(unitPath).isFile()) {
|
|
400
|
+
rmSync(disabledPath, { force: true });
|
|
401
|
+
copyFileSync(unitPath, disabledPath);
|
|
402
|
+
rmSync(unitPath, { force: true });
|
|
403
|
+
logs.push(`Retired legacy 8790 unit file → ${disabledPath}`);
|
|
404
|
+
}
|
|
405
|
+
} catch {}
|
|
406
|
+
try {
|
|
407
|
+
execFileSync(systemctlPath, ['--user', 'disable', '--now', unit], { stdio: 'ignore' });
|
|
408
|
+
logs.push(`Disabled legacy 8790 unit: ${unit}`);
|
|
409
|
+
} catch {}
|
|
410
|
+
try {
|
|
411
|
+
execFileSync(systemctlPath, ['--user', 'mask', '--force', unit], { stdio: 'ignore' });
|
|
412
|
+
logs.push(`Masked legacy 8790 unit: ${unit}`);
|
|
413
|
+
} catch {}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
try {
|
|
417
|
+
execFileSync(systemctlPath, ['--user', 'daemon-reload'], { stdio: 'ignore' });
|
|
418
|
+
} catch {}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
function installCodexBridgeSystemdUserService(ariaDir: string, logs: string[]): void {
|
|
422
|
+
const systemctlPath = '/bin/systemctl';
|
|
423
|
+
if (process.platform !== 'linux' || !existsSync(systemctlPath)) {
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
const serviceDir = path.join(homedir(), '.config', 'systemd', 'user');
|
|
428
|
+
const servicePath = path.join(serviceDir, 'aria-codex-bridge.service');
|
|
429
|
+
mkdirSync(serviceDir, { recursive: true, mode: 0o755 });
|
|
430
|
+
|
|
431
|
+
const unit = [
|
|
432
|
+
'[Unit]',
|
|
433
|
+
'Description=Aria Codex Enforcement Bridge',
|
|
434
|
+
'After=network.target aria-mounted-runtime.service',
|
|
435
|
+
'Requires=aria-mounted-runtime.service',
|
|
436
|
+
'',
|
|
437
|
+
'[Service]',
|
|
438
|
+
'Type=simple',
|
|
439
|
+
`EnvironmentFile=-${path.join(ariaDir, 'runtime', 'runtime.env')}`,
|
|
440
|
+
`ExecStart=${path.join(ariaDir, 'bin', 'aria-codex-bridge')}`,
|
|
441
|
+
'Restart=always',
|
|
442
|
+
'RestartSec=2',
|
|
443
|
+
'',
|
|
444
|
+
'[Install]',
|
|
445
|
+
'WantedBy=default.target',
|
|
446
|
+
'',
|
|
447
|
+
].join('\n');
|
|
448
|
+
|
|
449
|
+
writeFileSync(servicePath, unit, { mode: 0o644 });
|
|
450
|
+
logs.push(`Installed systemd user unit → ${servicePath}`);
|
|
451
|
+
|
|
452
|
+
try {
|
|
453
|
+
execFileSync(systemctlPath, ['--user', 'daemon-reload'], { stdio: 'ignore' });
|
|
454
|
+
execFileSync(systemctlPath, ['--user', 'enable', '--now', 'aria-codex-bridge.service'], { stdio: 'ignore' });
|
|
455
|
+
logs.push('Enabled and started systemd user service: aria-codex-bridge.service');
|
|
456
|
+
} catch (error) {
|
|
457
|
+
logs.push(`⚠ codex bridge service installed but not activated: ${error instanceof Error ? error.message : String(error)}`);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
259
461
|
function installLaunchAgent(ariaDir: string, logs: string[]): void {
|
|
260
462
|
if (process.platform !== 'darwin') return;
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
process.env.ARIA_HARNESS_BASE_URL ||
|
|
264
|
-
process.env.ARIA_HARNESS_URL ||
|
|
265
|
-
'https://harness.ariasos.com';
|
|
463
|
+
const localHarnessUrl = 'http://127.0.0.1:8790';
|
|
464
|
+
const upstreamHarnessUrl = canonicalUpstreamHarnessUrl();
|
|
266
465
|
|
|
267
466
|
const launchAgentDir = path.join(homedir(), 'Library', 'LaunchAgents');
|
|
268
467
|
const plistPath = path.join(launchAgentDir, 'com.aria.mounted-runtime.plist');
|
|
@@ -286,10 +485,20 @@ function installLaunchAgent(ariaDir: string, logs: string[]): void {
|
|
|
286
485
|
<string>4319</string>
|
|
287
486
|
<key>ARIA_RUNTIME_URL</key>
|
|
288
487
|
<string>http://127.0.0.1:4319</string>
|
|
289
|
-
|
|
290
|
-
<string>${
|
|
291
|
-
|
|
292
|
-
<string>${
|
|
488
|
+
<key>ARIA_HARNESS_DAEMON_URL</key>
|
|
489
|
+
<string>${localHarnessUrl}</string>
|
|
490
|
+
<key>ARIA_HIVE_RUNTIME_URL</key>
|
|
491
|
+
<string>${localHarnessUrl}</string>
|
|
492
|
+
<key>ARIA_HARNESS_BASE_URL</key>
|
|
493
|
+
<string>${localHarnessUrl}</string>
|
|
494
|
+
<key>ARIA_HARNESS_URL</key>
|
|
495
|
+
<string>${localHarnessUrl}</string>
|
|
496
|
+
<key>ARIA_UPSTREAM_HARNESS_URL</key>
|
|
497
|
+
<string>${upstreamHarnessUrl}</string>
|
|
498
|
+
<key>ARIA_FORGE_SERVICE_URL</key>
|
|
499
|
+
<string>${localHarnessUrl}/api/forge/psi</string>
|
|
500
|
+
<key>ARIA_UPSTREAM_FORGE_SERVICE_URL</key>
|
|
501
|
+
<string>${upstreamHarnessUrl}/api/forge/psi</string>
|
|
293
502
|
</dict>
|
|
294
503
|
<key>RunAtLoad</key>
|
|
295
504
|
<true/>
|
|
@@ -351,20 +560,31 @@ export async function installSharedRuntime(): Promise<string[]> {
|
|
|
351
560
|
}
|
|
352
561
|
|
|
353
562
|
const startWrapper = path.join(binDir, 'aria-runtime');
|
|
563
|
+
const harnessDaemonWrapper = path.join(binDir, 'aria-harnessd');
|
|
564
|
+
const codexBridgeWrapper = path.join(binDir, 'aria-codex-bridge');
|
|
354
565
|
const doctorWrapper = path.join(binDir, 'aria-runtime-doctor');
|
|
355
566
|
writeWrapper(startWrapper, path.join(runtimeDst, 'service.mjs'));
|
|
567
|
+
writeWrapper(harnessDaemonWrapper, path.join(runtimeDst, 'harness-daemon.mjs'));
|
|
568
|
+
writeWrapper(codexBridgeWrapper, path.join(runtimeDst, 'codex-bridge.mjs'));
|
|
356
569
|
writeWrapper(doctorWrapper, path.join(runtimeDst, 'doctor.mjs'));
|
|
357
570
|
const envPath = writeRuntimeEnv(runtimeDst);
|
|
358
571
|
installDisciplinePack(runtimeDst, logs);
|
|
572
|
+
syncDoctrineTriggerMap(logs);
|
|
359
573
|
installLocalQdrantService(ariaDir, logs);
|
|
574
|
+
retireLegacySoulPortForwardServices(logs);
|
|
575
|
+
installHarnessDaemonSystemdUserService(ariaDir, logs);
|
|
360
576
|
installSystemdUserService(ariaDir, logs);
|
|
577
|
+
installCodexBridgeSystemdUserService(ariaDir, logs);
|
|
361
578
|
installLaunchAgent(ariaDir, logs);
|
|
362
579
|
|
|
363
580
|
logs.push(`Installed shared Aria runtime → ${runtimeDst}`);
|
|
364
581
|
logs.push(`Installed runtime wrapper → ${startWrapper}`);
|
|
582
|
+
logs.push(`Installed harness daemon wrapper → ${harnessDaemonWrapper}`);
|
|
583
|
+
logs.push(`Installed Codex bridge wrapper → ${codexBridgeWrapper}`);
|
|
365
584
|
logs.push(`Installed runtime doctor → ${doctorWrapper}`);
|
|
366
585
|
logs.push(`Installed runtime env → ${envPath}`);
|
|
367
586
|
logs.push('Mount any client against ARIA_RUNTIME_URL=http://127.0.0.1:4319');
|
|
587
|
+
logs.push('Harness packet and local validation are served by aria-harnessd on http://127.0.0.1:8790.');
|
|
368
588
|
logs.push('Local Qdrant memory is mounted at http://127.0.0.1:6333 for garden pulse persistence.');
|
|
369
589
|
logs.push('Runtime lease is encrypted at rest and revalidated against /api/license/heartbeat');
|
|
370
590
|
logs.push('Forge synthesis is relayed through the canonical Aria endpoint unless ARIA_FORGE_SERVICE_URL overrides it.');
|
package/src/connectors/shell.ts
CHANGED
|
@@ -12,15 +12,32 @@ const SHELL_RC_FILES = ['.bashrc', '.bash_profile', '.profile', '.zshrc', '.zpro
|
|
|
12
12
|
const SHELL_HOOK_LINE = '[ -f "$HOME/.aria/shell/runtime-client-env.sh" ] && . "$HOME/.aria/shell/runtime-client-env.sh"';
|
|
13
13
|
|
|
14
14
|
function resolveToolPath(toolName: string): string | null {
|
|
15
|
+
const sanitizedPath = (process.env.PATH || '')
|
|
16
|
+
.split(path.delimiter)
|
|
17
|
+
.filter((entry) => entry && path.resolve(entry) !== path.resolve(WRAPPER_DIR))
|
|
18
|
+
.join(path.delimiter);
|
|
15
19
|
try {
|
|
16
|
-
const lines = execSync(`which -a ${toolName}`, {
|
|
20
|
+
const lines = execSync(`which -a ${toolName}`, {
|
|
21
|
+
encoding: 'utf-8',
|
|
22
|
+
env: {
|
|
23
|
+
...process.env,
|
|
24
|
+
PATH: sanitizedPath,
|
|
25
|
+
},
|
|
26
|
+
})
|
|
17
27
|
.split('\n')
|
|
18
28
|
.map((line) => line.trim())
|
|
19
29
|
.filter(Boolean);
|
|
20
30
|
const preferred = lines.find((candidate) => !candidate.startsWith(`${WRAPPER_DIR}/`));
|
|
21
31
|
return preferred || lines[0] || null;
|
|
22
32
|
} catch {
|
|
23
|
-
|
|
33
|
+
const fallbackCandidates = [
|
|
34
|
+
path.join(homedir(), '.npm-global', 'bin', toolName),
|
|
35
|
+
path.join(homedir(), '.local', 'bin', toolName),
|
|
36
|
+
path.join('/usr/local/bin', toolName),
|
|
37
|
+
path.join('/usr/bin', toolName),
|
|
38
|
+
];
|
|
39
|
+
const fallback = fallbackCandidates.find((candidate) => existsSync(candidate));
|
|
40
|
+
return fallback || null;
|
|
24
41
|
}
|
|
25
42
|
}
|
|
26
43
|
|
|
@@ -72,9 +89,66 @@ if [ -z "\${ARIA_API_KEY:-}" ]; then
|
|
|
72
89
|
fi
|
|
73
90
|
fi
|
|
74
91
|
fi
|
|
92
|
+
if [ -n "\${ARIA_API_KEY:-}" ] && [ -z "\${OPENAI_API_KEY:-}" ]; then
|
|
93
|
+
export OPENAI_API_KEY="$ARIA_API_KEY"
|
|
94
|
+
fi
|
|
75
95
|
`;
|
|
76
96
|
}
|
|
77
97
|
|
|
98
|
+
function buildToolExecBlock(toolName: string, toolPath: string): string {
|
|
99
|
+
if (toolName !== 'codex') {
|
|
100
|
+
return `exec "${toolPath}" "$@"`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return `for arg in "$@"; do
|
|
104
|
+
if [ "$arg" = "--remote" ]; then
|
|
105
|
+
exec "${toolPath}" "$@"
|
|
106
|
+
fi
|
|
107
|
+
done
|
|
108
|
+
|
|
109
|
+
case "\${1:-}" in
|
|
110
|
+
app-server|exec-server|exec|review)
|
|
111
|
+
exec "${toolPath}" "$@"
|
|
112
|
+
;;
|
|
113
|
+
esac
|
|
114
|
+
|
|
115
|
+
if [ "\${ARIA_CODEX_BYPASS_BRIDGE:-0}" = "1" ]; then
|
|
116
|
+
exec "${toolPath}" "$@"
|
|
117
|
+
fi
|
|
118
|
+
|
|
119
|
+
export ARIA_CODEX_REAL_BIN="\${ARIA_CODEX_REAL_BIN:-${toolPath}}"
|
|
120
|
+
export ARIA_CODEX_BRIDGE_HOST="\${ARIA_CODEX_BRIDGE_HOST:-127.0.0.1}"
|
|
121
|
+
export ARIA_CODEX_BRIDGE_PORT="\${ARIA_CODEX_BRIDGE_PORT:-4320}"
|
|
122
|
+
export ARIA_CODEX_DOWNSTREAM_PORT="\${ARIA_CODEX_DOWNSTREAM_PORT:-4321}"
|
|
123
|
+
|
|
124
|
+
if command -v systemctl >/dev/null 2>&1; then
|
|
125
|
+
systemctl --user import-environment ARIA_CODEX_REAL_BIN ARIA_CODEX_BRIDGE_HOST ARIA_CODEX_BRIDGE_PORT ARIA_CODEX_DOWNSTREAM_PORT >/dev/null 2>&1 || true
|
|
126
|
+
systemctl --user start aria-codex-bridge.service >/dev/null 2>&1 || true
|
|
127
|
+
fi
|
|
128
|
+
|
|
129
|
+
if ! (exec 9<>"/dev/tcp/$ARIA_CODEX_BRIDGE_HOST/$ARIA_CODEX_BRIDGE_PORT") >/dev/null 2>&1; then
|
|
130
|
+
nohup "$HOME/.aria/bin/aria-codex-bridge" >/dev/null 2>&1 &
|
|
131
|
+
fi
|
|
132
|
+
|
|
133
|
+
bridge_ready=0
|
|
134
|
+
for _aria_try in $(seq 1 50); do
|
|
135
|
+
if (exec 9<>"/dev/tcp/$ARIA_CODEX_BRIDGE_HOST/$ARIA_CODEX_BRIDGE_PORT") >/dev/null 2>&1; then
|
|
136
|
+
exec 9>&-
|
|
137
|
+
exec 9<&-
|
|
138
|
+
bridge_ready=1
|
|
139
|
+
break
|
|
140
|
+
fi
|
|
141
|
+
sleep 0.1
|
|
142
|
+
done
|
|
143
|
+
|
|
144
|
+
if [ "$bridge_ready" != "1" ]; then
|
|
145
|
+
echo "Aria Codex bridge did not become ready at ws://$ARIA_CODEX_BRIDGE_HOST:$ARIA_CODEX_BRIDGE_PORT" >&2
|
|
146
|
+
exit 1
|
|
147
|
+
fi
|
|
148
|
+
|
|
149
|
+
exec "${toolPath}" --remote "ws://$ARIA_CODEX_BRIDGE_HOST:$ARIA_CODEX_BRIDGE_PORT" "$@"`;
|
|
150
|
+
}
|
|
151
|
+
|
|
78
152
|
export async function connectShell(
|
|
79
153
|
toolName: string,
|
|
80
154
|
config: AriaConfig,
|
|
@@ -93,13 +167,14 @@ export async function connectShell(
|
|
|
93
167
|
|
|
94
168
|
const ariaBlock = buildShellWrapperBlock(config, toolName);
|
|
95
169
|
const runtimeBlock = buildRuntimeInjectionBlock();
|
|
170
|
+
const execBlock = buildToolExecBlock(toolName, toolPath);
|
|
96
171
|
const wrapperPath = path.join(WRAPPER_DIR, toolName);
|
|
97
172
|
const script = `#!/usr/bin/env bash
|
|
98
173
|
# ARIA HARNESS WRAPPER — generated by @aria/connector
|
|
99
174
|
# Wraps ${toolName} with Aria's cognitive harness
|
|
100
175
|
${ariaBlock}
|
|
101
176
|
${runtimeBlock}
|
|
102
|
-
|
|
177
|
+
${execBlock}
|
|
103
178
|
`;
|
|
104
179
|
|
|
105
180
|
writeFileSync(wrapperPath, script);
|
package/dist/cli-0.2.0.tgz
DELETED
|
Binary file
|