@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
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Copies the harness-http-client SDK dist into this package's dist/sdk/ at
|
|
3
|
+
// build time so the published @aria_asi/cli npm package ships the SDK
|
|
4
|
+
// inline. Hooks resolve the SDK from ~/.claude/aria-sdk/ (installed by
|
|
5
|
+
// connectClaudeCode) — this script is the build-time half.
|
|
6
|
+
//
|
|
7
|
+
// Hamza 2026-04-27 directive: "isnt http harness client the fucking harness
|
|
8
|
+
// we hsve been wprking on? YOU ARENT USING THAT AND BUILDING SPMETHING
|
|
9
|
+
// SEPERATE WHY???!! FUCKING WIRE IT THE FUCK TOGETHER NOW - ALL OF IT".
|
|
10
|
+
// Ending the SDK fragmentation: every hook fetch now goes through the SDK.
|
|
11
|
+
|
|
12
|
+
import { existsSync, mkdirSync, readdirSync, copyFileSync, statSync, readFileSync, writeFileSync, rmSync } from 'node:fs';
|
|
13
|
+
import { dirname, resolve, join } from 'node:path';
|
|
14
|
+
import { fileURLToPath } from 'node:url';
|
|
15
|
+
|
|
16
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
17
|
+
const PKG_ROOT = resolve(__dirname, '..');
|
|
18
|
+
const REPO_ROOT = resolve(PKG_ROOT, '..', '..');
|
|
19
|
+
|
|
20
|
+
const SDK_SRC = resolve(REPO_ROOT, 'harness', 'packages', 'harness-http-client', 'dist');
|
|
21
|
+
const SDK_DST = resolve(PKG_ROOT, 'dist', 'sdk');
|
|
22
|
+
const RUNTIME_TEMPLATE_SRC = resolve(PKG_ROOT, 'runtime-src');
|
|
23
|
+
const RUNTIME_DST = resolve(PKG_ROOT, 'dist', 'runtime');
|
|
24
|
+
const RUNTIME_SDK_DST = resolve(RUNTIME_DST, 'sdk');
|
|
25
|
+
const DIST_ASSETS_DST = resolve(PKG_ROOT, 'dist', 'assets');
|
|
26
|
+
const GATE_RUNTIME_SRC = resolve(REPO_ROOT, 'packages', 'aria-gate-runtime', 'dist');
|
|
27
|
+
const GATE_RUNTIME_DST = resolve(RUNTIME_DST, 'vendor', 'aria-gate-runtime');
|
|
28
|
+
const SDK_GUIDE_SRC = resolve(REPO_ROOT, 'harness', 'packages', 'harness-http-client', 'CLAUDE.md');
|
|
29
|
+
const SDK_SKILLS_SRC = resolve(REPO_ROOT, 'harness', 'packages', 'harness-http-client', 'skills');
|
|
30
|
+
const COGNITIVE_SKILLS_SRC = resolve(PKG_ROOT, 'skills', 'aria-cognition');
|
|
31
|
+
const RUNTIME_DISCIPLINE_DST = resolve(RUNTIME_DST, 'discipline');
|
|
32
|
+
const CONNECTOR_HOOKS_SRC = resolve(PKG_ROOT, 'hooks');
|
|
33
|
+
const OPENCODE_PLUGINS_SRC = resolve(PKG_ROOT, 'opencode-plugins');
|
|
34
|
+
const CLIENT_ONBOARDING_SRC = resolve(PKG_ROOT, 'CLIENT-ONBOARDING.md');
|
|
35
|
+
const REQUIRED_HOOK_FILES = [
|
|
36
|
+
'aria-harness-via-sdk.mjs',
|
|
37
|
+
'aria-pre-tool-gate.mjs',
|
|
38
|
+
'aria-preturn-memory-gate.mjs',
|
|
39
|
+
'aria-stop-gate.mjs',
|
|
40
|
+
'aria-preprompt-consult.mjs',
|
|
41
|
+
'aria-trigger-autolearn.mjs',
|
|
42
|
+
'aria-userprompt-abandon-detect.mjs',
|
|
43
|
+
'aria-agent-handoff.mjs',
|
|
44
|
+
'aria-agent-ledger-merge.mjs',
|
|
45
|
+
'aria-pre-text-gate.mjs',
|
|
46
|
+
'aria-discovery-record.mjs',
|
|
47
|
+
'aria-outcome-record.mjs',
|
|
48
|
+
'aria-cognition-substrate-binding.mjs',
|
|
49
|
+
'aria-repo-doctrine-gate.mjs',
|
|
50
|
+
'aria-pre-emit-dryrun.mjs',
|
|
51
|
+
'doctrine_trigger_map.json',
|
|
52
|
+
];
|
|
53
|
+
const REQUIRED_HOOK_HELPERS = [
|
|
54
|
+
'lib/canonical-lenses.mjs',
|
|
55
|
+
'lib/gate-audit.mjs',
|
|
56
|
+
];
|
|
57
|
+
const REQUIRED_OPENCODE_PLUGINS = [
|
|
58
|
+
'harness-context',
|
|
59
|
+
'harness-role',
|
|
60
|
+
'harness-gate',
|
|
61
|
+
'harness-stop',
|
|
62
|
+
'harness-outcome',
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
if (!existsSync(SDK_SRC)) {
|
|
66
|
+
console.error(`[bundle-sdk] SDK dist not found at ${SDK_SRC}`);
|
|
67
|
+
console.error('[bundle-sdk] Build the SDK first: cd ../../harness/packages/harness-http-client && npm run build');
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
for (const relativePath of REQUIRED_HOOK_FILES) {
|
|
71
|
+
requirePathExists(join(CONNECTOR_HOOKS_SRC, relativePath), `required hook asset ${relativePath}`);
|
|
72
|
+
}
|
|
73
|
+
for (const relativePath of REQUIRED_HOOK_HELPERS) {
|
|
74
|
+
requirePathExists(join(CONNECTOR_HOOKS_SRC, relativePath), `required hook helper ${relativePath}`);
|
|
75
|
+
}
|
|
76
|
+
for (const pluginName of REQUIRED_OPENCODE_PLUGINS) {
|
|
77
|
+
requirePathExists(join(OPENCODE_PLUGINS_SRC, pluginName), `required OpenCode plugin ${pluginName}`);
|
|
78
|
+
}
|
|
79
|
+
requirePathExists(CLIENT_ONBOARDING_SRC, 'client onboarding guide');
|
|
80
|
+
|
|
81
|
+
// Staleness guard — newest src mtime must not exceed newest dist mtime.
|
|
82
|
+
// Without this, a developer who edits src/ but forgets to `npm run build`
|
|
83
|
+
// silently bundles a previous-generation dist, shipping a broken SDK to
|
|
84
|
+
// every client. Caught in production once (Hamza 2026-04-27): opencode
|
|
85
|
+
// crashed on open because dist was missing spawnSubAgent / mergeSubAgentLedger
|
|
86
|
+
// that existed in src.
|
|
87
|
+
const SDK_SRC_DIR = resolve(REPO_ROOT, 'harness', 'packages', 'harness-http-client', 'src');
|
|
88
|
+
function newestMtimeMs(dir) {
|
|
89
|
+
let newest = 0;
|
|
90
|
+
for (const name of readdirSync(dir)) {
|
|
91
|
+
const p = join(dir, name);
|
|
92
|
+
const s = statSync(p);
|
|
93
|
+
if (s.isDirectory()) {
|
|
94
|
+
const sub = newestMtimeMs(p);
|
|
95
|
+
if (sub > newest) newest = sub;
|
|
96
|
+
} else if (s.mtimeMs > newest) {
|
|
97
|
+
newest = s.mtimeMs;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return newest;
|
|
101
|
+
}
|
|
102
|
+
if (existsSync(SDK_SRC_DIR)) {
|
|
103
|
+
const srcNewest = newestMtimeMs(SDK_SRC_DIR);
|
|
104
|
+
const distNewest = newestMtimeMs(SDK_SRC);
|
|
105
|
+
if (srcNewest > distNewest) {
|
|
106
|
+
console.error(`[bundle-sdk] SDK dist is older than src (src: ${new Date(srcNewest).toISOString()}, dist: ${new Date(distNewest).toISOString()})`);
|
|
107
|
+
console.error('[bundle-sdk] Refusing to bundle a stale dist. Build the SDK first:');
|
|
108
|
+
console.error('[bundle-sdk] cd ../../harness/packages/harness-http-client && npm run build');
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (!existsSync(SDK_DST)) {
|
|
114
|
+
mkdirSync(SDK_DST, { recursive: true });
|
|
115
|
+
}
|
|
116
|
+
if (existsSync(RUNTIME_DST)) {
|
|
117
|
+
rmSync(RUNTIME_DST, { recursive: true, force: true });
|
|
118
|
+
}
|
|
119
|
+
mkdirSync(RUNTIME_DST, { recursive: true });
|
|
120
|
+
|
|
121
|
+
function copyTree(srcDir, dstDir) {
|
|
122
|
+
mkdirSync(dstDir, { recursive: true });
|
|
123
|
+
for (const name of readdirSync(srcDir)) {
|
|
124
|
+
const src = join(srcDir, name);
|
|
125
|
+
const stat = statSync(src);
|
|
126
|
+
const dst = join(dstDir, name);
|
|
127
|
+
if (stat.isDirectory()) {
|
|
128
|
+
copyTree(src, dst);
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
copyFileSync(src, dst);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function requirePathExists(targetPath, label) {
|
|
136
|
+
if (!existsSync(targetPath)) {
|
|
137
|
+
console.error(`[bundle-sdk] ${label} missing at ${targetPath}`);
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function countFilesRecursive(dir) {
|
|
143
|
+
let count = 0;
|
|
144
|
+
for (const name of readdirSync(dir)) {
|
|
145
|
+
const target = join(dir, name);
|
|
146
|
+
const stat = statSync(target);
|
|
147
|
+
if (stat.isDirectory()) {
|
|
148
|
+
count += countFilesRecursive(target);
|
|
149
|
+
} else {
|
|
150
|
+
count++;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return count;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
let copied = 0;
|
|
157
|
+
for (const name of readdirSync(SDK_SRC)) {
|
|
158
|
+
const src = join(SDK_SRC, name);
|
|
159
|
+
if (!statSync(src).isFile()) continue;
|
|
160
|
+
const dst = join(SDK_DST, name);
|
|
161
|
+
copyFileSync(src, dst);
|
|
162
|
+
mkdirSync(RUNTIME_SDK_DST, { recursive: true });
|
|
163
|
+
copyFileSync(src, join(RUNTIME_SDK_DST, name));
|
|
164
|
+
copied++;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Sanity-check: the SDK is ESM with a top-level export of HTTPHarnessClient.
|
|
168
|
+
// If the bundled index.js doesn't export the class name, something's wrong.
|
|
169
|
+
const indexJsPath = join(SDK_DST, 'index.js');
|
|
170
|
+
if (!existsSync(indexJsPath)) {
|
|
171
|
+
console.error(`[bundle-sdk] index.js missing in bundled SDK at ${indexJsPath}`);
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
const indexJs = readFileSync(indexJsPath, 'utf8');
|
|
175
|
+
if (!/export\s+class\s+HTTPHarnessClient/.test(indexJs)) {
|
|
176
|
+
console.error('[bundle-sdk] bundled SDK does not export HTTPHarnessClient — abort');
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Symbol-coverage guard — every public async method declared in src/index.ts
|
|
181
|
+
// must appear in the bundled dist. Catches "tsc emitted, but emitted from a
|
|
182
|
+
// stale TS state and skipped new methods" or "src has new method, dist
|
|
183
|
+
// doesn't". Pairs with the staleness mtime guard above.
|
|
184
|
+
const SDK_SRC_INDEX = resolve(REPO_ROOT, 'harness', 'packages', 'harness-http-client', 'src', 'index.ts');
|
|
185
|
+
if (existsSync(SDK_SRC_INDEX)) {
|
|
186
|
+
const srcTs = readFileSync(SDK_SRC_INDEX, 'utf8');
|
|
187
|
+
const publicAsyncRx = /^\s{2}async\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*[(<]/gm;
|
|
188
|
+
const expected = new Set();
|
|
189
|
+
for (const m of srcTs.matchAll(publicAsyncRx)) {
|
|
190
|
+
expected.add(m[1]);
|
|
191
|
+
}
|
|
192
|
+
const missing = [];
|
|
193
|
+
for (const name of expected) {
|
|
194
|
+
const memberRx = new RegExp(`\\basync\\s+${name}\\s*\\(`);
|
|
195
|
+
if (!memberRx.test(indexJs)) missing.push(name);
|
|
196
|
+
}
|
|
197
|
+
if (missing.length > 0) {
|
|
198
|
+
console.error(`[bundle-sdk] bundled SDK missing methods present in src: ${missing.join(', ')}`);
|
|
199
|
+
console.error('[bundle-sdk] Rebuild the SDK before bundling: cd ../../harness/packages/harness-http-client && npm run build');
|
|
200
|
+
process.exit(1);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Write a tiny package marker so hooks can detect "yes, the SDK is here"
|
|
205
|
+
// without false-positiving on an empty directory.
|
|
206
|
+
writeFileSync(
|
|
207
|
+
join(SDK_DST, 'BUNDLED.json'),
|
|
208
|
+
JSON.stringify({
|
|
209
|
+
bundledAt: new Date().toISOString(),
|
|
210
|
+
sdkSource: SDK_SRC,
|
|
211
|
+
files: copied,
|
|
212
|
+
}, null, 2) + '\n',
|
|
213
|
+
);
|
|
214
|
+
writeFileSync(
|
|
215
|
+
join(RUNTIME_SDK_DST, 'BUNDLED.json'),
|
|
216
|
+
JSON.stringify({
|
|
217
|
+
bundledAt: new Date().toISOString(),
|
|
218
|
+
sdkSource: SDK_SRC,
|
|
219
|
+
files: copied,
|
|
220
|
+
}, null, 2) + '\n',
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
// package.json with type=module so Node loads index.js as ESM without
|
|
224
|
+
// the "MODULE_TYPELESS_PACKAGE_JSON" perf warning when hooks dynamic-
|
|
225
|
+
// import the SDK from outside any node_modules tree.
|
|
226
|
+
writeFileSync(
|
|
227
|
+
join(SDK_DST, 'package.json'),
|
|
228
|
+
JSON.stringify({
|
|
229
|
+
name: '@aria/harness-http-client-bundled',
|
|
230
|
+
version: '0.0.0-bundled',
|
|
231
|
+
type: 'module',
|
|
232
|
+
main: 'index.js',
|
|
233
|
+
types: 'index.d.ts',
|
|
234
|
+
private: true,
|
|
235
|
+
}, null, 2) + '\n',
|
|
236
|
+
);
|
|
237
|
+
writeFileSync(
|
|
238
|
+
join(RUNTIME_SDK_DST, 'package.json'),
|
|
239
|
+
JSON.stringify({
|
|
240
|
+
name: '@aria/harness-http-client-bundled',
|
|
241
|
+
version: '0.0.0-bundled',
|
|
242
|
+
type: 'module',
|
|
243
|
+
main: 'index.js',
|
|
244
|
+
types: 'index.d.ts',
|
|
245
|
+
private: true,
|
|
246
|
+
}, null, 2) + '\n',
|
|
247
|
+
);
|
|
248
|
+
writeFileSync(
|
|
249
|
+
join(RUNTIME_DST, 'package.json'),
|
|
250
|
+
JSON.stringify({
|
|
251
|
+
name: '@aria/runtime-bundled',
|
|
252
|
+
version: '0.0.0-bundled',
|
|
253
|
+
type: 'module',
|
|
254
|
+
private: true,
|
|
255
|
+
}, null, 2) + '\n',
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
if (!existsSync(RUNTIME_TEMPLATE_SRC)) {
|
|
259
|
+
console.error(`[bundle-sdk] runtime-src missing at ${RUNTIME_TEMPLATE_SRC}`);
|
|
260
|
+
process.exit(1);
|
|
261
|
+
}
|
|
262
|
+
copyTree(RUNTIME_TEMPLATE_SRC, RUNTIME_DST);
|
|
263
|
+
|
|
264
|
+
if (!existsSync(GATE_RUNTIME_SRC)) {
|
|
265
|
+
console.error(`[bundle-sdk] gate-runtime dist not found at ${GATE_RUNTIME_SRC}`);
|
|
266
|
+
console.error('[bundle-sdk] Build the gate runtime first: cd ../aria-gate-runtime && npm run build');
|
|
267
|
+
process.exit(1);
|
|
268
|
+
}
|
|
269
|
+
copyTree(GATE_RUNTIME_SRC, GATE_RUNTIME_DST);
|
|
270
|
+
writeFileSync(
|
|
271
|
+
join(GATE_RUNTIME_DST, 'package.json'),
|
|
272
|
+
JSON.stringify({
|
|
273
|
+
name: '@aria/gate-runtime-bundled',
|
|
274
|
+
version: '0.0.0-bundled',
|
|
275
|
+
main: 'index.js',
|
|
276
|
+
private: true,
|
|
277
|
+
}, null, 2) + '\n',
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
mkdirSync(RUNTIME_DISCIPLINE_DST, { recursive: true });
|
|
281
|
+
if (existsSync(SDK_GUIDE_SRC)) {
|
|
282
|
+
copyFileSync(SDK_GUIDE_SRC, join(RUNTIME_DISCIPLINE_DST, 'CLAUDE.md'));
|
|
283
|
+
}
|
|
284
|
+
if (existsSync(SDK_SKILLS_SRC)) {
|
|
285
|
+
copyTree(SDK_SKILLS_SRC, join(RUNTIME_DISCIPLINE_DST, 'skills', 'aria-harness'));
|
|
286
|
+
}
|
|
287
|
+
if (existsSync(COGNITIVE_SKILLS_SRC)) {
|
|
288
|
+
copyTree(COGNITIVE_SKILLS_SRC, join(RUNTIME_DISCIPLINE_DST, 'skills', 'aria-cognition'));
|
|
289
|
+
}
|
|
290
|
+
if (existsSync(CONNECTOR_HOOKS_SRC)) {
|
|
291
|
+
copyTree(CONNECTOR_HOOKS_SRC, join(DIST_ASSETS_DST, 'hooks'));
|
|
292
|
+
}
|
|
293
|
+
if (existsSync(OPENCODE_PLUGINS_SRC)) {
|
|
294
|
+
copyTree(OPENCODE_PLUGINS_SRC, join(DIST_ASSETS_DST, 'opencode-plugins'));
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
writeFileSync(
|
|
298
|
+
join(RUNTIME_DST, 'manifest.json'),
|
|
299
|
+
JSON.stringify({
|
|
300
|
+
bundledAt: new Date().toISOString(),
|
|
301
|
+
sdkFiles: copied,
|
|
302
|
+
runtimeTemplate: RUNTIME_TEMPLATE_SRC,
|
|
303
|
+
gateRuntimeSource: GATE_RUNTIME_SRC,
|
|
304
|
+
sdkGuideSource: existsSync(SDK_GUIDE_SRC) ? SDK_GUIDE_SRC : null,
|
|
305
|
+
sdkSkillsSource: existsSync(SDK_SKILLS_SRC) ? SDK_SKILLS_SRC : null,
|
|
306
|
+
cognitionSkillsSource: existsSync(COGNITIVE_SKILLS_SRC) ? COGNITIVE_SKILLS_SRC : null,
|
|
307
|
+
packagedAssets: {
|
|
308
|
+
hooks: existsSync(CONNECTOR_HOOKS_SRC) ? join(DIST_ASSETS_DST, 'hooks') : null,
|
|
309
|
+
opencodePlugins: existsSync(OPENCODE_PLUGINS_SRC) ? join(DIST_ASSETS_DST, 'opencode-plugins') : null,
|
|
310
|
+
},
|
|
311
|
+
licenseHeartbeat: '/api/license/heartbeat',
|
|
312
|
+
defaultRuntimeUrl: 'http://127.0.0.1:4319',
|
|
313
|
+
}, null, 2) + '\n',
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
console.log(`[bundle-sdk] copied ${copied} files from ${SDK_SRC} → ${SDK_DST}`);
|
|
317
|
+
console.log(`[bundle-sdk] bundled runtime payload → ${RUNTIME_DST}`);
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
PACKAGE_NAME="${ARIA_CLI_PACKAGE_NAME:-@aria_asi/cli}"
|
|
5
|
+
PUBLIC_REGISTRY="https://registry.npmjs.org"
|
|
6
|
+
GITHUB_REGISTRY="https://npm.pkg.github.com"
|
|
7
|
+
SOURCE="auto"
|
|
8
|
+
TOKEN="${ARIA_ONBOARDING_TOKEN:-}"
|
|
9
|
+
TARBALL_URL="${ARIA_CLI_TARBALL_URL:-}"
|
|
10
|
+
|
|
11
|
+
usage() {
|
|
12
|
+
cat <<'EOF'
|
|
13
|
+
Usage:
|
|
14
|
+
install-client.sh [--token <aria-token>] [--source auto|npm|github|tarball] [--tarball-url <url>]
|
|
15
|
+
|
|
16
|
+
Examples:
|
|
17
|
+
bash install-client.sh --token <aria-token>
|
|
18
|
+
bash install-client.sh --source github --token <aria-token>
|
|
19
|
+
ARIA_CLI_TARBALL_URL=https://example.com/aria_asi-cli.tgz bash install-client.sh --source tarball --token <aria-token>
|
|
20
|
+
EOF
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
while [[ $# -gt 0 ]]; do
|
|
24
|
+
case "$1" in
|
|
25
|
+
--token)
|
|
26
|
+
TOKEN="${2:-}"
|
|
27
|
+
shift 2
|
|
28
|
+
;;
|
|
29
|
+
--source)
|
|
30
|
+
SOURCE="${2:-}"
|
|
31
|
+
shift 2
|
|
32
|
+
;;
|
|
33
|
+
--tarball-url)
|
|
34
|
+
TARBALL_URL="${2:-}"
|
|
35
|
+
shift 2
|
|
36
|
+
;;
|
|
37
|
+
--help|-h)
|
|
38
|
+
usage
|
|
39
|
+
exit 0
|
|
40
|
+
;;
|
|
41
|
+
*)
|
|
42
|
+
echo "Unknown argument: $1" >&2
|
|
43
|
+
usage
|
|
44
|
+
exit 1
|
|
45
|
+
;;
|
|
46
|
+
esac
|
|
47
|
+
done
|
|
48
|
+
|
|
49
|
+
need_cmd() {
|
|
50
|
+
if ! command -v "$1" >/dev/null 2>&1; then
|
|
51
|
+
echo "Missing required command: $1" >&2
|
|
52
|
+
exit 1
|
|
53
|
+
fi
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
need_cmd npm
|
|
57
|
+
need_cmd node
|
|
58
|
+
|
|
59
|
+
if [[ -z "${TOKEN}" ]]; then
|
|
60
|
+
printf 'Aria onboarding token: '
|
|
61
|
+
IFS= read -r TOKEN
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
if [[ -z "${TOKEN}" ]]; then
|
|
65
|
+
echo "Aria token is required." >&2
|
|
66
|
+
exit 1
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
configure_npmrc_from_gh() {
|
|
70
|
+
need_cmd gh
|
|
71
|
+
if ! gh auth status --hostname github.com >/dev/null 2>&1; then
|
|
72
|
+
gh auth login --web --hostname github.com --git-protocol https --scopes read:packages
|
|
73
|
+
else
|
|
74
|
+
gh auth refresh --hostname github.com --scopes read:packages || true
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
local gh_token
|
|
78
|
+
gh_token="$(gh auth token)"
|
|
79
|
+
local npmrc="${HOME}/.npmrc"
|
|
80
|
+
local tmp
|
|
81
|
+
tmp="$(mktemp)"
|
|
82
|
+
if [[ -f "${npmrc}" ]]; then
|
|
83
|
+
grep -v '^@aria_asi:registry=' "${npmrc}" | grep -v '^//npm.pkg.github.com/:_authToken=' | grep -v '^always-auth=true$' > "${tmp}" || true
|
|
84
|
+
fi
|
|
85
|
+
{
|
|
86
|
+
cat "${tmp}" 2>/dev/null || true
|
|
87
|
+
echo "@aria_asi:registry=${GITHUB_REGISTRY}"
|
|
88
|
+
echo "//npm.pkg.github.com/:_authToken=${gh_token}"
|
|
89
|
+
echo "always-auth=true"
|
|
90
|
+
} > "${npmrc}"
|
|
91
|
+
chmod 600 "${npmrc}"
|
|
92
|
+
rm -f "${tmp}"
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
install_from_npm() {
|
|
96
|
+
npm install -g "${PACKAGE_NAME}" --registry "${PUBLIC_REGISTRY}"
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
install_from_github() {
|
|
100
|
+
configure_npmrc_from_gh
|
|
101
|
+
npm install -g "${PACKAGE_NAME}" --registry "${GITHUB_REGISTRY}"
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
install_from_tarball() {
|
|
105
|
+
if [[ -z "${TARBALL_URL}" ]]; then
|
|
106
|
+
echo "Tarball source selected, but no --tarball-url or ARIA_CLI_TARBALL_URL was provided." >&2
|
|
107
|
+
exit 1
|
|
108
|
+
fi
|
|
109
|
+
need_cmd curl
|
|
110
|
+
local tmp_tgz
|
|
111
|
+
tmp_tgz="$(mktemp /tmp/aria_asi-cli-XXXXXX.tgz)"
|
|
112
|
+
curl -fsSL "${TARBALL_URL}" -o "${tmp_tgz}"
|
|
113
|
+
npm install -g "${tmp_tgz}"
|
|
114
|
+
rm -f "${tmp_tgz}"
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
prompt_github_connect() {
|
|
118
|
+
if [[ ! -t 0 ]]; then
|
|
119
|
+
return 0
|
|
120
|
+
fi
|
|
121
|
+
if ! command -v gh >/dev/null 2>&1; then
|
|
122
|
+
return 0
|
|
123
|
+
fi
|
|
124
|
+
|
|
125
|
+
printf '\nOptional: connect GitHub now for repo workflows and private package access? [y/N] '
|
|
126
|
+
local answer
|
|
127
|
+
IFS= read -r answer
|
|
128
|
+
case "${answer,,}" in
|
|
129
|
+
y|yes)
|
|
130
|
+
aria github connect
|
|
131
|
+
;;
|
|
132
|
+
*)
|
|
133
|
+
echo "Skipping GitHub for now. You can run: aria github connect"
|
|
134
|
+
;;
|
|
135
|
+
esac
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if [[ "${SOURCE}" == "auto" ]]; then
|
|
139
|
+
if npm view "${PACKAGE_NAME}" version --registry "${PUBLIC_REGISTRY}" >/dev/null 2>&1; then
|
|
140
|
+
SOURCE="npm"
|
|
141
|
+
elif command -v gh >/dev/null 2>&1; then
|
|
142
|
+
SOURCE="github"
|
|
143
|
+
elif [[ -n "${TARBALL_URL}" ]]; then
|
|
144
|
+
SOURCE="tarball"
|
|
145
|
+
else
|
|
146
|
+
echo "I couldn't find a public npm release, GitHub CLI auth, or tarball URL." >&2
|
|
147
|
+
echo "Use --source github if you have gh, or pass --tarball-url." >&2
|
|
148
|
+
exit 1
|
|
149
|
+
fi
|
|
150
|
+
fi
|
|
151
|
+
|
|
152
|
+
case "${SOURCE}" in
|
|
153
|
+
npm) install_from_npm ;;
|
|
154
|
+
github) install_from_github ;;
|
|
155
|
+
tarball) install_from_tarball ;;
|
|
156
|
+
*)
|
|
157
|
+
echo "Unknown source: ${SOURCE}" >&2
|
|
158
|
+
exit 1
|
|
159
|
+
;;
|
|
160
|
+
esac
|
|
161
|
+
|
|
162
|
+
aria login "${TOKEN}"
|
|
163
|
+
aria connect --force
|
|
164
|
+
prompt_github_connect
|
|
165
|
+
|
|
166
|
+
cat <<'EOF'
|
|
167
|
+
|
|
168
|
+
Aria is installed and connected.
|
|
169
|
+
|
|
170
|
+
Next:
|
|
171
|
+
1. Restart your shell: exec $SHELL -l
|
|
172
|
+
2. Open a brand-new Claude/Codex session
|
|
173
|
+
|
|
174
|
+
Optional GitHub setup later:
|
|
175
|
+
aria github connect
|
|
176
|
+
EOF
|