@aiwg/cli 2026.9.2 → 2026.9.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/antigravity/provider-contract.v1.json +121 -0
- package/agentic/code/providers/capability-matrix.yaml +87 -1
- package/agentic/code/providers/model-capabilities.v1.json +31 -0
- package/agentic/code/providers/model-catalog.v1.json +29 -0
- package/agentic/code/providers/omp/README.md +58 -0
- package/agentic/code/providers/omp/aiwg-bridge.ts +52 -0
- package/dist/src/agents/agent-deployer.js +18 -0
- package/dist/src/agents/agent-packager.js +25 -0
- package/dist/src/artifacts/backends/sqlite-backend.js +18 -10
- package/dist/src/artifacts/query-engine.js +30 -0
- package/dist/src/cli/agent-spawn.js +13 -2
- package/dist/src/cli/handlers/help.js +3 -1
- package/dist/src/cli/handlers/init.js +2 -0
- package/dist/src/cli/handlers/models.js +1 -1
- package/dist/src/cli/handlers/runtime-info.js +8 -1
- package/dist/src/cli/handlers/session.js +5 -4
- package/dist/src/cli/handlers/sessions.js +26 -9
- package/dist/src/cli/handlers/setup.js +9 -2
- package/dist/src/cli/handlers/steward.js +13 -2
- package/dist/src/cli/handlers/subcommands.js +11 -0
- package/dist/src/cli/handlers/team.js +68 -7
- package/dist/src/cli/handlers/use.js +121 -9
- package/dist/src/cli/scope-resolver.js +7 -0
- package/dist/src/config/aiwg-config.js +1 -0
- package/dist/src/dataset/fortemi-live-qualification.d.ts +53 -0
- package/dist/src/dataset/fortemi-live-qualification.js +297 -0
- package/dist/src/dataset/index.d.ts +1 -0
- package/dist/src/dataset/index.js +1 -0
- package/dist/src/mcp/cli.mjs +30 -1
- package/dist/src/mcp/omp-config.mjs +128 -0
- package/dist/src/mcp/registry.js +45 -5
- package/dist/src/mcp/registry.mjs +29 -6
- package/dist/src/models/model-capabilities.v1.json +31 -0
- package/dist/src/models/model-catalog.v1.json +29 -0
- package/dist/src/models/model-discovery.js +46 -5
- package/dist/src/models/provider-policy.js +5 -3
- package/dist/src/plugin/skill-command-translator.js +2 -0
- package/dist/src/providers/capability-matrix.yaml +87 -1
- package/dist/src/providers/omp-agent.mjs +40 -0
- package/dist/src/providers/omp-diagnostics.mjs +15 -0
- package/dist/src/providers/omp-paths.mjs +38 -0
- package/dist/src/providers/provider-definitions.js +83 -0
- package/dist/src/providers/provider-definitions.mjs +25 -1
- package/dist/src/providers/provider-inventory.js +2 -0
- package/dist/src/sessions/adapters/omp.js +203 -0
- package/dist/src/sessions/batch-import.js +7 -0
- package/dist/src/sessions/contracts.js +1 -1
- package/dist/src/sessions/importer.js +4 -3
- package/dist/src/sessions/index.js +1 -0
- package/dist/src/sessions/readers.js +4 -3
- package/dist/src/sessions/workspace-discovery.js +12 -2
- package/dist/src/skills/deployer.js +21 -1
- package/dist/src/smiths/agentsmith/generator.js +1 -0
- package/dist/src/smiths/context-pipeline/parallelism-section.js +2 -0
- package/dist/src/smiths/context-pipeline/provider-policy.js +2 -2
- package/dist/src/smiths/context-pipeline/workspace-context.js +2 -2
- package/dist/src/storage/backends/fortemi.js +142 -17
- package/dist/src/storage/fortemi-qualification-receipt.js +206 -0
- package/dist/src/storage/fortemi-qualification.js +67 -6
- package/dist/src/storage/index.js +1 -0
- package/package.json +2 -1
- package/schemas/dataset/fortemi-live-qualification-receipt.v1.schema.json +132 -0
- package/tools/agents/deploy-agents.mjs +6 -3
- package/tools/agents/providers/antigravity.mjs +147 -0
- package/tools/agents/providers/omp.d.mts +4 -0
- package/tools/agents/providers/omp.mjs +256 -0
- package/tools/providers/antigravity-transport.mjs +124 -0
|
@@ -20,6 +20,7 @@ import { askString as sharedAskString, askYesNo as sharedAskYesNo } from '../pro
|
|
|
20
20
|
import { writeNormalizedAiwgMd } from '../../smiths/context-pipeline/finalization.js';
|
|
21
21
|
import { ensureWorkspaceContext } from '../../smiths/context-pipeline/workspace-context.js';
|
|
22
22
|
const PROVIDER_LABELS = {
|
|
23
|
+
antigravity: 'Google Antigravity .agents/',
|
|
23
24
|
claude: 'Claude Code .claude/',
|
|
24
25
|
copilot: 'GitHub Copilot .github/',
|
|
25
26
|
cursor: 'Cursor .cursor/',
|
|
@@ -30,6 +31,7 @@ const PROVIDER_LABELS = {
|
|
|
30
31
|
codex: 'OpenAI Codex ~/.codex/',
|
|
31
32
|
openclaw: 'OpenClaw ~/.openclaw/',
|
|
32
33
|
hermes: 'Hermes (MCP) aiwg mcp',
|
|
34
|
+
omp: 'Oh My Pi .omp/ + .agents/skills/',
|
|
33
35
|
pi: 'Pi Coding Agent .pi/ + .agents/skills/',
|
|
34
36
|
};
|
|
35
37
|
// Local aliases for the shared prompt utilities. These preserve existing
|
|
@@ -10,7 +10,7 @@ import { load as loadYaml } from 'js-yaml';
|
|
|
10
10
|
import { compileModelPolicy, validateCanonicalModelPolicy, validateUserProjectModelConfig, } from '../../models/provider-policy.js';
|
|
11
11
|
const TIERS = new Set(['economy', 'standard', 'premium', 'max-quality']);
|
|
12
12
|
const PROVIDERS = new Set([
|
|
13
|
-
'claude', 'codex', 'copilot', 'cursor', 'factory', 'hermes',
|
|
13
|
+
'antigravity', 'claude', 'codex', 'copilot', 'cursor', 'factory', 'hermes',
|
|
14
14
|
'opencode', 'openclaw', 'openhuman', 'warp', 'windsurf',
|
|
15
15
|
]);
|
|
16
16
|
function parseArgs(args) {
|
|
@@ -88,8 +88,13 @@ async function handleRuntimeInfo(args, cwd = process.cwd()) {
|
|
|
88
88
|
if (hasProviders) {
|
|
89
89
|
const { collectProviderInventory } = await import('../../providers/provider-inventory.js');
|
|
90
90
|
const inventory = await collectProviderInventory(cwd);
|
|
91
|
+
const selected = args[args.indexOf('--provider') + 1];
|
|
92
|
+
const ompSelected = args.includes('--provider') && ['omp', 'oh-my-pi'].includes(selected);
|
|
93
|
+
const ompRuntime = ompSelected
|
|
94
|
+
? await (await import('../../providers/omp-diagnostics.mjs')).diagnoseOmpRuntime({ cwd })
|
|
95
|
+
: undefined;
|
|
91
96
|
if (hasJson) {
|
|
92
|
-
console.log(JSON.stringify(inventory, null, 2));
|
|
97
|
+
console.log(JSON.stringify({ ...inventory, ...(ompRuntime ? { ompRuntime } : {}) }, null, 2));
|
|
93
98
|
}
|
|
94
99
|
else {
|
|
95
100
|
console.log('\nProvider Inventory');
|
|
@@ -109,6 +114,8 @@ async function handleRuntimeInfo(args, cwd = process.cwd()) {
|
|
|
109
114
|
for (const reason of provider.reasons)
|
|
110
115
|
console.log(` note: ${reason}`);
|
|
111
116
|
}
|
|
117
|
+
if (ompRuntime)
|
|
118
|
+
console.log(`\nOMP runtime: ${JSON.stringify(ompRuntime, null, 2)}`);
|
|
112
119
|
}
|
|
113
120
|
return;
|
|
114
121
|
}
|
|
@@ -26,6 +26,7 @@ import { readAiwgConfig, getDeploymentSummary, VALID_PROVIDERS, } from '../../co
|
|
|
26
26
|
import { getProviderConfig, isSpawnableProvider, PROVIDER_CONFIGS, } from '../agent-spawn.js';
|
|
27
27
|
import { useHandler as useFrameworkHandler } from './use.js';
|
|
28
28
|
import { debug } from '../log.js';
|
|
29
|
+
import { normalizeProviderDefinitionId } from '../../providers/provider-definitions.js';
|
|
29
30
|
// ── Provider resolution ──────────────────────────────────────────────────────
|
|
30
31
|
/**
|
|
31
32
|
* Resolve which provider to target.
|
|
@@ -33,11 +34,11 @@ import { debug } from '../log.js';
|
|
|
33
34
|
*/
|
|
34
35
|
async function resolveProvider(explicitProvider, cwd) {
|
|
35
36
|
if (explicitProvider) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
const normalized = normalizeProviderDefinitionId(explicitProvider);
|
|
38
|
+
if (!normalized || normalized === 'generic' || !VALID_PROVIDERS.includes(normalized)) {
|
|
39
|
+
throw new Error(`Unsupported provider '${explicitProvider}'`);
|
|
39
40
|
}
|
|
40
|
-
return
|
|
41
|
+
return normalized;
|
|
41
42
|
}
|
|
42
43
|
const config = await readAiwgConfig(cwd);
|
|
43
44
|
if (config?.providers?.[0]) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, realpathSync, statSync, } from 'node:fs';
|
|
2
2
|
import { dirname, isAbsolute, resolve, } from 'node:path';
|
|
3
3
|
import { pathToFileURL } from 'node:url';
|
|
4
|
-
import { CLAUDE_ADAPTER_VERSION, ClaudeSessionAdapter, CODEX_ADAPTER_VERSION, CodexSessionAdapter, COPILOT_ADAPTER_VERSION, CopilotSessionAdapter, CURSOR_ADAPTER_VERSION, CursorSessionAdapter, FACTORY_ADAPTER_VERSION, FactorySessionAdapter, HERMES_ADAPTER_VERSION, HermesSessionAdapter, OPENCODE_ADAPTER_VERSION, OpenCodeSessionAdapter, OPENCLAW_ADAPTER_VERSION, OpenClawSessionAdapter, OPENHUMAN_ADAPTER_VERSION, OpenHumanSessionAdapter, PI_ADAPTER_VERSION, PiSessionAdapter, WARP_ADAPTER_VERSION, WarpSessionAdapter, DEVIN_DESKTOP_ADAPTER_VERSION, DevinDesktopSessionAdapter, CandidateExtractionService, GENERIC_ADAPTER_VERSION, GenericSessionInterchangeAdapter, IncrementalSessionImporter, ImportLeaseContentionError, FilesystemMemoryDestination, FilesystemPromotionDispositionCoordinator, MemoryPromotionGateway, SESSION_CONTRACT_VERSION, SESSION_PROVIDER_IDS, SessionContractError, SessionRepository, SessionSourceSchema, StructuralCandidateExtractor, resolveMemoryConsumerManifest, assertSessionProviderId, acquireImportLease, defaultDiscoveryManifestPath, discoverWorkspaceHistories, deriveSessionTimeline, importDiscoveryManifest, previewDiscoveryImport, publicDiscoveryManifest, readDiscoveryManifest, redactSourceLocator, sha256, parseTimelineGap, writeDiscoveryManifest, } from '../../sessions/index.js';
|
|
4
|
+
import { CLAUDE_ADAPTER_VERSION, ClaudeSessionAdapter, CODEX_ADAPTER_VERSION, CodexSessionAdapter, COPILOT_ADAPTER_VERSION, CopilotSessionAdapter, CURSOR_ADAPTER_VERSION, CursorSessionAdapter, FACTORY_ADAPTER_VERSION, FactorySessionAdapter, HERMES_ADAPTER_VERSION, HermesSessionAdapter, OPENCODE_ADAPTER_VERSION, OpenCodeSessionAdapter, OPENCLAW_ADAPTER_VERSION, OpenClawSessionAdapter, OPENHUMAN_ADAPTER_VERSION, OpenHumanSessionAdapter, PI_ADAPTER_VERSION, PiSessionAdapter, OmpSessionAdapter, OMP_ADAPTER_VERSION, WARP_ADAPTER_VERSION, WarpSessionAdapter, DEVIN_DESKTOP_ADAPTER_VERSION, DevinDesktopSessionAdapter, CandidateExtractionService, GENERIC_ADAPTER_VERSION, GenericSessionInterchangeAdapter, IncrementalSessionImporter, ImportLeaseContentionError, FilesystemMemoryDestination, FilesystemPromotionDispositionCoordinator, MemoryPromotionGateway, SESSION_CONTRACT_VERSION, SESSION_PROVIDER_IDS, SessionContractError, SessionRepository, SessionSourceSchema, StructuralCandidateExtractor, resolveMemoryConsumerManifest, assertSessionProviderId, acquireImportLease, defaultDiscoveryManifestPath, discoverWorkspaceHistories, deriveSessionTimeline, importDiscoveryManifest, previewDiscoveryImport, publicDiscoveryManifest, readDiscoveryManifest, redactSourceLocator, sha256, parseTimelineGap, writeDiscoveryManifest, } from '../../sessions/index.js';
|
|
5
5
|
const JSON_CONTRACT_VERSION = '1.0.0';
|
|
6
6
|
async function createLineMemoryPromotionDestination(projectRoot, manifestPath) {
|
|
7
7
|
const modulePath = resolve(dirname(manifestPath), 'commands', 'line-memory.mjs');
|
|
@@ -54,6 +54,7 @@ Options:
|
|
|
54
54
|
--manifest <path> Override the discovery manifest path
|
|
55
55
|
--provider-home <path> Override the provider home root (testing/portable homes)
|
|
56
56
|
--codex-root <path> Explicitly authorize a shared Codex sessions/export root
|
|
57
|
+
--omp-root <path> Explicitly authorize an OMP profile sessions root
|
|
57
58
|
--confirm, --yes Confirm a persistent discovered batch import
|
|
58
59
|
--lock-wait-ms <n> Maximum import-lease wait (default 5000)
|
|
59
60
|
--inactivity-threshold <duration> Historical inactivity threshold (default 24h)
|
|
@@ -622,7 +623,7 @@ async function importSource(ctx, args) {
|
|
|
622
623
|
if (provider !== 'generic' && provider !== 'claude' && provider !== 'codex'
|
|
623
624
|
&& provider !== 'copilot' && provider !== 'cursor' && provider !== 'factory'
|
|
624
625
|
&& provider !== 'hermes' && provider !== 'opencode' && provider !== 'openclaw'
|
|
625
|
-
&& provider !== 'openhuman' && provider !== 'pi' && provider !== 'warp' && provider !== 'devin-desktop') {
|
|
626
|
+
&& provider !== 'openhuman' && provider !== 'pi' && provider !== 'omp' && provider !== 'warp' && provider !== 'devin-desktop') {
|
|
626
627
|
throw new CliError('UNSUPPORTED_OPERATION', `session import is not implemented for ${provider}`, EXIT.unsupported);
|
|
627
628
|
}
|
|
628
629
|
const sourceId = requiredValue(args, '--source-id');
|
|
@@ -639,9 +640,10 @@ async function importSource(ctx, args) {
|
|
|
639
640
|
const isOpenClaw = provider === 'openclaw';
|
|
640
641
|
const isOpenHuman = provider === 'openhuman';
|
|
641
642
|
const isPi = provider === 'pi';
|
|
643
|
+
const isOmp = provider === 'omp';
|
|
642
644
|
const isWarp = provider === 'warp';
|
|
643
645
|
const isDevinDesktop = provider === 'devin-desktop';
|
|
644
|
-
const adapter = isClaude
|
|
646
|
+
const adapter = isOmp ? new OmpSessionAdapter() : isClaude
|
|
645
647
|
? new ClaudeSessionAdapter()
|
|
646
648
|
: isCodex
|
|
647
649
|
? new CodexSessionAdapter()
|
|
@@ -666,7 +668,7 @@ async function importSource(ctx, args) {
|
|
|
666
668
|
: isDevinDesktop
|
|
667
669
|
? new DevinDesktopSessionAdapter()
|
|
668
670
|
: new GenericSessionInterchangeAdapter();
|
|
669
|
-
const locatorClass = isClaude
|
|
671
|
+
const locatorClass = isOmp ? 'omp-session-v3-jsonl' : isClaude
|
|
670
672
|
? (input.endsWith('.hooks.jsonl') ? 'claude-hook-jsonl' : 'claude-transcript-jsonl')
|
|
671
673
|
: isCodex
|
|
672
674
|
? (input.endsWith('.app-server.jsonl') ? 'codex-app-server-jsonl' : 'codex-rollout-jsonl')
|
|
@@ -698,7 +700,7 @@ async function importSource(ctx, args) {
|
|
|
698
700
|
const probe = await adapter.inspect(selectedSource);
|
|
699
701
|
const source = SessionSourceSchema.parse({
|
|
700
702
|
contractVersion: SESSION_CONTRACT_VERSION, sourceId, provider,
|
|
701
|
-
providerProfile: isClaude
|
|
703
|
+
providerProfile: isOmp ? 'native-title-slot-v3' : isClaude
|
|
702
704
|
? 'documented-local-jsonl'
|
|
703
705
|
: isCodex
|
|
704
706
|
? 'app-server-v2-rollout-fallback'
|
|
@@ -722,7 +724,7 @@ async function importSource(ctx, args) {
|
|
|
722
724
|
? 'opt-in-cascade-transcript-hook'
|
|
723
725
|
: 'manual-interchange',
|
|
724
726
|
locatorClass, redactedLocator: redactSourceLocator(input),
|
|
725
|
-
adapterVersion: isClaude
|
|
727
|
+
adapterVersion: isOmp ? OMP_ADAPTER_VERSION : isClaude
|
|
726
728
|
? CLAUDE_ADAPTER_VERSION
|
|
727
729
|
: isCodex
|
|
728
730
|
? CODEX_ADAPTER_VERSION
|
|
@@ -749,11 +751,11 @@ async function importSource(ctx, args) {
|
|
|
749
751
|
disposition: isWarp
|
|
750
752
|
? 'manual-only'
|
|
751
753
|
: isClaude || isCodex || isCopilot || isCursor || isFactory || isHermes
|
|
752
|
-
|| isOpenCode || isOpenClaw || isOpenHuman || isDevinDesktop
|
|
754
|
+
|| isOpenCode || isOpenClaw || isOpenHuman || isDevinDesktop || isOmp
|
|
753
755
|
? 'implemented' : 'manual-only',
|
|
754
756
|
operationalState: probe.operationalState,
|
|
755
757
|
consistency: probe.consistency, authorizedAt: new Date().toISOString(),
|
|
756
|
-
extensions: isClaude
|
|
758
|
+
extensions: isOmp ? { 'native.omp': {} } : isClaude
|
|
757
759
|
? { 'native.claude': {} }
|
|
758
760
|
: isCodex
|
|
759
761
|
? { 'native.codex': {} }
|
|
@@ -817,6 +819,8 @@ async function discoverWorkspace(ctx, args) {
|
|
|
817
819
|
providerHome: args.values.has('--provider-home')
|
|
818
820
|
? resolve(ctx.cwd, args.values.get('--provider-home'))
|
|
819
821
|
: undefined,
|
|
822
|
+
ompRoot: args.values.has('--omp-root')
|
|
823
|
+
? resolve(ctx.cwd, args.values.get('--omp-root')) : undefined,
|
|
820
824
|
codexRoot: args.values.has('--codex-root')
|
|
821
825
|
? resolve(ctx.cwd, args.values.get('--codex-root'))
|
|
822
826
|
: undefined,
|
|
@@ -1012,6 +1016,19 @@ function providerDisposition(provider) {
|
|
|
1012
1016
|
},
|
|
1013
1017
|
};
|
|
1014
1018
|
}
|
|
1019
|
+
if (provider === 'omp') {
|
|
1020
|
+
return {
|
|
1021
|
+
provider, disposition: 'implemented', operationalState: 'available',
|
|
1022
|
+
supportedOperations: ['discover', 'inspect', 'stream'],
|
|
1023
|
+
acquisitionModes: ['jsonl'], reasonCode: null,
|
|
1024
|
+
remediation: 'Authorize the selected OMP profile sessions root or an explicit native JSONL file.',
|
|
1025
|
+
evidence: {
|
|
1026
|
+
adapterVersion: OMP_ADAPTER_VERSION,
|
|
1027
|
+
verifiedAt: '2026-09-04',
|
|
1028
|
+
documentation: 'https://github.com/can1357/oh-my-pi/blob/main/packages/coding-agent/src/session/session-entries.ts',
|
|
1029
|
+
},
|
|
1030
|
+
};
|
|
1031
|
+
}
|
|
1015
1032
|
if (provider === 'pi') {
|
|
1016
1033
|
return {
|
|
1017
1034
|
provider, disposition: 'implemented', operationalState: 'available',
|
|
@@ -1121,7 +1138,7 @@ function parseArgs(argv) {
|
|
|
1121
1138
|
'--entity', '--sensitivity', '--extraction-state', '--page-size', '--max-documents',
|
|
1122
1139
|
'--state', '--reviewer', '--reason', '--policy-version', '--min-confidence',
|
|
1123
1140
|
'--consumer', '--actor-class', '--reason-code', '--dependent-action', '--basis',
|
|
1124
|
-
'--manifest', '--provider-home', '--codex-root', '--lock-wait-ms', '--min-coverage', '--gap',
|
|
1141
|
+
'--manifest', '--provider-home', '--codex-root', '--omp-root', '--lock-wait-ms', '--min-coverage', '--gap',
|
|
1125
1142
|
'--inactivity-threshold',
|
|
1126
1143
|
'--control-events',
|
|
1127
1144
|
'--session', '--status', '--actor', '--group-by',
|
|
@@ -5,6 +5,7 @@ import { AiwgError, EXIT_CODES } from '../errors.js';
|
|
|
5
5
|
import { askChoice, askString, askYesNo, createPromptInterface } from '../prompt-utils.js';
|
|
6
6
|
import * as ui from '../ui.js';
|
|
7
7
|
import { projectAiwgPath } from '../../config/project-artifacts.js';
|
|
8
|
+
import { normalizeProviderDefinitionId } from '../../providers/provider-definitions.js';
|
|
8
9
|
const DELIVERY_MODES = ['pr-required', 'feature-branch', 'direct'];
|
|
9
10
|
const FORCE_PUSH_POLICIES = ['never', 'own-branch-only', 'allowed'];
|
|
10
11
|
const ISSUE_PROVIDERS = ['gitea', 'github', 'local'];
|
|
@@ -56,7 +57,10 @@ function parseStringList(raw) {
|
|
|
56
57
|
}
|
|
57
58
|
function parseProviders(raw, fallback) {
|
|
58
59
|
const providers = parseStringList(raw);
|
|
59
|
-
return providers && providers.length > 0 ? providers : fallback;
|
|
60
|
+
return providers && providers.length > 0 ? normalizeProviders(providers) : fallback;
|
|
61
|
+
}
|
|
62
|
+
function normalizeProviders(providers) {
|
|
63
|
+
return providers.map(provider => normalizeProviderDefinitionId(provider) ?? provider);
|
|
60
64
|
}
|
|
61
65
|
export function parseSetupProjectOptions(ctx) {
|
|
62
66
|
const args = ctx.args;
|
|
@@ -88,7 +92,10 @@ export function parseSetupProjectOptions(ctx) {
|
|
|
88
92
|
trackerActorVia: parseEnum(flagValue(args, '--tracker-actor-via'), TRACKER_VIA, '--tracker-actor-via'),
|
|
89
93
|
customerTrackerActorLogin: flagValue(args, '--customer-tracker-actor-login'),
|
|
90
94
|
customerTrackerActorVia: parseEnum(flagValue(args, '--customer-tracker-actor-via'), TRACKER_VIA, '--customer-tracker-actor-via'),
|
|
91
|
-
providers:
|
|
95
|
+
providers: (() => {
|
|
96
|
+
const providers = parseStringList(flagValue(args, '--providers'));
|
|
97
|
+
return providers ? normalizeProviders(providers) : undefined;
|
|
98
|
+
})(),
|
|
92
99
|
};
|
|
93
100
|
}
|
|
94
101
|
export function detectGitRemotes(projectDir) {
|
|
@@ -82,7 +82,18 @@ function formatProvider(id, provider, matrix, meta) {
|
|
|
82
82
|
if (feat?.description)
|
|
83
83
|
lines.push(` ${feat.description}`);
|
|
84
84
|
if (isNative) {
|
|
85
|
-
if (
|
|
85
|
+
if (id === 'omp' && featureId === 'mcp') {
|
|
86
|
+
lines.push(' OMP supplies the native client. AIWG persistent injection/removal is available for project and profile scope; ephemeral injection is unsupported.');
|
|
87
|
+
lines.push(' example: aiwg mcp inject --provider omp --servers local-tools');
|
|
88
|
+
}
|
|
89
|
+
else if (id === 'omp' && featureId === 'behaviors') {
|
|
90
|
+
lines.push(' AIWG bridges selected handlers through an OMP extension; no default policy is installed. Permission-request and pre-compaction enforcement are unsupported.');
|
|
91
|
+
}
|
|
92
|
+
else if (id === 'omp' && (featureId === 'tasks' || featureId === 'agent_teams')) {
|
|
93
|
+
lines.push(' OMP native leaf tasks use AIWG workspace admission limits and verified child results; nested requests share the same scheduler.');
|
|
94
|
+
lines.push(' example: aiwg team run --provider omp --body-file tasks.json');
|
|
95
|
+
}
|
|
96
|
+
else if (feat?.native_example)
|
|
86
97
|
lines.push(` example: ${feat.native_example}`);
|
|
87
98
|
}
|
|
88
99
|
else if (isExternalStrategy(emulation)) {
|
|
@@ -195,7 +206,7 @@ async function handleSteward(args, ctx) {
|
|
|
195
206
|
aiwg steward permissions migrate --apply Back up and atomically normalize config
|
|
196
207
|
|
|
197
208
|
Providers:
|
|
198
|
-
claude-code, codex, copilot, cursor, factory, opencode, pi, warp, windsurf, hermes, openclaw
|
|
209
|
+
antigravity (agy), claude-code, codex, copilot, cursor, factory, opencode, pi, omp, warp, windsurf, hermes, openclaw
|
|
199
210
|
|
|
200
211
|
Features:
|
|
201
212
|
cron, agent_teams, tasks, mcp, behaviors, mission_control, daemon
|
|
@@ -689,6 +689,17 @@ export const removeHandler = {
|
|
|
689
689
|
category: "framework",
|
|
690
690
|
aliases: [],
|
|
691
691
|
async execute(ctx) {
|
|
692
|
+
// Explicit provider removal is separate from framework removal. The native
|
|
693
|
+
// adapter validates receipt hashes and preserves operator modifications.
|
|
694
|
+
const nativeRemovalProvider = parseRemoveProvider(ctx.args);
|
|
695
|
+
if (firstRemovePositional(ctx.args) === 'omp' && nativeRemovalProvider.provider === 'omp') {
|
|
696
|
+
const { uninstall } = await import('../../../tools/agents/providers/omp.mjs');
|
|
697
|
+
const { getProjectDir } = await import('../../config/aiwg-config.js');
|
|
698
|
+
const dryRun = ctx.args.includes('--dry-run');
|
|
699
|
+
const scope = ctx.args.includes('--user') || isScopeUser(ctx.args) ? 'user' : 'project';
|
|
700
|
+
const count = uninstall(getProjectDir({ cwd: ctx.cwd }, ctx.args), { dryRun, scope });
|
|
701
|
+
return { exitCode: 0, message: `${dryRun ? 'Would remove' : 'Removed'} ${count} unchanged OMP-owned files; operator files preserved.` };
|
|
702
|
+
}
|
|
692
703
|
// #1156 Phase 1 — `--scope user` / `--user`: revert the user-scope mirror
|
|
693
704
|
// for the given framework. Independent of any project; reads the per-user
|
|
694
705
|
// registry at ~/.aiwg/installed.json to find what was deployed, deletes
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Team Command Handler
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Routes declared teams across AIWG providers, including bounded native OMP tasks.
|
|
5
5
|
* Provides a provider-agnostic abstraction for declaring, deploying, and
|
|
6
6
|
* invoking agent teams. On Claude Code, delegates to native team mechanisms.
|
|
7
|
-
*
|
|
7
|
+
* OMP executes explicit task files; other providers use aiwg mc orchestration.
|
|
8
8
|
*
|
|
9
9
|
* Subcommands: run, list, info
|
|
10
10
|
*
|
|
@@ -12,13 +12,15 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import * as ui from '../ui.js';
|
|
14
14
|
import { promises as fs } from 'node:fs';
|
|
15
|
-
import { join, basename } from 'node:path';
|
|
15
|
+
import { join, basename, resolve } from 'node:path';
|
|
16
|
+
import { pathToFileURL } from 'node:url';
|
|
16
17
|
import { projectAiwgPath } from '../../config/project-artifacts.js';
|
|
18
|
+
import { normalizeProviderDefinitionId } from '../../providers/provider-definitions.js';
|
|
17
19
|
// ── Provider Detection ───────────────────────────────────────
|
|
18
20
|
function detectProvider(args) {
|
|
19
21
|
const providerFlag = parseFlag(args, '--provider');
|
|
20
22
|
if (providerFlag)
|
|
21
|
-
return providerFlag;
|
|
23
|
+
return normalizeProviderDefinitionId(providerFlag) ?? providerFlag;
|
|
22
24
|
// Claude Code sets CLAUDE_CODE_VERSION; API key presence is secondary heuristic
|
|
23
25
|
const isClaudeCode = process.env.CLAUDE_CODE_VERSION !== undefined ||
|
|
24
26
|
process.env.ANTHROPIC_API_KEY !== undefined;
|
|
@@ -103,7 +105,57 @@ async function listAllTeams(frameworkRoot, cwd) {
|
|
|
103
105
|
return teams;
|
|
104
106
|
}
|
|
105
107
|
// ── Subcommand: run ──────────────────────────────────────────
|
|
108
|
+
/** Public OMP dispatch delegates to the same bounded native runtime used by conformance. */
|
|
109
|
+
async function teamRunOmp(ctx) {
|
|
110
|
+
const allowed = new Set(['--provider', '--body-file', '--cwd', '--output-root', '--max-parallel', '--model', '--profile']);
|
|
111
|
+
const values = {};
|
|
112
|
+
for (let i = 0; i < ctx.args.length; i++) {
|
|
113
|
+
const flag = ctx.args[i];
|
|
114
|
+
if (flag === '--json')
|
|
115
|
+
continue;
|
|
116
|
+
if (!allowed.has(flag) || !ctx.args[i + 1] || ctx.args[i + 1].startsWith('--')) {
|
|
117
|
+
ui.error('OMP usage: aiwg team run --provider omp --body-file tasks.json [--cwd DIR] [--output-root DIR] [--max-parallel N] [--model provider/model] [--profile NAME]');
|
|
118
|
+
return { exitCode: 1 };
|
|
119
|
+
}
|
|
120
|
+
values[flag] = ctx.args[++i];
|
|
121
|
+
}
|
|
122
|
+
if (!values['--body-file']) {
|
|
123
|
+
ui.error('OMP native team dispatch requires --body-file tasks.json with explicit task ownership and tools.');
|
|
124
|
+
return { exitCode: 1 };
|
|
125
|
+
}
|
|
126
|
+
const maxParallel = values['--max-parallel'] === undefined ? 4 : Number(values['--max-parallel']);
|
|
127
|
+
if (!Number.isInteger(maxParallel) || maxParallel < 1) {
|
|
128
|
+
ui.error('OMP --max-parallel must be a positive integer.');
|
|
129
|
+
return { exitCode: 1 };
|
|
130
|
+
}
|
|
131
|
+
const controller = new AbortController();
|
|
132
|
+
const abort = () => controller.abort();
|
|
133
|
+
process.once('SIGINT', abort);
|
|
134
|
+
process.once('SIGTERM', abort);
|
|
135
|
+
try {
|
|
136
|
+
const payload = JSON.parse(await fs.readFile(resolve(ctx.cwd, values['--body-file']), 'utf8'));
|
|
137
|
+
const { runOmpTeam } = await import(pathToFileURL(join(ctx.frameworkRoot, 'tools/providers/omp-teams.mjs')).href);
|
|
138
|
+
const result = await runOmpTeam({
|
|
139
|
+
tasks: payload.tasks,
|
|
140
|
+
cwd: values['--cwd'] ? resolve(ctx.cwd, values['--cwd']) : ctx.cwd,
|
|
141
|
+
outputDir: values['--output-root'] ? resolve(ctx.cwd, values['--output-root']) : undefined,
|
|
142
|
+
maxParallel, model: values['--model'], profile: values['--profile'], signal: controller.signal,
|
|
143
|
+
});
|
|
144
|
+
console.log(JSON.stringify(result, null, 2));
|
|
145
|
+
return { exitCode: result.results.every((task) => task.status === 'completed') ? 0 : 1 };
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
ui.error(error instanceof SyntaxError ? 'OMP task body is invalid JSON.' : error instanceof Error ? error.message : 'OMP team dispatch failed.');
|
|
149
|
+
return { exitCode: 1 };
|
|
150
|
+
}
|
|
151
|
+
finally {
|
|
152
|
+
process.removeListener('SIGINT', abort);
|
|
153
|
+
process.removeListener('SIGTERM', abort);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
106
156
|
async function teamRun(ctx) {
|
|
157
|
+
if (['omp', 'oh-my-pi'].includes(detectProvider(ctx.args)))
|
|
158
|
+
return teamRunOmp(ctx);
|
|
107
159
|
const positional = getPositionalArgs(ctx.args);
|
|
108
160
|
const slug = positional[0];
|
|
109
161
|
if (!slug) {
|
|
@@ -186,7 +238,7 @@ async function teamList(ctx) {
|
|
|
186
238
|
ui.info('No teams found. Deploy the sdlc-complete framework with: aiwg use sdlc');
|
|
187
239
|
return { exitCode: 0 };
|
|
188
240
|
}
|
|
189
|
-
const backend = isNativeTeamsProvider(provider)
|
|
241
|
+
const backend = ['omp', 'oh-my-pi'].includes(provider) ? 'native (Oh My Pi)' : isNativeTeamsProvider(provider)
|
|
190
242
|
? 'native (Claude Code)'
|
|
191
243
|
: `aiwg mc emulation (${provider})`;
|
|
192
244
|
ui.blank();
|
|
@@ -277,21 +329,30 @@ function showTeamHelp() {
|
|
|
277
329
|
${ui.bold('Usage:')} aiwg team <subcommand> [options]
|
|
278
330
|
|
|
279
331
|
${ui.bold('Subcommands:')}
|
|
280
|
-
run <name>
|
|
332
|
+
run <name> Run a declared team (Claude native guidance or aiwg mc)
|
|
333
|
+
run --provider omp --body-file tasks.json Execute bounded native OMP tasks
|
|
281
334
|
list List available teams
|
|
282
335
|
info <name> Show team definition and agent roster
|
|
283
336
|
|
|
284
337
|
${ui.bold('Options:')}
|
|
285
|
-
--provider <p> Override provider: claude|warp|copilot|cursor|windsurf|opencode|factory|codex|openclaw
|
|
338
|
+
--provider <p> Override provider: antigravity|agy|claude|warp|copilot|cursor|windsurf|opencode|factory|codex|openclaw|omp|oh-my-pi
|
|
286
339
|
--objective "<text>" Set objective passed to mc dispatch agents
|
|
340
|
+
--body-file <file> OMP task JSON with explicit ownership and tools
|
|
341
|
+
--cwd <dir> OMP working directory (defaults to current workspace)
|
|
342
|
+
--output-root <dir> OMP result and control artifact directory
|
|
343
|
+
--max-parallel <n> OMP requested worker cap (workspace ceiling still applies)
|
|
344
|
+
--model <id> OMP coordinator/worker model selector
|
|
345
|
+
--profile <name> OMP native profile
|
|
287
346
|
--json Machine-readable output
|
|
288
347
|
|
|
289
348
|
${ui.bold('Provider Routing:')}
|
|
290
349
|
Claude Code Native agent team dispatch (@agent-name invocation)
|
|
350
|
+
Oh My Pi Bounded native task execution from --body-file
|
|
291
351
|
All others aiwg mc emulation (Mission Control sequential/parallel dispatch)
|
|
292
352
|
|
|
293
353
|
${ui.bold('Examples:')}
|
|
294
354
|
aiwg team run sdlc-review
|
|
355
|
+
aiwg team run --provider omp --body-file tasks.json
|
|
295
356
|
aiwg team run sdlc-review --provider cursor --objective "Phase gate review"
|
|
296
357
|
aiwg team run security-review --objective "Pre-release audit"
|
|
297
358
|
aiwg team list
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
import fs from 'fs/promises';
|
|
13
13
|
import path from 'path';
|
|
14
14
|
import os from 'os';
|
|
15
|
+
import { pathToFileURL } from 'node:url';
|
|
16
|
+
import { resolveOmpPaths } from '../../providers/omp-paths.mjs';
|
|
15
17
|
import YAML from 'yaml';
|
|
16
18
|
import { createScriptRunner } from './script-runner.js';
|
|
17
19
|
import { getFrameworkRoot, getVersionInfo } from '../../channel/manager.mjs';
|
|
@@ -1041,10 +1043,10 @@ async function reconcileDeployedSkillAssets(bundlePath, target, provider, option
|
|
|
1041
1043
|
}
|
|
1042
1044
|
const paths = getProviderPaths(provider);
|
|
1043
1045
|
const kernelSkillsPath = getProviderKernelSkillsPath(provider);
|
|
1044
|
-
const deployRoots =
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1046
|
+
const deployRoots = provider === 'omp' && options.scope === 'user'
|
|
1047
|
+
? [path.join(resolveOmpPaths({ cwd: target }).agentDir, 'skills')]
|
|
1048
|
+
: [...new Set([paths.skills, kernelSkillsPath]
|
|
1049
|
+
.filter((value) => Boolean(value)).map(value => resolveDeployPath(target, value)))];
|
|
1048
1050
|
for (const skillName of skillDirs) {
|
|
1049
1051
|
const sourceSkillDir = path.join(skillsRoot, skillName);
|
|
1050
1052
|
const sourceSkillMd = path.join(sourceSkillDir, 'SKILL.md');
|
|
@@ -1055,6 +1057,8 @@ async function reconcileDeployedSkillAssets(bundlePath, target, provider, option
|
|
|
1055
1057
|
catch {
|
|
1056
1058
|
continue;
|
|
1057
1059
|
}
|
|
1060
|
+
if (options.skipUndeployed && !(await Promise.all(deployRoots.map(root => fileExists(path.join(root, skillName, 'SKILL.md'))))).some(Boolean))
|
|
1061
|
+
continue;
|
|
1058
1062
|
const frontmatter = content.match(/^---\r?\n([\s\S]*?)\r?\n---/)?.[1] ?? '';
|
|
1059
1063
|
const declaredEntrypoint = frontmatter
|
|
1060
1064
|
.match(/^[ \t]+entrypoint:\s*["']?([^"'\s]+)["']?\s*$/m)?.[1];
|
|
@@ -1097,6 +1101,11 @@ async function reconcileDeployedSkillAssets(bundlePath, target, provider, option
|
|
|
1097
1101
|
if (!deployedSkillRoot)
|
|
1098
1102
|
throw new Error(`deployed skill '${skillName}' not found while reconciling support assets`);
|
|
1099
1103
|
const destination = path.join(deployedSkillRoot, skillName, ...normalized.split('/'));
|
|
1104
|
+
if (provider === 'omp') {
|
|
1105
|
+
const adapter = await import(pathToFileURL(path.join(await getFrameworkRoot(), 'tools/agents/providers/omp.mjs')).href);
|
|
1106
|
+
adapter.deploySkillSupportAsset(source, destination, { quiet: true });
|
|
1107
|
+
continue;
|
|
1108
|
+
}
|
|
1100
1109
|
await fs.mkdir(path.dirname(destination), { recursive: true });
|
|
1101
1110
|
await fs.copyFile(source, destination);
|
|
1102
1111
|
const mode = (await fs.stat(source)).mode & 0o777;
|
|
@@ -1348,6 +1357,18 @@ async function deployProjectLocalBundles(opts) {
|
|
|
1348
1357
|
}
|
|
1349
1358
|
}
|
|
1350
1359
|
}
|
|
1360
|
+
// Automatic reconciliation (also used by refresh/upgrade) must restore the
|
|
1361
|
+
// project search cache for existing bundles, just as a named local install
|
|
1362
|
+
// does. Named installs refresh once after all selected providers finish.
|
|
1363
|
+
if (deployed > 0 && !dryRun && !onlyBundleId) {
|
|
1364
|
+
try {
|
|
1365
|
+
await rebuildExternalBundleIndex(projectDir, 'project', verbose);
|
|
1366
|
+
}
|
|
1367
|
+
catch (error) {
|
|
1368
|
+
failed++;
|
|
1369
|
+
ui.warn(`Project-local index refresh failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1351
1372
|
// Refresh the project kernel quickref from either legacy operator input or
|
|
1352
1373
|
// managed project-local discovery whenever bundles deploy.
|
|
1353
1374
|
const { hasProjectQuickref, deployProjectQuickref } = await import('../../extensions/project-quickref.js');
|
|
@@ -1968,6 +1989,65 @@ async function rebuildExternalBundleIndex(projectDir, graph, verbose) {
|
|
|
1968
1989
|
}
|
|
1969
1990
|
ui.dim(` Refreshed ${graph}-scope capability index`);
|
|
1970
1991
|
}
|
|
1992
|
+
/** User OMP writes use native ownership receipts instead of an unconditional copy. */
|
|
1993
|
+
async function deployOmpUserSource(opts) {
|
|
1994
|
+
const adapter = await import(pathToFileURL(path.join(opts.frameworkRoot, 'tools/agents/providers/omp.mjs')).href);
|
|
1995
|
+
await adapter.deploy({ srcRoot: opts.source, target: opts.target, provider: 'omp', scope: 'user',
|
|
1996
|
+
mode: opts.mode ?? 'general', deployCommands: true, deploySkills: true, deployRules: true,
|
|
1997
|
+
copyStandardSkills: opts.copyAll, quiet: true, deployVersion: (await getVersionInfo()).version });
|
|
1998
|
+
const sourceBundles = new Set([opts.source]);
|
|
1999
|
+
const { resourceDirs } = resolveOmpPaths({ cwd: opts.target });
|
|
2000
|
+
const entries = {
|
|
2001
|
+
agents: [], commands: [], skills: [], rules: [], behaviors: [],
|
|
2002
|
+
};
|
|
2003
|
+
const belongsToBundle = (entry) => {
|
|
2004
|
+
if (entry.provider !== 'omp' || typeof entry.source !== 'string')
|
|
2005
|
+
return false;
|
|
2006
|
+
if (entry.transformation === 'omp-extension')
|
|
2007
|
+
return true;
|
|
2008
|
+
const relative = path.relative(opts.source, entry.source);
|
|
2009
|
+
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
|
|
2010
|
+
};
|
|
2011
|
+
const locations = resourceDirs;
|
|
2012
|
+
for (const kind of Object.keys(entries)) {
|
|
2013
|
+
const directory = locations[kind];
|
|
2014
|
+
if (kind === 'skills') {
|
|
2015
|
+
let children;
|
|
2016
|
+
try {
|
|
2017
|
+
children = await fs.readdir(directory);
|
|
2018
|
+
}
|
|
2019
|
+
catch {
|
|
2020
|
+
continue;
|
|
2021
|
+
}
|
|
2022
|
+
for (const child of children) {
|
|
2023
|
+
try {
|
|
2024
|
+
const receipt = JSON.parse(await fs.readFile(path.join(directory, child, '.aiwg-manifest.json'), 'utf8'));
|
|
2025
|
+
if (receipt.managed?.['SKILL.md'] && belongsToBundle(receipt.managed['SKILL.md'])) {
|
|
2026
|
+
entries.skills.push(child);
|
|
2027
|
+
const source = receipt.managed['SKILL.md'].source;
|
|
2028
|
+
if (typeof source === 'string')
|
|
2029
|
+
sourceBundles.add(path.dirname(path.dirname(path.dirname(source))));
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2032
|
+
catch { /* operator resources have no OMP receipt */ }
|
|
2033
|
+
}
|
|
2034
|
+
}
|
|
2035
|
+
else {
|
|
2036
|
+
try {
|
|
2037
|
+
const receipt = JSON.parse(await fs.readFile(path.join(directory, '.aiwg-manifest.json'), 'utf8'));
|
|
2038
|
+
entries[kind] = Object.entries(receipt.managed ?? {}).filter(([, entry]) => belongsToBundle(entry)).map(([name]) => name);
|
|
2039
|
+
}
|
|
2040
|
+
catch { /* no deployed resources of this kind */ }
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
for (const source of sourceBundles)
|
|
2044
|
+
await reconcileDeployedSkillAssets(source, opts.target, 'omp', { strictReferences: false, scope: 'user', skipUndeployed: !opts.copyAll });
|
|
2045
|
+
const { recordUserDeploy } = await import('../../config/user-registry.js');
|
|
2046
|
+
await recordUserDeploy({ framework: opts.bundle, provider: 'omp',
|
|
2047
|
+
version: (await getVersionInfo()).version, source: 'bundled',
|
|
2048
|
+
counts: { agents: entries.agents.length, commands: entries.commands.length,
|
|
2049
|
+
skills: entries.skills.length, rules: entries.rules.length }, entries });
|
|
2050
|
+
}
|
|
1971
2051
|
async function mirrorProjectLocalBundleToUserScope(opts) {
|
|
1972
2052
|
const paths = getProviderPaths(opts.provider);
|
|
1973
2053
|
const resolveProjectPath = (value) => !value ? '' : path.isAbsolute(value) ? value : path.join(opts.target, value);
|
|
@@ -2701,10 +2781,25 @@ export class UseHandler {
|
|
|
2701
2781
|
if (isAddon || isExtension) {
|
|
2702
2782
|
const providerIdx = remainingArgs.findIndex(a => a === '--provider' || a === '--platform');
|
|
2703
2783
|
const explicitAddonProvider = providerIdx >= 0 && remainingArgs[providerIdx + 1] ? remainingArgs[providerIdx + 1] : null;
|
|
2704
|
-
const provider = explicitAddonProvider ?? (config?.providers?.[0] ?? 'claude');
|
|
2784
|
+
const provider = resolveBuiltInProviderForUse(explicitAddonProvider ?? (config?.providers?.[0] ?? 'claude')).provider;
|
|
2705
2785
|
const targetIdx = remainingArgs.findIndex(a => a === '--target');
|
|
2706
2786
|
const target = targetIdx >= 0 && remainingArgs[targetIdx + 1] ? remainingArgs[targetIdx + 1] : process.cwd();
|
|
2707
2787
|
const dryRunAddon = remainingArgs.includes('--dry-run');
|
|
2788
|
+
let addonScope;
|
|
2789
|
+
try {
|
|
2790
|
+
addonScope = detectScope(remainingArgs);
|
|
2791
|
+
if (addonScope === 'project' && remainingArgs.includes('--user'))
|
|
2792
|
+
addonScope = 'user';
|
|
2793
|
+
}
|
|
2794
|
+
catch (error) {
|
|
2795
|
+
return { exitCode: 1, message: `Error: ${error instanceof Error ? error.message : String(error)}` };
|
|
2796
|
+
}
|
|
2797
|
+
if (addonScope === 'user' && !USER_SCOPE_PATHS[provider]) {
|
|
2798
|
+
return {
|
|
2799
|
+
exitCode: 1,
|
|
2800
|
+
message: `--scope user not supported for provider '${provider}' — see docs/customization/user-scope-deployment.md for the supported list`,
|
|
2801
|
+
};
|
|
2802
|
+
}
|
|
2708
2803
|
const runner = createScriptRunner(frameworkRoot);
|
|
2709
2804
|
const addonBaseArgs = ['--deploy-commands', '--deploy-skills', '--deploy-rules'];
|
|
2710
2805
|
// An explicitly selected upstream addon must be self-contained in the
|
|
@@ -2797,6 +2892,14 @@ export class UseHandler {
|
|
|
2797
2892
|
};
|
|
2798
2893
|
}
|
|
2799
2894
|
}
|
|
2895
|
+
if (!dryRunAddon && provider === 'omp' && (detectScope(remainingArgs) === 'user' || remainingArgs.includes('--user'))) {
|
|
2896
|
+
try {
|
|
2897
|
+
await deployOmpUserSource({ frameworkRoot, source: addonSource, target, bundle: framework, copyAll: true });
|
|
2898
|
+
}
|
|
2899
|
+
catch (error) {
|
|
2900
|
+
return { exitCode: 1, message: `OMP user deployment failed: ${error instanceof Error ? error.message : String(error)}` };
|
|
2901
|
+
}
|
|
2902
|
+
}
|
|
2800
2903
|
// Register only artifacts actually written by a confirmed deployment.
|
|
2801
2904
|
if (!dryRunAddon) {
|
|
2802
2905
|
try {
|
|
@@ -2922,7 +3025,7 @@ export class UseHandler {
|
|
|
2922
3025
|
catch {
|
|
2923
3026
|
// Profile selection is optional — don't fail deployment
|
|
2924
3027
|
}
|
|
2925
|
-
if (framework === 'aiwg-utils' &&
|
|
3028
|
+
if (framework === 'aiwg-utils' && !['pi', 'omp'].includes(provider) && !remainingArgs.includes('--dry-run')) {
|
|
2926
3029
|
const wrapperValidation = await validateDeployedModelWrappers({
|
|
2927
3030
|
provider: normalizeProviderDefinitionId(provider) ?? provider,
|
|
2928
3031
|
target,
|
|
@@ -3025,7 +3128,7 @@ export class UseHandler {
|
|
|
3025
3128
|
? withProviderOverride(deployFilteredArgs, provider)
|
|
3026
3129
|
: deployFilteredArgs;
|
|
3027
3130
|
const bulkKernelOnly = framework === 'all'
|
|
3028
|
-
&&
|
|
3131
|
+
&& !['pi', 'omp'].includes(provider)
|
|
3029
3132
|
&& !remainingArgs.includes('--copy-all')
|
|
3030
3133
|
&& !remainingArgs.includes('--copy-standard-skills');
|
|
3031
3134
|
if (bulkKernelOnly)
|
|
@@ -3234,7 +3337,7 @@ export class UseHandler {
|
|
|
3234
3337
|
// Pi model selection/headless routing is delivered by #2151. Until that
|
|
3235
3338
|
// adapter exists, do not require model-wrapper artifacts that Pi cannot
|
|
3236
3339
|
// load; resource deployment remains independently valid.
|
|
3237
|
-
if (!dryRun && !skipUtils && !bulkKernelOnly &&
|
|
3340
|
+
if (!dryRun && !skipUtils && !bulkKernelOnly && !['pi', 'omp'].includes(provider)) {
|
|
3238
3341
|
const wrapperValidation = await validateDeployedModelWrappers({
|
|
3239
3342
|
provider,
|
|
3240
3343
|
target,
|
|
@@ -3424,7 +3527,16 @@ export class UseHandler {
|
|
|
3424
3527
|
// mirror, record the deploy in the per-user registry at
|
|
3425
3528
|
// ~/.aiwg/installed.json so `aiwg list --scope user` and `aiwg remove
|
|
3426
3529
|
// --scope user` can find it from any cwd.
|
|
3427
|
-
if (scope === 'user' && provider
|
|
3530
|
+
if (scope === 'user' && provider === 'omp' && !dryRun) {
|
|
3531
|
+
try {
|
|
3532
|
+
await deployOmpUserSource({ frameworkRoot, source: frameworkRoot, target, bundle: framework, mode,
|
|
3533
|
+
copyAll: remainingArgs.includes('--copy-all') || remainingArgs.includes('--copy-standard-skills') });
|
|
3534
|
+
}
|
|
3535
|
+
catch (error) {
|
|
3536
|
+
return { exitCode: 1, message: `OMP user deployment failed: ${error instanceof Error ? error.message : String(error)}` };
|
|
3537
|
+
}
|
|
3538
|
+
}
|
|
3539
|
+
if (scope === 'user' && provider !== 'openhuman' && provider !== 'omp' && !dryRun) {
|
|
3428
3540
|
try {
|
|
3429
3541
|
const paths = getProviderPaths(provider);
|
|
3430
3542
|
const resolveProjectPath = (p) => !p ? '' : path.isAbsolute(p) ? p : path.join(target, p);
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* Per ADR-4 §2 path map. Per ADR-4 §1: `--scope user` and `--scope
|
|
10
10
|
* project` are mutually exclusive; default is `project`.
|
|
11
11
|
*/
|
|
12
|
+
import { resolveOmpPaths } from '../providers/omp-paths.mjs';
|
|
12
13
|
import { homedir } from 'node:os';
|
|
13
14
|
import * as path from 'node:path';
|
|
14
15
|
import { resolveHermesHome, resolveHermesHomePath } from '../providers/hermes-home.js';
|
|
@@ -57,6 +58,12 @@ export const USER_SCOPE_PATHS = {
|
|
|
57
58
|
rules: '',
|
|
58
59
|
behaviors: '',
|
|
59
60
|
},
|
|
61
|
+
get omp() {
|
|
62
|
+
const { agentDir } = resolveOmpPaths();
|
|
63
|
+
return { agents: path.join(agentDir, 'agents'), skills: path.join(agentDir, 'skills'),
|
|
64
|
+
commands: path.join(agentDir, 'prompts'), rules: path.join(agentDir, 'rules'),
|
|
65
|
+
behaviors: path.join(agentDir, 'extensions') };
|
|
66
|
+
},
|
|
60
67
|
pi: {
|
|
61
68
|
// Pi's global resource root is configurable. Unlike project deployment,
|
|
62
69
|
// user-scope resources belong under the effective agent directory. Keep
|