@oh-my-pi/pi-coding-agent 15.12.4 → 15.13.0
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/CHANGELOG.md +304 -6
- package/dist/cli.js +1015 -881
- package/dist/types/async/job-manager.d.ts +15 -0
- package/dist/types/autolearn/controller.d.ts +25 -0
- package/dist/types/autolearn/managed-skills.d.ts +45 -0
- package/dist/types/autoresearch/state.d.ts +1 -1
- package/dist/types/autoresearch/types.d.ts +1 -1
- package/dist/types/cli/args.d.ts +19 -1
- package/dist/types/cli/session-picker.d.ts +1 -1
- package/dist/types/cli/setup-cli.d.ts +1 -1
- package/dist/types/cli/setup-model-picker.d.ts +14 -0
- package/dist/types/collab/protocol.d.ts +1 -1
- package/dist/types/commands/say.d.ts +24 -0
- package/dist/types/config/keybindings.d.ts +3 -3
- package/dist/types/config/model-registry.d.ts +10 -0
- package/dist/types/config/models-config-schema.d.ts +12 -0
- package/dist/types/config/models-config.d.ts +8 -2
- package/dist/types/config/settings-schema.d.ts +261 -58
- package/dist/types/export/html/index.d.ts +2 -1
- package/dist/types/extensibility/extensions/model-api.d.ts +17 -0
- package/dist/types/extensibility/extensions/runner.d.ts +3 -1
- package/dist/types/extensibility/extensions/types.d.ts +47 -1
- package/dist/types/extensibility/hooks/index.d.ts +2 -1
- package/dist/types/extensibility/plugins/legacy-pi-compat.d.ts +9 -0
- package/dist/types/extensibility/plugins/loader.d.ts +11 -0
- package/dist/types/extensibility/shared-events.d.ts +1 -1
- package/dist/types/extensibility/skills.d.ts +10 -0
- package/dist/types/goals/guided-setup.d.ts +18 -0
- package/dist/types/goals/state.d.ts +1 -1
- package/dist/types/hindsight/transcript.d.ts +1 -1
- package/dist/types/index.d.ts +5 -0
- package/dist/types/internal-urls/local-protocol.d.ts +4 -2
- package/dist/types/main.d.ts +4 -3
- package/dist/types/mcp/startup-events.d.ts +11 -0
- package/dist/types/memories/index.d.ts +7 -0
- package/dist/types/memory-backend/local-backend.d.ts +4 -3
- package/dist/types/mnemopi/config.d.ts +4 -4
- package/dist/types/modes/components/agent-hub.d.ts +6 -0
- package/dist/types/modes/components/assistant-message.d.ts +1 -2
- package/dist/types/modes/components/compaction-summary-message.d.ts +15 -1
- package/dist/types/modes/components/custom-editor.d.ts +39 -1
- package/dist/types/modes/components/custom-editor.test.d.ts +1 -0
- package/dist/types/modes/components/session-selector.d.ts +1 -1
- package/dist/types/modes/components/tool-execution.d.ts +26 -16
- package/dist/types/modes/components/transcript-container.d.ts +23 -2
- package/dist/types/modes/components/tree-selector.d.ts +1 -1
- package/dist/types/modes/components/usage-row.d.ts +3 -0
- package/dist/types/modes/controllers/command-controller.d.ts +2 -2
- package/dist/types/modes/controllers/input-controller.d.ts +14 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +3 -1
- package/dist/types/modes/gradient-highlight.d.ts +9 -4
- package/dist/types/modes/image-references.d.ts +6 -0
- package/dist/types/modes/interactive-mode.d.ts +27 -3
- package/dist/types/modes/magic-keywords.d.ts +13 -1
- package/dist/types/modes/rpc/rpc-mode.d.ts +35 -1
- package/dist/types/modes/rpc/rpc-types.d.ts +9 -1
- package/dist/types/modes/runtime-init.d.ts +4 -0
- package/dist/types/modes/theme/theme.d.ts +13 -2
- package/dist/types/modes/types.d.ts +8 -2
- package/dist/types/modes/utils/ui-helpers.d.ts +1 -1
- package/dist/types/registry/agent-registry.d.ts +17 -0
- package/dist/types/secrets/obfuscator.d.ts +1 -1
- package/dist/types/session/agent-session.d.ts +14 -2
- package/dist/types/session/indexed-session-storage.d.ts +3 -4
- package/dist/types/session/session-context.d.ts +39 -0
- package/dist/types/session/session-entries.d.ts +159 -0
- package/dist/types/session/session-listing.d.ts +69 -0
- package/dist/types/session/session-loader.d.ts +16 -0
- package/dist/types/session/session-manager.d.ts +82 -474
- package/dist/types/session/session-migrations.d.ts +12 -0
- package/dist/types/session/session-paths.d.ts +25 -0
- package/dist/types/session/session-persistence.d.ts +8 -0
- package/dist/types/session/session-storage.d.ts +11 -12
- package/dist/types/session/snapcompact-inline.d.ts +12 -1
- package/dist/types/session/snapcompact-savings-journal.d.ts +46 -0
- package/dist/types/session/tool-choice-queue.d.ts +6 -6
- package/dist/types/stt/asr-client.d.ts +90 -0
- package/dist/types/stt/asr-protocol.d.ts +97 -0
- package/dist/types/stt/asr-worker.d.ts +2 -0
- package/dist/types/stt/downloader.d.ts +38 -0
- package/dist/types/stt/endpointer.d.ts +59 -0
- package/dist/types/stt/index.d.ts +5 -1
- package/dist/types/stt/models.d.ts +120 -0
- package/dist/types/stt/recorder.d.ts +17 -0
- package/dist/types/stt/stt-controller.d.ts +6 -0
- package/dist/types/stt/transcriber.d.ts +5 -7
- package/dist/types/stt/wav.d.ts +29 -0
- package/dist/types/system-prompt.d.ts +4 -0
- package/dist/types/task/executor.d.ts +2 -0
- package/dist/types/task/index.d.ts +9 -1
- package/dist/types/task/types.d.ts +36 -0
- package/dist/types/tools/bash.d.ts +2 -2
- package/dist/types/tools/eval-render.d.ts +1 -1
- package/dist/types/tools/index.d.ts +11 -1
- package/dist/types/tools/irc.d.ts +1 -0
- package/dist/types/tools/learn.d.ts +51 -0
- package/dist/types/tools/manage-skill.d.ts +40 -0
- package/dist/types/tools/plan-mode-guard.d.ts +10 -0
- package/dist/types/tools/renderers.d.ts +7 -11
- package/dist/types/tools/ssh.d.ts +1 -1
- package/dist/types/tools/todo.d.ts +1 -1
- package/dist/types/tools/tts.d.ts +25 -0
- package/dist/types/tools/write.d.ts +1 -1
- package/dist/types/tts/downloader.d.ts +20 -0
- package/dist/types/tts/index.d.ts +8 -0
- package/dist/types/tts/models.d.ts +82 -0
- package/dist/types/tts/player.d.ts +32 -0
- package/dist/types/tts/runtime.d.ts +6 -0
- package/dist/types/tts/streaming-player.d.ts +41 -0
- package/dist/types/tts/tts-client.d.ts +93 -0
- package/dist/types/tts/tts-protocol.d.ts +95 -0
- package/dist/types/tts/tts-worker.d.ts +2 -0
- package/dist/types/tts/vocalizer.d.ts +41 -0
- package/dist/types/tts/wav.d.ts +8 -0
- package/dist/types/utils/tool-choice.d.ts +8 -0
- package/dist/types/utils/tools-manager.d.ts +2 -1
- package/dist/types/utils/tools-manager.test.d.ts +1 -0
- package/dist/types/web/scrapers/github.d.ts +1 -1
- package/package.json +15 -14
- package/src/async/job-manager.ts +49 -0
- package/src/autolearn/controller.ts +139 -0
- package/src/autolearn/managed-skills.ts +257 -0
- package/src/autoresearch/state.ts +1 -1
- package/src/autoresearch/types.ts +1 -1
- package/src/cli/args.ts +56 -2
- package/src/cli/session-picker.ts +2 -1
- package/src/cli/setup-cli.ts +148 -47
- package/src/cli/setup-model-picker.ts +43 -0
- package/src/cli-commands.ts +1 -0
- package/src/cli.ts +45 -13
- package/src/collab/host.ts +1 -1
- package/src/collab/protocol.ts +1 -1
- package/src/commands/say.ts +102 -0
- package/src/commands/setup.ts +1 -1
- package/src/commit/agentic/tools/analyze-file.ts +3 -0
- package/src/config/keybindings.ts +2 -2
- package/src/config/model-discovery.ts +11 -5
- package/src/config/model-registry.ts +64 -9
- package/src/config/models-config-schema.ts +4 -1
- package/src/config/models-config.ts +2 -1
- package/src/config/settings-schema.ts +248 -32
- package/src/config/settings.ts +10 -0
- package/src/discovery/builtin.ts +23 -1
- package/src/discovery/claude-plugins.ts +44 -5
- package/src/discovery/helpers.ts +41 -1
- package/src/eval/__tests__/budget-bridge.test.ts +1 -1
- package/src/eval/js/shared/prelude.txt +69 -17
- package/src/export/html/index.ts +3 -6
- package/src/extensibility/extensions/model-api.ts +41 -0
- package/src/extensibility/extensions/runner.ts +4 -0
- package/src/extensibility/extensions/types.ts +52 -1
- package/src/extensibility/extensions/wrapper.ts +41 -5
- package/src/extensibility/hooks/index.ts +2 -1
- package/src/extensibility/plugins/legacy-pi-compat.ts +43 -13
- package/src/extensibility/plugins/loader.ts +30 -19
- package/src/extensibility/plugins/manager.ts +221 -90
- package/src/extensibility/shared-events.ts +1 -1
- package/src/extensibility/skills.ts +96 -15
- package/src/goals/guided-setup.ts +133 -0
- package/src/goals/state.ts +1 -1
- package/src/hindsight/transcript.ts +1 -1
- package/src/index.ts +5 -0
- package/src/internal-urls/docs-index.generated.ts +10 -10
- package/src/internal-urls/history-protocol.ts +1 -1
- package/src/internal-urls/local-protocol.ts +29 -7
- package/src/main.ts +27 -7
- package/src/mcp/startup-events.ts +21 -0
- package/src/mcp/transports/stdio.ts +2 -1
- package/src/memories/index.ts +146 -11
- package/src/memory-backend/local-backend.ts +11 -5
- package/src/mnemopi/backend.ts +1 -0
- package/src/mnemopi/config.ts +26 -10
- package/src/modes/acp/acp-agent.ts +3 -5
- package/src/modes/components/agent-hub.ts +49 -4
- package/src/modes/components/assistant-message.ts +4 -37
- package/src/modes/components/compaction-summary-message.ts +125 -26
- package/src/modes/components/custom-editor.test.ts +96 -0
- package/src/modes/components/custom-editor.ts +164 -8
- package/src/modes/components/session-selector.ts +1 -1
- package/src/modes/components/settings-defs.ts +7 -0
- package/src/modes/components/tool-execution.ts +82 -43
- package/src/modes/components/transcript-container.ts +70 -1
- package/src/modes/components/tree-selector.ts +1 -1
- package/src/modes/components/usage-row.ts +18 -0
- package/src/modes/components/user-message.ts +4 -2
- package/src/modes/controllers/command-controller.ts +14 -4
- package/src/modes/controllers/event-controller.ts +78 -11
- package/src/modes/controllers/extension-ui-controller.ts +6 -0
- package/src/modes/controllers/input-controller.ts +258 -27
- package/src/modes/controllers/selector-controller.ts +12 -2
- package/src/modes/gradient-highlight.ts +21 -9
- package/src/modes/image-references.ts +20 -0
- package/src/modes/interactive-mode.ts +286 -40
- package/src/modes/magic-keywords.ts +27 -5
- package/src/modes/rpc/rpc-mode.ts +146 -14
- package/src/modes/rpc/rpc-subagents.ts +2 -2
- package/src/modes/rpc/rpc-types.ts +8 -2
- package/src/modes/runtime-init.ts +28 -3
- package/src/modes/theme/theme.ts +98 -50
- package/src/modes/types.ts +6 -2
- package/src/modes/utils/hotkeys-markdown.ts +1 -1
- package/src/modes/utils/ui-helpers.ts +34 -6
- package/src/priority.json +5 -1
- package/src/prompts/agents/task.md +1 -0
- package/src/prompts/goals/guided-goal-interview.md +8 -0
- package/src/prompts/goals/guided-goal-system.md +12 -0
- package/src/prompts/memories/read-path.md +6 -0
- package/src/prompts/system/autolearn-guidance-learn.md +1 -0
- package/src/prompts/system/autolearn-guidance.md +7 -0
- package/src/prompts/system/autolearn-nudge.md +3 -0
- package/src/prompts/system/eager-task.md +7 -0
- package/src/prompts/system/eager-todo.md +11 -6
- package/src/prompts/system/subagent-system-prompt.md +4 -0
- package/src/prompts/system/system-prompt.md +10 -5
- package/src/prompts/system/title-marker-instruction.md +1 -0
- package/src/prompts/system/title-system-marker.md +16 -0
- package/src/prompts/tools/job.md +1 -0
- package/src/prompts/tools/learn.md +7 -0
- package/src/prompts/tools/manage-skill.md +9 -0
- package/src/prompts/tools/task.md +3 -0
- package/src/registry/agent-registry.ts +30 -0
- package/src/sdk.ts +88 -24
- package/src/secrets/obfuscator.ts +1 -1
- package/src/session/agent-session.ts +209 -87
- package/src/session/history-storage.ts +2 -2
- package/src/session/indexed-session-storage.ts +7 -17
- package/src/session/session-context.ts +352 -0
- package/src/session/session-entries.ts +194 -0
- package/src/session/session-listing.ts +588 -0
- package/src/session/session-loader.ts +106 -0
- package/src/session/session-manager.ts +933 -3145
- package/src/session/session-migrations.ts +78 -0
- package/src/session/session-paths.ts +193 -0
- package/src/session/session-persistence.ts +131 -0
- package/src/session/session-storage.ts +91 -50
- package/src/session/snapcompact-inline.ts +21 -1
- package/src/session/snapcompact-savings-journal.ts +113 -0
- package/src/session/tool-choice-queue.ts +23 -11
- package/src/slash-commands/builtin-registry.ts +25 -3
- package/src/stt/asr-client.ts +520 -0
- package/src/stt/asr-protocol.ts +65 -0
- package/src/stt/asr-worker.ts +790 -0
- package/src/stt/downloader.ts +107 -47
- package/src/stt/endpointer.ts +259 -0
- package/src/stt/index.ts +5 -1
- package/src/stt/models.ts +150 -0
- package/src/stt/recorder.ts +247 -60
- package/src/stt/stt-controller.ts +201 -22
- package/src/stt/transcriber.ts +37 -68
- package/src/stt/wav.ts +173 -0
- package/src/system-prompt.ts +8 -0
- package/src/task/agents.ts +1 -2
- package/src/task/executor.ts +49 -15
- package/src/task/index.ts +60 -6
- package/src/task/render.ts +83 -8
- package/src/task/types.ts +53 -0
- package/src/tools/ask.ts +8 -0
- package/src/tools/bash.ts +4 -3
- package/src/tools/eval-render.ts +4 -3
- package/src/tools/index.ts +40 -4
- package/src/tools/irc.ts +10 -2
- package/src/tools/job.ts +14 -2
- package/src/tools/learn.ts +144 -0
- package/src/tools/manage-skill.ts +104 -0
- package/src/tools/plan-mode-guard.ts +53 -19
- package/src/tools/renderers.ts +7 -11
- package/src/tools/ssh.ts +4 -3
- package/src/tools/todo.ts +1 -1
- package/src/tools/tts.ts +203 -92
- package/src/tools/write.ts +18 -2
- package/src/tts/downloader.ts +64 -0
- package/src/tts/index.ts +8 -0
- package/src/tts/models.ts +137 -0
- package/src/tts/player.ts +137 -0
- package/src/tts/runtime.ts +21 -0
- package/src/tts/streaming-player.ts +266 -0
- package/src/tts/tts-client.ts +647 -0
- package/src/tts/tts-protocol.ts +60 -0
- package/src/tts/tts-worker.ts +497 -0
- package/src/tts/vocalizer.ts +162 -0
- package/src/tts/wav.ts +58 -0
- package/src/utils/title-generator.ts +48 -5
- package/src/utils/tool-choice.ts +16 -0
- package/src/utils/tools-manager.test.ts +25 -0
- package/src/utils/tools-manager.ts +19 -1
- package/src/web/scrapers/github.ts +96 -0
- package/src/web/search/index.ts +13 -0
- package/src/web/search/providers/searxng.ts +13 -1
- package/dist/types/stt/setup.d.ts +0 -18
- package/src/stt/setup.ts +0 -52
- package/src/stt/transcribe.py +0 -70
|
@@ -1,33 +1,85 @@
|
|
|
1
1
|
if (!globalThis.__omp_js_prelude_loaded__) {
|
|
2
2
|
globalThis.__omp_js_prelude_loaded__ = true;
|
|
3
3
|
|
|
4
|
+
const isNil = value => value === undefined || value === null;
|
|
4
5
|
const isPlainObject = value => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
const positionalOptions = (name, args, keys, example) => {
|
|
7
|
+
for (let index = keys.length; index < args.length; index++) {
|
|
8
|
+
if (!isNil(args[index])) {
|
|
9
|
+
throw new TypeError(
|
|
10
|
+
`${name}() accepts at most ${keys.length} positional optional args; got ${args.length}. Pass ${name}(..., ${example}) for named options.`,
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
const options = {};
|
|
15
|
+
for (let index = 0; index < keys.length && index < args.length; index++) {
|
|
16
|
+
const value = args[index];
|
|
17
|
+
if (!isNil(value)) options[keys[index]] = value;
|
|
18
|
+
}
|
|
19
|
+
return options;
|
|
20
|
+
};
|
|
21
|
+
const optionsArg = (name, value, rest, keys, example) => {
|
|
22
|
+
if (isNil(value)) return positionalOptions(name, [value, ...rest], keys, example);
|
|
23
|
+
if (isPlainObject(value)) {
|
|
24
|
+
if (rest.some(arg => !isNil(arg))) {
|
|
25
|
+
throw new TypeError(
|
|
26
|
+
`${name}() takes either a single trailing options object like ${example} or positional optional args; do not mix both forms.`,
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
return value;
|
|
10
30
|
}
|
|
11
|
-
if (
|
|
12
|
-
|
|
13
|
-
const kind = Array.isArray(value) ? "an array" : typeof value;
|
|
31
|
+
if (typeof value === "object") {
|
|
32
|
+
const kind = Array.isArray(value) ? "an array" : value.constructor?.name ?? "object";
|
|
14
33
|
throw new TypeError(
|
|
15
|
-
`${name}() options must be a
|
|
34
|
+
`${name}() options must be a plain object like ${example}, null/undefined, or positional optional args, not ${kind}.`,
|
|
16
35
|
);
|
|
17
36
|
}
|
|
18
|
-
return value;
|
|
37
|
+
return positionalOptions(name, [value, ...rest], keys, example);
|
|
19
38
|
};
|
|
20
39
|
const callHelper = (name, ...args) => globalThis.__omp_helpers__[name](...args);
|
|
40
|
+
const hasScheme = path => typeof path === "string" && /^[A-Za-z][A-Za-z0-9+.-]*:\/\//.test(path);
|
|
41
|
+
const shouldDelegateRead = path => hasScheme(path) && !path.toLowerCase().startsWith("local://");
|
|
42
|
+
const withReadLineSelector = (path, options) => {
|
|
43
|
+
const offset = typeof options.offset === "number" ? options.offset : 1;
|
|
44
|
+
const limit = typeof options.limit === "number" ? options.limit : undefined;
|
|
45
|
+
if (offset <= 1 && limit === undefined) return path;
|
|
46
|
+
if (limit !== undefined && limit <= 0) return null;
|
|
47
|
+
const start = Math.max(1, offset);
|
|
48
|
+
if (limit === undefined) return `${path}:${start}-`;
|
|
49
|
+
return `${path}:${start}-${start + limit - 1}`;
|
|
50
|
+
};
|
|
51
|
+
const readToolText = async path => {
|
|
52
|
+
const res = await globalThis.__omp_call_tool__("read", { path });
|
|
53
|
+
return res && typeof res === "object" && "text" in res ? res.text : res;
|
|
54
|
+
};
|
|
21
55
|
|
|
22
|
-
|
|
56
|
+
|
|
57
|
+
const read = async (path, opts, ...rest) => {
|
|
58
|
+
const options = optionsArg("read", opts, rest, ["offset", "limit"], "{ offset, limit }");
|
|
59
|
+
if (shouldDelegateRead(path)) {
|
|
60
|
+
const toolPath = withReadLineSelector(path, options);
|
|
61
|
+
return toolPath === null ? "" : readToolText(toolPath);
|
|
62
|
+
}
|
|
63
|
+
return callHelper("read", path, options);
|
|
64
|
+
};
|
|
23
65
|
const write = async (path, data) => callHelper("writeFile", path, data);
|
|
24
66
|
const append = (path, content) => callHelper("append", path, content);
|
|
25
|
-
const sort = (text, opts, ...rest) =>
|
|
26
|
-
|
|
67
|
+
const sort = (text, opts, ...rest) =>
|
|
68
|
+
callHelper("sortText", text, optionsArg("sort", opts, rest, ["reverse", "unique"], "{ reverse, unique }"));
|
|
69
|
+
const uniq = (text, opts, ...rest) => callHelper("uniqText", text, optionsArg("uniq", opts, rest, ["count"], "{ count }"));
|
|
27
70
|
const counter = (items, opts, ...rest) =>
|
|
28
|
-
callHelper("counter", items, optionsArg("counter", opts, rest, "{ limit, reverse }"));
|
|
71
|
+
callHelper("counter", items, optionsArg("counter", opts, rest, ["limit", "reverse"], "{ limit, reverse }"));
|
|
29
72
|
const diff = (a, b) => callHelper("diff", a, b);
|
|
30
|
-
const tree = (path = ".", opts, ...rest) =>
|
|
73
|
+
const tree = (path = ".", opts, ...rest) => {
|
|
74
|
+
if (isPlainObject(path) && opts === undefined && rest.length === 0) {
|
|
75
|
+
return callHelper("tree", ".", path);
|
|
76
|
+
}
|
|
77
|
+
return callHelper(
|
|
78
|
+
"tree",
|
|
79
|
+
isNil(path) ? "." : path,
|
|
80
|
+
optionsArg("tree", opts, rest, ["maxDepth", "showHidden"], "{ maxDepth, showHidden }"),
|
|
81
|
+
);
|
|
82
|
+
};
|
|
31
83
|
const env = (key, value) => callHelper("env", key, value);
|
|
32
84
|
|
|
33
85
|
const tool = new Proxy(
|
|
@@ -58,14 +110,14 @@ if (!globalThis.__omp_js_prelude_loaded__) {
|
|
|
58
110
|
const hasOwn = (object, key) => Object.prototype.hasOwnProperty.call(object, key);
|
|
59
111
|
|
|
60
112
|
const completion = async (prompt, opts, ...rest) => {
|
|
61
|
-
const o = optionsArg("completion", opts, rest, "{ model, system, schema }");
|
|
113
|
+
const o = optionsArg("completion", opts, rest, ["model", "system", "schema"], "{ model, system, schema }");
|
|
62
114
|
const res = await globalThis.__omp_call_tool__("__completion__", { prompt, ...o });
|
|
63
115
|
const text = res && typeof res === "object" ? res.text : res;
|
|
64
116
|
return hasOwn(o, "schema") ? JSON.parse(text) : text;
|
|
65
117
|
};
|
|
66
118
|
|
|
67
119
|
const agent = async (prompt, opts, ...rest) => {
|
|
68
|
-
const o = optionsArg("agent", opts, rest, "{ agentType, model, label, schema }");
|
|
120
|
+
const o = optionsArg("agent", opts, rest, ["agentType", "model", "label", "schema"], "{ agentType, model, label, schema }");
|
|
69
121
|
const res = await globalThis.__omp_call_tool__("__agent__", { prompt, ...o });
|
|
70
122
|
const text = res && typeof res === "object" ? res.text : res;
|
|
71
123
|
return hasOwn(o, "schema") ? JSON.parse(text) : text;
|
package/src/export/html/index.ts
CHANGED
|
@@ -3,12 +3,9 @@ import * as path from "node:path";
|
|
|
3
3
|
import type { AgentState } from "@oh-my-pi/pi-agent-core";
|
|
4
4
|
import { APP_NAME, isEnoent } from "@oh-my-pi/pi-utils";
|
|
5
5
|
import { getResolvedThemeColors, getThemeExportColors } from "../../modes/theme/theme";
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
type SessionHeader,
|
|
10
|
-
SessionManager,
|
|
11
|
-
} from "../../session/session-manager";
|
|
6
|
+
import type { SessionEntry, SessionHeader } from "../../session/session-entries";
|
|
7
|
+
import { loadEntriesFromFile } from "../../session/session-loader";
|
|
8
|
+
import { SessionManager } from "../../session/session-manager";
|
|
12
9
|
import templateCss from "./template.css" with { type: "text" };
|
|
13
10
|
import templateHtml from "./template.html" with { type: "text" };
|
|
14
11
|
import templateJs from "./template.js" with { type: "text" };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model query facade exposed to extensions as `ctx.models`.
|
|
3
|
+
*
|
|
4
|
+
* Read-only: lets an extension select a model the same way core does — list
|
|
5
|
+
* authenticated models, read the session model, resolve a model string or role
|
|
6
|
+
* alias, and compare model families — without touching the mutable registry or
|
|
7
|
+
* duplicating resolution/family heuristics.
|
|
8
|
+
*/
|
|
9
|
+
import type { Api, Model } from "@oh-my-pi/pi-ai";
|
|
10
|
+
import { modelFamilyToken } from "@oh-my-pi/pi-catalog/identity";
|
|
11
|
+
import type { ModelRegistry } from "../../config/model-registry";
|
|
12
|
+
import { getModelMatchPreferences, resolveModelRoleValue } from "../../config/model-resolver";
|
|
13
|
+
import type { Settings } from "../../config/settings";
|
|
14
|
+
import type { ExtensionModelQuery } from "./types";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Build the `ctx.models` facade. `getModel` is read lazily so `current()` always
|
|
18
|
+
* reflects the live session model (it can change mid-session via `/model`).
|
|
19
|
+
*/
|
|
20
|
+
export function createExtensionModelQuery(
|
|
21
|
+
modelRegistry: ModelRegistry,
|
|
22
|
+
settings: Settings | undefined,
|
|
23
|
+
getModel: () => Model | undefined,
|
|
24
|
+
): ExtensionModelQuery {
|
|
25
|
+
return {
|
|
26
|
+
list: () => modelRegistry.getAvailable(),
|
|
27
|
+
current: () => getModel(),
|
|
28
|
+
// resolveModelRoleValue expands a role alias (`pi/slow`) to its full configured
|
|
29
|
+
// priority list and tries each pattern — the same path core selection uses — so a
|
|
30
|
+
// fallback model lower in the list still resolves. Plain model strings pass through
|
|
31
|
+
// as a single pattern.
|
|
32
|
+
resolve: (spec: string): Model<Api> | undefined =>
|
|
33
|
+
resolveModelRoleValue(spec, modelRegistry.getAvailable(), {
|
|
34
|
+
settings,
|
|
35
|
+
matchPreferences: getModelMatchPreferences(settings),
|
|
36
|
+
modelRegistry,
|
|
37
|
+
}).model,
|
|
38
|
+
family: (model: Model<Api>): string =>
|
|
39
|
+
modelFamilyToken(modelRegistry.getCanonicalId(model) ?? model.id) || model.provider.toLowerCase(),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -6,9 +6,11 @@ import type { CredentialDisabledEvent, ImageContent, Model, ProviderResponseMeta
|
|
|
6
6
|
import type { KeyId } from "@oh-my-pi/pi-tui";
|
|
7
7
|
import { logger } from "@oh-my-pi/pi-utils";
|
|
8
8
|
import type { ModelRegistry } from "../../config/model-registry";
|
|
9
|
+
import type { Settings } from "../../config/settings";
|
|
9
10
|
import type { MemoryRuntimeContext } from "../../memory-backend";
|
|
10
11
|
import { type Theme, theme } from "../../modes/theme/theme";
|
|
11
12
|
import type { SessionManager } from "../../session/session-manager";
|
|
13
|
+
import { createExtensionModelQuery } from "./model-api";
|
|
12
14
|
import type {
|
|
13
15
|
AfterProviderResponseEvent,
|
|
14
16
|
AssistantThinkingRenderer,
|
|
@@ -207,6 +209,7 @@ export class ExtensionRunner {
|
|
|
207
209
|
private readonly sessionManager: SessionManager,
|
|
208
210
|
private readonly modelRegistry: ModelRegistry,
|
|
209
211
|
getMemory?: () => MemoryRuntimeContext | undefined,
|
|
212
|
+
private readonly settings?: Settings,
|
|
210
213
|
) {
|
|
211
214
|
this.#uiContext = noOpUIContext;
|
|
212
215
|
this.#getMemoryFn = getMemory;
|
|
@@ -479,6 +482,7 @@ export class ExtensionRunner {
|
|
|
479
482
|
get model() {
|
|
480
483
|
return getModel();
|
|
481
484
|
},
|
|
485
|
+
models: createExtensionModelQuery(this.modelRegistry, this.settings, getModel),
|
|
482
486
|
isIdle: () => this.#isIdleFn(),
|
|
483
487
|
abort: () => this.#abortFn(),
|
|
484
488
|
hasPendingMessages: () => this.#hasPendingMessagesFn(),
|
|
@@ -56,6 +56,7 @@ import type {
|
|
|
56
56
|
SearchToolInput,
|
|
57
57
|
WriteToolInput,
|
|
58
58
|
} from "../../tools";
|
|
59
|
+
import type { ApprovalMode } from "../../tools/approval";
|
|
59
60
|
import type { EventBus } from "../../utils/event-bus";
|
|
60
61
|
import type {
|
|
61
62
|
AgentEndEvent,
|
|
@@ -293,6 +294,32 @@ export interface CompactOptions {
|
|
|
293
294
|
// surface (model registry, system prompt, shutdown, full session manager
|
|
294
295
|
// access). Field overlap is incidental; merging into a base would require
|
|
295
296
|
// hooks to widen their public contract.
|
|
297
|
+
/**
|
|
298
|
+
* Read-only model query facade exposed at `ctx.models`. Lets an extension select a
|
|
299
|
+
* model the same way core does — list authenticated models, read the session model,
|
|
300
|
+
* resolve a model string or role alias, and compare model families — without reaching
|
|
301
|
+
* into the mutable registry or re-implementing matching/family heuristics.
|
|
302
|
+
*/
|
|
303
|
+
export interface ExtensionModelQuery {
|
|
304
|
+
/** Authenticated models available this session (the same set `--model` selection sees). */
|
|
305
|
+
list(): Model[];
|
|
306
|
+
/** The current session model, if one is set. */
|
|
307
|
+
current(): Model | undefined;
|
|
308
|
+
/**
|
|
309
|
+
* Resolve a model string (`provider/id`, bare id) or role alias (`pi/slow`, a
|
|
310
|
+
* configured role) to a Model, using the same settings-backed aliases and match
|
|
311
|
+
* preferences as core selection. Thinking/routing suffixes are accepted and resolved
|
|
312
|
+
* to the base model (pass effort separately). Returns undefined when nothing matches.
|
|
313
|
+
*/
|
|
314
|
+
resolve(spec: string): Model | undefined;
|
|
315
|
+
/**
|
|
316
|
+
* Opaque lineage token for "are these the same family?" comparisons — every Claude
|
|
317
|
+
* point release shares a token, Claude and GPT differ. Backed by catalog canonical
|
|
318
|
+
* identity. Compare it; do not persist it (the vocabulary tracks new releases).
|
|
319
|
+
*/
|
|
320
|
+
family(model: Model): string;
|
|
321
|
+
}
|
|
322
|
+
|
|
296
323
|
export interface ExtensionContext {
|
|
297
324
|
/** UI methods for user interaction */
|
|
298
325
|
ui: ExtensionUIContext;
|
|
@@ -310,6 +337,8 @@ export interface ExtensionContext {
|
|
|
310
337
|
modelRegistry: ModelRegistry;
|
|
311
338
|
/** Current model (may be undefined) */
|
|
312
339
|
model: Model | undefined;
|
|
340
|
+
/** Read-only model query facade: list / current / resolve / family. */
|
|
341
|
+
models: ExtensionModelQuery;
|
|
313
342
|
/** Whether the agent is idle (not streaming) */
|
|
314
343
|
isIdle(): boolean;
|
|
315
344
|
/** Abort the current agent operation */
|
|
@@ -608,6 +637,24 @@ export interface InputEvent {
|
|
|
608
637
|
// Tool Events
|
|
609
638
|
// ============================================================================
|
|
610
639
|
|
|
640
|
+
export interface ToolApprovalRequestedEvent {
|
|
641
|
+
type: "tool_approval_requested";
|
|
642
|
+
sessionId: string;
|
|
643
|
+
toolCallId: string;
|
|
644
|
+
toolName: string;
|
|
645
|
+
reason?: string;
|
|
646
|
+
approvalMode: ApprovalMode;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
export interface ToolApprovalResolvedEvent {
|
|
650
|
+
type: "tool_approval_resolved";
|
|
651
|
+
sessionId: string;
|
|
652
|
+
toolCallId: string;
|
|
653
|
+
toolName: string;
|
|
654
|
+
approved: boolean;
|
|
655
|
+
reason?: string;
|
|
656
|
+
}
|
|
657
|
+
|
|
611
658
|
interface ToolCallEventBase {
|
|
612
659
|
type: "tool_call";
|
|
613
660
|
toolCallId: string;
|
|
@@ -775,7 +822,9 @@ export type ExtensionEvent =
|
|
|
775
822
|
| UserPythonEvent
|
|
776
823
|
| InputEvent
|
|
777
824
|
| ToolCallEvent
|
|
778
|
-
| ToolResultEvent
|
|
825
|
+
| ToolResultEvent
|
|
826
|
+
| ToolApprovalRequestedEvent
|
|
827
|
+
| ToolApprovalResolvedEvent;
|
|
779
828
|
|
|
780
829
|
// ============================================================================
|
|
781
830
|
// Event Results
|
|
@@ -946,6 +995,8 @@ export interface ExtensionAPI {
|
|
|
946
995
|
on(event: "goal_updated", handler: ExtensionHandler<GoalUpdatedEvent>): void;
|
|
947
996
|
on(event: "credential_disabled", handler: ExtensionHandler<CredentialDisabledEvent>): void;
|
|
948
997
|
on(event: "input", handler: ExtensionHandler<InputEvent, InputEventResult>): void;
|
|
998
|
+
on(event: "tool_approval_requested", handler: ExtensionHandler<ToolApprovalRequestedEvent>): void;
|
|
999
|
+
on(event: "tool_approval_resolved", handler: ExtensionHandler<ToolApprovalResolvedEvent>): void;
|
|
949
1000
|
on(event: "tool_call", handler: ExtensionHandler<ToolCallEvent, ToolCallEventResult>): void;
|
|
950
1001
|
on(event: "tool_result", handler: ExtensionHandler<ToolResultEvent, ToolResultEventResult>): void;
|
|
951
1002
|
on(event: "user_bash", handler: ExtensionHandler<UserBashEvent, UserBashEventResult>): void;
|
|
@@ -121,8 +121,36 @@ export class ExtensionToolWrapper<TParameters extends TSchema = TSchema, TDetail
|
|
|
121
121
|
const approvalCheck = requiresApproval(this.tool, params, approvalMode, userPolicies);
|
|
122
122
|
|
|
123
123
|
if (approvalCheck.required) {
|
|
124
|
+
const hasApprovalHandlers =
|
|
125
|
+
this.runner.hasHandlers("tool_approval_requested") || this.runner.hasHandlers("tool_approval_resolved");
|
|
126
|
+
const sessionId = context?.sessionManager?.getSessionId() ?? "";
|
|
127
|
+
if (hasApprovalHandlers) {
|
|
128
|
+
await this.runner.emit({
|
|
129
|
+
type: "tool_approval_requested",
|
|
130
|
+
sessionId,
|
|
131
|
+
toolName: this.tool.name,
|
|
132
|
+
toolCallId,
|
|
133
|
+
...(approvalCheck.reason ? { reason: approvalCheck.reason } : {}),
|
|
134
|
+
approvalMode,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const resolveApproval = async (approved: boolean, reason?: string) => {
|
|
139
|
+
if (!hasApprovalHandlers) return;
|
|
140
|
+
await this.runner.emit({
|
|
141
|
+
type: "tool_approval_resolved",
|
|
142
|
+
sessionId,
|
|
143
|
+
toolName: this.tool.name,
|
|
144
|
+
toolCallId,
|
|
145
|
+
approved,
|
|
146
|
+
...(reason ? { reason } : {}),
|
|
147
|
+
});
|
|
148
|
+
};
|
|
149
|
+
|
|
124
150
|
// Check if UI is available
|
|
125
151
|
if (!this.runner.hasUI()) {
|
|
152
|
+
const reason = "no interactive UI available";
|
|
153
|
+
await resolveApproval(false, reason);
|
|
126
154
|
throw new Error(
|
|
127
155
|
`Tool "${this.tool.name}" requires approval but no interactive UI available.\n` +
|
|
128
156
|
`Options:\n` +
|
|
@@ -133,11 +161,19 @@ export class ExtensionToolWrapper<TParameters extends TSchema = TSchema, TDetail
|
|
|
133
161
|
}
|
|
134
162
|
|
|
135
163
|
const uiContext = this.runner.getUIContext();
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
164
|
+
let choice: string | undefined;
|
|
165
|
+
try {
|
|
166
|
+
choice = await uiContext.select(formatApprovalPrompt(this.tool, params, approvalCheck.reason), [
|
|
167
|
+
"Approve",
|
|
168
|
+
"Deny",
|
|
169
|
+
]);
|
|
170
|
+
} catch (err) {
|
|
171
|
+
await resolveApproval(false, err instanceof Error ? err.message : "approval aborted");
|
|
172
|
+
throw err;
|
|
173
|
+
}
|
|
174
|
+
const approved = choice === "Approve";
|
|
175
|
+
await resolveApproval(approved, approved ? undefined : "denied by user");
|
|
176
|
+
if (!approved) {
|
|
141
177
|
throw new Error(`Tool call denied by user: ${this.tool.name}`);
|
|
142
178
|
}
|
|
143
179
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export type {
|
|
1
|
+
export type { UsageStatistics } from "../../session/session-entries";
|
|
2
|
+
export type { ReadonlySessionManager } from "../../session/session-manager";
|
|
2
3
|
export * from "./loader";
|
|
3
4
|
export * from "./runner";
|
|
4
5
|
export * from "./tool-wrapper";
|
|
@@ -30,16 +30,28 @@ const PI_PACKAGE_ALTERNATION = PI_PACKAGE_NAMES.join("|");
|
|
|
30
30
|
// root that we relocated under a different folder. Each entry rewrites
|
|
31
31
|
// `<pkg>/<from>` → `<pkg>/<to>` after the scope has been canonicalised, so
|
|
32
32
|
// plugins importing the upstream layout still resolve to a real file in our
|
|
33
|
-
// bundled copy.
|
|
34
|
-
//
|
|
33
|
+
// bundled copy. Entries ending in `/` rewrite the whole subtree; add new
|
|
34
|
+
// `pkg/from -> pkg/to` pairs whenever an upstream-only subpath breaks resolution.
|
|
35
35
|
const PI_SUBPATH_REMAPS: ReadonlyMap<string, string> = new Map<string, string>([
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
// real `@oh-my-pi/pi-ai/oauth` export, so the legacy subpath canonicalizes
|
|
39
|
-
// straight to it with no rewrite. Add `from -> to` entries here whenever a
|
|
40
|
-
// future upstream-only subpath surfaces that breaks resolution.
|
|
36
|
+
["pi-ai/utils/oauth", "pi-ai/oauth"],
|
|
37
|
+
["pi-ai/utils/oauth/", "pi-ai/oauth/"],
|
|
41
38
|
]);
|
|
42
39
|
|
|
40
|
+
function remapLegacyPiSubpath(rest: string): string {
|
|
41
|
+
const exact = PI_SUBPATH_REMAPS.get(rest);
|
|
42
|
+
if (exact) {
|
|
43
|
+
return exact;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
for (const [from, to] of PI_SUBPATH_REMAPS) {
|
|
47
|
+
if (from.endsWith("/") && rest.startsWith(from)) {
|
|
48
|
+
return `${to}${rest.slice(from.length)}`;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return rest;
|
|
53
|
+
}
|
|
54
|
+
|
|
43
55
|
const LEGACY_PI_SPECIFIER_FILTER = new RegExp(`^@(?:${PI_SCOPE_ALTERNATION})/(?:${PI_PACKAGE_ALTERNATION})(?:/.*)?$`);
|
|
44
56
|
const LEGACY_PI_IMPORT_SPECIFIER_REGEX = new RegExp(
|
|
45
57
|
`((?:from\\s+|import\\s+|import\\s*\\(\\s*)["'])(@(?:${PI_SCOPE_ALTERNATION})/(?:${PI_PACKAGE_ALTERNATION})(?:/[^"'()\\s]+)?)(["'])`,
|
|
@@ -101,6 +113,28 @@ export function __computeBunfsPackageRoot(metaDir: string, pathImpl: typeof path
|
|
|
101
113
|
return pathImpl.join(metaDir, "packages");
|
|
102
114
|
}
|
|
103
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Compute the package root for the npm prebuilt `dist/cli.js` bundle.
|
|
118
|
+
*
|
|
119
|
+
* `bundle-dist.ts` defines `process.env.PI_BUNDLED="true"`; after bundling,
|
|
120
|
+
* `import.meta.dir` points at `<package>/dist`. Do not resolve the package via
|
|
121
|
+
* bare `@oh-my-pi/pi-coding-agent` here: from a global install Bun can pick an
|
|
122
|
+
* older cache entry, recreating mixed-runtime plugin loading.
|
|
123
|
+
*/
|
|
124
|
+
export function __computeBundledSelfPackageRoot(metaDir: string, pathImpl: typeof path = path): string {
|
|
125
|
+
const normalizedMetaDir = pathImpl.normalize(metaDir);
|
|
126
|
+
if (pathImpl.basename(normalizedMetaDir) === "dist") {
|
|
127
|
+
return pathImpl.resolve(metaDir, "..");
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const pluginsDirSuffix = pathImpl.join("src", "extensibility", "plugins");
|
|
131
|
+
if (normalizedMetaDir.endsWith(pluginsDirSuffix)) {
|
|
132
|
+
return pathImpl.resolve(metaDir, "..", "..", "..");
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return pathImpl.resolve(metaDir);
|
|
136
|
+
}
|
|
137
|
+
|
|
104
138
|
const BUNFS_PACKAGE_ROOT = IS_COMPILED_BINARY ? __computeBunfsPackageRoot(import.meta.dir) : null;
|
|
105
139
|
|
|
106
140
|
function bunfsPath(...segments: string[]): string {
|
|
@@ -112,11 +146,7 @@ function bunfsPath(...segments: string[]): string {
|
|
|
112
146
|
|
|
113
147
|
function resolveBundledSelfPackageRoot(): string | undefined {
|
|
114
148
|
if (!process.env.PI_BUNDLED) return undefined;
|
|
115
|
-
|
|
116
|
-
return path.dirname(Bun.resolveSync("@oh-my-pi/pi-coding-agent/package.json", import.meta.dir));
|
|
117
|
-
} catch {
|
|
118
|
-
return undefined;
|
|
119
|
-
}
|
|
149
|
+
return __computeBundledSelfPackageRoot(import.meta.dir);
|
|
120
150
|
}
|
|
121
151
|
|
|
122
152
|
const BUNDLED_SELF_PACKAGE_ROOT = resolveBundledSelfPackageRoot();
|
|
@@ -208,7 +238,7 @@ function remapLegacyPiSpecifier(specifier: string): string | null {
|
|
|
208
238
|
return null;
|
|
209
239
|
}
|
|
210
240
|
const rest = specifier.slice(slashIdx + 1);
|
|
211
|
-
const remappedSubpath =
|
|
241
|
+
const remappedSubpath = remapLegacyPiSubpath(rest);
|
|
212
242
|
return `${CANONICAL_PI_SCOPE}/${remappedSubpath}`;
|
|
213
243
|
}
|
|
214
244
|
|
|
@@ -172,34 +172,49 @@ function resolveManifestEntryFile(joined: string): string | null {
|
|
|
172
172
|
* Handles both single-string and string[] base entries, plus feature-specific entries.
|
|
173
173
|
*/
|
|
174
174
|
function resolvePluginPaths(plugin: InstalledPlugin, key: "tools" | "hooks" | "commands" | "extensions"): string[] {
|
|
175
|
-
const
|
|
175
|
+
const resolved: string[] = [];
|
|
176
|
+
for (const entry of resolvePluginManifestEntries(plugin, key)) {
|
|
177
|
+
if (entry.resolvedPath) {
|
|
178
|
+
resolved.push(entry.resolvedPath);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return resolved;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Declared manifest entries paired with their resolved file path. Returns one
|
|
186
|
+
* record per declared entry — base entries first, then enabled-feature entries
|
|
187
|
+
* — so callers (e.g. install-time validation) can detect manifest entries that
|
|
188
|
+
* point at missing files instead of silently skipping them like
|
|
189
|
+
* {@link resolvePluginPaths} does.
|
|
190
|
+
*/
|
|
191
|
+
export function resolvePluginManifestEntries(
|
|
192
|
+
plugin: InstalledPlugin,
|
|
193
|
+
key: "tools" | "hooks" | "commands" | "extensions",
|
|
194
|
+
): Array<{ entry: string; resolvedPath: string | null }> {
|
|
195
|
+
const declared: Array<{ entry: string; resolvedPath: string | null }> = [];
|
|
176
196
|
const manifest = plugin.manifest;
|
|
177
197
|
|
|
178
|
-
|
|
198
|
+
const resolveEntry = (entry: string): { entry: string; resolvedPath: string | null } => ({
|
|
199
|
+
entry,
|
|
200
|
+
resolvedPath: resolveManifestEntryFile(path.join(plugin.path, entry)),
|
|
201
|
+
});
|
|
202
|
+
|
|
179
203
|
const base = manifest[key];
|
|
180
204
|
if (base) {
|
|
181
205
|
const entries = Array.isArray(base) ? base : [base];
|
|
182
206
|
for (const entry of entries) {
|
|
183
|
-
|
|
184
|
-
if (resolved) {
|
|
185
|
-
paths.push(resolved);
|
|
186
|
-
}
|
|
207
|
+
declared.push(resolveEntry(entry));
|
|
187
208
|
}
|
|
188
209
|
}
|
|
189
210
|
|
|
190
|
-
// Feature-specific entries
|
|
191
211
|
if (manifest.features && plugin.enabledFeatures) {
|
|
192
212
|
const enabledSet = new Set(plugin.enabledFeatures);
|
|
193
|
-
|
|
194
213
|
for (const [featName, feat] of Object.entries(manifest.features)) {
|
|
195
214
|
if (!enabledSet.has(featName)) continue;
|
|
196
|
-
|
|
197
215
|
if (feat[key]) {
|
|
198
216
|
for (const entry of feat[key]) {
|
|
199
|
-
|
|
200
|
-
if (resolved) {
|
|
201
|
-
paths.push(resolved);
|
|
202
|
-
}
|
|
217
|
+
declared.push(resolveEntry(entry));
|
|
203
218
|
}
|
|
204
219
|
}
|
|
205
220
|
}
|
|
@@ -207,19 +222,15 @@ function resolvePluginPaths(plugin: InstalledPlugin, key: "tools" | "hooks" | "c
|
|
|
207
222
|
// null means use defaults - enable features with default: true
|
|
208
223
|
for (const [_featName, feat] of Object.entries(manifest.features)) {
|
|
209
224
|
if (!feat.default) continue;
|
|
210
|
-
|
|
211
225
|
if (feat[key]) {
|
|
212
226
|
for (const entry of feat[key]) {
|
|
213
|
-
|
|
214
|
-
if (resolved) {
|
|
215
|
-
paths.push(resolved);
|
|
216
|
-
}
|
|
227
|
+
declared.push(resolveEntry(entry));
|
|
217
228
|
}
|
|
218
229
|
}
|
|
219
230
|
}
|
|
220
231
|
}
|
|
221
232
|
|
|
222
|
-
return
|
|
233
|
+
return declared;
|
|
223
234
|
}
|
|
224
235
|
|
|
225
236
|
export function resolvePluginToolPaths(plugin: InstalledPlugin): string[] {
|