@ghl-ai/aw 0.1.70-beta.3 → 0.1.70-beta.5
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/commands/init.mjs +31 -3
- package/integrations.mjs +82 -7
- package/package.json +1 -1
package/commands/init.mjs
CHANGED
|
@@ -35,7 +35,7 @@ import { loadConfig as ensureTelemetryConfig } from '../telemetry.mjs';
|
|
|
35
35
|
import { installAwEcc, AW_ECC_TAG } from '../ecc.mjs';
|
|
36
36
|
import { removeWorkspaceHookDefaults } from '../codex.mjs';
|
|
37
37
|
import { readHookManifest, pruneStaleHooks, writeHookManifest } from '../hook-cleanup.mjs';
|
|
38
|
-
import { installIntegration, autoInstallIntegrations } from '../integrations.mjs';
|
|
38
|
+
import { installIntegration, autoInstallIntegrations, getSuggestedIntegrationStatuses } from '../integrations.mjs';
|
|
39
39
|
import {
|
|
40
40
|
initPersistentClone,
|
|
41
41
|
isValidClone,
|
|
@@ -77,6 +77,30 @@ function writeHookManifestBestEffort(manifest, context) {
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
function formatIntegrationStatusSummary(statuses, installedNow = []) {
|
|
81
|
+
if (!statuses || statuses.length === 0) return null;
|
|
82
|
+
|
|
83
|
+
const installedNowSet = new Set(installedNow);
|
|
84
|
+
const lines = statuses.map((entry) => {
|
|
85
|
+
if (entry.status === 'installed') {
|
|
86
|
+
const note = installedNowSet.has(entry.label) ? '(installed now)' : '(installed)';
|
|
87
|
+
return ` ${chalk.green('✓')} ${entry.label} ${chalk.dim(note)}`;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (entry.status === 'skipped') {
|
|
91
|
+
const note = entry.reason ? `(skipped: ${entry.reason})` : '(skipped)';
|
|
92
|
+
return ` ${chalk.yellow('!')} ${entry.label} ${chalk.dim(note)}`;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return ` ${chalk.dim('○')} ${entry.label} ${chalk.dim('(not installed)')}`;
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
return [
|
|
99
|
+
` ${chalk.green('✓')} Integrations:`,
|
|
100
|
+
...lines,
|
|
101
|
+
].join('\n');
|
|
102
|
+
}
|
|
103
|
+
|
|
80
104
|
export async function syncEccAfterAwUpdate(updateResult, cwd, { silent = false } = {}) {
|
|
81
105
|
if (updateResult?.status !== 'upgraded' || !updateResult.packageRoot) {
|
|
82
106
|
return { synced: false, reason: updateResult?.reason || updateResult?.status || 'not-upgraded' };
|
|
@@ -487,8 +511,10 @@ export async function initCommand(args) {
|
|
|
487
511
|
|
|
488
512
|
// Auto-install suggested integrations (Codex, Caveman, Graphify, etc) - unless --no-integrations
|
|
489
513
|
let installedIntegrations = [];
|
|
514
|
+
let integrationStatuses = [];
|
|
490
515
|
if (!silent && !skipIntegrations && !isNewSubTeam) {
|
|
491
516
|
installedIntegrations = await autoInstallIntegrations(effectiveNamespace, { silent });
|
|
517
|
+
integrationStatuses = getSuggestedIntegrationStatuses(effectiveNamespace, { home: HOME });
|
|
492
518
|
}
|
|
493
519
|
|
|
494
520
|
if (silent) {
|
|
@@ -511,7 +537,7 @@ export async function initCommand(args) {
|
|
|
511
537
|
? ` ${chalk.green('✓')} Removed ${removedLegacyStartupFiles.length} legacy repo startup file${removedLegacyStartupFiles.length > 1 ? 's' : ''}`
|
|
512
538
|
: null,
|
|
513
539
|
cwd !== HOME && isWorktree(join(cwd, '.aw')) ? ` ${chalk.green('✓')} Project linked` : null,
|
|
514
|
-
|
|
540
|
+
formatIntegrationStatusSummary(integrationStatuses, installedIntegrations),
|
|
515
541
|
].filter(Boolean).join('\n'));
|
|
516
542
|
}
|
|
517
543
|
return;
|
|
@@ -680,8 +706,10 @@ export async function initCommand(args) {
|
|
|
680
706
|
|
|
681
707
|
// Auto-install suggested integrations (Codex, Caveman, Graphify, etc) - unless --no-integrations
|
|
682
708
|
let installedIntegrations = [];
|
|
709
|
+
let integrationStatuses = [];
|
|
683
710
|
if (!silent && !skipIntegrations) {
|
|
684
711
|
installedIntegrations = await autoInstallIntegrations(activeNamespace(), { silent });
|
|
712
|
+
integrationStatuses = getSuggestedIntegrationStatuses(activeNamespace(), { home: HOME });
|
|
685
713
|
}
|
|
686
714
|
|
|
687
715
|
// Offer to update if a newer version is available
|
|
@@ -704,7 +732,7 @@ export async function initCommand(args) {
|
|
|
704
732
|
awUsageHooksReport ? ` ${chalk.green('✓')} ${awUsageHooksReport}` : null,
|
|
705
733
|
` ${chalk.green('✓')} IDE task: auto-sync on workspace open`,
|
|
706
734
|
cwd !== HOME && isWorktree(join(cwd, '.aw')) ? ` ${chalk.green('✓')} Linked in current project` : null,
|
|
707
|
-
|
|
735
|
+
formatIntegrationStatusSummary(integrationStatuses, installedIntegrations),
|
|
708
736
|
'',
|
|
709
737
|
` ${chalk.dim('Existing repos:')} ${chalk.bold('cd <project> && aw link')}`,
|
|
710
738
|
` ${chalk.dim('New clones:')} auto-linked via git hook`,
|
package/integrations.mjs
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
mkdirSync,
|
|
16
16
|
rmSync,
|
|
17
17
|
} from 'node:fs';
|
|
18
|
-
import { join, basename } from 'node:path';
|
|
18
|
+
import { join, basename, delimiter } from 'node:path';
|
|
19
19
|
import { homedir } from 'node:os';
|
|
20
20
|
import * as fmt from './fmt.mjs';
|
|
21
21
|
import { chalk } from './fmt.mjs';
|
|
@@ -36,6 +36,29 @@ function getErrorMessage(error) {
|
|
|
36
36
|
return error instanceof Error ? error.message : String(error);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
function shellQuote(value) {
|
|
40
|
+
return `'${String(value).replaceAll("'", "'\\''")}'`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function installerEnv(home = HOME) {
|
|
44
|
+
const pathEntries = [
|
|
45
|
+
join(home, '.local', 'bin'),
|
|
46
|
+
join(home, '.cargo', 'bin'),
|
|
47
|
+
join(home, 'bin'),
|
|
48
|
+
process.env.PATH || '',
|
|
49
|
+
].filter(Boolean);
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
...process.env,
|
|
53
|
+
HOME: home,
|
|
54
|
+
PATH: pathEntries.join(delimiter),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function posixInstallerCommand(url, runner = 'bash') {
|
|
59
|
+
return `bash -o pipefail -c ${shellQuote(`curl -fsSL ${shellQuote(url)} | ${runner}`)}`;
|
|
60
|
+
}
|
|
61
|
+
|
|
39
62
|
// ────────────────────────────────────────────────────────────────────────────────
|
|
40
63
|
// INTEGRATION REGISTRY
|
|
41
64
|
// ────────────────────────────────────────────────────────────────────────────────
|
|
@@ -76,7 +99,7 @@ export const INTEGRATIONS = {
|
|
|
76
99
|
description: 'CLI proxy that filters/compresses shell output (git, tests, logs) by 60-90%',
|
|
77
100
|
scripts: {
|
|
78
101
|
win32: null, // use WSL fallback
|
|
79
|
-
posix: 'https://raw.githubusercontent.com/rtk-ai/rtk/
|
|
102
|
+
posix: 'https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh',
|
|
80
103
|
},
|
|
81
104
|
postInstall: [
|
|
82
105
|
'rtk init -g', // Claude Code
|
|
@@ -110,11 +133,11 @@ export const INTEGRATIONS = {
|
|
|
110
133
|
posix: null, // no binary — installed entirely via npx below
|
|
111
134
|
},
|
|
112
135
|
postInstall: [
|
|
113
|
-
'npx skills@latest add mattpocock/skills',
|
|
136
|
+
'npx skills@latest add mattpocock/skills --global --all',
|
|
114
137
|
],
|
|
115
138
|
teams: [],
|
|
116
139
|
requiresAuth: false,
|
|
117
|
-
authNote: '
|
|
140
|
+
authNote: 'Installs all bundled skills and agents globally. Then run /setup-matt-pocock-skills once per repo.',
|
|
118
141
|
},
|
|
119
142
|
|
|
120
143
|
// PYTHON CLIs (installed via uv / pipx / pip, then runs post-install hooks)
|
|
@@ -601,6 +624,7 @@ async function runClaudePlugin(installCmd, { silent = false, marketplaceSource =
|
|
|
601
624
|
|
|
602
625
|
async function runUniversalInstaller(integration, key, { silent = false, home = HOME } = {}) {
|
|
603
626
|
const spinner = silent ? null : fmt.spinner();
|
|
627
|
+
const env = installerEnv(home);
|
|
604
628
|
|
|
605
629
|
if (!silent) spinner.start(`Installing ${integration.label} for all detected IDEs...`);
|
|
606
630
|
|
|
@@ -633,7 +657,7 @@ async function runUniversalInstaller(integration, key, { silent = false, home =
|
|
|
633
657
|
}
|
|
634
658
|
|
|
635
659
|
if (wslOk) {
|
|
636
|
-
cmd = `wsl --
|
|
660
|
+
cmd = `wsl -- ${posixInstallerCommand(integration.scripts.posix, 'sh')}`;
|
|
637
661
|
} else if (integration.npmPackage) {
|
|
638
662
|
if (!silent) fmt.logWarn('WSL/bash not available — installing via npm instead');
|
|
639
663
|
cmd = `npm install -g ${integration.npmPackage}`;
|
|
@@ -651,13 +675,14 @@ async function runUniversalInstaller(integration, key, { silent = false, home =
|
|
|
651
675
|
}
|
|
652
676
|
}
|
|
653
677
|
} else {
|
|
654
|
-
cmd =
|
|
678
|
+
cmd = posixInstallerCommand(integration.scripts.posix);
|
|
655
679
|
}
|
|
656
680
|
|
|
657
681
|
if (cmd) {
|
|
658
682
|
await execAsync(cmd, {
|
|
659
683
|
timeout: 5 * 60 * 1000,
|
|
660
684
|
maxBuffer: 20 * 1024 * 1024,
|
|
685
|
+
env,
|
|
661
686
|
});
|
|
662
687
|
}
|
|
663
688
|
|
|
@@ -673,7 +698,11 @@ async function runUniversalInstaller(integration, key, { silent = false, home =
|
|
|
673
698
|
}
|
|
674
699
|
|
|
675
700
|
try {
|
|
676
|
-
await execAsync(finalPostCmd, {
|
|
701
|
+
await execAsync(finalPostCmd, {
|
|
702
|
+
timeout: 60 * 1000,
|
|
703
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
704
|
+
env,
|
|
705
|
+
});
|
|
677
706
|
} catch (e) {
|
|
678
707
|
failedPostInstalls.push(finalPostCmd);
|
|
679
708
|
if (!silent) fmt.logWarn(`Post-install step failed: ${finalPostCmd} — ${getErrorMessage(e)}`);
|
|
@@ -1028,6 +1057,52 @@ export function suggestForTeam(namespace) {
|
|
|
1028
1057
|
.map(([key]) => key);
|
|
1029
1058
|
}
|
|
1030
1059
|
|
|
1060
|
+
export function getSuggestedIntegrationStatuses(namespace, options = {}) {
|
|
1061
|
+
const manifest = readManifest(options.home);
|
|
1062
|
+
|
|
1063
|
+
return suggestForTeam(namespace).map((key) => {
|
|
1064
|
+
const integration = INTEGRATIONS[key];
|
|
1065
|
+
const entry = manifest.installed[key];
|
|
1066
|
+
|
|
1067
|
+
if (entry && entry.status !== 'skipped') {
|
|
1068
|
+
return {
|
|
1069
|
+
key,
|
|
1070
|
+
label: integration.label,
|
|
1071
|
+
type: integration.type,
|
|
1072
|
+
status: 'installed',
|
|
1073
|
+
installedAt: entry.installedAt || null,
|
|
1074
|
+
};
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
if (entry?.status === 'skipped') {
|
|
1078
|
+
return {
|
|
1079
|
+
key,
|
|
1080
|
+
label: integration.label,
|
|
1081
|
+
type: integration.type,
|
|
1082
|
+
status: 'skipped',
|
|
1083
|
+
reason: entry.reason || 'previous setup skipped',
|
|
1084
|
+
};
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
if (integration.requiresGitSubmodule && !hasGitSubmoduleSupport()) {
|
|
1088
|
+
return {
|
|
1089
|
+
key,
|
|
1090
|
+
label: integration.label,
|
|
1091
|
+
type: integration.type,
|
|
1092
|
+
status: 'skipped',
|
|
1093
|
+
reason: 'Git submodule support unavailable',
|
|
1094
|
+
};
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
return {
|
|
1098
|
+
key,
|
|
1099
|
+
label: integration.label,
|
|
1100
|
+
type: integration.type,
|
|
1101
|
+
status: 'pending',
|
|
1102
|
+
};
|
|
1103
|
+
});
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1031
1106
|
// ────────────────────────────────────────────────────────────────────────────────
|
|
1032
1107
|
// AUTO-INSTALL (called from init.mjs - installs suggested integrations)
|
|
1033
1108
|
// ────────────────────────────────────────────────────────────────────────────────
|