Commit Graph

160 Commits

Author SHA1 Message Date
roboomp c74e9d324f fix(extensions): disambiguated .agent dirs provider tab label
The /extensions dashboard built one tab per provider from its displayName.
The .agent/.agents config-standard provider used "Agents (standard)", which
collided with the first-class /agents subagents feature even though the tab
only surfaces skills, rules, prompts, commands, and context/system files.
Renamed DISPLAY_NAME to "Agent Dirs (.agent/.agents)".

Fixes #5821
2026-07-17 09:04:40 +00:00
roboomp 64e6ffc454 fix(discovery): isolated Claude local plugins
Filtered Claude Code local marketplace entries against the canonical active project before exposing plugin roots.

Fixes #5750
2026-07-16 20:29:36 +00:00
can1357 61cb9cb4e3 merged PR #5562: fix(discovery): root Codex config.toml MCP command/cwd at config dir 2026-07-16 03:31:55 +02:00
can1357 b52c798025 feat(coding-agent/discovery): set builtin discovery rules to interruptMode never
- Added `interruptMode: never` to all updated Go, Rust, and TypeScript built-in discovery rule files.
- Changed `ts-no-inline-cast-access.md` from `interruptMode: tool-only` to `interruptMode: never`.
2026-07-15 14:34:38 +02:00
roboomp 0d0df064e0 fix(discovery): gated cwd-based command rooting to codex importer
The previous follow-up rooted path-like commands at the resolved cwd in
the shared resolvePluginStdioPaths helper, which regressed plugin
.mcp.json semantics: plugin commands are relative to the plugin package
root, so a plugin shipping ./bin/server with cwd="work" would resolve to
<pkg>/work/bin/server and ENOENT. Add a commandBase parameter defaulting
to "config-dir" (the plugin contract) and pass "cwd" only from the Codex
importer, where the OS resolves the relative command against the spawned
process cwd.

Fixes #5561
2026-07-15 10:05:08 +00:00
roboomp e88c45f063 fix(discovery): resolved plugin stdio command against rooted cwd
resolvePluginStdioPaths resolved a path-like command against the config
directory unconditionally, but the stdio transport spawns the subprocess
with the rooted cwd as its process cwd, so the OS resolves a relative
command from there. For cwd="server", command="./bin/mcp" that meant OMP
looked for <configDir>/bin/mcp instead of <configDir>/server/bin/mcp.
Root cwd first, then resolve path-like commands from that rooted cwd,
falling back to configDir only when no cwd is set.

Fixes #5561
2026-07-15 09:56:18 +00:00
roboomp d6683c351a fix(discovery): rooted codex toml mcp command/cwd at config dir
The Codex config.toml importer copied only command/args/url into the
returned MCPServer, dropping cwd and leaving relative command values
verbatim. MCP stdio spawning resolved those against the session cwd, so
the bundled Codex Computer Use server (relative command, cwd = ".") failed
with ENOENT. Route command/cwd through resolvePluginStdioPaths against the
config directory, matching the claude-plugins/omp-plugins fix in #5481.

Fixes #5561
2026-07-15 09:43:46 +00:00
can1357 425e583ae0 feat(coding-agent): added support for task-agent field and model resolution
- Added schema and type updates for task-agent fields and model resolver settings.
- Extended discovery helper logic to carry resolved task-agent metadata through execution setup.
- Updated task/agent registration and execution paths to use the new capability/field data.
- Expanded test coverage for agent-field parsing, model resolution, and executor prewalk behavior.
2026-07-15 00:50:55 +02:00
can1357 52f0d3f9e6 fix(discovery): tolerate malformed plugin cwd 2026-07-14 22:58:46 +02:00
roboomp 6467a3119e fix(discovery): rooted relative plugin mcp command and cwd at config dir
Discovered plugin .mcp.json stdio servers launched relative command/cwd
values against the session cwd instead of the plugin's config directory,
breaking bundled ChatGPT/Codex plugins (e.g. Computer Use) with ENOENT
when spawning ./... from an unrelated cwd.

The claude-plugins and omp-plugins providers now resolve relative cwd and
path-like command (./ or ../) against the .mcp.json directory via a shared
resolvePluginStdioPaths helper; bare executables such as npx are left
untouched so PATH lookup still works.

Fixes #5330
2026-07-14 18:36:21 +00:00
can1357 441037025a feat(coding-agent): updated thinking-level configuration and precedence
- Configured the default `task` subagent to use `auto` thinking.
- Enabled `auto` as a valid thinking-level value in agent frontmatter.
- Adjusted thinking-level precedence to ensure that explicit `:level` suffixes in resolved model patterns override agent-defined defaults.
2026-07-11 13:35:05 +02:00
can1357 7e4360d317 fix(discovery): preserve marketplace-root skill selection 2026-07-08 15:19:38 +02:00
can1357 5d20a739b7 merge PR #4610: fix(discovery): accept array-form Claude plugin manifest paths 2026-07-08 15:19:37 +02:00
roboomp 071f199a1d fix(agent): kept project sticky rules active
Synthesized project .omp/RULES.md as a distinct sticky rule name so capability dedup no longer shadows it behind the user sticky rule.

Added a public rules capability regression test covering user and project sticky RULES.md files loading together.

Fixes #4739
2026-07-06 19:43:46 +00:00
roboomp 914dc9551a fix(coding-agent): kept claude home skills user-scoped
Skipped the home directory during Claude project skill walk-up so disabling Claude user skills cannot reload the same files as project skills.

Added regression coverage for the home-skill duplicate path with an enabled agents fallback.

Fixes #4648
2026-07-06 01:06:48 +00:00
roboomp c92cf0a905 fix(discovery): load Claude plugin skill paths that point at a SKILL.md directory
Claude plugin manifests may declare a `skills` path that resolves directly to a
directory whose `SKILL.md` IS the skill (e.g. `"skills": ["./"]` or a
subdirectory containing only `SKILL.md`). `scanSkillsFromDir` only scanned
`<dir>/<name>/SKILL.md` children, so the single-skill directory layout — the
common shape the Claude plugins reference documents for plugins shipping one
skill — silently dropped every array-form manifest entry that pointed at it.

Add an opt-in `includeSelf` flag to `ScanSkillsFromDirOptions`: when set,
`<dir>/SKILL.md` (if present) is loaded as a skill in addition to the existing
child scan. The Claude plugin skills loader opts in; every other provider
(agents, builtin, claude.ts, codex, github, omp-plugins, opencode) keeps the
strict child-scan semantic they rely on. Frontmatter `name` still wins over
the directory basename fallback.

Regression test: `skills: ["./single"]` where `./single/SKILL.md` is the only
skill file loads the skill under its frontmatter name.
2026-07-05 12:23:18 +00:00
roboomp c42d2b2907 fix(discovery): load file-form Claude plugin commands
Claude plugin manifests allow command path entries to name either directories
or flat `.md` command files. The array resolver was now preserving those file
paths, but `loadSlashCommands` still sent every resolved entry through
`loadFilesFromDir`, which only globs inside directories. A manifest such as
`{"commands":["./custom/deploy.md"]}` therefore replaced the default scan
and then loaded nothing.

Teach the command loader to stat each resolved entry: `.md` files are read as
single slash commands with the same plugin namespace and source metadata as
directory-loaded files; directories continue through `loadFilesFromDir`.
Missing entries keep the existing silent-empty behavior.

Add a regression test covering a mixed array of a direct command file and a
command directory while proving default `commands/` remains replaced unless
listed explicitly.
2026-07-05 12:16:02 +00:00
roboomp f276d80fc4 fix(discovery): honour per-field Claude plugin path merge semantics
Review feedback on #4610: array-form skills was silently replacing the
default `skills/` scan when the manifest declared any explicit entries.
Per the Claude plugins reference "Path behavior rules"
(https://code.claude.com/docs/en/plugins-reference#path-behavior-rules):

- `skills` ADDS to the default `skills/` scan
- `commands` / `slash-commands` REPLACE the default `commands/` scan

`resolvePluginDir` now takes an explicit `includeFallback` flag. `loadSkills`
passes `true` (fallback + declared entries, deduped by resolved absolute
path so a manifest may still list `./skills` alongside extras without
double-load); `loadSlashCommands` passes `false` (replace semantic
preserved). Deduplication keeps the fallback first and declared entries
in manifest order.

Regression tests cover both semantics: skills-array merges with default
`skills/`; commands-array replaces default `commands/` so a stray
`commands/default.md` no longer loads once the manifest declares an
alternative — matching Claude's documented behavior.
2026-07-05 12:09:22 +00:00
roboomp d9ef874e2b fix(discovery): accept array-form Claude plugin manifest paths
The Claude plugin manifest allows `commands`, `slash-commands`, and `skills`
to be either a single string or an array of strings — documented under
https://code.claude.com/docs/en/plugins-reference#path-behavior-rules and
used by real marketplace plugins such as addyosmani/agent-skills whose
plugin.json declares `"commands": ["./.claude/commands", "./commands"]`.

`resolvePluginDir` in `packages/coding-agent/src/discovery/claude-plugins.ts`
typed those manifest fields as `string` only, so array-shaped values were
silently dropped: no items loaded, no warning surfaced. Slash commands
(`spec`, `plan`, `build`, `test`, `review`) never appeared in the picker.

Normalize `string | string[]` at the resolver, load every in-root entry,
and emit one out-of-plugin-root warning per bad entry so misconfigured
paths remain observable. Skills and slash-command loaders now fan out over
the resolved directory list and merge warnings from all sources.

Fixes #4609
2026-07-05 12:02:47 +00:00
roboomp 15c4835e99 fix(coding-agent): cached plugin extension resolution
- Added shared plugin cache invalidators wired through clearClaudePluginRootsCache.\n- Memoized enabled plugin discovery and legacy bare dependency fallback resolution.\n- Added regression coverage for cache reuse and invalidation.\n\nFixes #4197
2026-07-02 04:54:10 +00:00
can1357 dcc7a1ce2c feat(coding-agent/discovery): added Go syntax and API discovery rules
- Added eight new Go-specific rules to the discovery package.
- Registered the new Go rules in the default rule source index.
- Covered the new Go AST matching conditions with test cases in `builtin-defaults.test.ts`.
2026-06-30 09:49:59 +02:00
roboomp 500c39aa2e fix(extensions): isolate codex hook scripts so process.exit cannot kill OMP startup
Codex discovery surfaced every `~/.codex/hooks/*.{ts,js}` file as an OMP
hook (silently defaulting untyped names to `pre:<basename>`), and
`discoverExtensionPaths` then handed those paths to `loadExtension` for
dynamic import. A standalone Codex hook script with a top-level
`process.exit(0)` terminated the host CLI cleanly — `try/catch` around
`await import()` cannot intercept a synchronous exit, so OMP died at the
`loadExtensions:start` startup marker with no error surface.

Two-layer fix:

- `packages/coding-agent/src/extensibility/utils.ts`: new
  `withExitGuard` helper patches `process.exit` for the duration of a
  guarded callback so an exit raises `ExtensionExitError` instead of
  terminating the process; nested and concurrent guards restore correctly
  via depth counter.
- `extensibility/extensions/loader.ts`, `extensibility/hooks/loader.ts`,
  and `extensibility/plugins/manager.ts` wrap their dynamic-import sites
  in `withExitGuard` so the existing per-module `try/catch` records the
  intercepted exit as a load error and OMP keeps starting.
- `discovery/codex.ts:loadHooks` no longer treats arbitrary files as
  OMP hooks: only `pre-<tool>.{ts,js}` and `post-<tool>.{ts,js}` are
  registered. Files like `memory-bank-reminder.ts` are silently skipped
  rather than imported as extension factories.

Adds regression coverage:

- `test/extension-loader-process-exit.test.ts` — `loadExtensions` /
  `loadHooks` return errors and leave `process.exit` restored when a
  module exits at import time; sibling modules still load.
- `test/discovery/codex-hooks-discovery.test.ts` — codex provider
  registers `pre-*` / `post-*` files and drops everything else.

Fixes #3680
2026-06-27 20:38:53 +00:00
roboomp e36172c32c fix(coding-agent): hid marketplace plugins from npm lists
Filtered marketplace-managed runtime symlinks out of the npm plugin listing and OMP extension-package status provider while keeping marketplace installs available to the runtime loader. Added regressions for both duplicate surfaces.

Fixes #3628
2026-06-27 05:04:28 +00:00
roboomp 7289cd4baf fix(mcp): expanded plugin env headers
Expanded environment variable placeholders in Claude marketplace plugin MCP url and headers before registration. Added a regression test covering context7-style HTTP server headers.\n\nFixes #3621
2026-06-27 03:16:45 +00:00
can1357 ae1650d689 refactor: renamed search and find tools to grep and glob
- Renamed the `find` and `search` tools to `glob` and `grep` respectively across the codebase to improve command clarity.
- Implemented full-stack support for the renamed tools, including CLI arguments, system prompts, SDK exports, and tool registration.
- Added automated migration logic in `settings` to transform legacy `find` and `search` configuration keys to their new equivalents.
- Updated the `collab-web` renderer registry to ensure backwards compatibility with legacy tool outputs.
2026-06-27 00:57:55 +02:00
roboomp bcfb5b5d8b fix(marketplace): preserved plugin root scope
Carried user/project root scope through enabled plugin enumeration so project marketplace installs keep project-level discovery metadata.
2026-06-22 08:59:24 +00:00
roboomp c531117869 fix(mcp): normalized opencode command arrays
Mapped OpenCode MCP array commands to stdio command plus args and accepted environment as the provider-native env key.\n\nAdded regression coverage for array command normalization, environment mapping, env fallback, and empty args omission.\n\nFixes #3180
2026-06-21 09:23:54 +00:00
can1357 9478e3cc5c refactor: replaced ReturnType<typeof setTimeout> with Timer type
- Replaced usage of `ReturnType<typeof setTimeout>` and `ReturnType<typeof setInterval>` with the explicit `Timer` type across the codebase.
- Updated several type definitions and function signatures to use concrete types instead of inferred return types for improved clarity and maintainability.
2026-06-19 17:38:07 +02:00
can1357 a050474af7 feat: migrated validation schemas and tool definitions from Zod to ArkType
- Migrated all wire protocol, schema definitions, and tools validation from Zod to ArkType across multiple packages.
- Updated extension runtimes, custom tools loader, and TypeBox compatibility shim to expose and use ArkType instances.
- Added a comprehensive ArkType migration guide, validation parity tests, and helper utilities.
- Removed redundant PDF asset routing and parsing implementations from the read tool.
2026-06-18 00:59:53 +02:00
can1357 ee41822c27 feat(coding-agent/discovery): added ts-no-inline-cast-access rule to built-in discovery rules
- Added a new builtin rule definition file, `ts-no-inline-cast-access.md`, with AST patterns that flag inline cast member access and usage guidance.
- Registered the new rule in `src/discovery/builtin-rules/index.ts` so it is included in the built-in TypeScript rule set.
- Updated `ts-no-any.md` to recommend schema parsing at trust boundaries and clarified when to choose schema parsing, guards, or unchecked casts.
2026-06-17 20:42:39 +02:00
can1357 c509a5d59c fix(coding-agent): honor comma-separated and **/* Copilot applyTo globs
GitHub documents applyTo as a single comma-separated string (e.g.
"**/*.ts,**/*.tsx") and treats both ** and **/* as all-files. The rule
loader kept the whole CSV value as one glob and missed **/* for
always-apply. Split applyTo via parseCSV and include **/* as all-files.

Addresses review feedback on #2734.
2026-06-16 14:23:50 +02:00
roboomp 063ce1ba00 fix(coding-agent): loaded github instruction rules
Added GitHub Copilot instruction-file discovery to the github rule provider path, mapping applyTo frontmatter into always-apply or glob-scoped rules and avoiding duplicate always-apply prompt content when context imports the same file.\n\nFixes #2731
2026-06-16 02:30:58 +00:00
can1357 b7a6a5e44c Merge PR #2651: fix(coding-agent): hide plugin skills from slash commands 2026-06-15 19:46:13 +02:00
can1357 ec752d77e8 Merge PR #1983: feat(discovery): GitHub Copilot user-global instructions, env dirs, and prompts (#1913, #1915, #1916) 2026-06-15 19:46:12 +02:00
roboomp b21385d13c fix(coding-agent): hid plugin skills from slash commands
Removed Claude marketplace plugin skill mirroring from slash-command discovery while keeping real plugin commands registered.\n\nFixes #2645
2026-06-15 12:52:12 +00:00
Ogrodev 87da6d373f fix(coding-agent): scope managed skills to profiles 2026-06-14 20:49:05 -03:00
Ogrodev 0123a46f83 Merge remote-tracking branch 'upstream/main' into feat/profiles-and-alias
# Conflicts:
#	packages/coding-agent/src/cli/args.ts
2026-06-14 19:10:31 -03:00
SUPREME 12ef9b11a9 fix(discovery): follow symlinked extension packages 2026-06-14 17:25:53 +02:00
can1357 7985e760d7 Merge remote-tracking branch 'origin/farm/391be2bd/discover-plugin-skills' 2026-06-14 17:10:19 +02:00
roboomp fde233278c fix(cli): synthesize plugin skill slash commands from directory basename
When a Claude plugin skill's SKILL.md frontmatter uses a display-style
name (e.g. `name: Understand Anything`), the synthesized slash command
inherited that text. `expandSlashCommand` splits the command at the
first whitespace, so `/understand` never resolved and the multi-word
form could not expand either.

Use `path.basename(path.dirname(skill.path))` so the slash command
always matches the documented `skills/<name>/SKILL.md` → `/<name>`
contract while the frontmatter still drives the description/body.

Fixes #2415
2026-06-14 07:12:42 +00:00
metaphorics 18ee97751a feat(coding-agent): opt-in experimental auto-learn (memory + isolated managed skills)
Add a default-off "auto-learn" loop. When `autolearn.enabled` is set, after the
agent stops a session controller nudges it to capture reusable lessons: durable
facts go to long-term memory and repeatable procedures become "managed skills" —
SKILL.md files written to an isolated ~/.omp/agent/managed-skills directory that is
discovered and surfaced like authored skills but never overwrites them.

Two tools back this:
- `manage_skill` — create/update/delete managed skills.
- `learn` — record a lesson, optionally minting/enhancing a managed skill in the
  same call (requires a hindsight/mnemopi memory backend).

The nudge is passive by default (a hidden reminder rides the next turn);
`autolearn.autoContinue` instead auto-runs one capture turn at stop, and
`autolearn.minToolCalls` (default 5) gates trivial turns. Plan/goal-mode turns and
subagents are never nudged, and the controller re-checks the live setting at fire
time so a mid-session opt-out takes effect.

Isolation & precedence: managed skills are a separate lowest-priority discovery
provider, so an authored skill of the same name wins across every provider and
custom directory regardless of third-party toggles; a disabled higher-priority
authored skill can never hide a managed one, and managed never masks an enabled
authored skill. Managed names and descriptions are sanitized on both write and
read (control/format chars, angle brackets, and Markdown fences) before they render
into the system prompt, and the SKILL.md byte cap is enforced on the final
serialized file.

Default off → zero footprint when disabled.
2026-06-14 10:45:23 +09:00
roboomp 0b444b83bf fix(cli): exposed claude plugin skills as slash commands
Loaded Claude Code marketplace plugin SKILL.md files into the slash-command capability so Claude-native plugin docs like /understand work in autocomplete and invocation.\n\nAdded a regression covering OMP installed plugin registries and bare slash-command expansion.\n\nFixes #2415
2026-06-12 19:28:35 +00:00
Asaf Mahlev a8db2747e5 fix(discovery): correct Copilot custom-instruction-dir and prompt handling
Address review against GitHub Copilot CLI docs (add-custom-instructions):

- COPILOT_CUSTOM_INSTRUCTIONS_DIRS: each dir contributes AGENTS.md (context) and .github/instructions/**/*.instructions.md (recursive), per spec. Dropped the non-spec <dir>/copilot-instructions.md and the wrong top-level <dir>/*.instructions.md scan.

- Scan the project .github/instructions/ tree recursively ('within or below').

- Prompts: .github/prompts/*.prompt.md is a VS Code construct, not a Copilot CLI feature; dropped the fictional ~/.copilot/prompts/ user dir and reframed comments/descriptions accordingly.
2026-06-12 19:15:34 +03:00
Asaf Mahlev 873f3222a1 feat(discovery): GitHub Copilot user-global instructions and prompts
The github provider only scanned the project .github/ tree, so Copilot CLI's user-global config was ignored. Add user-global instructions (~/.copilot/copilot-instructions.md), COPILOT_HOME relocation, COPILOT_CUSTOM_INSTRUCTIONS_DIRS (copilot-instructions.md + *.instructions.md), and prompt discovery (*.prompt.md in .github/prompts/ and ~/.copilot/prompts/).

Closes #1913, #1915, #1916.
2026-06-12 19:15:33 +03:00
Ogrodev 2f60eaf938 feat(coding-agent): bind MCP OAuth credentials per profile via url-keyed ids
Store MCP OAuth credentials under deterministic mcp_oauth:<url> ids in each
profile's agent.db with refresh material embedded, so a definition-only entry
in a shared project mcp.json resolves each profile's own credential instead
of profiles clobbering each other's auth.credentialId pointer.

- Refresh material is single-source: embedded credential fields win over the
  config auth block (which may belong to another profile); legacy rows fall
  back to the auth block wholesale
- Wire the 401 refresh hook off the resolvable credential, not the auth
  block, so definition-only bindings refresh mid-session too
- The url-keyed fallback never overrides a pinned Authorization header
- Send prompt=consent by default (oauth.prompt to override, "" to omit) so
  reauth can switch accounts past an active browser session
- /mcp reauth fails fast on stdio transports (with an mcp-remote ~/.mcp-auth
  hint), probes http/sse without OAuth injection, GCs the superseded legacy
  row only after the flow succeeds, and leaves definition-only entries
  untouched on disk
- DCR-issued client secrets stay embedded in the stored credential and are
  never written into config files; user-supplied secrets survive reauth
2026-06-10 18:40:07 -03:00
Ogrodev 73b1f895d1 Merge upstream/main into feat/profiles-and-alias 2026-06-08 15:54:57 -03:00
can1357 6ceda1d477 Merge remote-tracking branch 'origin/farm/dd3aaf05/expand-agents-md-at-imports' 2026-06-08 19:08:37 +02:00
roboomp 8500070700 fix(coding-agent): expanded @-imports in AGENTS.md/CLAUDE.md context files
CLAUDE.md, AGENTS.md, GEMINI.md (and the other discovered context-file
flavors) all carry the @-import convention every other agent ships:
`@path/to/file` inside a memory file inlines that file's contents at
launch. The discovery loaders previously read the file content verbatim
and handed it straight to the system prompt builder, so a CLAUDE.md
whose entire body is `@AGENTS.md` shipped a single literal `@AGENTS.md`
line and Claude never saw the project rules.

Added discovery/at-imports.ts implementing the Claude-Code semantics:
relative paths resolve against the importing file's directory, `~/`
expands to home, recursion stops at MAX_AT_IMPORT_DEPTH (5) with cycle
detection, fenced code blocks and inline code spans are opaque so
`npm install @types/node` and `git@github.com` round-trip verbatim, and
missing files keep the literal @-token intact. Wired the expander
into loadProjectContextFiles so every provider that registers under
the context-file capability benefits without per-provider plumbing.

Fixes #2111
2026-06-08 15:02:18 +00:00
can1357 bf6b80e575 feat(discovery): added built-in test timers rule to defaults
- Added a new built-in TTSR rule `ts-no-test-timers.md` that flags `Bun.sleep`, `setTimeout`, and `setInterval` usage in `*.test.ts` files.
- Registered `ts-no-test-timers` in the built-in rules index so it ships with default discovery providers.
- Updated builtin-defaults tests to enforce rule-name uniqueness and verify the new rule only matches in `*.test.ts` scopes.
2026-06-08 15:18:54 +02:00
can1357 a84da2a61e feat(coding-agent): added AST-condition matching for interrupt flow rule handling
- Added astCondition to rule frontmatter parsing and rule metadata, with AST-grep normalization.
- Updated TTSR bucketing so astCondition-only rules are treated as interruptible matches.
- Added ts-redundant-clear-guard as a built-in JS/TS tool rule for guarded clear* calls.
- Added AST snapshot matching in agent sessions with per-stream cache throttling and cleanup.
2026-06-08 14:57:17 +02:00