@oh-my-pi/pi-coding-agent 17.2.9 → 17.2.11
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 +83 -0
- package/dist/{CHANGELOG-8yy8h3bc.md → CHANGELOG-d9xenpn9.md} +83 -0
- package/dist/cli.js +10208 -12596
- package/dist/types/capability/mcp.d.ts +11 -0
- package/dist/types/capability/skill.d.ts +6 -0
- package/dist/types/cli/args.d.ts +1 -0
- package/dist/types/cli/command-help.d.ts +3 -0
- package/dist/types/commands/share.d.ts +25 -0
- package/dist/types/commit/agentic/index.d.ts +3 -1
- package/dist/types/commit/execute.d.ts +32 -0
- package/dist/types/commit/index.d.ts +2 -1
- package/dist/types/commit/pipeline.d.ts +7 -1
- package/dist/types/config/model-registry.d.ts +4 -0
- package/dist/types/config/model-resolver.d.ts +13 -0
- package/dist/types/config/settings-schema.d.ts +1 -34
- package/dist/types/discovery/agent-plugin-format.d.ts +143 -0
- package/dist/types/discovery/agent-plugins.d.ts +1 -0
- package/dist/types/discovery/contained-path.d.ts +34 -0
- package/dist/types/discovery/index.d.ts +1 -0
- package/dist/types/extensibility/custom-commands/types.d.ts +5 -5
- package/dist/types/extensibility/custom-tools/types.d.ts +3 -3
- package/dist/types/extensibility/extensions/loader.d.ts +9 -2
- package/dist/types/extensibility/extensions/types.d.ts +45 -8
- package/dist/types/extensibility/hooks/types.d.ts +5 -5
- package/dist/types/extensibility/shared-events.d.ts +3 -2
- package/dist/types/extensibility/skills.d.ts +5 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/main.d.ts +1 -1
- package/dist/types/mcp/transports/header-policy.d.ts +45 -0
- package/dist/types/mcp/types.d.ts +15 -0
- package/dist/types/modes/acp/acp-agent.d.ts +1 -1
- package/dist/types/modes/acp/acp-client-bridge.d.ts +1 -1
- package/dist/types/modes/acp/acp-event-mapper.d.ts +1 -1
- package/dist/types/modes/acp/acp-mode.d.ts +1 -1
- package/dist/types/modes/components/agent-hub-projection.d.ts +38 -0
- package/dist/types/modes/components/agent-hub-renderer.d.ts +41 -0
- package/dist/types/modes/components/agent-hub.d.ts +14 -5
- package/dist/types/modes/components/agent-transcript-viewer.d.ts +2 -0
- package/dist/types/modes/components/chat-transcript-builder.d.ts +2 -0
- package/dist/types/modes/components/custom-editor.d.ts +1 -2
- package/dist/types/modes/components/model-browser.d.ts +9 -1
- package/dist/types/modes/components/status-line/types.d.ts +2 -0
- package/dist/types/modes/components/tool-execution.d.ts +2 -0
- package/dist/types/modes/interactive-mode.d.ts +8 -1
- package/dist/types/modes/utils/transcript-render-helpers.d.ts +3 -2
- package/dist/types/registry/agent-registry.d.ts +47 -0
- package/dist/types/registry/persisted-agents.d.ts +3 -1
- package/dist/types/secrets/index.d.ts +23 -1
- package/dist/types/session/agent-session-events.d.ts +2 -2
- package/dist/types/session/agent-session.d.ts +4 -2
- package/dist/types/session/messages.d.ts +1 -0
- package/dist/types/session/prewalk.d.ts +3 -1
- package/dist/types/session/session-entries.d.ts +10 -0
- package/dist/types/session/session-loader.d.ts +11 -1
- package/dist/types/session/session-manager.d.ts +9 -1
- package/dist/types/session/session-tools.d.ts +18 -1
- package/dist/types/session/turn-recovery.d.ts +7 -2
- package/dist/types/slash-commands/acp-builtins.d.ts +1 -1
- package/dist/types/slash-commands/available-commands.d.ts +1 -1
- package/dist/types/task/executor.d.ts +6 -0
- package/dist/types/task/index.d.ts +4 -3
- package/dist/types/task/read-only-policy.d.ts +3 -0
- package/dist/types/task/structured-subagent.d.ts +2 -0
- package/dist/types/task/types.d.ts +4 -0
- package/dist/types/tools/bash.d.ts +3 -3
- package/dist/types/tools/browser/launch.d.ts +2 -1
- package/dist/types/tools/browser/tab-worker.d.ts +2 -2
- package/dist/types/tools/path-utils.d.ts +1 -0
- package/dist/types/tools/read.d.ts +1 -5
- package/dist/types/tools/run-scope.d.ts +27 -1
- package/dist/types/tools/shell-tokenize.d.ts +16 -0
- package/dist/types/tools/terminal-output.d.ts +1 -1
- package/dist/types/utils/turndown.d.ts +1 -1
- package/dist/types/vibe/runtime.d.ts +2 -3
- package/dist/types/web/scrapers/readthedocs.d.ts +0 -3
- package/dist/types/web/search/providers/browser-headers.d.ts +2 -3
- package/examples/custom-tools/README.md +1 -1
- package/examples/extensions/README.md +1 -1
- package/examples/extensions/api-demo.ts +5 -6
- package/examples/extensions/chalk-logger.ts +1 -1
- package/examples/extensions/hello.ts +2 -2
- package/examples/extensions/reload-runtime.ts +1 -1
- package/examples/extensions/tools.ts +2 -2
- package/examples/extensions/with-deps/index.ts +1 -1
- package/examples/sdk/06-extensions.ts +1 -1
- package/package.json +15 -31
- package/scripts/bundle-dist.ts +1 -11
- package/scripts/legacy-pi-virtual-module.ts +4 -1
- package/src/advisor/runtime.ts +54 -0
- package/src/capability/mcp.ts +11 -0
- package/src/capability/skill.ts +6 -0
- package/src/cli/agents-cli.ts +1 -1
- package/src/cli/args.ts +24 -2
- package/src/cli/auth-broker-cli.ts +1 -1
- package/src/cli/auth-gateway-cli.ts +1 -1
- package/src/cli/bench-cli.ts +1 -1
- package/src/cli/claude-trace-cli.ts +1 -1
- package/src/cli/command-help.ts +4 -0
- package/src/cli/config-cli.ts +1 -1
- package/src/cli/dry-balance-cli.ts +1 -1
- package/src/cli/file-processor.ts +1 -1
- package/src/cli/flag-tables.ts +4 -0
- package/src/cli/gallery-cli.ts +1 -1
- package/src/cli/grep-cli.ts +1 -1
- package/src/cli/grievances-cli.ts +1 -1
- package/src/cli/help-extra.ts +1 -1
- package/src/cli/models-cli.ts +1 -1
- package/src/cli/plugin-cli.ts +1 -1
- package/src/cli/read-cli.ts +1 -1
- package/src/cli/setup-cli.ts +1 -1
- package/src/cli/shell-cli.ts +1 -1
- package/src/cli/ssh-cli.ts +1 -1
- package/src/cli/stats-cli.ts +1 -1
- package/src/cli/tiny-models-cli.ts +1 -1
- package/src/cli/ttsr-cli.ts +1 -1
- package/src/cli/update-cli.ts +1 -1
- package/src/cli/usage-cli.ts +1 -1
- package/src/cli/web-search-cli.ts +1 -1
- package/src/cli/worktree-cli.ts +1 -1
- package/src/cli-commands.ts +5 -0
- package/src/commands/commit.ts +16 -3
- package/src/commands/say.ts +1 -1
- package/src/commands/share.ts +71 -0
- package/src/commands/token.ts +1 -1
- package/src/commit/agentic/agent.ts +1 -1
- package/src/commit/agentic/index.ts +39 -21
- package/src/commit/cli.ts +1 -1
- package/src/commit/execute.ts +56 -0
- package/src/commit/index.ts +2 -1
- package/src/commit/pipeline.ts +20 -7
- package/src/config/model-discovery.ts +1 -1
- package/src/config/model-registry.ts +21 -1
- package/src/config/model-resolver.ts +54 -7
- package/src/config/settings-schema.ts +2 -33
- package/src/config/settings.ts +46 -0
- package/src/discovery/agent-plugin-format.ts +551 -0
- package/src/discovery/agent-plugins.ts +341 -0
- package/src/discovery/agents.ts +4 -2
- package/src/discovery/builtin-rules/ts-no-inline-cast-access.md +5 -4
- package/src/discovery/builtin-rules/ts-no-tiny-functions.md +1 -1
- package/src/discovery/claude-plugins.ts +21 -5
- package/src/discovery/contained-path.ts +78 -0
- package/src/discovery/helpers.ts +23 -9
- package/src/discovery/index.ts +1 -0
- package/src/discovery/omp-plugins.ts +20 -7
- package/src/eval/py/runner.py +38 -1
- package/src/exec/non-interactive-env.ts +1 -0
- package/src/extensibility/custom-commands/loader.ts +4 -4
- package/src/extensibility/custom-commands/types.ts +5 -5
- package/src/extensibility/custom-tools/loader.ts +4 -4
- package/src/extensibility/custom-tools/types.ts +3 -3
- package/src/extensibility/extensions/loader.ts +85 -20
- package/src/extensibility/extensions/runner.ts +6 -0
- package/src/extensibility/extensions/types.ts +51 -8
- package/src/extensibility/hooks/loader.ts +4 -5
- package/src/extensibility/hooks/types.ts +5 -5
- package/src/extensibility/plugins/legacy-pi-compat.ts +53 -0
- package/src/extensibility/plugins/marketplace/manager.ts +2 -1
- package/src/extensibility/shared-events.ts +3 -2
- package/src/extensibility/skills.ts +9 -0
- package/src/index.ts +2 -2
- package/src/internal-urls/memory-protocol.ts +5 -1
- package/src/internal-urls/skill-protocol.ts +14 -0
- package/src/internal-urls/vault-protocol.ts +2 -2
- package/src/launch/client.ts +11 -1
- package/src/launch/protocol.ts +7 -2
- package/src/launch/terminal-output.ts +1 -1
- package/src/main.ts +88 -23
- package/src/markit/converters/docx.ts +1 -1
- package/src/markit/converters/epub.ts +1 -1
- package/src/markit/converters/pptx.ts +1 -1
- package/src/markit/converters/xlsx.ts +1 -1
- package/src/mcp/config.ts +3 -0
- package/src/mcp/manager.ts +12 -9
- package/src/mcp/transports/header-policy.ts +95 -0
- package/src/mcp/transports/http.ts +35 -52
- package/src/mcp/transports/sse.ts +20 -27
- package/src/mcp/types.ts +15 -0
- package/src/modes/acp/acp-agent.ts +20 -9
- package/src/modes/acp/acp-client-bridge.ts +1 -1
- package/src/modes/acp/acp-event-mapper.ts +1 -1
- package/src/modes/acp/acp-mode.ts +1 -1
- package/src/modes/components/agent-dashboard.ts +2 -0
- package/src/modes/components/agent-hub-projection.ts +248 -0
- package/src/modes/components/agent-hub-renderer.ts +194 -0
- package/src/modes/components/agent-hub.ts +674 -207
- package/src/modes/components/agent-transcript-viewer.ts +3 -0
- package/src/modes/components/assistant-message.ts +1 -1
- package/src/modes/components/chat-transcript-builder.ts +3 -0
- package/src/modes/components/custom-editor.ts +0 -9
- package/src/modes/components/extensions/inspector-panel.ts +11 -6
- package/src/modes/components/footer.ts +1 -3
- package/src/modes/components/model-browser.ts +11 -3
- package/src/modes/components/model-hub.ts +4 -1
- package/src/modes/components/status-line/component.ts +1 -0
- package/src/modes/components/status-line/segments.ts +10 -7
- package/src/modes/components/status-line/types.ts +2 -0
- package/src/modes/components/tool-execution.ts +13 -16
- package/src/modes/components/tree-selector.ts +62 -3
- package/src/modes/controllers/command-controller.ts +4 -1
- package/src/modes/controllers/event-controller.ts +44 -20
- package/src/modes/controllers/extension-ui-controller.ts +2 -2
- package/src/modes/controllers/input-controller.ts +20 -2
- package/src/modes/controllers/mcp-command-controller.ts +81 -20
- package/src/modes/controllers/selector-controller.ts +41 -49
- package/src/modes/controllers/streaming-reveal.ts +1 -1
- package/src/modes/interactive-mode.ts +13 -2
- package/src/modes/rpc/rpc-mode.ts +2 -2
- package/src/modes/runtime-init.ts +1 -1
- package/src/modes/theme/theme.ts +2 -2
- package/src/modes/utils/transcript-render-helpers.ts +4 -2
- package/src/modes/utils/ui-helpers.ts +1 -0
- package/src/prompts/tools/computer.md +1 -1
- package/src/registry/agent-lifecycle.ts +14 -7
- package/src/registry/agent-registry.ts +65 -2
- package/src/registry/persisted-agents.ts +341 -16
- package/src/sdk.ts +6 -49
- package/src/secrets/index.ts +52 -1
- package/src/session/agent-session-events.ts +2 -2
- package/src/session/agent-session.ts +54 -16
- package/src/session/messages.ts +1 -0
- package/src/session/prewalk.ts +57 -17
- package/src/session/session-context.ts +3 -5
- package/src/session/session-entries.ts +10 -0
- package/src/session/session-handoff.ts +5 -1
- package/src/session/session-listing.ts +1 -1
- package/src/session/session-loader.ts +74 -8
- package/src/session/session-manager.ts +22 -2
- package/src/session/session-paths.ts +57 -9
- package/src/session/session-tools.ts +65 -4
- package/src/session/todo-tracker.ts +11 -1
- package/src/session/turn-recovery.ts +96 -74
- package/src/slash-commands/acp-builtins.ts +1 -1
- package/src/slash-commands/available-commands.ts +1 -1
- package/src/slash-commands/builtin-registry.ts +12 -8
- package/src/task/executor.ts +70 -20
- package/src/task/index.ts +30 -34
- package/src/task/isolation-runner.ts +24 -11
- package/src/task/persisted-revive.ts +12 -5
- package/src/task/read-only-policy.ts +27 -0
- package/src/task/structured-subagent.ts +14 -4
- package/src/task/types.ts +4 -0
- package/src/tools/auto-generated-guard.ts +1 -1
- package/src/tools/bash-interactive.ts +4 -4
- package/src/tools/bash-skill-urls.ts +15 -0
- package/src/tools/bash.ts +16 -17
- package/src/tools/browser/cmux/cmux-tab.ts +66 -18
- package/src/tools/browser/launch.ts +41 -12
- package/src/tools/browser/readable.ts +9 -9
- package/src/tools/browser/tab-supervisor.ts +12 -3
- package/src/tools/browser/tab-worker-entry.ts +1 -1
- package/src/tools/browser/tab-worker.ts +101 -12
- package/src/tools/debug.ts +1 -1
- package/src/tools/fetch.ts +1 -1
- package/src/tools/jtd-to-json-schema.ts +123 -21
- package/src/tools/path-utils.ts +9 -2
- package/src/tools/read.ts +21 -9
- package/src/tools/run-scope.ts +290 -4
- package/src/tools/shell-tokenize.ts +98 -0
- package/src/tools/terminal-output.ts +1 -1
- package/src/tools/todo.ts +1 -1
- package/src/utils/clipboard.ts +10 -2
- package/src/utils/external-editor.ts +4 -2
- package/src/utils/jj.ts +1 -1
- package/src/utils/turndown.ts +1 -2
- package/src/vibe/runtime.ts +5 -5
- package/src/web/scrapers/arxiv.ts +1 -1
- package/src/web/scrapers/go-pkg.ts +1 -1
- package/src/web/scrapers/iacr.ts +1 -1
- package/src/web/scrapers/readthedocs.ts +2 -1
- package/src/web/scrapers/twitter.ts +2 -2
- package/src/web/scrapers/types.ts +1 -1
- package/src/web/scrapers/wikipedia.ts +1 -1
- package/src/web/search/providers/browser-headers.ts +12 -39
- package/src/web/search/providers/codex.ts +3 -26
- package/src/web/search/providers/ecosia.ts +1 -1
- package/src/web/search/providers/exa.ts +1 -1
- package/src/web/search/providers/google.ts +1 -1
- package/src/web/search/providers/mojeek.ts +1 -1
- package/src/web/search/providers/startpage.ts +1 -1
- package/src/markit/converters/mammoth.d.ts +0 -24
|
@@ -423,6 +423,25 @@ function isGlobalRequireCall(node: StructuralAstNode | null, scope: BindingScope
|
|
|
423
423
|
);
|
|
424
424
|
}
|
|
425
425
|
|
|
426
|
+
/**
|
|
427
|
+
* Whether `node` is a `createRequire(...)` factory call imported from
|
|
428
|
+
* `node:module` (or its `module` alias).
|
|
429
|
+
*/
|
|
430
|
+
function isCreateRequireInvocation(
|
|
431
|
+
node: StructuralAstNode | null,
|
|
432
|
+
createRequireBindings: ReadonlySet<string>,
|
|
433
|
+
moduleNamespaceBindings: ReadonlySet<string>,
|
|
434
|
+
): boolean {
|
|
435
|
+
if (node?.type !== "CallExpression") return false;
|
|
436
|
+
const callee = asAstNode(node.callee);
|
|
437
|
+
if (callee?.type === "Identifier" && typeof callee.name === "string") {
|
|
438
|
+
return createRequireBindings.has(callee.name);
|
|
439
|
+
}
|
|
440
|
+
if (callee?.type !== "MemberExpression" || staticMemberPropertyName(callee) !== "createRequire") return false;
|
|
441
|
+
const object = asAstNode(callee.object);
|
|
442
|
+
return object?.type === "Identifier" && typeof object.name === "string" && moduleNamespaceBindings.has(object.name);
|
|
443
|
+
}
|
|
444
|
+
|
|
426
445
|
function staticMemberPropertyName(node: StructuralAstNode): string | null {
|
|
427
446
|
const property = asAstNode(node.property);
|
|
428
447
|
if (node.computed !== true && property?.type === "Identifier" && typeof property.name === "string") {
|
|
@@ -458,6 +477,28 @@ function collectExtensionSpecifierReferences(
|
|
|
458
477
|
references.push({ kind, specifier: node.value, start: node.start, end: node.end });
|
|
459
478
|
}
|
|
460
479
|
};
|
|
480
|
+
const createRequireBindings = new Set<string>();
|
|
481
|
+
const moduleNamespaceBindings = new Set<string>();
|
|
482
|
+
for (const { node } of collectScopedAstNodes(ast, candidate => candidate.type === "ImportDeclaration")) {
|
|
483
|
+
const source = asAstNode(node.source);
|
|
484
|
+
if (source?.type !== "StringLiteral" || (source.value !== "node:module" && source.value !== "module")) continue;
|
|
485
|
+
for (const value of Array.isArray(node.specifiers) ? node.specifiers : []) {
|
|
486
|
+
const specifier = asAstNode(value);
|
|
487
|
+
const local = asAstNode(specifier?.local);
|
|
488
|
+
if (local?.type !== "Identifier" || typeof local.name !== "string") continue;
|
|
489
|
+
if (specifier?.type === "ImportNamespaceSpecifier") {
|
|
490
|
+
moduleNamespaceBindings.add(local.name);
|
|
491
|
+
} else if (specifier?.type === "ImportSpecifier") {
|
|
492
|
+
const imported = asAstNode(specifier.imported);
|
|
493
|
+
if (
|
|
494
|
+
(imported?.type === "Identifier" && imported.name === "createRequire") ||
|
|
495
|
+
(imported?.type === "StringLiteral" && imported.value === "createRequire")
|
|
496
|
+
) {
|
|
497
|
+
createRequireBindings.add(local.name);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
461
502
|
for (const { node, scope } of collectScopedAstNodes(ast, isSpecifierReferenceNode)) {
|
|
462
503
|
if (
|
|
463
504
|
node.type === "ImportDeclaration" ||
|
|
@@ -478,6 +519,18 @@ function collectExtensionSpecifierReferences(
|
|
|
478
519
|
record("import", nodeArgument(node, 0));
|
|
479
520
|
} else if (isIdentifier(callee, "require") && !scopeHasBinding(scope, REQUIRE_BINDING)) {
|
|
480
521
|
record("require", nodeArgument(node, 0));
|
|
522
|
+
} else if (isCreateRequireInvocation(callee, createRequireBindings, moduleNamespaceBindings)) {
|
|
523
|
+
// `createRequire(base)(spec)` — pin the invoked bare dependency so it
|
|
524
|
+
// loads without a runtime `node_modules` lookup. Relative specifiers
|
|
525
|
+
// resolve against `base`, which is not rewritten, so restrict to bare.
|
|
526
|
+
const argument = nodeArgument(node, 0);
|
|
527
|
+
if (
|
|
528
|
+
argument?.type === "StringLiteral" &&
|
|
529
|
+
typeof argument.value === "string" &&
|
|
530
|
+
isBareExtensionDependencySpecifier(argument.value)
|
|
531
|
+
) {
|
|
532
|
+
record("require", argument);
|
|
533
|
+
}
|
|
481
534
|
}
|
|
482
535
|
}
|
|
483
536
|
}
|
|
@@ -408,7 +408,7 @@ export class MarketplaceManager {
|
|
|
408
408
|
/**
|
|
409
409
|
* Resolve plugin version from multiple sources:
|
|
410
410
|
* 1. Catalog entry version (if set)
|
|
411
|
-
* 2. Plugin manifest (.claude-plugin/plugin.json or package.json)
|
|
411
|
+
* 2. Plugin manifest (.claude-plugin/plugin.json, Agent Plugins root plugin.json, or package.json)
|
|
412
412
|
* 3. Git SHA from source (truncated to 7 chars)
|
|
413
413
|
* 4. Fallback "0.0.0"
|
|
414
414
|
*/
|
|
@@ -419,6 +419,7 @@ export class MarketplaceManager {
|
|
|
419
419
|
// 2. Plugin manifest
|
|
420
420
|
for (const manifestPath of [
|
|
421
421
|
path.join(sourcePath, ".claude-plugin", "plugin.json"),
|
|
422
|
+
path.join(sourcePath, "plugin.json"),
|
|
422
423
|
path.join(sourcePath, "package.json"),
|
|
423
424
|
]) {
|
|
424
425
|
try {
|
|
@@ -249,7 +249,8 @@ export interface AutoRetryStartEvent {
|
|
|
249
249
|
errorId?: number;
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
-
|
|
252
|
+
/** Persisted retry error whose transcript presentation changed when the retry saga settled. */
|
|
253
|
+
export interface RetryErrorUpdate {
|
|
253
254
|
entryId: string;
|
|
254
255
|
persistenceKey?: string;
|
|
255
256
|
note: string;
|
|
@@ -262,7 +263,7 @@ export interface AutoRetryEndEvent {
|
|
|
262
263
|
success: boolean;
|
|
263
264
|
attempt: number;
|
|
264
265
|
finalError?: string;
|
|
265
|
-
|
|
266
|
+
retryErrors?: RetryErrorUpdate[];
|
|
266
267
|
}
|
|
267
268
|
|
|
268
269
|
// ============================================================================
|
|
@@ -27,6 +27,11 @@ export interface Skill {
|
|
|
27
27
|
* prompt's `<skills>` listing.
|
|
28
28
|
*/
|
|
29
29
|
hide?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Filesystem-resolved plugin root for Agent Plugin skills (spec §4.1):
|
|
32
|
+
* every `skill://` resource access must realpath-resolve within it.
|
|
33
|
+
*/
|
|
34
|
+
containRoot?: string;
|
|
30
35
|
/** Source metadata for display */
|
|
31
36
|
_source?: SourceMeta;
|
|
32
37
|
}
|
|
@@ -104,6 +109,7 @@ export async function loadSkillsFromDir(options: LoadSkillsFromDirOptions): Prom
|
|
|
104
109
|
filePath: capSkill.path,
|
|
105
110
|
baseDir: capSkill.path.replace(/[\\/]SKILL\.md$/, ""),
|
|
106
111
|
source: options.source,
|
|
112
|
+
...(capSkill.containRoot !== undefined && { containRoot: capSkill.containRoot }),
|
|
107
113
|
hide: capSkill.frontmatter?.hide === true || capSkill.frontmatter?.disableModelInvocation === true,
|
|
108
114
|
_source: capSkill._source,
|
|
109
115
|
})),
|
|
@@ -239,6 +245,7 @@ export async function loadSkills(options: LoadSkillsOptions = {}): Promise<LoadS
|
|
|
239
245
|
filePath: capSkill.path,
|
|
240
246
|
baseDir: capSkill.path.replace(/[\\/]SKILL\.md$/, ""),
|
|
241
247
|
source: `${capSkill._source.provider}:${capSkill.level}`,
|
|
248
|
+
...(capSkill.containRoot !== undefined && { containRoot: capSkill.containRoot }),
|
|
242
249
|
hide: capSkill.frontmatter?.hide === true || capSkill.frontmatter?.disableModelInvocation === true,
|
|
243
250
|
_source: capSkill._source,
|
|
244
251
|
});
|
|
@@ -276,6 +283,7 @@ export async function loadSkills(options: LoadSkillsOptions = {}): Promise<LoadS
|
|
|
276
283
|
filePath: capSkill.path,
|
|
277
284
|
baseDir: capSkill.path.replace(/[\\/]SKILL\.md$/, ""),
|
|
278
285
|
source: "custom:user",
|
|
286
|
+
...(capSkill.containRoot !== undefined && { containRoot: capSkill.containRoot }),
|
|
279
287
|
hide: capSkill.frontmatter?.hide === true || capSkill.frontmatter?.disableModelInvocation === true,
|
|
280
288
|
_source: { ...capSkill._source, providerName: "Custom" },
|
|
281
289
|
},
|
|
@@ -376,6 +384,7 @@ export async function loadSkills(options: LoadSkillsOptions = {}): Promise<LoadS
|
|
|
376
384
|
filePath: capSkill.path,
|
|
377
385
|
baseDir: capSkill.path.replace(/[\\/]SKILL\.md$/, ""),
|
|
378
386
|
source: `${capSkill._source.provider}:${capSkill.level}`,
|
|
387
|
+
...(capSkill.containRoot !== undefined && { containRoot: capSkill.containRoot }),
|
|
379
388
|
hide: capSkill.frontmatter?.hide === true || capSkill.frontmatter?.disableModelInvocation === true,
|
|
380
389
|
_source: capSkill._source,
|
|
381
390
|
});
|
package/src/index.ts
CHANGED
|
@@ -2,12 +2,12 @@ import { HookEditorComponent, HookInputComponent, HookSelectorComponent } from "
|
|
|
2
2
|
|
|
3
3
|
// Core session management
|
|
4
4
|
|
|
5
|
+
export * as zod from "@oh-my-pi/omptype/zod";
|
|
6
|
+
export { z } from "@oh-my-pi/omptype/zod";
|
|
5
7
|
// Re-export TUI components for custom tool rendering
|
|
6
8
|
export { Container, Markdown, Spacer, Text } from "@oh-my-pi/pi-tui";
|
|
7
9
|
// Logging
|
|
8
10
|
export { getAgentDir, logger, VERSION } from "@oh-my-pi/pi-utils";
|
|
9
|
-
export * as zod from "zod/v4";
|
|
10
|
-
export { z } from "zod/v4";
|
|
11
11
|
export * from "./config/keybindings";
|
|
12
12
|
export * from "./config/model-registry";
|
|
13
13
|
// Prompt templates
|
|
@@ -290,6 +290,10 @@ export class MemoryProtocolHandler implements ProtocolHandler {
|
|
|
290
290
|
readonly immutable = true;
|
|
291
291
|
|
|
292
292
|
async resolve(url: InternalUrl, context?: ResolveContext): Promise<InternalResource> {
|
|
293
|
+
const backend = memoryBackendFromContext(context);
|
|
294
|
+
if (backend === "off") {
|
|
295
|
+
throw new Error("Unknown protocol: memory://");
|
|
296
|
+
}
|
|
293
297
|
const namespace = url.rawHost || url.hostname;
|
|
294
298
|
if (!namespace) {
|
|
295
299
|
throw new Error("memory:// URL requires a namespace: memory://root or memory://<memory-id>");
|
|
@@ -303,7 +307,7 @@ export class MemoryProtocolHandler implements ProtocolHandler {
|
|
|
303
307
|
if (namespace !== MEMORY_NAMESPACE) {
|
|
304
308
|
const mnemopiStates = mnemopiSessionStatesFromRegistry();
|
|
305
309
|
const hindsightActive =
|
|
306
|
-
|
|
310
|
+
backend === "hindsight" ||
|
|
307
311
|
(mnemopiStates.length === 0 &&
|
|
308
312
|
AgentRegistry.global()
|
|
309
313
|
.list()
|
|
@@ -11,6 +11,7 @@ import type * as fsTypes from "node:fs";
|
|
|
11
11
|
import * as fs from "node:fs/promises";
|
|
12
12
|
import * as path from "node:path";
|
|
13
13
|
import { isEnoent } from "@oh-my-pi/pi-utils";
|
|
14
|
+
import { resolveContainedPath } from "../discovery/contained-path";
|
|
14
15
|
import { getActiveSkills } from "../extensibility/skills";
|
|
15
16
|
import { isMarkdownPath } from "../utils/lang-from-path";
|
|
16
17
|
import { buildDirectoryResource } from "./filesystem-resource";
|
|
@@ -76,6 +77,19 @@ export class SkillProtocolHandler implements ProtocolHandler {
|
|
|
76
77
|
if (!resolvedPath.startsWith(resolvedBaseDir + path.sep) && resolvedPath !== resolvedBaseDir) {
|
|
77
78
|
throw new Error("Path traversal is not allowed");
|
|
78
79
|
}
|
|
80
|
+
// Agent Plugin skills (§4.1): the resource must canonically resolve
|
|
81
|
+
// within the plugin root; a dangling or unresolvable path fails closed.
|
|
82
|
+
// Symlinks may target other files inside the same package.
|
|
83
|
+
if (skill.containRoot) {
|
|
84
|
+
const contained = await resolveContainedPath(skill.containRoot, resolvedPath);
|
|
85
|
+
if (contained.status === "outside") {
|
|
86
|
+
throw new Error(`skill:// path resolves outside the plugin root: ${url.href}`);
|
|
87
|
+
}
|
|
88
|
+
if (contained.status === "missing") {
|
|
89
|
+
throw new Error(`File not found: ${resolvedPath}`);
|
|
90
|
+
}
|
|
91
|
+
targetPath = contained.realPath;
|
|
92
|
+
}
|
|
79
93
|
} else {
|
|
80
94
|
targetPath = context?.pathOnly === true ? skill.baseDir : skill.filePath;
|
|
81
95
|
}
|
|
@@ -787,7 +787,7 @@ export class VaultProtocolHandler implements ProtocolHandler {
|
|
|
787
787
|
const cacheKey = parsed.ref.active ? "_" : (parsed.ref.vault ?? "_");
|
|
788
788
|
let cliInfo = cachedVaultInfo.get(cacheKey);
|
|
789
789
|
if (cliInfo === undefined) {
|
|
790
|
-
const result = await this.#spawn([
|
|
790
|
+
const result = await this.#spawn([...this.#vaultCliArg(parsed.ref), "vault", "info"], context);
|
|
791
791
|
assertCliSuccess("vault info", result);
|
|
792
792
|
cliInfo = result.stdout.trim();
|
|
793
793
|
cachedVaultInfo.set(cacheKey, cliInfo);
|
|
@@ -926,7 +926,7 @@ export class VaultProtocolHandler implements ProtocolHandler {
|
|
|
926
926
|
context?: ResolveContext,
|
|
927
927
|
): Promise<InternalResource> {
|
|
928
928
|
const invocation = buildObsidianCliInvocation(parsed);
|
|
929
|
-
const args = [...
|
|
929
|
+
const args = [...this.#vaultCliArg(parsed.ref), ...invocation.args];
|
|
930
930
|
const result = await this.#spawn(args, context);
|
|
931
931
|
assertCliSuccess(invocation.opLabel, result);
|
|
932
932
|
return {
|
package/src/launch/client.ts
CHANGED
|
@@ -367,7 +367,17 @@ class SocketDaemonClient implements DaemonBrokerClient {
|
|
|
367
367
|
try {
|
|
368
368
|
message = parseDaemonWireMessage(decoded);
|
|
369
369
|
} catch (error) {
|
|
370
|
-
|
|
370
|
+
const parseError = error instanceof Error ? error : new Error(String(error));
|
|
371
|
+
if (
|
|
372
|
+
typeof decoded === "object" &&
|
|
373
|
+
decoded !== null &&
|
|
374
|
+
"event" in decoded &&
|
|
375
|
+
decoded.event === "daemon-completed"
|
|
376
|
+
) {
|
|
377
|
+
logger.warn("Ignoring malformed daemon completion", { error: parseError.message });
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
this.#rejectPending(parseError);
|
|
371
381
|
continue;
|
|
372
382
|
}
|
|
373
383
|
if ("event" in message) {
|
package/src/launch/protocol.ts
CHANGED
|
@@ -168,6 +168,11 @@ function optionalString(value: unknown, label: string): string | undefined {
|
|
|
168
168
|
return stringValue(value, label);
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
+
function optionalRawString(value: unknown, label: string): string | undefined {
|
|
172
|
+
if (value === undefined) return undefined;
|
|
173
|
+
return rawString(value, label);
|
|
174
|
+
}
|
|
175
|
+
|
|
171
176
|
function booleanValue(value: unknown, label: string): boolean {
|
|
172
177
|
if (typeof value !== "boolean") throw new Error(`${label} must be a boolean`);
|
|
173
178
|
return value;
|
|
@@ -272,7 +277,7 @@ export function parseDaemonSnapshot(value: unknown): DaemonSnapshot {
|
|
|
272
277
|
restartCount: numberValue(source.restartCount, "daemon.restartCount"),
|
|
273
278
|
outputBytes: numberValue(source.outputBytes, "daemon.outputBytes"),
|
|
274
279
|
owner: optionalString(source.owner, "daemon.owner"),
|
|
275
|
-
readyMatch:
|
|
280
|
+
readyMatch: optionalRawString(source.readyMatch, "daemon.readyMatch"),
|
|
276
281
|
readyPending: source.readyPending === undefined ? undefined : readyPendingList(source.readyPending),
|
|
277
282
|
persist: booleanValue(source.persist, "daemon.persist"),
|
|
278
283
|
detached: source.detached === undefined ? false : booleanValue(source.detached, "daemon.detached"),
|
|
@@ -427,7 +432,7 @@ export function parseDaemonRpcResult(operation: DaemonOperation, value: unknown)
|
|
|
427
432
|
return {
|
|
428
433
|
op: "wait",
|
|
429
434
|
daemon: parseDaemonSnapshot(source.daemon),
|
|
430
|
-
matched:
|
|
435
|
+
matched: optionalRawString(source.matched, "result.matched"),
|
|
431
436
|
timedOut: booleanValue(source.timedOut, "result.timedOut"),
|
|
432
437
|
};
|
|
433
438
|
case "send":
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { logger } from "@oh-my-pi/pi-utils";
|
|
2
|
-
import xterm, { type Terminal as XtermTerminal } from "@
|
|
2
|
+
import xterm, { type Terminal as XtermTerminal } from "@oh-my-pi/pi-utils/vterm";
|
|
3
3
|
import { readTerminalRows } from "../tools/terminal-output";
|
|
4
4
|
import { DAEMON_PTY_COLUMNS, DAEMON_PTY_ROWS } from "./protocol";
|
|
5
5
|
|
package/src/main.ts
CHANGED
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
setProjectDir,
|
|
22
22
|
VERSION,
|
|
23
23
|
} from "@oh-my-pi/pi-utils";
|
|
24
|
-
import chalk from "chalk";
|
|
24
|
+
import chalk from "@oh-my-pi/pi-utils/chalk";
|
|
25
25
|
import { reset as resetCapabilities } from "./capability";
|
|
26
26
|
import { type Args, reportUnrecognizedFlags } from "./cli/args";
|
|
27
27
|
import { applyExtensionFlags, type ExtensionFlagSink } from "./cli/extension-flags";
|
|
@@ -52,6 +52,7 @@ import {
|
|
|
52
52
|
} from "./discovery/helpers";
|
|
53
53
|
import { injectOmpExtensionCliRoots } from "./discovery/omp-extension-roots";
|
|
54
54
|
import { formatExtensionLoadNotifications } from "./extensibility/extensions/load-errors";
|
|
55
|
+
import { loadExtensions } from "./extensibility/extensions/loader";
|
|
55
56
|
import { ExtensionRunner } from "./extensibility/extensions/runner";
|
|
56
57
|
import type { ExtensionUIContext } from "./extensibility/extensions/types";
|
|
57
58
|
import { scheduleMarketplaceAutoUpdate } from "./extensibility/plugins/marketplace-auto-update";
|
|
@@ -358,11 +359,31 @@ export interface AcpSessionFactoryOptions {
|
|
|
358
359
|
sessionDir?: string;
|
|
359
360
|
authStorage: AuthStorage;
|
|
360
361
|
modelRegistry: ModelRegistry;
|
|
361
|
-
parsedArgs: Pick<Args, "apiKey">;
|
|
362
|
+
parsedArgs: Pick<Args, "apiKey" | "trustedExtensions">;
|
|
362
363
|
rawArgs: string[];
|
|
363
364
|
createSession: (options: CreateAgentSessionOptions) => Promise<CreateAgentSessionResult>;
|
|
364
365
|
}
|
|
365
366
|
|
|
367
|
+
async function loadTrustedSessionExtensions(
|
|
368
|
+
options: Pick<CreateAgentSessionOptions, "additionalExtensionPaths">,
|
|
369
|
+
cwd: string,
|
|
370
|
+
eventBus: EventBus,
|
|
371
|
+
) {
|
|
372
|
+
const paths = options.additionalExtensionPaths ?? [];
|
|
373
|
+
for (const trustedPath of paths) {
|
|
374
|
+
let stat: fsSync.Stats;
|
|
375
|
+
try {
|
|
376
|
+
stat = fsSync.statSync(trustedPath);
|
|
377
|
+
} catch {
|
|
378
|
+
throw new Error(`Trusted extension must be an existing module file: ${trustedPath}`);
|
|
379
|
+
}
|
|
380
|
+
if (!stat.isFile()) {
|
|
381
|
+
throw new Error(`Trusted extension must be a module file, not a directory: ${trustedPath}`);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return loadExtensions(paths, cwd, eventBus);
|
|
385
|
+
}
|
|
386
|
+
|
|
366
387
|
/**
|
|
367
388
|
* Build the per-`session/new` factory used by ACP mode.
|
|
368
389
|
*
|
|
@@ -385,6 +406,16 @@ export function createAcpSessionFactory(args: AcpSessionFactoryOptions): AcpSess
|
|
|
385
406
|
// policy (PR #3736 follow-up).
|
|
386
407
|
const titleSystemPromptSource = discoverTitleSystemPromptFile(cwd);
|
|
387
408
|
const titleSystemPrompt = await resolvePromptInput(titleSystemPromptSource, "title system prompt");
|
|
409
|
+
const eventBus = new EventBus();
|
|
410
|
+
const trustedExtensions =
|
|
411
|
+
args.parsedArgs.trustedExtensions && args.parsedArgs.trustedExtensions.length > 0
|
|
412
|
+
? await loadTrustedSessionExtensions(args.baseOptions, cwd, eventBus)
|
|
413
|
+
: undefined;
|
|
414
|
+
if (trustedExtensions && trustedExtensions.errors.length > 0) {
|
|
415
|
+
throw new Error(
|
|
416
|
+
`Trusted extension failed to load: ${trustedExtensions.errors.map(item => item.error).join("; ")}`,
|
|
417
|
+
);
|
|
418
|
+
}
|
|
388
419
|
const { session: nextSession } = await args.createSession({
|
|
389
420
|
...args.baseOptions,
|
|
390
421
|
cwd,
|
|
@@ -398,6 +429,8 @@ export function createAcpSessionFactory(args: AcpSessionFactoryOptions): AcpSess
|
|
|
398
429
|
deferUsageReserveConfirmation: true,
|
|
399
430
|
enableMCP: false,
|
|
400
431
|
titleSystemPrompt,
|
|
432
|
+
eventBus,
|
|
433
|
+
preloadedExtensions: trustedExtensions,
|
|
401
434
|
});
|
|
402
435
|
if (args.parsedArgs.apiKey && !args.baseOptions.model && nextSession.model) {
|
|
403
436
|
args.authStorage.setRuntimeApiKey(nextSession.model.provider, args.parsedArgs.apiKey);
|
|
@@ -1000,11 +1033,12 @@ export async function buildSessionOptions(
|
|
|
1000
1033
|
if (parsed.noPrewalk && (parsed.prewalk || parsed.prewalkInto !== undefined)) {
|
|
1001
1034
|
throw new Error("--no-prewalk cannot be combined with --prewalk or --prewalk-into");
|
|
1002
1035
|
}
|
|
1036
|
+
const explicitPrewalk = parsed.prewalk === true || parsed.prewalkInto !== undefined;
|
|
1003
1037
|
const prewalkEnabled = parsed.noPrewalk
|
|
1004
1038
|
? false
|
|
1005
|
-
:
|
|
1039
|
+
: explicitPrewalk
|
|
1006
1040
|
? true
|
|
1007
|
-
: activeSettings.get("prewalk.enabled");
|
|
1041
|
+
: !restoringSession && activeSettings.get("prewalk.enabled");
|
|
1008
1042
|
if (prewalkEnabled) {
|
|
1009
1043
|
const rolePattern = expandRoleAlias(parsed.prewalkInto ?? DEFAULT_PREWALK_TARGET, activeSettings);
|
|
1010
1044
|
const resolved = resolveCliModel({ cliModel: rolePattern, modelRegistry, preferences: modelMatchPreferences });
|
|
@@ -1114,14 +1148,34 @@ export async function buildSessionOptions(
|
|
|
1114
1148
|
options.rules = [];
|
|
1115
1149
|
}
|
|
1116
1150
|
|
|
1117
|
-
//
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1151
|
+
// Trusted extension paths are an exact allowlist for extension modules.
|
|
1152
|
+
if (parsed.trustedExtensions && parsed.trustedExtensions.length > 0) {
|
|
1153
|
+
const trustedPaths = parsed.trustedExtensions.map(trustedPath => {
|
|
1154
|
+
let resolvedPath: string;
|
|
1155
|
+
let stat: fsSync.Stats;
|
|
1156
|
+
try {
|
|
1157
|
+
resolvedPath = fsSync.realpathSync.native(trustedPath);
|
|
1158
|
+
stat = fsSync.statSync(resolvedPath);
|
|
1159
|
+
} catch {
|
|
1160
|
+
throw new Error(`Trusted extension must be an existing module file: ${trustedPath}`);
|
|
1161
|
+
}
|
|
1162
|
+
if (!stat.isFile()) {
|
|
1163
|
+
throw new Error(`Trusted extension must be a module file, not a directory: ${trustedPath}`);
|
|
1164
|
+
}
|
|
1165
|
+
return resolvedPath;
|
|
1166
|
+
});
|
|
1124
1167
|
options.disableExtensionDiscovery = true;
|
|
1168
|
+
options.additionalExtensionPaths = trustedPaths;
|
|
1169
|
+
} else {
|
|
1170
|
+
// Additional extension paths from CLI
|
|
1171
|
+
const cliExtensionPaths = [...(parsed.extensions ?? []), ...(parsed.hooks ?? [])];
|
|
1172
|
+
if (cliExtensionPaths.length > 0) {
|
|
1173
|
+
options.additionalExtensionPaths = cliExtensionPaths;
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
if (parsed.noExtensions) {
|
|
1177
|
+
options.disableExtensionDiscovery = true;
|
|
1178
|
+
}
|
|
1125
1179
|
}
|
|
1126
1180
|
|
|
1127
1181
|
return options;
|
|
@@ -1194,16 +1248,20 @@ export async function runRootCommand(
|
|
|
1194
1248
|
// warning before we reach the await site below.
|
|
1195
1249
|
pluginPreloadPromise.catch(() => {});
|
|
1196
1250
|
|
|
1197
|
-
//
|
|
1198
|
-
//
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1251
|
+
// Trusted files load as exact module paths, never as package roots whose
|
|
1252
|
+
// sibling hooks/tools/commands/MCP content could be discovered implicitly.
|
|
1253
|
+
if (!parsedArgs.trustedExtensions?.length) {
|
|
1254
|
+
// Register CLI-provided extension package paths (`--extension`, `--hook`) so
|
|
1255
|
+
// the `omp-plugins` discovery provider can surface their `skills/`, `hooks/`,
|
|
1256
|
+
// `tools/`, `commands/`, `rules/`, `prompts/`, and `.mcp.json` sub-trees.
|
|
1257
|
+
// Explicit roots remain authorized under `--no-extensions`; only ambient
|
|
1258
|
+
// extension discovery is disabled.
|
|
1259
|
+
const cliExtensions = [...(parsedArgs.extensions ?? []), ...(parsedArgs.hooks ?? [])];
|
|
1260
|
+
injectOmpExtensionCliRoots(cliExtensions, home, getProjectDir(), {
|
|
1261
|
+
mode: parsedArgs.noExtensions ? "explicit-only" : "merge",
|
|
1262
|
+
replace: true,
|
|
1263
|
+
});
|
|
1264
|
+
}
|
|
1207
1265
|
|
|
1208
1266
|
let cwd = getProjectDir();
|
|
1209
1267
|
// Classify the host before opening auth or settings storage so every
|
|
@@ -1542,12 +1600,14 @@ export async function runRootCommand(
|
|
|
1542
1600
|
// string-flag value such as `--target @notes.md` is the flag's value, not a
|
|
1543
1601
|
// file — and the same result is handed to createAgentSession via
|
|
1544
1602
|
// `preloadedExtensions` so the discovery work is not repeated.
|
|
1545
|
-
if (isInteractive) {
|
|
1603
|
+
if (isInteractive && !parsedArgs.trustedExtensions?.length) {
|
|
1546
1604
|
sessionOptions.extensions = [...(sessionOptions.extensions ?? []), createWarpEventBridgeExtension()];
|
|
1547
1605
|
}
|
|
1548
1606
|
|
|
1549
1607
|
const eventBus = new EventBus();
|
|
1550
|
-
const extensionsResult =
|
|
1608
|
+
const extensionsResult = parsedArgs.trustedExtensions?.length
|
|
1609
|
+
? await loadTrustedSessionExtensions(sessionOptions, cwd, eventBus)
|
|
1610
|
+
: await loadSessionExtensions(sessionOptions, cwd, settingsInstance, eventBus);
|
|
1551
1611
|
const extensionFlagSink: ExtensionFlagSink = {
|
|
1552
1612
|
getFlags: () => ExtensionRunner.aggregateFlags(extensionsResult.extensions),
|
|
1553
1613
|
setFlagValue: (name, value) => {
|
|
@@ -1556,6 +1616,11 @@ export async function runRootCommand(
|
|
|
1556
1616
|
};
|
|
1557
1617
|
const initialArgs = applyExtensionFlags(extensionFlagSink, rawArgs) ?? parsedArgs;
|
|
1558
1618
|
normalizeContinueSessionArgs(initialArgs, rawArgs);
|
|
1619
|
+
if ((parsedArgs.trustedExtensions?.length ?? 0) > 0 && extensionsResult.errors.length > 0) {
|
|
1620
|
+
throw new Error(
|
|
1621
|
+
`Trusted extension failed to load: ${extensionsResult.errors.map(item => item.error).join("; ")}`,
|
|
1622
|
+
);
|
|
1623
|
+
}
|
|
1559
1624
|
for (const message of formatExtensionLoadNotifications(extensionsResult.errors)) {
|
|
1560
1625
|
if (isInteractive) {
|
|
1561
1626
|
notifs.push({ kind: "warn", message });
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Adapted from markit-ai (MIT). See ../NOTICE.
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import mammoth from "
|
|
3
|
+
import mammoth from "@oh-my-pi/pi-utils/docx";
|
|
4
4
|
import { createTurndown, normalizeTablesHtml } from "../../utils/turndown";
|
|
5
5
|
import type { ConversionResult, Converter, StreamInfo } from "../types";
|
|
6
6
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Adapted from markit-ai (MIT). See ../NOTICE.
|
|
2
|
-
import { XMLParser } from "
|
|
2
|
+
import { XMLParser } from "@oh-my-pi/pi-utils/xml";
|
|
3
3
|
import { createTurndown, normalizeTablesHtml } from "../../utils/turndown";
|
|
4
4
|
import { unzip, unzipText } from "../../utils/zip";
|
|
5
5
|
import type { ConversionResult, Converter, StreamInfo } from "../types";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Adapted from markit-ai (MIT). See ../NOTICE.
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import { XMLParser } from "
|
|
3
|
+
import { XMLParser } from "@oh-my-pi/pi-utils/xml";
|
|
4
4
|
import { unzip, unzipText } from "../../utils/zip";
|
|
5
5
|
import type { ConversionResult, Converter, StreamInfo } from "../types";
|
|
6
6
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Adapted from markit-ai (MIT). See ../NOTICE.
|
|
2
|
-
import { XMLParser } from "
|
|
2
|
+
import { XMLParser } from "@oh-my-pi/pi-utils/xml";
|
|
3
3
|
import { unzip, unzipText } from "../../utils/zip";
|
|
4
4
|
import type { ConversionResult, Converter, StreamInfo } from "../types";
|
|
5
5
|
|
package/src/mcp/config.ts
CHANGED
|
@@ -54,6 +54,7 @@ function convertToLegacyConfig(server: MCPServer): MCPServerConfig {
|
|
|
54
54
|
};
|
|
55
55
|
if (server.args) config.args = server.args;
|
|
56
56
|
if (server.env) config.env = server.env;
|
|
57
|
+
if (server.envPolicy) config.envPolicy = server.envPolicy;
|
|
57
58
|
if (server.cwd) config.cwd = server.cwd;
|
|
58
59
|
return config;
|
|
59
60
|
}
|
|
@@ -65,6 +66,7 @@ function convertToLegacyConfig(server: MCPServer): MCPServerConfig {
|
|
|
65
66
|
url: server.url ?? "",
|
|
66
67
|
};
|
|
67
68
|
if (server.headers) config.headers = server.headers;
|
|
69
|
+
if (server.headerPolicy) config.headerPolicy = server.headerPolicy;
|
|
68
70
|
return config;
|
|
69
71
|
}
|
|
70
72
|
|
|
@@ -75,6 +77,7 @@ function convertToLegacyConfig(server: MCPServer): MCPServerConfig {
|
|
|
75
77
|
url: server.url ?? "",
|
|
76
78
|
};
|
|
77
79
|
if (server.headers) config.headers = server.headers;
|
|
80
|
+
if (server.headerPolicy) config.headerPolicy = server.headerPolicy;
|
|
78
81
|
return config;
|
|
79
82
|
}
|
|
80
83
|
|
package/src/mcp/manager.ts
CHANGED
|
@@ -37,6 +37,7 @@ import type { McpConnectionStatusEvent } from "./startup-events";
|
|
|
37
37
|
import type { MCPToolDetails } from "./tool-bridge";
|
|
38
38
|
import { DeferredMCPTool, MCPTool } from "./tool-bridge";
|
|
39
39
|
import type { MCPToolCache } from "./tool-cache";
|
|
40
|
+
import { setGeneratedHeader } from "./transports/header-policy";
|
|
40
41
|
import type {
|
|
41
42
|
MCPAuthChallenge,
|
|
42
43
|
MCPGetPromptResult,
|
|
@@ -1458,13 +1459,11 @@ export class MCPManager {
|
|
|
1458
1459
|
|
|
1459
1460
|
if (credential) {
|
|
1460
1461
|
if (resolved.type === "http" || resolved.type === "sse") {
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
},
|
|
1467
|
-
};
|
|
1462
|
+
// Client-generated authorization wins over any configured header
|
|
1463
|
+
// with the same case-insensitive name (Agent Plugins §7.2.1).
|
|
1464
|
+
const headers = { ...resolved.headers };
|
|
1465
|
+
setGeneratedHeader(headers, "Authorization", `Bearer ${credential.access}`);
|
|
1466
|
+
resolved = { ...resolved, headers };
|
|
1468
1467
|
} else {
|
|
1469
1468
|
resolved = {
|
|
1470
1469
|
...resolved,
|
|
@@ -1481,7 +1480,9 @@ export class MCPManager {
|
|
|
1481
1480
|
}
|
|
1482
1481
|
|
|
1483
1482
|
if (resolved.type !== "http" && resolved.type !== "sse") {
|
|
1484
|
-
|
|
1483
|
+
// Literal env values (Agent Plugins §§4.1/9.2) are opaque package data:
|
|
1484
|
+
// no env-name lookup, no `!command` execution, no dropping empty values.
|
|
1485
|
+
if (resolved.env && resolved.envPolicy !== "literal") {
|
|
1485
1486
|
const nextEnv: Record<string, string> = {};
|
|
1486
1487
|
for (const [key, value] of Object.entries(resolved.env)) {
|
|
1487
1488
|
const resolvedValue = await resolveConfigValue(value);
|
|
@@ -1490,7 +1491,9 @@ export class MCPManager {
|
|
|
1490
1491
|
resolved = { ...resolved, env: nextEnv };
|
|
1491
1492
|
}
|
|
1492
1493
|
} else {
|
|
1493
|
-
|
|
1494
|
+
// Origin-locked servers (Agent Plugins §9.2) carry literal header
|
|
1495
|
+
// values: no placeholder or environment-variable expansion.
|
|
1496
|
+
if (resolved.headers && resolved.headerPolicy !== "origin-locked") {
|
|
1494
1497
|
const nextHeaders: Record<string, string> = {};
|
|
1495
1498
|
for (const [key, value] of Object.entries(resolved.headers)) {
|
|
1496
1499
|
const resolvedValue = await resolveConfigValue(value);
|