@aiwg/cli 2026.10.1 → 2026.10.3
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/agentic/code/providers/capability-matrix.yaml +270 -0
- package/agentic/code/providers/model-capabilities.v1.json +3091 -24
- package/bin/aiwg.mjs +86 -21
- package/dist/src/a2a/codecs.js +9 -0
- package/dist/src/artifacts/corpus-tools/vision-extract.js +105 -15
- package/dist/src/artifacts/repair.js +9 -4
- package/dist/src/channel/manager.mjs +59 -10
- package/dist/src/cli/child-process-result.js +40 -0
- package/dist/src/cli/env.js +38 -16
- package/dist/src/cli/flag-parsing.js +236 -0
- package/dist/src/cli/handlers/decision.js +210 -4
- package/dist/src/cli/handlers/diagnose.js +9 -2
- package/dist/src/cli/handlers/feedback.js +14 -5
- package/dist/src/cli/handlers/init.js +245 -30
- package/dist/src/cli/handlers/mc.js +23 -0
- package/dist/src/cli/handlers/models.js +69 -6
- package/dist/src/cli/handlers/ralph.js +3 -0
- package/dist/src/cli/handlers/refresh.js +16 -0
- package/dist/src/cli/handlers/regenerate.js +14 -0
- package/dist/src/cli/handlers/runtime-info.js +24 -9
- package/dist/src/cli/handlers/script-runner.js +16 -6
- package/dist/src/cli/handlers/session.js +396 -62
- package/dist/src/cli/handlers/sessions.js +146 -40
- package/dist/src/cli/handlers/setup-manifest.js +439 -39
- package/dist/src/cli/handlers/setup.js +139 -39
- package/dist/src/cli/handlers/subcommands.js +3 -1
- package/dist/src/cli/handlers/team.js +18 -8
- package/dist/src/cli/handlers/use.js +13 -0
- package/dist/src/cli/handlers/utilities.js +106 -23
- package/dist/src/cli/prompt-utils.js +72 -0
- package/dist/src/cli/provider-resolution.js +11 -0
- package/dist/src/config/aiwg-config.js +268 -4
- package/dist/src/config/cli.js +146 -19
- package/dist/src/config/dispatch-thresholds-runtime.mjs +38 -0
- package/dist/src/config/project-artifacts-health.mjs +14 -3
- package/dist/src/config/user-config.js +36 -10
- package/dist/src/decision/adapters/jev.js +75 -27
- package/dist/src/decision/driver.js +3 -1
- package/dist/src/decision/entry.js +38 -6
- package/dist/src/decision/heldout/collector.js +10 -1
- package/dist/src/decision/index.js +1 -0
- package/dist/src/decision/interop.js +60 -8
- package/dist/src/decision/ledger.js +839 -0
- package/dist/src/decision/validate.js +6 -3
- package/dist/src/effects/dispatch-verifier.js +252 -0
- package/dist/src/effects/index.js +1 -0
- package/dist/src/features/installer.js +2 -2
- package/dist/src/flow/graph-metadata.js +5 -0
- package/dist/src/gates/providers/loader.js +3 -1
- package/dist/src/installation/manager-command.mjs +1 -1
- package/dist/src/installation/manager.mjs +17 -2
- package/dist/src/lint/runner.js +2 -2
- package/dist/src/mcp/adapters/codex-runtime.js +360 -56
- package/dist/src/mcp/cli.mjs +587 -77
- package/dist/src/mcp/config-file.mjs +279 -0
- package/dist/src/mcp/config-layers.mjs +348 -0
- package/dist/src/mcp/credentials.mjs +484 -0
- package/dist/src/mcp/grok-build-config.mjs +16 -26
- package/dist/src/mcp/helpers.mjs +106 -2
- package/dist/src/mcp/omp-config.mjs +50 -29
- package/dist/src/mcp/profiles.js +97 -23
- package/dist/src/mcp/profiles.mjs +99 -27
- package/dist/src/mcp/registry.js +264 -57
- package/dist/src/mcp/registry.mjs +198 -45
- package/dist/src/mcp/server.mjs +403 -20
- package/dist/src/mcp/toml-string.mjs +9 -0
- package/dist/src/mcp/toml-strip-mcp.mjs +135 -0
- package/dist/src/mcp/tool-filters.mjs +357 -0
- package/dist/src/mcp/tools/agentic-sandbox.mjs +3 -1
- package/dist/src/mcp/tools/decision.mjs +21 -3
- package/dist/src/mcp/tools/orchestration.mjs +38 -0
- package/dist/src/mcp/tools/subsystems.mjs +39 -8
- package/dist/src/mcp/tools/worker-invoke.mjs +1539 -0
- package/dist/src/mcp/tools/worker-shell-control.mjs +258 -0
- package/dist/src/mcp/tools/worker-stdin-runtime.mjs +79 -0
- package/dist/src/memory/project-registry.js +2 -2
- package/dist/src/mission-protocol/codecs.js +639 -1
- package/dist/src/mission-protocol/types.js +110 -0
- package/dist/src/mission-protocol/worker-status.js +2 -0
- package/dist/src/models/config-loader.js +70 -13
- package/dist/src/models/grok-build-models.js +93 -41
- package/dist/src/models/model-capabilities.v1.json +3091 -24
- package/dist/src/models/model-discovery.js +862 -63
- package/dist/src/models/provider-policy.js +625 -11
- package/dist/src/models/qualification-digest.mjs +17 -0
- package/dist/src/models/resolver.js +259 -0
- package/dist/src/models/worker-direct-readiness.js +529 -0
- package/dist/src/models/worker-dispatch-offer.js +169 -0
- package/dist/src/models/worker-health-readiness.js +131 -0
- package/dist/src/models/worker-installation.mjs +879 -0
- package/dist/src/models/wrapper-route.js +18 -0
- package/dist/src/ops/registry.js +9 -14
- package/dist/src/plugins/standalone-packager.js +4 -3
- package/dist/src/process/bounded-child-process.mjs +387 -0
- package/dist/src/process/cli-command.mjs +75 -0
- package/dist/src/providers/capability-matrix.js +8 -0
- package/dist/src/providers/capability-matrix.yaml +270 -0
- package/dist/src/providers/grok-build-headless.js +43 -21
- package/dist/src/providers/provider-definitions.js +9 -1
- package/dist/src/providers/provider-definitions.mjs +9 -2
- package/dist/src/serve/executor-registry.js +16 -24
- package/dist/src/serve/fleet-mission-conductor.js +9 -0
- package/dist/src/serve/mission-conductor.js +9 -0
- package/dist/src/serve/shared-host-scheduler.js +2 -0
- package/dist/src/serve/worker-invocation.js +538 -0
- package/dist/src/serve/worker-stdin-frame.mjs +107 -0
- package/dist/src/sessions/adapter-registry.js +45 -0
- package/dist/src/sessions/adapters/generic.js +37 -3
- package/dist/src/sessions/adapters/grokbot-locator.js +111 -0
- package/dist/src/sessions/adapters/grokbot.js +423 -24
- package/dist/src/sessions/adapters/muse-workspace-scan.js +108 -0
- package/dist/src/sessions/adapters/muse.js +68 -29
- package/dist/src/sessions/adapters/pi.js +1 -0
- package/dist/src/sessions/batch-contracts.js +13 -1
- package/dist/src/sessions/batch-import.js +23 -42
- package/dist/src/sessions/candidates.js +47 -11
- package/dist/src/sessions/contracts.js +35 -0
- package/dist/src/sessions/coverage-preflight.js +134 -0
- package/dist/src/sessions/discovery.js +3 -0
- package/dist/src/sessions/grok-build-cli.js +67 -5
- package/dist/src/sessions/importer.js +24 -8
- package/dist/src/sessions/index.js +2 -0
- package/dist/src/sessions/repository.js +54 -13
- package/dist/src/sessions/workspace-discovery.js +99 -37
- package/dist/src/skills/adapters/clawhub.js +10 -8
- package/dist/src/skills/adapters/openclaw.js +10 -7
- package/dist/src/smiths/context-pipeline/parallelism-section.js +192 -3
- package/dist/src/smiths/context-pipeline/workspace-context.js +116 -9
- package/dist/src/smiths/hook-bridge/codex-translator.js +6 -5
- package/dist/src/smiths/mcpsmith/example.js +1 -1
- package/dist/src/smiths/toolsmith/runtime-discovery.mjs +10 -14
- package/dist/src/storage/backends/logseq.js +68 -7
- package/dist/src/storage/fortemi-qualification-receipt.js +2 -2
- package/dist/src/testing/generators/test-code-generator.js +57 -30
- package/dist/src/uhp/client.js +11 -1
- package/dist/src/uhp/mission.js +5 -0
- package/dist/src/update/checker.mjs +5 -5
- package/dist/src/update/notifier.mjs +54 -2
- package/dist/src/writing/fidelity.js +18 -1
- package/package.json +18 -1
- package/schemas/mission-v1.schema.json +2429 -0
- package/schemas/models/model-catalog.v1.schema.json +301 -0
- package/schemas/models/model-config-compatibility.v1.schema.json +281 -0
- package/schemas/models/model-policy.v1.schema.json +14 -0
- package/schemas/models/provider-model-capabilities.v1.schema.json +1066 -0
- package/tools/_resolve-impl.mjs +39 -0
- package/tools/agents/deploy-agents.mjs +15 -2
- package/tools/agents/providers/base.mjs +49 -32
- package/tools/agents/providers/grokbot.mjs +11 -12
- package/tools/agents/providers/hermes.mjs +6 -3
- package/tools/agents/providers/omp.mjs +5 -2
- package/tools/agents/providers/openclaw-translator.mjs +19 -5
- package/tools/providers/deepseek-harness-transport.mjs +358 -0
- package/tools/providers/omp-transport.mjs +192 -0
- package/tools/ralph-external/lib/claude-adapter.mjs +389 -0
- package/tools/ralph-external/lib/codex-adapter.mjs +432 -0
- package/tools/ralph-external/lib/deepseek-harness-adapter.mjs +397 -0
- package/tools/ralph-external/lib/factory-adapter.mjs +503 -0
- package/tools/ralph-external/lib/muse-adapter.mjs +364 -0
- package/tools/ralph-external/lib/omp-adapter.mjs +315 -0
- package/tools/ralph-external/lib/opencode-adapter.mjs +575 -0
- package/tools/ralph-external/lib/openhuman-adapter.mjs +75 -0
- package/tools/ralph-external/lib/pi-adapter.mjs +333 -0
- package/tools/ralph-external/lib/provider-adapter.mjs +690 -0
- package/tools/ralph-external/lib/worker-health.mjs +439 -0
- package/vscode-extension/schemas/aiwg.config.v1.json +1953 -0
package/tools/_resolve-impl.mjs
CHANGED
|
@@ -46,6 +46,45 @@ function resolveCandidate(root, relativeFromSrc, base) {
|
|
|
46
46
|
*
|
|
47
47
|
* Prefers dist/src/ when present. Set AIWG_RESOLVE_IMPL_FROM=dist or src to
|
|
48
48
|
* force a side during CI/package-layout checks.
|
|
49
|
+
*
|
|
50
|
+
* ## Why a tools/ script that imports src/ needs this (#3062)
|
|
51
|
+
*
|
|
52
|
+
* The npm package ships the `tools/` tree (with maintainer-only exceptions
|
|
53
|
+
* below) and `dist/src/`; it does not ship `src/` itself (see `files` in
|
|
54
|
+
* package.json). A script under `tools/` that imports `../../src/<module>`
|
|
55
|
+
* directly by relative path works from a git checkout (`src/` exists
|
|
56
|
+
* there) but throws `ERR_MODULE_NOT_FOUND` once installed from npm, where
|
|
57
|
+
* only `dist/src/<module>` exists. Any shipped `.mjs` file under `tools/`
|
|
58
|
+
* or `bin/` that needs something under `src/` must resolve it through
|
|
59
|
+
* `importImpl(import.meta.url, '<module-path-relative-to-src>')` instead of
|
|
60
|
+
* a literal relative import, so it finds `dist/src/` when installed and
|
|
61
|
+
* `src/` in a checkout. `test/integration/tools-packed-relative-imports.test.ts`
|
|
62
|
+
* guards this for every relative import already known to resolve.
|
|
63
|
+
*
|
|
64
|
+
* Directories `package.json`'s `files` excludes from the npm package
|
|
65
|
+
* (`tools/benchmarks/`, `tools/ci/`, `tools/contrib/`, `tools/docker/`,
|
|
66
|
+
* `tools/eval/`, `tools/lint/` other than its listed exceptions,
|
|
67
|
+
* `tools/manifest/` other than its listed exception, `tools/qualification/`,
|
|
68
|
+
* and `tools/release/`) are maintainer/CI-only: they never run from an
|
|
69
|
+
* installed package, so a literal `../../src/<module>` import there is
|
|
70
|
+
* fine and does not need `importImpl`. Keep that distinction explicit at
|
|
71
|
+
* each such import site rather than silently mixing styles within one
|
|
72
|
+
* shipped-vs-not-shipped directory. `tools/benchmarks/` and
|
|
73
|
+
* `tools/qualification/` were excluded specifically because nothing
|
|
74
|
+
* shipped ever referenced them (#3062 B/C finding 2) — removing them
|
|
75
|
+
* also trims install size (#3075).
|
|
76
|
+
*
|
|
77
|
+
* `.ts` files directly under `tools/**` that remain shipped (e.g. under
|
|
78
|
+
* `tools/decision/`, `tools/experiments/`) are a separate, still-open
|
|
79
|
+
* case: they are only ever run via `tsx` through an `npm run` script in a
|
|
80
|
+
* checkout (there is no compile step that makes them directly
|
|
81
|
+
* `node`-executable), so they also keep literal `src/**` imports — there
|
|
82
|
+
* is no installed-package code path that reaches them to break. This is
|
|
83
|
+
* pre-existing, documented debt (see the baseline in
|
|
84
|
+
* `test/integration/tools-packed-relative-imports.test.ts`), not a
|
|
85
|
+
* recommendation to add more of it: a new shipped `.ts` tool should
|
|
86
|
+
* resolve through `importImpl` like everything else unless it has the
|
|
87
|
+
* same checkout-only justification.
|
|
49
88
|
*/
|
|
50
89
|
export function resolveImpl(callerUrl, relativeFromSrc) {
|
|
51
90
|
const root = findPackageRoot(callerUrl);
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
* Options:
|
|
12
12
|
* --source <path> Source directory (defaults to repo root)
|
|
13
13
|
* --target <path> Target directory (defaults to cwd)
|
|
14
|
+
* --scope <user|project> Deployment scope (default: project)
|
|
15
|
+
* --user Shorthand for --scope user
|
|
14
16
|
* --mode <type> Deployment mode: general, sdlc, marketing (alias: mmk), media-curator, research, both, or all (default)
|
|
15
17
|
* --deploy-commands Deploy commands in addition to agents
|
|
16
18
|
* --deploy-skills Deploy skills in addition to agents
|
|
@@ -472,10 +474,10 @@ function pruneStaleAiwgArtifacts(provider, target, srcRoot, opts, explicitSource
|
|
|
472
474
|
// Argument Parsing
|
|
473
475
|
// ============================================================================
|
|
474
476
|
|
|
475
|
-
function parseArgs() {
|
|
476
|
-
const args = process.argv.slice(2);
|
|
477
|
+
export function parseArgs(args = process.argv.slice(2)) {
|
|
477
478
|
const cfg = {
|
|
478
479
|
source: null,
|
|
480
|
+
userScope: false,
|
|
479
481
|
target: process.cwd(),
|
|
480
482
|
mode: 'all', // 'general', 'sdlc', 'marketing', 'media-curator', 'research', 'both' (legacy), or 'all'
|
|
481
483
|
dryRun: false,
|
|
@@ -521,6 +523,14 @@ function parseArgs() {
|
|
|
521
523
|
if (a === '--source' && args[i + 1]) cfg.source = path.resolve(args[++i]);
|
|
522
524
|
else if (a === '--target' && args[i + 1]) cfg.target = path.resolve(args[++i]);
|
|
523
525
|
else if (a === '--mode' && args[i + 1]) cfg.mode = String(args[++i]).toLowerCase();
|
|
526
|
+
else if (a === '--scope') {
|
|
527
|
+
const scope = args[++i];
|
|
528
|
+
if (scope !== 'user' && scope !== 'project') {
|
|
529
|
+
throw new Error(`--scope expected 'user' or 'project', got '${scope ?? '(missing)'}'`);
|
|
530
|
+
}
|
|
531
|
+
cfg.userScope = scope === 'user';
|
|
532
|
+
}
|
|
533
|
+
else if (a === '--user') cfg.userScope = true;
|
|
524
534
|
else if (a === '--dry-run') cfg.dryRun = true;
|
|
525
535
|
else if (a === '--force') cfg.force = true;
|
|
526
536
|
else if ((a === '--provider' || a === '--platform') && args[i + 1]) cfg.provider = String(args[++i]).toLowerCase();
|
|
@@ -577,6 +587,8 @@ Usage:
|
|
|
577
587
|
Options:
|
|
578
588
|
--source <path> Source directory (defaults to repo root)
|
|
579
589
|
--target <path> Target directory (defaults to cwd)
|
|
590
|
+
--scope <user|project> Deployment scope (default: project)
|
|
591
|
+
--user Shorthand for --scope user
|
|
580
592
|
--mode <type> Deployment mode: general, sdlc, marketing (alias: mmk), media-curator, research, both, or all (default)
|
|
581
593
|
--deploy-commands Deploy commands in addition to agents
|
|
582
594
|
--deploy-skills Deploy skills in addition to agents
|
|
@@ -1000,6 +1012,7 @@ export async function main() {
|
|
|
1000
1012
|
const opts = {
|
|
1001
1013
|
srcRoot,
|
|
1002
1014
|
target: cfg.target,
|
|
1015
|
+
...(cfg.userScope ? { userScope: true } : {}),
|
|
1003
1016
|
mode: cfg.mode,
|
|
1004
1017
|
// Provider aliases are selectors, not artifact identities. Passing the
|
|
1005
1018
|
// canonical id keeps generated frontmatter byte-identical for devin,
|
|
@@ -11,10 +11,13 @@
|
|
|
11
11
|
import realFs from 'fs';
|
|
12
12
|
import path from 'path';
|
|
13
13
|
import os from 'os';
|
|
14
|
+
import yaml from 'yaml';
|
|
14
15
|
import { classifyModelRole } from './model-role.mjs';
|
|
15
16
|
import { createHash } from 'crypto';
|
|
16
17
|
import { createRequire } from 'module';
|
|
17
|
-
import {
|
|
18
|
+
import { importImpl } from '../../_resolve-impl.mjs';
|
|
19
|
+
|
|
20
|
+
const { boundedExecFileSync } = await importImpl(import.meta.url, 'process/bounded-child-process.mjs');
|
|
18
21
|
|
|
19
22
|
// Use graceful-fs to prevent EMFILE crashes on systems with low ulimit.
|
|
20
23
|
// graceful-fs queues open() calls when FD pressure is detected and retries
|
|
@@ -376,41 +379,38 @@ const PROVIDER_TO_PLATFORM = {
|
|
|
376
379
|
|
|
377
380
|
/**
|
|
378
381
|
* Parse the platforms: field from a SKILL.md frontmatter block.
|
|
379
|
-
*
|
|
380
|
-
* Returns null if
|
|
381
|
-
* Returns an empty array
|
|
382
|
+
* Accepts a string or a list of strings; all alone means unrestricted.
|
|
383
|
+
* Returns null if platforms is missing, or no frontmatter is present.
|
|
384
|
+
* Returns an empty array for malformed frontmatter or invalid platforms.
|
|
382
385
|
*/
|
|
383
386
|
export function parseSkillPlatforms(content) {
|
|
384
|
-
|
|
385
|
-
if (
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
// Inline array: platforms: [claude-code, codex] or platforms: [all]
|
|
390
|
-
const inlineMatch = fm.match(/^platforms:\s*\[([^\]]*)\]/m);
|
|
391
|
-
if (inlineMatch) {
|
|
392
|
-
const items = inlineMatch[1].split(',').map(s => s.trim()).filter(Boolean);
|
|
393
|
-
if (items.length === 0 || (items.length === 1 && items[0] === 'all')) return null;
|
|
394
|
-
return items;
|
|
387
|
+
// A leading UTF-8 BOM must not hide the frontmatter (and its restrictions).
|
|
388
|
+
if (content.charCodeAt(0) === 0xfeff) content = content.slice(1);
|
|
389
|
+
const fmMatch = content.match(/^---\r?\n([\s\S]*?)^---[ \t]*(?:\r?\n|$)/m);
|
|
390
|
+
if (!fmMatch || fmMatch.index !== 0) {
|
|
391
|
+
return /^---[ \t]*(?:\r?\n|$)/.test(content) ? [] : null;
|
|
395
392
|
}
|
|
396
393
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
.map(line => line.match(/^[ \t]+-[ \t]+(\S+)/)?.[1])
|
|
406
|
-
.filter(Boolean);
|
|
407
|
-
return items.length > 0 ? items : null;
|
|
394
|
+
let metadata;
|
|
395
|
+
try {
|
|
396
|
+
const document = yaml.parseDocument(fmMatch[1]);
|
|
397
|
+
if (document.errors.length > 0) return [];
|
|
398
|
+
if (!document.contents) return null; // Empty frontmatter has no restrictions.
|
|
399
|
+
metadata = document.toJS();
|
|
400
|
+
} catch {
|
|
401
|
+
return [];
|
|
408
402
|
}
|
|
403
|
+
if (!metadata || typeof metadata !== 'object' || Array.isArray(metadata)) return [];
|
|
404
|
+
// The yaml package leaves merge keys unresolved, so platforms could arrive only
|
|
405
|
+
// through `<<`; without an explicit key that is ambiguous, so fail closed.
|
|
406
|
+
if (!Object.hasOwn(metadata, 'platforms')) return Object.hasOwn(metadata, '<<') ? [] : null;
|
|
409
407
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
408
|
+
const platforms = metadata.platforms;
|
|
409
|
+
const items = typeof platforms === 'string' ? [platforms] : platforms;
|
|
410
|
+
if (!Array.isArray(items) || !items.every(item => typeof item === 'string')) return [];
|
|
411
|
+
const normalized = items.map(item => item.trim());
|
|
412
|
+
if (normalized.some(item => !item)) return [];
|
|
413
|
+
return normalized.length === 1 && normalized[0] === 'all' ? null : normalized;
|
|
414
414
|
}
|
|
415
415
|
|
|
416
416
|
/**
|
|
@@ -1811,7 +1811,7 @@ export function buildRemotesTopologyBlock(targetDir) {
|
|
|
1811
1811
|
|
|
1812
1812
|
function getUrl(remote) {
|
|
1813
1813
|
try {
|
|
1814
|
-
return
|
|
1814
|
+
return boundedExecFileSync('git', ['-C', targetDir, 'remote', 'get-url', '--', remote], 'quick', {
|
|
1815
1815
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
1816
1816
|
encoding: 'utf8',
|
|
1817
1817
|
}).trim();
|
|
@@ -2350,7 +2350,7 @@ export function getAddonCommandFiles(srcRoot, excludeAddons = [], options = {})
|
|
|
2350
2350
|
}
|
|
2351
2351
|
|
|
2352
2352
|
/**
|
|
2353
|
-
* Get
|
|
2353
|
+
* Get skill directories from a direct addon/framework source or all addons
|
|
2354
2354
|
* @param {string} srcRoot - Source root directory
|
|
2355
2355
|
* @param {string[]} excludeAddons - Addon names to exclude (default: none)
|
|
2356
2356
|
* @returns {string[]} - Array of skill directory paths
|
|
@@ -2358,6 +2358,8 @@ export function getAddonCommandFiles(srcRoot, excludeAddons = [], options = {})
|
|
|
2358
2358
|
export function getAddonSkillDirs(srcRoot, excludeAddons = []) {
|
|
2359
2359
|
const addons = discoverAddons(srcRoot);
|
|
2360
2360
|
const dirs = [];
|
|
2361
|
+
const directDir = getDirectSourceDir(srcRoot, excludeAddons);
|
|
2362
|
+
if (directDir) dirs.push(...listSkillDirs(directDir));
|
|
2361
2363
|
|
|
2362
2364
|
for (const addon of addons) {
|
|
2363
2365
|
if (excludeAddons.includes(addon.name)) continue;
|
|
@@ -2371,6 +2373,21 @@ export function getAddonSkillDirs(srcRoot, excludeAddons = []) {
|
|
|
2371
2373
|
return dirs;
|
|
2372
2374
|
}
|
|
2373
2375
|
|
|
2376
|
+
// `aiwg use <addon>` passes the component itself as --source. Keep bulk
|
|
2377
|
+
// repository discovery unchanged, even if the repo has a top-level skills/.
|
|
2378
|
+
function getDirectSourceDir(srcRoot, excludeAddons) {
|
|
2379
|
+
if (fs.existsSync(path.join(srcRoot, 'agentic', 'code')) ||
|
|
2380
|
+
excludeAddons.includes(path.basename(path.resolve(srcRoot)))) return null;
|
|
2381
|
+
const dir = path.join(srcRoot, 'skills');
|
|
2382
|
+
if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) return null;
|
|
2383
|
+
const relative = path.relative(fs.realpathSync(srcRoot), fs.realpathSync(dir));
|
|
2384
|
+
if (relative === '..' || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
|
|
2385
|
+
console.warn(`Warning: Skipping direct skills directory ${dir}: resolves outside source root ${srcRoot}`);
|
|
2386
|
+
return null;
|
|
2387
|
+
}
|
|
2388
|
+
return dir;
|
|
2389
|
+
}
|
|
2390
|
+
|
|
2374
2391
|
/**
|
|
2375
2392
|
* Get all rule files from all addons
|
|
2376
2393
|
* @param {string} srcRoot - Source root directory
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Grok Bot provider (
|
|
2
|
+
* Grok Bot provider (stable).
|
|
3
3
|
*
|
|
4
4
|
* Discover-first project bridge + fail-closed user skill root.
|
|
5
5
|
* Never targets `.cursor/**` or invents `~/.grokbot`.
|
|
@@ -127,21 +127,18 @@ export function deployRules() {
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
/**
|
|
130
|
-
* Deploy skills only
|
|
130
|
+
* Deploy skills only at user scope with AIWG_GROKBOT_SKILLS_DIR configured.
|
|
131
131
|
* Kernel → configured root; standard → index/discovery unless --copy-all
|
|
132
132
|
* (then `<root>/.aiwg/skills`).
|
|
133
133
|
*/
|
|
134
134
|
export function deploySkills(skillDirs, targetDir, opts = {}) {
|
|
135
|
-
|
|
136
|
-
if (!root) {
|
|
135
|
+
if (opts.userScope !== true && opts.scope !== 'user') {
|
|
137
136
|
if (!opts.quiet) {
|
|
138
|
-
console.log(
|
|
139
|
-
`\n Grok Bot: skipping native skill copy (${SKILLS_DIR_ENV} unset). ` +
|
|
140
|
-
'Skills remain available via aiwg discover / aiwg show.',
|
|
141
|
-
);
|
|
137
|
+
console.log('\n Grok Bot: project bridge only; native skills require --scope user.');
|
|
142
138
|
}
|
|
143
139
|
return 0;
|
|
144
140
|
}
|
|
141
|
+
const root = assertUserScopeConfigured(opts);
|
|
145
142
|
|
|
146
143
|
if (root.includes(`${path.sep}.cursor${path.sep}`) || root.endsWith(`${path.sep}.cursor`) || root.includes('/.cursor/') || root.endsWith('/.cursor')) {
|
|
147
144
|
throw new Error(
|
|
@@ -178,14 +175,14 @@ export async function postDeploy(targetDir, opts = {}) {
|
|
|
178
175
|
}
|
|
179
176
|
if (!opts.quiet) {
|
|
180
177
|
const root = resolveGrokbotSkillsDir(opts.env || process.env);
|
|
181
|
-
if (root) {
|
|
178
|
+
if (root && (opts.userScope === true || opts.scope === 'user')) {
|
|
182
179
|
console.log(
|
|
183
180
|
'Grok Bot: after deploy, start a new agent chat or re-read skills. ' +
|
|
184
181
|
'Live refresh is not claimed until product behavior is verified.',
|
|
185
182
|
);
|
|
186
183
|
} else {
|
|
187
184
|
console.log(
|
|
188
|
-
`Grok Bot: project bridge only.
|
|
185
|
+
`Grok Bot: project bridge only. Use --scope user with ${SKILLS_DIR_ENV} for native skills.`,
|
|
189
186
|
);
|
|
190
187
|
}
|
|
191
188
|
}
|
|
@@ -197,7 +194,7 @@ export function getFileExtension() {
|
|
|
197
194
|
|
|
198
195
|
/**
|
|
199
196
|
* Assert user-scope is allowed. Called when the orchestrator is mirroring
|
|
200
|
-
* to user scope or when opts.scope === 'user'.
|
|
197
|
+
* to user scope or when opts.userScope === true / opts.scope === 'user'.
|
|
201
198
|
*/
|
|
202
199
|
export function assertUserScopeConfigured(opts = {}) {
|
|
203
200
|
const root = resolveGrokbotSkillsDir(opts.env || process.env);
|
|
@@ -227,7 +224,9 @@ export async function deploy(opts = {}) {
|
|
|
227
224
|
console.log(`Mode: ${mode}`);
|
|
228
225
|
const root = resolveGrokbotSkillsDir(opts.env || process.env);
|
|
229
226
|
console.log(
|
|
230
|
-
|
|
227
|
+
(opts.userScope === true || scope === 'user')
|
|
228
|
+
? `User skills root: ${root || `(unset — set ${SKILLS_DIR_ENV})`}`
|
|
229
|
+
: 'Skills: project bridge only (no native skill writes)',
|
|
231
230
|
);
|
|
232
231
|
if (opts.dryRun) console.log('Dry-run: no filesystem mutations');
|
|
233
232
|
}
|
|
@@ -26,7 +26,6 @@ import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
|
|
|
26
26
|
import {
|
|
27
27
|
ensureDir,
|
|
28
28
|
listMdFiles,
|
|
29
|
-
listSkillDirs,
|
|
30
29
|
deploySkillDir,
|
|
31
30
|
deploySkillsWithKernelRouting,
|
|
32
31
|
isKernelSkill,
|
|
@@ -466,7 +465,7 @@ export async function deploy(opts) {
|
|
|
466
465
|
if ((shouldDeploySkills || skillsOnly) && !opts.commandsOnly && !opts.rulesOnly) {
|
|
467
466
|
const allSkillDirs = [];
|
|
468
467
|
|
|
469
|
-
// Addon skills (
|
|
468
|
+
// Addon skills, including a direct addon source (#2873, #3035).
|
|
470
469
|
allSkillDirs.push(...getAddonSkillDirs(srcRoot));
|
|
471
470
|
|
|
472
471
|
// Framework skills
|
|
@@ -665,7 +664,11 @@ export function updateBundledManifest(kernelSkillNames, opts) {
|
|
|
665
664
|
*/
|
|
666
665
|
export function migrateLegacySkillPath(opts) {
|
|
667
666
|
const { dryRun, quiet } = opts;
|
|
668
|
-
|
|
667
|
+
// Resolve through the same HERMES_HOME contract as every other path in
|
|
668
|
+
// this provider (env var first, platform default otherwise): with
|
|
669
|
+
// HERMES_HOME set, the legacy tree lives under that root — never under
|
|
670
|
+
// the process home directory.
|
|
671
|
+
const legacyPath = path.join(getHermesHome(), '.aiwg', 'skills');
|
|
669
672
|
const newPath = paths.skills;
|
|
670
673
|
|
|
671
674
|
let legacyExists = false;
|
|
@@ -3,7 +3,7 @@ import fs from 'node:fs';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { createHash } from 'node:crypto';
|
|
5
5
|
import YAML from 'yaml';
|
|
6
|
-
import {
|
|
6
|
+
import { importImpl } from '../../_resolve-impl.mjs';
|
|
7
7
|
import { collectFrameworkArtifacts, getAddonFiles, isKernelSkill, listMdFiles, listSkillDirs, normalizeDeploymentMode, resolveAiwgRoot } from './base.mjs';
|
|
8
8
|
export const name = 'omp';
|
|
9
9
|
export const aliases = ['oh-my-pi'];
|
|
@@ -18,7 +18,10 @@ function parse(content) {
|
|
|
18
18
|
}
|
|
19
19
|
const render = (metadata, body) => `---\n${YAML.stringify(metadata)}---\n\n${body.trim()}\n`;
|
|
20
20
|
function diagnostic(opts, message) { opts.diagnostics?.push(message); if (!opts.quiet) console.warn(`OMP: ${message}`); }
|
|
21
|
-
|
|
21
|
+
// Resolved through the shared resolver: an installed package ships these
|
|
22
|
+
// modules under dist/src, not src, so a literal path into src fails there.
|
|
23
|
+
const { resolveOmpPaths } = await importImpl(import.meta.url, 'providers/omp-paths.mjs');
|
|
24
|
+
const { transformAgent, mapModel } = await importImpl(import.meta.url, 'providers/omp-agent.mjs');
|
|
22
25
|
export { transformAgent, mapModel };
|
|
23
26
|
const array = value => Array.isArray(value) ? value : typeof value === 'string' ? value.split(',').map(s => s.trim()).filter(Boolean) : [];
|
|
24
27
|
export function transformCommand(src, content, opts = {}) {
|
|
@@ -120,6 +120,20 @@ function parseBehaviorFrontmatter(content) {
|
|
|
120
120
|
return frontmatter;
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
+
/** Encode a complete YAML double-quoted scalar. */
|
|
124
|
+
function yamlString(value) {
|
|
125
|
+
return JSON.stringify(value)
|
|
126
|
+
.replace(/\u0085/g, '\\u0085')
|
|
127
|
+
.replace(/\u2028/g, '\\u2028')
|
|
128
|
+
.replace(/\u2029/g, '\\u2029');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Keep metadata within a single line or block comment. */
|
|
132
|
+
function escapeComment(value) {
|
|
133
|
+
return String(value).replace(/\*\//g, '* /')
|
|
134
|
+
.replace(/[\r\n\u2028\u2029]/g, (char) => '\\u' + char.charCodeAt(0).toString(16).padStart(4, '0'));
|
|
135
|
+
}
|
|
136
|
+
|
|
123
137
|
/**
|
|
124
138
|
* Render the HOOK.md content for OpenClaw's hook loader.
|
|
125
139
|
*
|
|
@@ -133,15 +147,15 @@ function parseBehaviorFrontmatter(content) {
|
|
|
133
147
|
export function renderHookMd(behavior) {
|
|
134
148
|
const events = Object.keys(behavior.hooks || {});
|
|
135
149
|
const eventsList = events.length > 0
|
|
136
|
-
? events.map((e) => ` - ${e}`).join('\n')
|
|
150
|
+
? events.map((e) => ` - ${yamlString(e)}`).join('\n')
|
|
137
151
|
: ' []';
|
|
138
152
|
|
|
139
|
-
const description = (behavior.description || '').
|
|
153
|
+
const description = yamlString((behavior.description || '').slice(0, 200));
|
|
140
154
|
|
|
141
155
|
return [
|
|
142
156
|
'---',
|
|
143
|
-
`name: ${behavior.name}`,
|
|
144
|
-
`description:
|
|
157
|
+
`name: ${yamlString(behavior.name)}`,
|
|
158
|
+
`description: ${description}`,
|
|
145
159
|
'events:',
|
|
146
160
|
eventsList,
|
|
147
161
|
'handler: ./handler.js',
|
|
@@ -193,7 +207,7 @@ export function renderHandlerJs(behavior, scriptsRelDir = './scripts') {
|
|
|
193
207
|
|
|
194
208
|
return `#!/usr/bin/env node
|
|
195
209
|
// Generated by AIWG (PUW-008/PUW-009). Do not edit; regenerated on \`aiwg use\`.
|
|
196
|
-
// Handler for OpenClaw hook \`${behavior.name}\`. Dispatches to scripts in
|
|
210
|
+
// Handler for OpenClaw hook \`${escapeComment(behavior.name)}\`. Dispatches to scripts in
|
|
197
211
|
// ./scripts/ based on the event delivered by OpenClaw's hook loader.
|
|
198
212
|
//
|
|
199
213
|
// Stdin contract (AIWG canonical, per ADR-3 §3):
|