@aiwg/cli 2026.9.2 → 2026.9.4

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.
Files changed (68) hide show
  1. package/README.md +21 -0
  2. package/agentic/code/providers/antigravity/provider-contract.v1.json +121 -0
  3. package/agentic/code/providers/capability-matrix.yaml +87 -1
  4. package/agentic/code/providers/model-capabilities.v1.json +31 -0
  5. package/agentic/code/providers/model-catalog.v1.json +29 -0
  6. package/agentic/code/providers/omp/README.md +58 -0
  7. package/agentic/code/providers/omp/aiwg-bridge.ts +52 -0
  8. package/dist/src/agents/agent-deployer.js +18 -0
  9. package/dist/src/agents/agent-packager.js +25 -0
  10. package/dist/src/artifacts/backends/sqlite-backend.js +18 -10
  11. package/dist/src/artifacts/query-engine.js +30 -0
  12. package/dist/src/cli/agent-spawn.js +13 -2
  13. package/dist/src/cli/handlers/help.js +3 -1
  14. package/dist/src/cli/handlers/init.js +2 -0
  15. package/dist/src/cli/handlers/models.js +1 -1
  16. package/dist/src/cli/handlers/runtime-info.js +8 -1
  17. package/dist/src/cli/handlers/session.js +5 -4
  18. package/dist/src/cli/handlers/sessions.js +26 -9
  19. package/dist/src/cli/handlers/setup.js +9 -2
  20. package/dist/src/cli/handlers/steward.js +13 -2
  21. package/dist/src/cli/handlers/subcommands.js +11 -0
  22. package/dist/src/cli/handlers/team.js +68 -7
  23. package/dist/src/cli/handlers/use.js +158 -9
  24. package/dist/src/cli/scope-resolver.js +7 -0
  25. package/dist/src/config/aiwg-config.js +1 -0
  26. package/dist/src/dataset/fortemi-live-qualification.d.ts +53 -0
  27. package/dist/src/dataset/fortemi-live-qualification.js +297 -0
  28. package/dist/src/dataset/index.d.ts +1 -0
  29. package/dist/src/dataset/index.js +1 -0
  30. package/dist/src/mcp/cli.mjs +30 -1
  31. package/dist/src/mcp/omp-config.mjs +128 -0
  32. package/dist/src/mcp/registry.js +45 -5
  33. package/dist/src/mcp/registry.mjs +29 -6
  34. package/dist/src/models/model-capabilities.v1.json +31 -0
  35. package/dist/src/models/model-catalog.v1.json +29 -0
  36. package/dist/src/models/model-discovery.js +46 -5
  37. package/dist/src/models/provider-policy.js +5 -3
  38. package/dist/src/plugin/skill-command-translator.js +2 -0
  39. package/dist/src/providers/capability-matrix.yaml +87 -1
  40. package/dist/src/providers/omp-agent.mjs +40 -0
  41. package/dist/src/providers/omp-diagnostics.mjs +15 -0
  42. package/dist/src/providers/omp-paths.mjs +38 -0
  43. package/dist/src/providers/provider-definitions.js +83 -0
  44. package/dist/src/providers/provider-definitions.mjs +25 -1
  45. package/dist/src/providers/provider-inventory.js +2 -0
  46. package/dist/src/sessions/adapters/omp.js +203 -0
  47. package/dist/src/sessions/batch-import.js +7 -0
  48. package/dist/src/sessions/contracts.js +1 -1
  49. package/dist/src/sessions/importer.js +4 -3
  50. package/dist/src/sessions/index.js +1 -0
  51. package/dist/src/sessions/readers.js +4 -3
  52. package/dist/src/sessions/workspace-discovery.js +12 -2
  53. package/dist/src/skills/deployer.js +21 -1
  54. package/dist/src/smiths/agentsmith/generator.js +1 -0
  55. package/dist/src/smiths/context-pipeline/parallelism-section.js +2 -0
  56. package/dist/src/smiths/context-pipeline/provider-policy.js +2 -2
  57. package/dist/src/smiths/context-pipeline/workspace-context.js +2 -2
  58. package/dist/src/storage/backends/fortemi.js +142 -17
  59. package/dist/src/storage/fortemi-qualification-receipt.js +206 -0
  60. package/dist/src/storage/fortemi-qualification.js +67 -6
  61. package/dist/src/storage/index.js +1 -0
  62. package/package.json +2 -1
  63. package/schemas/dataset/fortemi-live-qualification-receipt.v1.schema.json +132 -0
  64. package/tools/agents/deploy-agents.mjs +6 -3
  65. package/tools/agents/providers/antigravity.mjs +147 -0
  66. package/tools/agents/providers/omp.d.mts +4 -0
  67. package/tools/agents/providers/omp.mjs +256 -0
  68. package/tools/providers/antigravity-transport.mjs +124 -0
package/README.md CHANGED
@@ -961,6 +961,27 @@ If both `aiwg` and `@aiwg/cli` were installed into the same prefix, the most
961
961
  recent install owns the shared executable link. Remove both, then install the
962
962
  distribution you intend to use.
963
963
 
964
+ ### Bundled setup requires the full package
965
+
966
+ `aiwg use all` and named framework setup such as `aiwg use sdlc` need the
967
+ framework and addon sources included in `aiwg`. The lightweight `@aiwg/cli`
968
+ package supports signed web lookup and external project-local bundle deployment;
969
+ web lookup does not download a complete source tree for bundled setup.
970
+
971
+ If setup reports that the full package is required, replace the lightweight
972
+ global installation and rerun setup with your provider:
973
+
974
+ ```bash
975
+ npm uninstall -g @aiwg/cli
976
+ npm install -g aiwg
977
+ aiwg use all --provider pi
978
+ ```
979
+
980
+ Older CLI versions can instead report `ENOENT` while scanning
981
+ `@aiwg/cli/agentic/code/addons`. The same recovery applies. Existing project
982
+ files are retained; the prerequisite check now stops before deployment or
983
+ project initialization, including in dry-run mode.
984
+
964
985
  ## Migrating Between Distributions
965
986
 
966
987
  From full AIWG to the lightweight package:
@@ -0,0 +1,121 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "contractVersion": "1.0.0",
4
+ "provider": "antigravity",
5
+ "aliases": ["agy"],
6
+ "displayName": "Google Antigravity CLI",
7
+ "status": "experimental",
8
+ "qualifiedCli": {
9
+ "executable": "agy",
10
+ "version": "1.1.26",
11
+ "platform": "linux-x64",
12
+ "observedOn": "2026-09-04",
13
+ "authenticatedExecution": false
14
+ },
15
+ "evidence": [
16
+ {
17
+ "id": "official-transition",
18
+ "url": "https://developers.googleblog.com/an-important-update-transitioning-gemini-cli-to-antigravity-cli/",
19
+ "retrieved": "2026-09-04",
20
+ "confidence": "high"
21
+ },
22
+ {
23
+ "id": "official-install",
24
+ "url": "https://antigravity.google/docs/cli/install/",
25
+ "retrieved": "2026-09-04",
26
+ "confidence": "high"
27
+ },
28
+ {
29
+ "id": "official-headless",
30
+ "url": "https://antigravity.google/docs/cli/headless/",
31
+ "retrieved": "2026-09-04",
32
+ "confidence": "high"
33
+ },
34
+ {
35
+ "id": "official-mcp",
36
+ "url": "https://antigravity.google/docs/cli/mcp/",
37
+ "retrieved": "2026-09-04",
38
+ "confidence": "high"
39
+ },
40
+ {
41
+ "id": "official-skills",
42
+ "url": "https://antigravity.google/docs/cli/plugins/",
43
+ "retrieved": "2026-09-04",
44
+ "confidence": "medium",
45
+ "notes": "Official pages disagree about the global skills directory and flat versus nested project layouts."
46
+ },
47
+ {
48
+ "id": "official-subagents",
49
+ "url": "https://antigravity.google/docs/cli/subagents/",
50
+ "retrieved": "2026-09-04",
51
+ "confidence": "high"
52
+ },
53
+ {
54
+ "id": "local-cli-help",
55
+ "path": "test/fixtures/providers/antigravity-conformance/help-1.1.26.json",
56
+ "retrieved": "2026-09-04",
57
+ "confidence": "high",
58
+ "sanitized": true
59
+ }
60
+ ],
61
+ "surfaces": {
62
+ "selection": { "classification": "native", "canonical": "antigravity", "aliases": ["agy"] },
63
+ "context": {
64
+ "classification": "native",
65
+ "projectFiles": ["AGENTS.md", "GEMINI.md"],
66
+ "precedence": "provider-defined; no undocumented include syntax assumed"
67
+ },
68
+ "workspaceSkills": {
69
+ "classification": "native",
70
+ "path": ".agents/skills",
71
+ "layout": "nested-skill-md",
72
+ "notes": "AIWG deploys directories containing SKILL.md and preserves unrelated children."
73
+ },
74
+ "globalSkills": {
75
+ "classification": "unknown",
76
+ "enabled": false,
77
+ "candidates": ["~/.gemini/antigravity-cli/skills", "~/.gemini/config/skills"],
78
+ "reason": "Conflicting official documentation; deferred pending a safe version-pinned probe."
79
+ },
80
+ "customAgents": {
81
+ "classification": "native",
82
+ "projectPaths": [".agents/agents/<name>.md", ".agents/agents/<name>/agent.md"],
83
+ "selectedLayout": "flat-markdown",
84
+ "projection": "degraded",
85
+ "reason": "Only AIWG tool names with documented Antigravity equivalents are projected; provider-specific model policy remains runtime-scoped."
86
+ },
87
+ "mcp": {
88
+ "classification": "native",
89
+ "projectPath": ".agents/mcp_config.json",
90
+ "userPath": "~/.gemini/config/mcp_config.json",
91
+ "serversKey": "mcpServers",
92
+ "remoteUrlKey": "serverUrl",
93
+ "merge": "preserve unrelated top-level keys and operator-owned server names"
94
+ },
95
+ "headless": {
96
+ "classification": "native",
97
+ "baseArgs": ["-p"],
98
+ "jsonArgs": ["--output-format", "json"],
99
+ "streamArgs": ["--output-format", "stream-json"],
100
+ "interactiveStreamArgs": ["--input-format", "stream-json", "--output-format", "stream-json"],
101
+ "continueFlags": ["--continue", "--conversation"],
102
+ "dangerousFlag": "--dangerously-skip-permissions",
103
+ "defaultPermissionMode": "request-review",
104
+ "stdout": "protocol",
105
+ "stderr": "diagnostics"
106
+ },
107
+ "teams": { "classification": "emulated", "adapter": "aiwg-mc" },
108
+ "cron": { "classification": "external", "adapter": "operator-owned scheduler invoking the bounded headless adapter" },
109
+ "tasks": { "classification": "emulated", "adapter": "aiwg-mc" },
110
+ "behaviors": { "classification": "unsupported" },
111
+ "missionControl": { "classification": "emulated", "adapter": "aiwg-mc" },
112
+ "daemon": { "classification": "unsupported" },
113
+ "plugins": { "classification": "unknown", "enabled": false }
114
+ },
115
+ "safety": {
116
+ "normalCi": "offline-only",
117
+ "readsUserConfiguration": false,
118
+ "writesAuthOrPermissionSettings": false,
119
+ "liveSmoke": "opt-in-only"
120
+ }
121
+ }
@@ -361,7 +361,7 @@ providers:
361
361
 
362
362
  hermes:
363
363
  display_name: Hermes
364
- status: experimental
364
+ status: stable
365
365
  daemon_tier: unsupported
366
366
  daemon_pty_adapter: false
367
367
  artifact_paths:
@@ -470,6 +470,51 @@ providers:
470
470
  deploy_target: mixed
471
471
  aggregated_output: true
472
472
 
473
+ antigravity:
474
+ display_name: Google Antigravity CLI
475
+ aliases:
476
+ - agy
477
+ status: experimental
478
+ executable: agy
479
+ qualified_version: 1.1.26
480
+ qualification_evidence: agentic/code/providers/antigravity/provider-contract.v1.json
481
+ daemon_tier: unsupported
482
+ daemon_pty_adapter: false
483
+ artifact_paths:
484
+ agents: .agents/agents/
485
+ commands: "(not deployed; no qualified native command surface)"
486
+ skills: .agents/skills/
487
+ rules: AGENTS.md
488
+ behaviors: "(not supported)"
489
+ mcp_project: .agents/mcp_config.json
490
+ mcp_user: "~/.gemini/config/mcp_config.json"
491
+ native_features:
492
+ cron: false
493
+ agent_teams: false
494
+ tasks: false
495
+ mcp: true
496
+ behaviors: false
497
+ mission_control: false
498
+ daemon: false
499
+ emulation:
500
+ cron: external-trigger
501
+ agent_teams: aiwg-mc
502
+ tasks: aiwg-mc
503
+ mcp: native
504
+ behaviors: null
505
+ mission_control: aiwg-mc
506
+ daemon: null
507
+ hook_wiring:
508
+ at_link_support: false
509
+ fallback: full-inject
510
+ context_file: AGENTS.md
511
+ interaction:
512
+ structured_questions: none
513
+ fallback: markdown
514
+ notes: No stable structured-question tool contract was qualified for CLI 1.1.26.
515
+ deploy_target: project
516
+ aggregated_output: false
517
+
473
518
  pi:
474
519
  display_name: Pi Coding Agent
475
520
  aliases:
@@ -511,6 +556,47 @@ providers:
511
556
  deploy_target: project
512
557
  aggregated_output: false
513
558
 
559
+ omp:
560
+ display_name: Oh My Pi
561
+ aliases:
562
+ - oh-my-pi
563
+ status: experimental
564
+ daemon_tier: unsupported
565
+ daemon_pty_adapter: false
566
+ artifact_paths:
567
+ agents: .omp/agents/
568
+ commands: .omp/prompts/
569
+ skills: .agents/skills/
570
+ skills_cross_agent: .agents/skills/
571
+ rules: .omp/rules/
572
+ behaviors: .omp/extensions/
573
+ native_features:
574
+ cron: false
575
+ agent_teams: true
576
+ tasks: true
577
+ mcp: true
578
+ behaviors: true
579
+ mission_control: false
580
+ daemon: false
581
+ emulation:
582
+ cron: external-trigger
583
+ agent_teams: null
584
+ tasks: null
585
+ mcp: null
586
+ behaviors: null
587
+ mission_control: aiwg-mc
588
+ daemon: null
589
+ hook_wiring:
590
+ at_link_support: true
591
+ fallback: full-inject
592
+ context_file: .omp/AGENTS.md
593
+ interaction:
594
+ structured_questions: none
595
+ fallback: markdown
596
+ notes: OMP integration uses Markdown questions; native UI questions require an interactive runtime.
597
+ deploy_target: project
598
+ aggregated_output: false
599
+
514
600
  # Feature definitions — documents what each feature key means and
515
601
  # what emulation strategies are available when native support is absent.
516
602
  features:
@@ -3,6 +3,17 @@
3
3
  "version": "1.0.0",
4
4
  "verifiedAt": "2026-07-20",
5
5
  "providers": {
6
+ "antigravity": {
7
+ "agent": "native", "skill": "native", "globalChild": "inherited",
8
+ "identifierSyntax": "model identifier accepted by Antigravity CLI 1.1.26 --model",
9
+ "effortValues": ["low", "medium", "high"],
10
+ "inheritance": "Omitted model and effort inherit the invoking Antigravity session",
11
+ "invalidPinFallback": "Provider validation/error; never assume fallback",
12
+ "configTarget": "agy launch arguments; custom-agent model tiers are not projected from generic AIWG model ids",
13
+ "artifactFormat": "YAML frontmatter plus Markdown; runtime --model and --effort flags",
14
+ "verification": "Pinned offline contract; authenticated model selection was not executed",
15
+ "sourceUrl": "https://antigravity.google/docs/cli/subagents/", "verifiedAt": "2026-09-04"
16
+ },
6
17
  "claude": {
7
18
  "agent": "native", "skill": "native", "globalChild": "inherited",
8
19
  "identifierSyntax": "Claude alias or accepted Anthropic model ID",
@@ -76,6 +87,26 @@
76
87
  "verification": "Inspect active profile and run metadata",
77
88
  "sourceUrl": "https://docs.warp.dev/agent-platform/capabilities/agent-profiles-permissions", "verifiedAt": "2026-07-20"
78
89
  },
90
+ "omp": {
91
+ "agent": "native",
92
+ "skill": "inherited",
93
+ "globalChild": "native",
94
+ "identifierSyntax": "provider/model identifier accepted by OMP --model",
95
+ "effortValues": [
96
+ "minimal",
97
+ "low",
98
+ "medium",
99
+ "high",
100
+ "xhigh"
101
+ ],
102
+ "inheritance": "Omitted model and thinking level inherit the invoking Pi session",
103
+ "invalidPinFallback": "Pi resolves against its configured catalog and exits on invalid explicit selection",
104
+ "configTarget": "OMP native agent frontmatter and runtime launch arguments",
105
+ "artifactFormat": "model and thinkingLevel frontmatter; --model and --thinking runtime flags",
106
+ "verification": "Pinned OMP 18.1.10 source and live OpenRouter smoke; individual role defaults remain operator configured",
107
+ "sourceUrl": "https://github.com/can1357/oh-my-pi/tree/5964a0f7649275bcde818f20073193fd032451f2/packages/coding-agent",
108
+ "verifiedAt": "2026-09-04"
109
+ },
79
110
  "pi": {
80
111
  "agent": "native", "skill": "inherited", "globalChild": "native",
81
112
  "identifierSyntax": "provider/model identifier accepted by Pi --model",
@@ -4,6 +4,14 @@
4
4
  "refreshedAt": "2026-07-20",
5
5
  "staleAfterDays": 90,
6
6
  "providers": {
7
+ "antigravity": {
8
+ "roles": {
9
+ "reasoning": { "id": "configured/reasoning", "status": "unverified", "observed": false },
10
+ "coding": { "id": "configured/coding", "status": "unverified", "observed": false },
11
+ "efficiency": { "id": "configured/efficiency", "status": "unverified", "observed": false }
12
+ },
13
+ "sourceUrl": "https://antigravity.google/docs/cli/overview/", "verifiedAt": "2026-09-04"
14
+ },
7
15
  "claude": {
8
16
  "roles": {
9
17
  "reasoning": { "id": "claude-opus-4-7", "status": "active", "observed": false },
@@ -52,6 +60,27 @@
52
60
  },
53
61
  "sourceUrl": "https://opencode.ai/docs/models", "verifiedAt": "2026-07-20"
54
62
  },
63
+ "omp": {
64
+ "roles": {
65
+ "reasoning": {
66
+ "id": "configured/reasoning",
67
+ "status": "unverified",
68
+ "observed": false
69
+ },
70
+ "coding": {
71
+ "id": "configured/coding",
72
+ "status": "unverified",
73
+ "observed": false
74
+ },
75
+ "efficiency": {
76
+ "id": "configured/efficiency",
77
+ "status": "unverified",
78
+ "observed": false
79
+ }
80
+ },
81
+ "sourceUrl": "https://github.com/can1357/oh-my-pi/tree/5964a0f7649275bcde818f20073193fd032451f2/packages/coding-agent",
82
+ "verifiedAt": "2026-09-04"
83
+ },
55
84
  "pi": {
56
85
  "roles": {
57
86
  "reasoning": { "id": "configured/reasoning", "status": "unverified", "observed": false },
@@ -0,0 +1,58 @@
1
+ # OMP native resources
2
+
3
+ The experimental `omp` provider targets Oh My Pi 18.1.10, reviewed at commit
4
+ `5964a0f7649275bcde818f20073193fd032451f2`. It remains separate from `pi`.
5
+
6
+ Project agents, Markdown prompts, rules and extensions use `.omp/agents`,
7
+ `.omp/prompts`, `.omp/rules` and `.omp/extensions`. Kernel skills use
8
+ `.agents/skills/<name>/SKILL.md`; `--copy-all` places standard skills in that
9
+ same one-level native directory. Default standard skills remain in the AIWG
10
+ source corpus for `aiwg discover` and `aiwg show`. Duplicate basenames fail
11
+ with a collision diagnostic before overwriting a different resource.
12
+
13
+ The `.omp/AGENTS.md` managed block uses native relative imports of root
14
+ WORKSPACE.md and AIWG.md. Other Markdown links remain ordinary links.
15
+ OMP's standalone root AGENTS discovery and foreign provider discovery are
16
+ independent: disable/enable those through OMP itself. AIWG does not rewrite
17
+ `disabledProviders`, foreign-user opt-in, extension settings or credentials.
18
+ Nearest native context and root-to-cwd standalone context can coexist. A
19
+ nested `.omp/AGENTS.md` shadows ancestor native context and rules: include
20
+ `@../../WORKSPACE.md` and `@../../AIWG.md` explicitly when the nested native
21
+ configuration is one directory below the repository root, or import the
22
+ ancestor bootstrap. OMP expands imports and deduplicates overlapping prompt blocks. Operator
23
+ content outside the bootstrap markers survives regeneration.
24
+
25
+ Agent descriptions and system prompt bodies retain their source text.
26
+ Explicit model IDs and priority lists pass through; configured model roles
27
+ use `modelsConfig.omp[role]`. Unmapped roles inherit the session model with a
28
+ degraded diagnostic. Unknown tool names are omitted with diagnostics. OMP
29
+ interprets an empty spawn list as absent, then infers wildcard spawns from
30
+ `task`; the adapter therefore removes `task` unless explicit spawn targets
31
+ or an explicit wildcard are supplied. Tool definitions are capability
32
+ selection, not a security sandbox.
33
+
34
+ The bridge registers native session start/shutdown, before-agent-start,
35
+ agent-end, tool-call and tool-result handlers. `/aiwg-bridge-status` reports
36
+ registration counts. No default policy handler is installed. Consumers use
37
+ `registerAiwgHandler` to attach an explicitly selected policy; tool-call
38
+ blocks are returned to the native harness and handler failure blocks that
39
+ call. Permission-request and pre-compaction enforcement are unsupported.
40
+ Native hook installation is distinct from this extension. Markdown prompts
41
+ are never executable custom commands.
42
+
43
+ `registerAiwgTool` accepts OMP's native tool definition together with input
44
+ and output validators. It propagates cancellation and execution errors,
45
+ and rejects invalid input/output. Runtime modules must be reviewed just
46
+ like any other executable OMP extension.
47
+
48
+ Deployment records SHA-256 ownership and transformation receipts beside
49
+ each resource. Refresh preserves operator creations and modifications,
50
+ even with force. The provider uninstall routine removes only unchanged
51
+ OMP-owned receipt entries and its own bootstrap markers. Disabling native
52
+ extension discovery remains an OMP setting; explicit extension paths may
53
+ still load despite `--no-extensions`.
54
+
55
+ Remove a complete OMP deployment with `aiwg remove omp --provider omp`.
56
+ Use `--dry-run` to preview or `--scope user` for the resolved OMP profile.
57
+ This is distinct from removing a single AIWG framework. Modified files and
58
+ unowned files remain, including other extensions and provider resources.
@@ -0,0 +1,52 @@
1
+ /** Native OMP bridge. Policy handlers are explicitly registered; no prompt-only enforcement. */
2
+ import type { ExtensionAPI, ToolDefinition } from '@oh-my-pi/pi-coding-agent';
3
+
4
+ export const supportedEvents = ['session_start', 'before_agent_start', 'tool_call', 'tool_result', 'agent_end', 'session_shutdown'] as const;
5
+ export const unsupportedEvents = ['permission_request', 'pre_compact_enforcement', 'native_hook_installation'] as const;
6
+ type Decision = { block: true; reason: string } | undefined;
7
+ type Handler = (event: unknown, context: unknown) => unknown | Promise<unknown>;
8
+ const handlers = new Map<string, Handler[]>();
9
+ export function registerAiwgHandler(event: string, handler: Handler): () => void {
10
+ if (!(supportedEvents as readonly string[]).includes(event)) throw new Error(`Unsupported OMP bridge event: ${event}`);
11
+ const list = handlers.get(event) || []; list.push(handler); handlers.set(event, list);
12
+ return () => { const at = list.indexOf(handler); if (at >= 0) list.splice(at, 1); };
13
+ }
14
+ export async function dispatchAiwgEvent(event: string, payload: unknown, context: unknown): Promise<Decision> {
15
+ for (const handler of handlers.get(event) || []) {
16
+ try {
17
+ const result = await handler(payload, context) as Decision;
18
+ if (event === 'tool_call' && result?.block) return { block: true, reason: String(result.reason || 'Denied by AIWG handler') };
19
+ } catch (error) {
20
+ if (event === 'tool_call') return { block: true, reason: `AIWG handler failed: ${error instanceof Error ? error.message : String(error)}` };
21
+ throw error;
22
+ }
23
+ }
24
+ return undefined;
25
+ }
26
+ /** ToolSmith callers provide schemas and validators; unsupported output never reaches OMP. */
27
+ export function registerAiwgTool(api: ExtensionAPI, tool: ToolDefinition, validateInput: (input: unknown) => boolean, validateOutput: (output: unknown) => boolean): void {
28
+ if (!tool.name || !tool.parameters || typeof tool.execute !== 'function') throw new Error('Invalid OMP custom tool contract');
29
+ api.registerTool({ ...tool, async execute(id, params, signal, update, context) {
30
+ if (signal?.aborted) throw new Error('AIWG tool cancelled');
31
+ if (!validateInput(params)) throw new Error('Invalid AIWG tool input');
32
+ const result = await tool.execute(id, params, signal, update, context);
33
+ if (signal?.aborted) throw new Error('AIWG tool cancelled');
34
+ if (!validateOutput(result)) throw new Error('Invalid AIWG tool output');
35
+ return result;
36
+ } });
37
+ }
38
+ export default function aiwgBridge(api: ExtensionAPI): void {
39
+ api.on('session_start', async (event, context) => { await dispatchAiwgEvent('session_start', event, context); });
40
+ api.on('before_agent_start', async (event, context) => { await dispatchAiwgEvent('before_agent_start', event, context); });
41
+ api.on('tool_call', (event, context) => dispatchAiwgEvent('tool_call', event, context));
42
+ api.on('tool_result', async (event, context) => { await dispatchAiwgEvent('tool_result', event, context); });
43
+ api.on('agent_end', async (event, context) => { await dispatchAiwgEvent('agent_end', event, context); });
44
+ api.on('session_shutdown', async (event, context) => { await dispatchAiwgEvent('session_shutdown', event, context); handlers.clear(); });
45
+ api.registerCommand('aiwg-bridge-status', {
46
+ description: 'Show active AIWG OMP lifecycle bridge registrations',
47
+ async handler(args, context) {
48
+ if (args.trim()) throw new Error('aiwg-bridge-status accepts no arguments');
49
+ context.ui.notify(`AIWG OMP bridge: ${supportedEvents.join(', ')}. Registered handlers: ${[...handlers.values()].reduce((n, list) => n + list.length, 0)}.`, 'info');
50
+ },
51
+ });
52
+ }
@@ -14,6 +14,7 @@
14
14
  import * as fs from 'fs/promises';
15
15
  import * as path from 'path';
16
16
  import { existsSync } from 'fs';
17
+ import YAML from 'yaml';
17
18
  import { AgentValidator } from './agent-validator.js';
18
19
  import { AgentPackager } from './agent-packager.js';
19
20
  import { getProviderDefinition } from '../providers/provider-definitions.js';
@@ -244,6 +245,23 @@ export class AgentDeployer {
244
245
  }
245
246
  }
246
247
  }
248
+ // Preserve provider-native fields consumed by the OMP packager. The
249
+ // historical line parser cannot represent arrays, booleans or objects.
250
+ const native = YAML.parse(frontmatter) || {};
251
+ for (const key of ['thinkingLevel', 'spawns', 'blocking', 'output', 'autoloadSkills', 'readSummarize', 'prewalk', 'advisor']) {
252
+ if (native[key] !== undefined)
253
+ Object.assign(metadata, { [key]: native[key] });
254
+ }
255
+ if (Array.isArray(native.model)) {
256
+ metadata.modelPriority = native.model;
257
+ delete metadata.model;
258
+ }
259
+ if (Array.isArray(native.tools))
260
+ metadata.tools = native.tools;
261
+ if (typeof native.name === 'string')
262
+ metadata.name = native.name;
263
+ if (typeof native.description === 'string')
264
+ metadata.description = native.description;
247
265
  return metadata;
248
266
  }
249
267
  /**
@@ -4,10 +4,14 @@
4
4
  * Converts agents to platform-specific formats.
5
5
  */
6
6
  import { getProviderDefinition } from '../providers/provider-definitions.js';
7
+ import YAML from 'yaml';
8
+ import { transformAgent as transformOmpAgent } from '../providers/omp-agent.mjs';
7
9
  export class AgentPackager {
8
10
  getAgentFormatAdapters() {
9
11
  return {
10
12
  'claude-markdown': (agent) => this.convertToClaudeFormat(agent),
13
+ 'antigravity-markdown': (agent) => this.convertToAntigravityFormat(agent),
14
+ 'omp-markdown': (agent) => this.convertToOmpFormat(agent),
11
15
  'cursor-json': (agent) => this.convertToCursorFormat(agent),
12
16
  'codex-markdown': (agent) => this.convertToCodexFormat(agent),
13
17
  'copilot-markdown': (agent) => this.convertToGenericFormat(agent),
@@ -16,6 +20,22 @@ export class AgentPackager {
16
20
  'windsurf-markdown': (agent) => this.convertToWindsurfFormat(agent),
17
21
  };
18
22
  }
23
+ /** Antigravity custom agents use Markdown with provider-native tool identifiers. */
24
+ convertToAntigravityFormat(agent) {
25
+ const lines = ['---', `name: ${agent.metadata.name}`, `description: ${agent.metadata.description}`];
26
+ const toolMap = new Map([
27
+ ['Read', 'view_file'],
28
+ ['Write', 'write_to_file'],
29
+ ['Edit', 'replace_file_content'],
30
+ ['Grep', 'grep_search'],
31
+ ['Bash', 'run_command'],
32
+ ]);
33
+ const tools = (agent.metadata.tools ?? []).map(tool => toolMap.get(tool)).filter((tool) => Boolean(tool));
34
+ if (tools.length)
35
+ lines.push('tools:', ...tools.map(tool => ` - ${tool}`));
36
+ lines.push('---', '', agent.content);
37
+ return lines.join('\n');
38
+ }
19
39
  /**
20
40
  * Package agent for target platform
21
41
  */
@@ -35,6 +55,11 @@ export class AgentPackager {
35
55
  format: definition.id,
36
56
  };
37
57
  }
58
+ /** Preserve native OMP metadata without passing through another provider's serializer. */
59
+ convertToOmpFormat(agent) {
60
+ const metadata = { ...agent.metadata, model: agent.metadata.modelPriority ?? agent.metadata.model };
61
+ return transformOmpAgent(agent.filePath, `---\n${YAML.stringify(metadata)}---\n${agent.content}`);
62
+ }
38
63
  /**
39
64
  * Convert to Claude Code format (.md with YAML frontmatter)
40
65
  */
@@ -50,28 +50,36 @@ export class SqliteGraphBackend {
50
50
  catch {
51
51
  throw new Error('sqlite backend is unavailable; run `aiwg features install sqlite`');
52
52
  }
53
- this.assertSafeSqliteVersion();
54
- const requestedJournal = dbPath === ':memory:' ? 'memory' : 'wal';
55
- const actualJournal = String(this.db.pragma(`journal_mode = ${requestedJournal}`, { simple: true })).toLowerCase();
56
- if (actualJournal !== requestedJournal) {
53
+ try {
54
+ // Changing journal mode may return SQLITE_BUSY without invoking SQLite's
55
+ // busy handler during a lock upgrade. Retry initialization as a whole:
56
+ // pragmas are idempotent and failed schema transactions roll back.
57
+ this.withBusyContext('initializing the graph database', () => {
58
+ this.assertSafeSqliteVersion();
59
+ const requestedJournal = dbPath === ':memory:' ? 'memory' : 'wal';
60
+ const actualJournal = String(this.db.pragma(`journal_mode = ${requestedJournal}`, { simple: true })).toLowerCase();
61
+ if (actualJournal !== requestedJournal) {
62
+ throw new Error(`sqlite backend requested journal_mode=${requestedJournal} but received ${actualJournal}`);
63
+ }
64
+ this.db.pragma(`synchronous = ${options.synchronous ?? 'NORMAL'}`);
65
+ this.db.pragma('wal_autocheckpoint = 1000');
66
+ this.migrateSchema();
67
+ });
68
+ }
69
+ catch (error) {
57
70
  this.db.close();
58
- throw new Error(`sqlite backend requested journal_mode=${requestedJournal} but received ${actualJournal}`);
71
+ throw error;
59
72
  }
60
- this.db.pragma(`synchronous = ${options.synchronous ?? 'NORMAL'}`);
61
- this.db.pragma('wal_autocheckpoint = 1000');
62
- this.migrateSchema();
63
73
  }
64
74
  assertSafeSqliteVersion() {
65
75
  const version = String(this.db.prepare('SELECT sqlite_version() AS version').get().version);
66
76
  if (!isWalResetSafeVersion(version)) {
67
- this.db.close();
68
77
  throw new Error(`sqlite backend requires a WAL-reset-safe SQLite build (3.44.6, 3.50.7, or >=3.51.3); found ${version}`);
69
78
  }
70
79
  }
71
80
  migrateSchema() {
72
81
  const current = Number(this.db.pragma('user_version', { simple: true }));
73
82
  if (current > SCHEMA_VERSION) {
74
- this.db.close();
75
83
  throw new Error(`sqlite graph schema ${current} is newer than supported schema ${SCHEMA_VERSION}`);
76
84
  }
77
85
  if (current === SCHEMA_VERSION)
@@ -101,6 +101,22 @@ function containsTokenSequence(haystack, needle) {
101
101
  function withIndexProvenance(entry, graph) {
102
102
  return { ...entry, indexGraph: graph, indexScope: graphScope(graph) };
103
103
  }
104
+ /** Keep existing project capabilities visible while their derived cache is unavailable. */
105
+ function projectCapabilityFallback(cwd) {
106
+ const index = loadGraphIndexFile(cwd, 'metadata.json', 'project');
107
+ if (index) {
108
+ const entries = Object.values(index.entries).map((entry) => withIndexProvenance(entry, 'project'));
109
+ if (entries.length > 0) {
110
+ // One diagnostic per command, on stderr so JSON and skill bodies stay parseable.
111
+ console.error('Warning: project capability cache is unavailable or stale; using the local project index. Run `aiwg index sync` to repair the cache.');
112
+ return entries;
113
+ }
114
+ }
115
+ if (['extensions', 'addons', 'frameworks', 'plugins', 'skills'].some((dir) => fs.existsSync(projectAiwgPath(cwd, dir)))) {
116
+ console.error('Warning: project capabilities could not be loaded: the cache is unavailable and the local project index is missing or empty. Run `aiwg index build --graph project` to repair discovery.');
117
+ }
118
+ return index ? [] : null;
119
+ }
104
120
  function discoveryIdForEntry(entry) {
105
121
  return stableRecordId(recordTypeForEntry(entry, 'v2'), entry.path);
106
122
  }
@@ -919,6 +935,13 @@ export async function discoverCapability(cwd, params) {
919
935
  let unavailableReason;
920
936
  for (const graph of graphs) {
921
937
  const loaded = loadFortemiCoreMetadataEntries(cwd, graph, verifiedSourcePaths);
938
+ if (loaded.reason && graph === 'project' && !params.graph) {
939
+ const fallback = projectCapabilityFallback(cwd);
940
+ if (fallback) {
941
+ entries.push(...fallback);
942
+ continue;
943
+ }
944
+ }
922
945
  if (loaded.reason)
923
946
  unavailableReason ??= loaded.reason;
924
947
  entries.push(...loaded.entries.map((entry) => withIndexProvenance(entry, graph)));
@@ -1373,6 +1396,13 @@ async function loadShowEntries(cwd, params) {
1373
1396
  let unavailableReason;
1374
1397
  for (const graph of graphs) {
1375
1398
  const loaded = loadFortemiCoreMetadataEntries(cwd, graph);
1399
+ if (loaded.reason && graph === 'project' && !params.graph) {
1400
+ const fallback = projectCapabilityFallback(cwd);
1401
+ if (fallback) {
1402
+ entries.push(...fallback);
1403
+ continue;
1404
+ }
1405
+ }
1376
1406
  if (loaded.reason)
1377
1407
  unavailableReason ??= loaded.reason;
1378
1408
  entries.push(...loaded.entries.map((entry) => withIndexProvenance(entry, graph)));