@ghl-ai/aw 0.1.51 → 0.1.53
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/c4/templates/scripts/aw-c4-bootstrap.sh +5 -4
- package/cli.mjs +17 -9
- package/commands/c4.mjs +17 -9
- package/commands/doctor.mjs +2 -2
- package/commands/init.mjs +23 -5
- package/commands/integrations.mjs +268 -0
- package/commands/mcp.mjs +90 -0
- package/commands/nuke.mjs +1 -1
- package/commands/pull.mjs +3 -2
- package/commands/startup.mjs +22 -3
- package/ecc.mjs +1 -1
- package/integrate.mjs +94 -21
- package/integrations/context-mode.mjs +237 -57
- package/integrations.mjs +971 -0
- package/mcp.mjs +132 -16
- package/package.json +4 -3
- package/render-rules.mjs +25 -1
- package/startup.mjs +52 -8
package/commands/startup.mjs
CHANGED
|
@@ -4,6 +4,8 @@ import { join } from 'node:path';
|
|
|
4
4
|
import * as fmt from '../fmt.mjs';
|
|
5
5
|
import { chalk } from '../fmt.mjs';
|
|
6
6
|
import { removeWorkspaceHookDefaults } from '../codex.mjs';
|
|
7
|
+
import { syncHomeHarnessInstructions } from '../integrate.mjs';
|
|
8
|
+
import { renderRules } from '../render-rules.mjs';
|
|
7
9
|
import {
|
|
8
10
|
applyStoredStartupPreferences,
|
|
9
11
|
getStartupStatus,
|
|
@@ -33,19 +35,27 @@ export function routingCommand(args) {
|
|
|
33
35
|
|
|
34
36
|
saveStartupPreferences(mode, HOME);
|
|
35
37
|
const updatedFiles = applyStoredStartupPreferences(HOME);
|
|
38
|
+
const updatedHomeInstructionFiles = syncHomeHarnessInstructions(HOME);
|
|
39
|
+
renderRules(cwd, { homeDir: HOME });
|
|
36
40
|
const status = getStartupStatus(HOME);
|
|
41
|
+
const changedFiles = [...updatedFiles, ...updatedHomeInstructionFiles];
|
|
42
|
+
const effectiveModeLabel = status.effectiveMode === 'enabled' ? chalk.green('enabled') : chalk.yellow('disabled');
|
|
37
43
|
|
|
38
44
|
fmt.outro([
|
|
39
45
|
`⟁ Session routing ${action === 'disable' ? 'disabled' : 'enabled'}`,
|
|
40
46
|
'',
|
|
41
47
|
` ${chalk.green('✓')} Preference saved: ${chalk.dim(status.preferencesPath.replace(`${HOME}/`, '~/'))}`,
|
|
48
|
+
` ${chalk.green('✓')} Default AW router/rules: ${effectiveModeLabel}`,
|
|
42
49
|
` ${chalk.green('✓')} Claude session routing: ${status.claudeDisabled ? chalk.yellow('disabled') : chalk.green('enabled')}`,
|
|
43
50
|
` ${chalk.green('✓')} Codex session routing: ${status.codexHooksEnabled && status.codexSessionStartPresent ? chalk.green('enabled') : chalk.yellow('disabled')}`,
|
|
44
51
|
` ${chalk.green('✓')} Cursor session routing: ${status.cursorSessionStartPresent ? chalk.green('enabled') : chalk.yellow('disabled')}`,
|
|
52
|
+
updatedHomeInstructionFiles.length > 0
|
|
53
|
+
? ` ${chalk.green('✓')} Updated ${updatedHomeInstructionFiles.length} home instruction file${updatedHomeInstructionFiles.length > 1 ? 's' : ''}`
|
|
54
|
+
: null,
|
|
45
55
|
removedLegacyFiles.length > 0
|
|
46
56
|
? ` ${chalk.green('✓')} Removed ${removedLegacyFiles.length} legacy repo routing file${removedLegacyFiles.length > 1 ? 's' : ''} from the current project`
|
|
47
57
|
: null,
|
|
48
|
-
|
|
58
|
+
changedFiles.length === 0
|
|
49
59
|
? ` ${chalk.dim('Note:')} no global routing files needed changes`
|
|
50
60
|
: null,
|
|
51
61
|
].filter(Boolean).join('\n'));
|
|
@@ -53,6 +63,9 @@ export function routingCommand(args) {
|
|
|
53
63
|
|
|
54
64
|
function renderStatus() {
|
|
55
65
|
const status = getStartupStatus(HOME);
|
|
66
|
+
const modeLabel = status.envDisableDefaultRouting
|
|
67
|
+
? `${status.effectiveMode} (${status.envDisableDefaultRoutingName}=1 override; saved preference: ${status.mode})`
|
|
68
|
+
: status.mode;
|
|
56
69
|
const codexStatus = status.codexHooksEnabled && status.codexSessionStartPresent
|
|
57
70
|
? 'enabled'
|
|
58
71
|
: status.codexSessionStartPresent && !status.codexHooksEnabled
|
|
@@ -67,14 +80,20 @@ function renderStatus() {
|
|
|
67
80
|
: status.claudePluginEnabled && !status.claudePluginInstalled
|
|
68
81
|
? 'misconfigured (plugin enabled in settings but not installed)'
|
|
69
82
|
: 'disabled (plugin not installed)';
|
|
83
|
+
const cursorStatus = status.cursorSessionStartPresent
|
|
84
|
+
? 'enabled'
|
|
85
|
+
: status.cursorAnySessionStartPresent
|
|
86
|
+
? 'disabled (non-AW sessionStart hook present)'
|
|
87
|
+
: 'disabled';
|
|
70
88
|
|
|
71
89
|
fmt.note([
|
|
72
|
-
`${chalk.dim('mode:')} ${
|
|
90
|
+
`${chalk.dim('mode:')} ${modeLabel}`,
|
|
73
91
|
`${chalk.dim('prefs:')} ${status.preferencesPath.replace(`${HOME}/`, '~/')}`,
|
|
92
|
+
`${chalk.dim('default AW router/rules:')} ${status.effectiveMode}`,
|
|
74
93
|
`${chalk.dim('claude session routing:')} ${claudeStatus}`,
|
|
75
94
|
`${chalk.dim('codex session routing:')} ${codexStatus}`,
|
|
76
95
|
`${chalk.dim('codex runtime:')} ${status.codexSessionStartScriptInstalled ? 'installed' : 'not installed'}`,
|
|
77
|
-
`${chalk.dim('cursor session routing:')} ${
|
|
96
|
+
`${chalk.dim('cursor session routing:')} ${cursorStatus}`,
|
|
78
97
|
`${chalk.dim('cursor runtime:')} ${status.cursorSessionStartScriptInstalled ? 'installed' : 'not installed'}`,
|
|
79
98
|
process.cwd() !== HOME
|
|
80
99
|
? `${chalk.dim('current repo legacy routing files:')} ${hasLegacyRepoStartupDefaults(process.cwd()) ? 'present' : 'not detected'}`
|
package/ecc.mjs
CHANGED
|
@@ -12,7 +12,7 @@ import { applyStoredStartupPreferences } from "./startup.mjs";
|
|
|
12
12
|
|
|
13
13
|
const AW_ECC_REPO_SSH = "git@github.com:shreyansh-ghl/aw-ecc.git";
|
|
14
14
|
const AW_ECC_REPO_HTTPS = "https://github.com/shreyansh-ghl/aw-ecc.git";
|
|
15
|
-
export const AW_ECC_TAG = "v1.4.
|
|
15
|
+
export const AW_ECC_TAG = "v1.4.61";
|
|
16
16
|
|
|
17
17
|
const MARKETPLACE_NAME = "aw-marketplace";
|
|
18
18
|
const PLUGIN_KEY = `aw@${MARKETPLACE_NAME}`;
|
package/integrate.mjs
CHANGED
|
@@ -12,6 +12,11 @@ import {
|
|
|
12
12
|
renderRules,
|
|
13
13
|
resolveRulesSourceDir,
|
|
14
14
|
} from './render-rules.mjs';
|
|
15
|
+
import { isDefaultRoutingEnabled } from './startup.mjs';
|
|
16
|
+
import {
|
|
17
|
+
AW_DOCS_DIR,
|
|
18
|
+
defaultAwDocsGithubDocsConfig,
|
|
19
|
+
} from './constants.mjs';
|
|
15
20
|
|
|
16
21
|
const AW_ROUTER_BRIDGE_HEADER = 'AW Router Bridge';
|
|
17
22
|
const AW_ROUTER_BRIDGE_START_MARKER = '<!-- aw-managed:start router-bridge -->';
|
|
@@ -146,11 +151,13 @@ function applyManagedInstructionSections(content, file, rulesSections = {}, opti
|
|
|
146
151
|
const rulesHeader = file === 'CLAUDE.md' ? CLAUDE_RULES_HEADER : AGENTS_RULES_HEADER;
|
|
147
152
|
const rulesSection = file === 'CLAUDE.md' ? rulesSections.claudeSection : rulesSections.agentsSection;
|
|
148
153
|
const includeBridge = options.includeBridge !== false;
|
|
154
|
+
const managedBoundary = '<!-- aw-managed: content below is regenerated by `aw init` — put your own content above this line -->';
|
|
149
155
|
|
|
150
156
|
let next = stripLegacyRepoInstructionContent(content, file);
|
|
151
157
|
next = stripManagedBlock(next, AW_ROUTER_BRIDGE_START_MARKER, AW_ROUTER_BRIDGE_END_MARKER);
|
|
152
158
|
next = stripManagedSection(next, AW_ROUTER_BRIDGE_HEADER, [rulesHeader]);
|
|
153
159
|
next = stripManagedSection(next, rulesHeader);
|
|
160
|
+
next = next.split('\n').filter(line => line.trim() !== managedBoundary).join('\n');
|
|
154
161
|
next = next.trimEnd();
|
|
155
162
|
|
|
156
163
|
const sections = [includeBridge ? generateAwRouterBridgeSection() : null, rulesSection].filter(Boolean);
|
|
@@ -161,12 +168,8 @@ function applyManagedInstructionSections(content, file, rulesSections = {}, opti
|
|
|
161
168
|
// Marker tells users (and aw init) where the managed section starts.
|
|
162
169
|
// Everything BEFORE this marker is repo-owned and never touched by aw.
|
|
163
170
|
// Everything AFTER is managed by aw — re-rendered on every aw init.
|
|
164
|
-
const managedBoundary = '<!-- aw-managed: content below is regenerated by `aw init` — put your own content above this line -->';
|
|
165
171
|
const appended = [managedBoundary, ...sections].join('\n\n').trim();
|
|
166
|
-
|
|
167
|
-
// when re-running aw init.
|
|
168
|
-
const cleaned = next.split('\n').filter(line => line.trim() !== managedBoundary).join('\n').trimEnd();
|
|
169
|
-
return cleaned ? `${cleaned}\n\n${appended}\n` : `${appended}\n`;
|
|
172
|
+
return next ? `${next}\n\n${appended}\n` : `${appended}\n`;
|
|
170
173
|
}
|
|
171
174
|
|
|
172
175
|
/**
|
|
@@ -276,7 +279,33 @@ function syncHomeInstructionFile(destPath, file, rulesSection) {
|
|
|
276
279
|
return destPath;
|
|
277
280
|
}
|
|
278
281
|
|
|
282
|
+
function stripManagedHomeInstructionFile(destPath, file) {
|
|
283
|
+
if (!existsSync(destPath)) return null;
|
|
284
|
+
|
|
285
|
+
const existing = readFileSync(destPath, 'utf8');
|
|
286
|
+
const updated = applyManagedInstructionSections(existing, file, {}, { includeBridge: false });
|
|
287
|
+
const emptyDefault = defaultInstructionPreamble(file).trim();
|
|
288
|
+
|
|
289
|
+
if (updated.trim() === '' || updated.trim() === emptyDefault) {
|
|
290
|
+
rmSync(destPath, { force: true });
|
|
291
|
+
return destPath;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (updated === existing) return null;
|
|
295
|
+
|
|
296
|
+
writeFileSync(destPath, updated);
|
|
297
|
+
return destPath;
|
|
298
|
+
}
|
|
299
|
+
|
|
279
300
|
export function syncHomeHarnessInstructions(homeDir = homedir()) {
|
|
301
|
+
if (!isDefaultRoutingEnabled(homeDir)) {
|
|
302
|
+
return [
|
|
303
|
+
stripManagedHomeInstructionFile(join(homeDir, '.codex', 'AGENTS.md'), 'AGENTS.md'),
|
|
304
|
+
stripManagedHomeInstructionFile(join(homeDir, '.claude', 'CLAUDE.md'), 'CLAUDE.md'),
|
|
305
|
+
stripManagedHomeInstructionFile(join(homeDir, '.cursor', 'AGENTS.md'), 'AGENTS.md'),
|
|
306
|
+
].filter(Boolean);
|
|
307
|
+
}
|
|
308
|
+
|
|
280
309
|
const rulesDir = resolveRulesSourceDir(homeDir, { homeDir });
|
|
281
310
|
const codexRulesSection = rulesDir
|
|
282
311
|
? generateAgentsMdRulesSection(rulesDir, {
|
|
@@ -585,14 +614,14 @@ Run with: \`/platform:eval agent:<slug>\` or \`/platform:eval skill:<slug>\`
|
|
|
585
614
|
* Creates run tracking, learnings, task board, and cache directories.
|
|
586
615
|
*/
|
|
587
616
|
export function initAwDocs(cwd) {
|
|
588
|
-
const awDocsDir = join(cwd,
|
|
589
|
-
|
|
617
|
+
const awDocsDir = join(cwd, AW_DOCS_DIR);
|
|
618
|
+
const alreadyInitialized = existsSync(awDocsDir);
|
|
590
619
|
|
|
591
620
|
const dirs = [
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
621
|
+
`${AW_DOCS_DIR}/runs`,
|
|
622
|
+
`${AW_DOCS_DIR}/learnings`,
|
|
623
|
+
`${AW_DOCS_DIR}/tasks`,
|
|
624
|
+
`${AW_DOCS_DIR}/cache`,
|
|
596
625
|
];
|
|
597
626
|
|
|
598
627
|
for (const dir of dirs) {
|
|
@@ -600,7 +629,9 @@ export function initAwDocs(cwd) {
|
|
|
600
629
|
}
|
|
601
630
|
|
|
602
631
|
// STATE.md — workspace state
|
|
603
|
-
|
|
632
|
+
const statePath = join(awDocsDir, 'STATE.md');
|
|
633
|
+
if (!existsSync(statePath)) {
|
|
634
|
+
writeFileSync(statePath, `---
|
|
604
635
|
active_run: null
|
|
605
636
|
last_run: null
|
|
606
637
|
last_workflow: null
|
|
@@ -613,24 +644,60 @@ pending_sync_count: 0
|
|
|
613
644
|
|
|
614
645
|
No active runs. Use \`/aw:<team>-<command>\` to start a workflow.
|
|
615
646
|
`);
|
|
647
|
+
}
|
|
616
648
|
|
|
617
649
|
// config.json — registry paths, sync settings
|
|
618
|
-
|
|
650
|
+
const configPath = join(awDocsDir, 'config.json');
|
|
651
|
+
const defaultConfig = {
|
|
619
652
|
sync: {
|
|
620
653
|
eager: true,
|
|
621
654
|
batch_threshold: 10,
|
|
622
655
|
mcp_memory_enabled: true,
|
|
656
|
+
github_docs: defaultAwDocsGithubDocsConfig(),
|
|
623
657
|
},
|
|
624
658
|
paths: {
|
|
625
|
-
runs:
|
|
626
|
-
learnings:
|
|
627
|
-
tasks:
|
|
628
|
-
cache:
|
|
659
|
+
runs: `${AW_DOCS_DIR}/runs`,
|
|
660
|
+
learnings: `${AW_DOCS_DIR}/learnings`,
|
|
661
|
+
tasks: `${AW_DOCS_DIR}/tasks`,
|
|
662
|
+
cache: `${AW_DOCS_DIR}/cache`,
|
|
629
663
|
},
|
|
630
|
-
}
|
|
664
|
+
};
|
|
665
|
+
let nextConfig = defaultConfig;
|
|
666
|
+
if (existsSync(configPath)) {
|
|
667
|
+
try {
|
|
668
|
+
const existing = JSON.parse(readFileSync(configPath, 'utf8'));
|
|
669
|
+
nextConfig = {
|
|
670
|
+
...existing,
|
|
671
|
+
sync: {
|
|
672
|
+
...defaultConfig.sync,
|
|
673
|
+
...(existing.sync || {}),
|
|
674
|
+
github_docs: {
|
|
675
|
+
...defaultConfig.sync.github_docs,
|
|
676
|
+
...(existing.sync?.github_docs || {}),
|
|
677
|
+
},
|
|
678
|
+
},
|
|
679
|
+
paths: {
|
|
680
|
+
...defaultConfig.paths,
|
|
681
|
+
...(existing.paths || {}),
|
|
682
|
+
},
|
|
683
|
+
};
|
|
684
|
+
} catch (e) {
|
|
685
|
+
fmt.logWarn(`Could not migrate ${AW_DOCS_DIR}/config.json: ${e.message}`);
|
|
686
|
+
nextConfig = null;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
if (nextConfig) {
|
|
690
|
+
const nextConfigText = JSON.stringify(nextConfig, null, 2) + '\n';
|
|
691
|
+
const existingText = existsSync(configPath) ? readFileSync(configPath, 'utf8') : '';
|
|
692
|
+
if (existingText !== nextConfigText) {
|
|
693
|
+
writeFileSync(configPath, nextConfigText);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
631
696
|
|
|
632
697
|
// BOARD.md — task board
|
|
633
|
-
|
|
698
|
+
const boardPath = join(awDocsDir, 'tasks', 'BOARD.md');
|
|
699
|
+
if (!existsSync(boardPath)) {
|
|
700
|
+
writeFileSync(boardPath, `---
|
|
634
701
|
tasks: []
|
|
635
702
|
updated_at: null
|
|
636
703
|
---
|
|
@@ -639,11 +706,17 @@ updated_at: null
|
|
|
639
706
|
|
|
640
707
|
No active tasks. Tasks are created during workflow execution.
|
|
641
708
|
`);
|
|
709
|
+
}
|
|
642
710
|
|
|
643
711
|
// _pending-sync.jsonl — sync queue (empty)
|
|
644
|
-
|
|
712
|
+
const pendingSyncPath = join(awDocsDir, 'learnings', '_pending-sync.jsonl');
|
|
713
|
+
if (!existsSync(pendingSyncPath)) {
|
|
714
|
+
writeFileSync(pendingSyncPath, '');
|
|
715
|
+
}
|
|
645
716
|
|
|
646
|
-
|
|
717
|
+
if (!alreadyInitialized) {
|
|
718
|
+
fmt.logSuccess('Orchestration state ready');
|
|
719
|
+
}
|
|
647
720
|
}
|
|
648
721
|
|
|
649
722
|
/**
|