@ghl-ai/aw 0.1.47-beta.10 → 0.1.47-beta.11
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/push.mjs +59 -6
- package/constants.mjs +8 -0
- package/integrate.mjs +64 -16
- package/package.json +1 -1
package/commands/push.mjs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
existsSync,
|
|
5
|
+
lstatSync,
|
|
5
6
|
statSync,
|
|
6
7
|
readFileSync,
|
|
7
8
|
appendFileSync,
|
|
@@ -36,6 +37,7 @@ import {
|
|
|
36
37
|
AW_DOCS_PUBLISH_DIR,
|
|
37
38
|
AW_DOCS_PUBLIC_BASE_URL,
|
|
38
39
|
AW_CO_AUTHOR,
|
|
40
|
+
defaultAwDocsGithubDocsConfig,
|
|
39
41
|
} from '../constants.mjs';
|
|
40
42
|
import { resolveInput } from '../paths.mjs';
|
|
41
43
|
import { walkRegistryTree, getAllFiles } from '../registry.mjs';
|
|
@@ -172,6 +174,34 @@ function readAwDocsConfig(projectRoot) {
|
|
|
172
174
|
}
|
|
173
175
|
}
|
|
174
176
|
|
|
177
|
+
function writeAwDocsConfigIfChanged(projectRoot, config) {
|
|
178
|
+
const configPath = join(projectRoot, AW_DOCS_DIR, 'config.json');
|
|
179
|
+
const nextText = JSON.stringify(config, null, 2) + '\n';
|
|
180
|
+
const existingText = existsSync(configPath) ? readFileSync(configPath, 'utf8') : '';
|
|
181
|
+
if (existingText !== nextText) {
|
|
182
|
+
mkdirSync(dirname(configPath), { recursive: true });
|
|
183
|
+
writeFileSync(configPath, nextText);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function ensureAwDocsPublishConfig(projectRoot) {
|
|
188
|
+
const config = readAwDocsConfig(projectRoot);
|
|
189
|
+
const defaultGithubDocs = defaultAwDocsGithubDocsConfig();
|
|
190
|
+
const next = {
|
|
191
|
+
...config,
|
|
192
|
+
sync: {
|
|
193
|
+
...(config.sync || {}),
|
|
194
|
+
github_docs: {
|
|
195
|
+
...defaultGithubDocs,
|
|
196
|
+
...(config.sync?.github_docs || {}),
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
writeAwDocsConfigIfChanged(projectRoot, next);
|
|
202
|
+
return next;
|
|
203
|
+
}
|
|
204
|
+
|
|
175
205
|
function repoCloneUrl(repo) {
|
|
176
206
|
const value = String(repo || '').trim();
|
|
177
207
|
if (!value) return AW_DOCS_URL;
|
|
@@ -180,7 +210,7 @@ function repoCloneUrl(repo) {
|
|
|
180
210
|
}
|
|
181
211
|
|
|
182
212
|
function resolveAwDocsPublishConfig(projectRoot) {
|
|
183
|
-
const config =
|
|
213
|
+
const config = ensureAwDocsPublishConfig(projectRoot);
|
|
184
214
|
const githubDocs = config.sync?.github_docs || {};
|
|
185
215
|
const repo = process.env.AW_DOCS_REPO || githubDocs.repo || AW_DOCS_REPO;
|
|
186
216
|
const branch = AW_DOCS_BASE_BRANCH;
|
|
@@ -201,6 +231,24 @@ function resolveAwDocsPublishConfig(projectRoot) {
|
|
|
201
231
|
};
|
|
202
232
|
}
|
|
203
233
|
|
|
234
|
+
function isOnlyUntrackedAwSymlink(status, cloneDir) {
|
|
235
|
+
const lines = status.trim().split('\n').filter(Boolean);
|
|
236
|
+
if (lines.length !== 1 || !/^\?\?\s+\.aw\/?$/.test(lines[0])) return false;
|
|
237
|
+
try {
|
|
238
|
+
return lstatSync(join(cloneDir, '.aw')).isSymbolicLink();
|
|
239
|
+
} catch {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
async function getGitStatus(repoDir) {
|
|
245
|
+
const { stdout } = await execFile('git', ['status', '--porcelain'], {
|
|
246
|
+
cwd: repoDir,
|
|
247
|
+
encoding: 'utf8',
|
|
248
|
+
});
|
|
249
|
+
return stdout;
|
|
250
|
+
}
|
|
251
|
+
|
|
204
252
|
function parseGitHubRepo(remoteUrl) {
|
|
205
253
|
const match = remoteUrl.trim().match(/github\.com[:/]([^/]+)\/(.+?)(?:\.git)?$/);
|
|
206
254
|
if (!match) return null;
|
|
@@ -249,12 +297,17 @@ async function ensureAwDocsRepoClone(home, publishConfig) {
|
|
|
249
297
|
});
|
|
250
298
|
}
|
|
251
299
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
300
|
+
let status = await getGitStatus(cloneDir);
|
|
301
|
+
if (status.trim() && isOnlyUntrackedAwSymlink(status, cloneDir)) {
|
|
302
|
+
rmSync(join(cloneDir, '.aw'), { force: true });
|
|
303
|
+
status = await getGitStatus(cloneDir);
|
|
304
|
+
}
|
|
256
305
|
if (status.trim()) {
|
|
257
|
-
throw new Error(
|
|
306
|
+
throw new Error([
|
|
307
|
+
`AW docs repo worktree is dirty: ${cloneDir}`,
|
|
308
|
+
status.trim(),
|
|
309
|
+
'Clean the cached docs repo or set AW_DOCS_WORKTREE to a clean clone before publishing.',
|
|
310
|
+
].join('\n'));
|
|
258
311
|
}
|
|
259
312
|
|
|
260
313
|
await execFile('git', ['fetch', 'origin'], {
|
package/constants.mjs
CHANGED
|
@@ -34,6 +34,14 @@ export const AW_DOCS_SEED_BRANCH = process.env.AW_DOCS_SEED_BRANCH || 'scaffold'
|
|
|
34
34
|
export const AW_DOCS_PUBLISH_DIR = 'aw_docs';
|
|
35
35
|
export const AW_DOCS_PUBLIC_BASE_URL = process.env.AW_DOCS_PUBLIC_BASE_URL || `https://github.com/${AW_DOCS_REPO}/blob/${AW_DOCS_BASE_BRANCH}`;
|
|
36
36
|
|
|
37
|
+
export function defaultAwDocsGithubDocsConfig() {
|
|
38
|
+
return {
|
|
39
|
+
enabled: true,
|
|
40
|
+
repo: AW_DOCS_REPO,
|
|
41
|
+
dest: AW_DOCS_PUBLISH_DIR,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
37
45
|
/** Persistent git clone root — ~/.aw/ */
|
|
38
46
|
export const AW_HOME = join(homedir(), '.aw');
|
|
39
47
|
|
package/integrate.mjs
CHANGED
|
@@ -13,6 +13,10 @@ import {
|
|
|
13
13
|
resolveRulesSourceDir,
|
|
14
14
|
} from './render-rules.mjs';
|
|
15
15
|
import { isDefaultRoutingEnabled } from './startup.mjs';
|
|
16
|
+
import {
|
|
17
|
+
AW_DOCS_DIR,
|
|
18
|
+
defaultAwDocsGithubDocsConfig,
|
|
19
|
+
} from './constants.mjs';
|
|
16
20
|
|
|
17
21
|
const AW_ROUTER_BRIDGE_HEADER = 'AW Router Bridge';
|
|
18
22
|
const AW_ROUTER_BRIDGE_START_MARKER = '<!-- aw-managed:start router-bridge -->';
|
|
@@ -610,14 +614,14 @@ Run with: \`/platform:eval agent:<slug>\` or \`/platform:eval skill:<slug>\`
|
|
|
610
614
|
* Creates run tracking, learnings, task board, and cache directories.
|
|
611
615
|
*/
|
|
612
616
|
export function initAwDocs(cwd) {
|
|
613
|
-
const awDocsDir = join(cwd,
|
|
614
|
-
|
|
617
|
+
const awDocsDir = join(cwd, AW_DOCS_DIR);
|
|
618
|
+
const alreadyInitialized = existsSync(awDocsDir);
|
|
615
619
|
|
|
616
620
|
const dirs = [
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
+
`${AW_DOCS_DIR}/runs`,
|
|
622
|
+
`${AW_DOCS_DIR}/learnings`,
|
|
623
|
+
`${AW_DOCS_DIR}/tasks`,
|
|
624
|
+
`${AW_DOCS_DIR}/cache`,
|
|
621
625
|
];
|
|
622
626
|
|
|
623
627
|
for (const dir of dirs) {
|
|
@@ -625,7 +629,9 @@ export function initAwDocs(cwd) {
|
|
|
625
629
|
}
|
|
626
630
|
|
|
627
631
|
// STATE.md — workspace state
|
|
628
|
-
|
|
632
|
+
const statePath = join(awDocsDir, 'STATE.md');
|
|
633
|
+
if (!existsSync(statePath)) {
|
|
634
|
+
writeFileSync(statePath, `---
|
|
629
635
|
active_run: null
|
|
630
636
|
last_run: null
|
|
631
637
|
last_workflow: null
|
|
@@ -638,24 +644,60 @@ pending_sync_count: 0
|
|
|
638
644
|
|
|
639
645
|
No active runs. Use \`/aw:<team>-<command>\` to start a workflow.
|
|
640
646
|
`);
|
|
647
|
+
}
|
|
641
648
|
|
|
642
649
|
// config.json — registry paths, sync settings
|
|
643
|
-
|
|
650
|
+
const configPath = join(awDocsDir, 'config.json');
|
|
651
|
+
const defaultConfig = {
|
|
644
652
|
sync: {
|
|
645
653
|
eager: true,
|
|
646
654
|
batch_threshold: 10,
|
|
647
655
|
mcp_memory_enabled: true,
|
|
656
|
+
github_docs: defaultAwDocsGithubDocsConfig(),
|
|
648
657
|
},
|
|
649
658
|
paths: {
|
|
650
|
-
runs:
|
|
651
|
-
learnings:
|
|
652
|
-
tasks:
|
|
653
|
-
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`,
|
|
654
663
|
},
|
|
655
|
-
}
|
|
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
|
+
}
|
|
656
696
|
|
|
657
697
|
// BOARD.md — task board
|
|
658
|
-
|
|
698
|
+
const boardPath = join(awDocsDir, 'tasks', 'BOARD.md');
|
|
699
|
+
if (!existsSync(boardPath)) {
|
|
700
|
+
writeFileSync(boardPath, `---
|
|
659
701
|
tasks: []
|
|
660
702
|
updated_at: null
|
|
661
703
|
---
|
|
@@ -664,11 +706,17 @@ updated_at: null
|
|
|
664
706
|
|
|
665
707
|
No active tasks. Tasks are created during workflow execution.
|
|
666
708
|
`);
|
|
709
|
+
}
|
|
667
710
|
|
|
668
711
|
// _pending-sync.jsonl — sync queue (empty)
|
|
669
|
-
|
|
712
|
+
const pendingSyncPath = join(awDocsDir, 'learnings', '_pending-sync.jsonl');
|
|
713
|
+
if (!existsSync(pendingSyncPath)) {
|
|
714
|
+
writeFileSync(pendingSyncPath, '');
|
|
715
|
+
}
|
|
670
716
|
|
|
671
|
-
|
|
717
|
+
if (!alreadyInitialized) {
|
|
718
|
+
fmt.logSuccess('Orchestration state ready');
|
|
719
|
+
}
|
|
672
720
|
}
|
|
673
721
|
|
|
674
722
|
/**
|