@ghl-ai/aw 0.1.47-beta.7 → 0.1.47-beta.9

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.
@@ -209,7 +209,7 @@ function directoryContainsGeneratedRuleFiles(dirPath, extension) {
209
209
  try {
210
210
  return readdirSync(dirPath, { withFileTypes: true })
211
211
  .filter(entry => entry.isFile() && entry.name.endsWith(extension))
212
- .some(entry => readText(join(dirPath, entry.name)).startsWith(GENERATED_RULE_HEADER));
212
+ .some(entry => readText(join(dirPath, entry.name)).includes(GENERATED_RULE_HEADER));
213
213
  } catch {
214
214
  return false;
215
215
  }
@@ -500,7 +500,7 @@ function listGeneratedRuleFiles(dirPath, extension) {
500
500
  return readdirSync(dirPath, { withFileTypes: true })
501
501
  .filter(entry => entry.isFile() && entry.name.endsWith(extension))
502
502
  .map(entry => join(dirPath, entry.name))
503
- .filter(filePath => readText(filePath).startsWith(GENERATED_RULE_HEADER));
503
+ .filter(filePath => readText(filePath).includes(GENERATED_RULE_HEADER));
504
504
  } catch {
505
505
  return [];
506
506
  }
package/commands/push.mjs CHANGED
@@ -161,6 +161,46 @@ function collectProjectAwDocs(cwd, home) {
161
161
  return { projectRoot, files };
162
162
  }
163
163
 
164
+ function readAwDocsConfig(projectRoot) {
165
+ const configPath = join(projectRoot, AW_DOCS_DIR, 'config.json');
166
+ if (!existsSync(configPath)) return {};
167
+
168
+ try {
169
+ return JSON.parse(readFileSync(configPath, 'utf8'));
170
+ } catch (e) {
171
+ throw new Error(`Invalid ${AW_DOCS_DIR}/config.json: ${e.message}`);
172
+ }
173
+ }
174
+
175
+ function repoCloneUrl(repo) {
176
+ const value = String(repo || '').trim();
177
+ if (!value) return AW_DOCS_URL;
178
+ if (/^(?:https?:\/\/|git@|ssh:\/\/|file:\/\/)/.test(value)) return value;
179
+ return `https://github.com/${value.replace(/\.git$/, '')}.git`;
180
+ }
181
+
182
+ function resolveAwDocsPublishConfig(projectRoot) {
183
+ const config = readAwDocsConfig(projectRoot);
184
+ const githubDocs = config.sync?.github_docs || {};
185
+ const repo = process.env.AW_DOCS_REPO || githubDocs.repo || AW_DOCS_REPO;
186
+ const branch = process.env.AW_DOCS_BASE_BRANCH || githubDocs.branch || AW_DOCS_BASE_BRANCH;
187
+ const repoUrl = process.env.AW_DOCS_REPO_URL || githubDocs.repo_url || repoCloneUrl(repo);
188
+ const dest = safePathSegment(process.env.AW_DOCS_PUBLISH_DIR || githubDocs.dest || AW_DOCS_PUBLISH_DIR, AW_DOCS_PUBLISH_DIR);
189
+ const publicBaseUrl = process.env.AW_DOCS_PUBLIC_BASE_URL
190
+ || githubDocs.teamofone_base_url
191
+ || `https://github.com/${String(repo).replace(/\.git$/, '')}/blob/${branch}`;
192
+
193
+ return {
194
+ enabled: githubDocs.enabled !== false,
195
+ repo,
196
+ repoUrl,
197
+ branch,
198
+ seedBranch: process.env.AW_DOCS_SEED_BRANCH || githubDocs.seed_branch || AW_DOCS_SEED_BRANCH,
199
+ dest,
200
+ publicBaseUrl,
201
+ };
202
+ }
203
+
164
204
  function parseGitHubRepo(remoteUrl) {
165
205
  const match = remoteUrl.trim().match(/github\.com[:/]([^/]+)\/(.+?)(?:\.git)?$/);
166
206
  if (!match) return null;
@@ -200,11 +240,11 @@ async function getProjectSourceRepo(projectRoot) {
200
240
  return `local/${basename(projectRoot)}`;
201
241
  }
202
242
 
203
- async function ensureAwDocsRepoClone(home) {
243
+ async function ensureAwDocsRepoClone(home, publishConfig) {
204
244
  const cloneDir = process.env.AW_DOCS_WORKTREE || join(home, '.aw-ghl-aw-docs');
205
245
 
206
246
  if (!existsSync(join(cloneDir, '.git'))) {
207
- await execFile('git', ['clone', AW_DOCS_URL, cloneDir], {
247
+ await execFile('git', ['clone', publishConfig.repoUrl, cloneDir], {
208
248
  encoding: 'utf8',
209
249
  });
210
250
  }
@@ -222,18 +262,18 @@ async function ensureAwDocsRepoClone(home) {
222
262
  encoding: 'utf8',
223
263
  });
224
264
 
225
- const hasPublishBranch = await remoteBranchExists(cloneDir, AW_DOCS_BASE_BRANCH);
265
+ const hasPublishBranch = await remoteBranchExists(cloneDir, publishConfig.branch);
226
266
  const checkoutStart = hasPublishBranch
227
- ? `origin/${AW_DOCS_BASE_BRANCH}`
228
- : `origin/${AW_DOCS_SEED_BRANCH}`;
267
+ ? `origin/${publishConfig.branch}`
268
+ : `origin/${publishConfig.seedBranch}`;
229
269
 
230
- await execFile('git', ['checkout', '-B', AW_DOCS_BASE_BRANCH, checkoutStart], {
270
+ await execFile('git', ['checkout', '-B', publishConfig.branch, checkoutStart], {
231
271
  cwd: cloneDir,
232
272
  encoding: 'utf8',
233
273
  });
234
274
 
235
275
  if (hasPublishBranch) {
236
- await execFile('git', ['pull', '--ff-only', 'origin', AW_DOCS_BASE_BRANCH], {
276
+ await execFile('git', ['pull', '--ff-only', 'origin', publishConfig.branch], {
237
277
  cwd: cloneDir,
238
278
  encoding: 'utf8',
239
279
  });
@@ -253,8 +293,14 @@ async function remoteBranchExists(repoDir, branchName) {
253
293
  }
254
294
  }
255
295
 
256
- function awDocsRemoteUrl(publishedPath) {
257
- return `${AW_DOCS_PUBLIC_BASE_URL.replace(/\/$/, '')}/${publishedPath.split('/').map(encodeURIComponent).join('/')}`;
296
+ function awDocsRemoteUrl(publishedPath, publishConfig) {
297
+ return `${publishConfig.publicBaseUrl.replace(/\/$/, '')}/${publishedPath.split('/').map(encodeURIComponent).join('/')}`;
298
+ }
299
+
300
+ function awDocsRepositoryUrl(publishedPath, publishConfig) {
301
+ const repo = String(publishConfig.repo || AW_DOCS_REPO).replace(/\.git$/, '');
302
+ if (!repo.includes('/')) return awDocsRemoteUrl(publishedPath, publishConfig);
303
+ return `https://github.com/${repo}/blob/${publishConfig.branch}/${publishedPath.split('/').map(encodeURIComponent).join('/')}`;
258
304
  }
259
305
 
260
306
  function printAwDocsLinks(links, limit = 10) {
@@ -266,12 +312,13 @@ function printAwDocsLinks(links, limit = 10) {
266
312
  }
267
313
  }
268
314
 
269
- function writeAwDocsLinkSummary(projectRoot, links) {
315
+ function writeAwDocsLinkSummary(projectRoot, links, publishConfig) {
270
316
  const summaryPath = join(projectRoot, AW_DOCS_DIR, 'last-publish.json');
271
317
  const payload = {
272
318
  generatedAt: new Date().toISOString(),
273
- branch: AW_DOCS_BASE_BRANCH,
274
- repo: AW_DOCS_REPO,
319
+ branch: publishConfig.branch,
320
+ repo: publishConfig.repo,
321
+ targetPath: publishConfig.dest,
275
322
  links,
276
323
  };
277
324
  try {
@@ -281,13 +328,13 @@ function writeAwDocsLinkSummary(projectRoot, links) {
281
328
  }
282
329
  }
283
330
 
284
- async function commitAndPushAwDocsRepo(docsRepoDir, commitMessage) {
331
+ async function commitAndPushAwDocsRepo(docsRepoDir, { message, branch }) {
285
332
  await execFile('git', ['add', '-A'], { cwd: docsRepoDir, encoding: 'utf8' });
286
- await execFile('git', ['commit', '-m', commitMessage], {
333
+ await execFile('git', ['commit', '-m', message], {
287
334
  cwd: docsRepoDir,
288
335
  encoding: 'utf8',
289
336
  });
290
- await execFile('git', ['push', '-u', 'origin', `HEAD:${AW_DOCS_BASE_BRANCH}`], {
337
+ await execFile('git', ['push', '-u', 'origin', `HEAD:${branch}`], {
291
338
  cwd: docsRepoDir,
292
339
  encoding: 'utf8',
293
340
  });
@@ -301,7 +348,7 @@ function titleForAwDoc(relPath) {
301
348
  return `${label} ${ext}`;
302
349
  }
303
350
 
304
- function updateAwDocsManifest(docsRepoDir, { repoSlug, sourceRepo, githubUsername, docs }) {
351
+ function updateAwDocsManifest(docsRepoDir, { repoSlug, sourceRepo, githubUsername, docs, publishConfig }) {
305
352
  const manifestPath = join(docsRepoDir, 'manifest.json');
306
353
  const manifest = existsSync(manifestPath)
307
354
  ? JSON.parse(readFileSync(manifestPath, 'utf8'))
@@ -320,7 +367,8 @@ function updateAwDocsManifest(docsRepoDir, { repoSlug, sourceRepo, githubUsernam
320
367
  docs: docs.map(doc => ({
321
368
  relPath: doc.relPath,
322
369
  publishedPath: doc.publishedPath,
323
- remoteUrl: awDocsRemoteUrl(doc.publishedPath),
370
+ remoteUrl: awDocsRemoteUrl(doc.publishedPath, publishConfig),
371
+ repositoryUrl: awDocsRepositoryUrl(doc.publishedPath, publishConfig),
324
372
  sha: createHash('sha256').update(readFileSync(join(docsRepoDir, doc.publishedPath))).digest('hex'),
325
373
  syncedAt: now,
326
374
  title: titleForAwDoc(doc.relPath),
@@ -335,22 +383,29 @@ async function publishProjectAwDocs(cwd, home, dryRun) {
335
383
  const { projectRoot, files } = collectProjectAwDocs(cwd, home);
336
384
  if (files.length === 0) return { hasDocs: false, publishedPaths: [] };
337
385
 
386
+ const publishConfig = resolveAwDocsPublishConfig(projectRoot);
387
+ if (!publishConfig.enabled) {
388
+ fmt.logWarn(`${AW_DOCS_DIR}/config.json sync.github_docs.enabled is false; skipping AW docs publish`);
389
+ return { hasDocs: true, skipped: true, publishedPaths: [], links: [] };
390
+ }
391
+
338
392
  const sourceRepo = await getProjectSourceRepo(projectRoot);
339
393
  const repoSlug = repoSlugFromSource(sourceRepo, projectRoot);
340
394
  const githubUsername = safePathSegment(await getGitHubUser(), 'unknown');
341
395
  const docs = files.map(file => ({
342
396
  ...file,
343
- publishedPath: `${AW_DOCS_PUBLISH_DIR}/${repoSlug}/${githubUsername}/${file.relPath}`,
397
+ publishedPath: `${publishConfig.dest}/${repoSlug}/${githubUsername}/${file.relPath}`,
344
398
  }));
345
399
  const publishedPaths = docs.map(doc => doc.publishedPath);
346
400
  const links = docs.map(doc => ({
347
401
  relPath: doc.relPath,
348
402
  publishedPath: doc.publishedPath,
349
- remoteUrl: awDocsRemoteUrl(doc.publishedPath),
403
+ remoteUrl: awDocsRemoteUrl(doc.publishedPath, publishConfig),
404
+ repositoryUrl: awDocsRepositoryUrl(doc.publishedPath, publishConfig),
350
405
  }));
351
406
 
352
407
  if (dryRun) {
353
- fmt.logInfo(`${chalk.bold(files.length)} AW doc${files.length > 1 ? 's' : ''} to publish directly to ${AW_DOCS_REPO}`);
408
+ fmt.logInfo(`${chalk.bold(files.length)} AW doc${files.length > 1 ? 's' : ''} to publish directly to ${publishConfig.repo}`);
354
409
  for (const link of links.slice(0, 40)) {
355
410
  fmt.logMessage(` ${chalk.yellow('AWDOC')}/${link.publishedPath}`);
356
411
  fmt.logMessage(` ${chalk.cyan(link.remoteUrl)}`);
@@ -361,10 +416,10 @@ async function publishProjectAwDocs(cwd, home, dryRun) {
361
416
  }
362
417
 
363
418
  const s = fmt.spinner();
364
- s.start(`Publishing ${files.length} AW doc${files.length > 1 ? 's' : ''} to ${AW_DOCS_REPO}...`);
419
+ s.start(`Publishing ${files.length} AW doc${files.length > 1 ? 's' : ''} to ${publishConfig.repo}...`);
365
420
  try {
366
- const docsRepoDir = await ensureAwDocsRepoClone(home);
367
- rmSync(join(docsRepoDir, AW_DOCS_PUBLISH_DIR, repoSlug, githubUsername), {
421
+ const docsRepoDir = await ensureAwDocsRepoClone(home, publishConfig);
422
+ rmSync(join(docsRepoDir, publishConfig.dest, repoSlug, githubUsername), {
368
423
  recursive: true,
369
424
  force: true,
370
425
  });
@@ -373,7 +428,7 @@ async function publishProjectAwDocs(cwd, home, dryRun) {
373
428
  mkdirSync(dirname(dest), { recursive: true });
374
429
  copyFileSync(doc.absPath, dest);
375
430
  }
376
- updateAwDocsManifest(docsRepoDir, { repoSlug, sourceRepo, githubUsername, docs });
431
+ updateAwDocsManifest(docsRepoDir, { repoSlug, sourceRepo, githubUsername, docs, publishConfig });
377
432
 
378
433
  const { stdout: status } = await execFile('git', ['status', '--porcelain'], {
379
434
  cwd: docsRepoDir,
@@ -381,14 +436,17 @@ async function publishProjectAwDocs(cwd, home, dryRun) {
381
436
  });
382
437
  if (!status.trim()) {
383
438
  s.stop('AW docs already up to date');
384
- writeAwDocsLinkSummary(projectRoot, links);
439
+ writeAwDocsLinkSummary(projectRoot, links, publishConfig);
385
440
  printAwDocsLinks(links);
386
441
  return { hasDocs: true, publishedPaths, links };
387
442
  }
388
443
 
389
- await commitAndPushAwDocsRepo(docsRepoDir, `docs(aw): sync ${repoSlug}/${githubUsername} AW docs`);
390
- writeAwDocsLinkSummary(projectRoot, links);
391
- s.stop(`Published AW docs to ${AW_DOCS_REPO}`);
444
+ await commitAndPushAwDocsRepo(docsRepoDir, {
445
+ message: `docs(aw): sync ${repoSlug}/${githubUsername} AW docs`,
446
+ branch: publishConfig.branch,
447
+ });
448
+ writeAwDocsLinkSummary(projectRoot, links, publishConfig);
449
+ s.stop(`Published AW docs to ${publishConfig.repo}`);
392
450
  printAwDocsLinks(links);
393
451
  return { hasDocs: true, publishedPaths, links };
394
452
  } catch (e) {
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.43";
15
+ export const AW_ECC_TAG = "v1.4.55";
16
16
 
17
17
  const MARKETPLACE_NAME = "aw-marketplace";
18
18
  const PLUGIN_KEY = `aw@${MARKETPLACE_NAME}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ghl-ai/aw",
3
- "version": "0.1.47-beta.7",
3
+ "version": "0.1.47-beta.9",
4
4
  "description": "Agentic Workspace CLI — pull, push & manage agents, skills and commands from the registry",
5
5
  "type": "module",
6
6
  "bin": {