@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
package/src/tools/run-scope.ts
CHANGED
|
@@ -1,6 +1,285 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
1
2
|
import { untilAborted } from "@oh-my-pi/pi-utils/abortable";
|
|
3
|
+
import * as postmortem from "@oh-my-pi/pi-utils/postmortem";
|
|
2
4
|
import { ToolError, throwIfAborted } from "./tool-errors";
|
|
3
5
|
|
|
6
|
+
const browserRunRejections = new WeakMap<object, object>();
|
|
7
|
+
|
|
8
|
+
/** Associates a browser operation failure with its owning evaluated run. */
|
|
9
|
+
export function markBrowserRunRejection<T>(reason: T, owner: object): T {
|
|
10
|
+
if (reason !== null && (typeof reason === "object" || typeof reason === "function")) {
|
|
11
|
+
browserRunRejections.set(reason, owner);
|
|
12
|
+
}
|
|
13
|
+
return reason;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Returns whether a rejection was marked for the specified evaluated run. */
|
|
17
|
+
export function isBrowserRunRejection(reason: unknown, owner: object): boolean {
|
|
18
|
+
return (
|
|
19
|
+
reason !== null &&
|
|
20
|
+
(typeof reason === "object" || typeof reason === "function") &&
|
|
21
|
+
browserRunRejections.get(reason) === owner
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Returns whether a rejection belongs to the marked browser run or its evaluated source file. */
|
|
26
|
+
export function isBrowserRunOwnedRejection(reason: unknown, owner: object, filename: string): boolean {
|
|
27
|
+
if (isBrowserRunRejection(reason, owner)) return true;
|
|
28
|
+
return reason instanceof Error && typeof reason.stack === "string" && reason.stack.includes(filename);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
type FloatingRejectionHandler = (reason: unknown) => void;
|
|
32
|
+
|
|
33
|
+
interface ObservedPromiseState {
|
|
34
|
+
handled: boolean;
|
|
35
|
+
userContinuationFailed: boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const observedBrowserPromises = new WeakMap<Promise<unknown>, ObservedPromiseState>();
|
|
39
|
+
const observedPromiseConstructor = { [Symbol.species]: Promise };
|
|
40
|
+
|
|
41
|
+
type PromiseCombinatorName = "all" | "race";
|
|
42
|
+
type PromiseCombinator = (this: PromiseConstructor, values: Iterable<unknown>) => Promise<unknown>;
|
|
43
|
+
|
|
44
|
+
interface PromiseCombinatorTrackingContext {
|
|
45
|
+
owner: object;
|
|
46
|
+
onFloatingRejection: FloatingRejectionHandler;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const PROMISE_COMBINATORS: readonly PromiseCombinatorName[] = ["all", "race"];
|
|
50
|
+
const NativePromise = Promise;
|
|
51
|
+
const nativePromiseCombinators: Record<PromiseCombinatorName, PromiseCombinator> = {
|
|
52
|
+
all: Promise.all,
|
|
53
|
+
race: Promise.race,
|
|
54
|
+
};
|
|
55
|
+
const promiseCombinatorTracking = new AsyncLocalStorage<PromiseCombinatorTrackingContext>();
|
|
56
|
+
let previousPromiseDescriptor: PropertyDescriptor | undefined;
|
|
57
|
+
let promiseCombinatorTrackingScopes = 0;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Observes native promise-combinator results derived from browser promises for
|
|
61
|
+
* the duration of one evaluated run. Native `await` remains unchanged; dropped
|
|
62
|
+
* user continuations from `Promise.all` and `Promise.race` are routed to the
|
|
63
|
+
* owning run.
|
|
64
|
+
*/
|
|
65
|
+
export async function withBrowserPromiseCombinatorTracking<T>(
|
|
66
|
+
owner: object,
|
|
67
|
+
onFloatingRejection: FloatingRejectionHandler,
|
|
68
|
+
run: () => Promise<T>,
|
|
69
|
+
): Promise<T> {
|
|
70
|
+
installPromiseCombinatorTracking();
|
|
71
|
+
try {
|
|
72
|
+
return await promiseCombinatorTracking.run({ owner, onFloatingRejection }, run);
|
|
73
|
+
} finally {
|
|
74
|
+
restorePromiseCombinatorTracking();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function installPromiseCombinatorTracking(): void {
|
|
79
|
+
if (promiseCombinatorTrackingScopes > 0) {
|
|
80
|
+
promiseCombinatorTrackingScopes++;
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const descriptor = Object.getOwnPropertyDescriptor(globalThis, "Promise");
|
|
84
|
+
if (!descriptor) throw new Error("Global Promise descriptor is unavailable");
|
|
85
|
+
const trackedPromise = createTrackedPromiseConstructor();
|
|
86
|
+
Object.defineProperty(globalThis, "Promise", { ...descriptor, value: trackedPromise });
|
|
87
|
+
previousPromiseDescriptor = descriptor;
|
|
88
|
+
promiseCombinatorTrackingScopes = 1;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function restorePromiseCombinatorTracking(): void {
|
|
92
|
+
if (promiseCombinatorTrackingScopes > 1) {
|
|
93
|
+
promiseCombinatorTrackingScopes--;
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const descriptor = previousPromiseDescriptor;
|
|
97
|
+
try {
|
|
98
|
+
if (!descriptor) throw new Error("Global Promise tracking scope is not installed");
|
|
99
|
+
Object.defineProperty(globalThis, "Promise", descriptor);
|
|
100
|
+
} finally {
|
|
101
|
+
previousPromiseDescriptor = undefined;
|
|
102
|
+
promiseCombinatorTrackingScopes = 0;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function createTrackedPromiseConstructor(): PromiseConstructor {
|
|
107
|
+
class TrackedPromise<T> extends NativePromise<T> {}
|
|
108
|
+
for (const name of PROMISE_COMBINATORS) {
|
|
109
|
+
const original = nativePromiseCombinators[name];
|
|
110
|
+
Object.defineProperty(TrackedPromise, name, {
|
|
111
|
+
configurable: true,
|
|
112
|
+
writable: true,
|
|
113
|
+
value(this: PromiseConstructor, values: Iterable<unknown>): Promise<unknown> {
|
|
114
|
+
let hasObservedInput = false;
|
|
115
|
+
const result = Reflect.apply(original, this, [
|
|
116
|
+
tapObservedBrowserPromises(values, () => {
|
|
117
|
+
hasObservedInput = true;
|
|
118
|
+
}),
|
|
119
|
+
]) as Promise<unknown>;
|
|
120
|
+
const context = promiseCombinatorTracking.getStore();
|
|
121
|
+
return hasObservedInput && context
|
|
122
|
+
? observeBrowserRunPromise(result, context.owner, context.onFloatingRejection)
|
|
123
|
+
: result;
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return TrackedPromise;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function* tapObservedBrowserPromises(
|
|
131
|
+
values: Iterable<unknown>,
|
|
132
|
+
onObserved: () => void,
|
|
133
|
+
): Generator<unknown, void, undefined> {
|
|
134
|
+
for (const value of values) {
|
|
135
|
+
if (observedBrowserPromises.has(value as Promise<unknown>)) onObserved();
|
|
136
|
+
yield value;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Observes every explicit continuation of a browser promise without replacing
|
|
142
|
+
* the native promise. Browser failures remain contained; an unhandled error
|
|
143
|
+
* created by user continuation code is reported to the owning run.
|
|
144
|
+
*/
|
|
145
|
+
export function observeBrowserRunPromise<T>(
|
|
146
|
+
promise: Promise<T>,
|
|
147
|
+
owner: object,
|
|
148
|
+
onFloatingRejection: FloatingRejectionHandler,
|
|
149
|
+
): Promise<T> {
|
|
150
|
+
return observeBrowserRunPromiseWithState(promise, owner, onFloatingRejection, {
|
|
151
|
+
handled: false,
|
|
152
|
+
userContinuationFailed: false,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function observeBrowserRunPromiseWithState<T>(
|
|
157
|
+
promise: Promise<T>,
|
|
158
|
+
owner: object,
|
|
159
|
+
onFloatingRejection: FloatingRejectionHandler,
|
|
160
|
+
state: ObservedPromiseState,
|
|
161
|
+
): Promise<T> {
|
|
162
|
+
if (observedBrowserPromises.has(promise)) return promise;
|
|
163
|
+
observedBrowserPromises.set(promise, state);
|
|
164
|
+
const originalThen = promise.then.bind(promise);
|
|
165
|
+
const originalFinally = promise.finally.bind(promise);
|
|
166
|
+
void originalThen(undefined, reason => {
|
|
167
|
+
setTimeout(() => {
|
|
168
|
+
if (!state.handled && (state.userContinuationFailed || !isBrowserRunRejection(reason, owner))) {
|
|
169
|
+
onFloatingRejection(reason);
|
|
170
|
+
}
|
|
171
|
+
}, 0);
|
|
172
|
+
});
|
|
173
|
+
Object.defineProperties(promise, {
|
|
174
|
+
constructor: { configurable: true, value: observedPromiseConstructor },
|
|
175
|
+
// biome-ignore lint/suspicious/noThenProperty: native Promise continuations must remain thenable.
|
|
176
|
+
then: {
|
|
177
|
+
configurable: true,
|
|
178
|
+
value: <TResult1 = T, TResult2 = never>(
|
|
179
|
+
onFulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null,
|
|
180
|
+
onRejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,
|
|
181
|
+
): Promise<TResult1 | TResult2> => {
|
|
182
|
+
state.handled = true;
|
|
183
|
+
const childState = createContinuationState();
|
|
184
|
+
return observeBrowserRunPromiseWithState(
|
|
185
|
+
originalThen(
|
|
186
|
+
recordContinuationFailure(onFulfilled, childState),
|
|
187
|
+
recordContinuationFailure(onRejected, childState),
|
|
188
|
+
),
|
|
189
|
+
owner,
|
|
190
|
+
onFloatingRejection,
|
|
191
|
+
childState,
|
|
192
|
+
);
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
catch: {
|
|
196
|
+
configurable: true,
|
|
197
|
+
value: <TResult = never>(
|
|
198
|
+
onRejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | null,
|
|
199
|
+
): Promise<T | TResult> => {
|
|
200
|
+
state.handled = true;
|
|
201
|
+
const childState = createContinuationState();
|
|
202
|
+
return observeBrowserRunPromiseWithState(
|
|
203
|
+
originalThen(undefined, recordContinuationFailure(onRejected, childState)),
|
|
204
|
+
owner,
|
|
205
|
+
onFloatingRejection,
|
|
206
|
+
childState,
|
|
207
|
+
);
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
finally: {
|
|
211
|
+
configurable: true,
|
|
212
|
+
value: (onFinally?: (() => void) | null): Promise<T> => {
|
|
213
|
+
state.handled = true;
|
|
214
|
+
const childState = createContinuationState();
|
|
215
|
+
return observeBrowserRunPromiseWithState(
|
|
216
|
+
originalFinally(recordContinuationFailure(onFinally, childState)),
|
|
217
|
+
owner,
|
|
218
|
+
onFloatingRejection,
|
|
219
|
+
childState,
|
|
220
|
+
);
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
});
|
|
224
|
+
return promise;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function createContinuationState(): ObservedPromiseState {
|
|
228
|
+
return { handled: false, userContinuationFailed: false };
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function recordContinuationFailure<TArgs extends unknown[], TResult>(
|
|
232
|
+
continuation: ((...args: TArgs) => TResult | PromiseLike<TResult>) | null | undefined,
|
|
233
|
+
state: ObservedPromiseState,
|
|
234
|
+
): ((...args: TArgs) => TResult | PromiseLike<TResult>) | null | undefined {
|
|
235
|
+
if (!continuation) return continuation;
|
|
236
|
+
return (...args) => {
|
|
237
|
+
try {
|
|
238
|
+
const result = continuation(...args);
|
|
239
|
+
if (!isThenable(result)) return result;
|
|
240
|
+
return Promise.resolve(result).catch(reason => {
|
|
241
|
+
state.userContinuationFailed = true;
|
|
242
|
+
throw reason;
|
|
243
|
+
}) as PromiseLike<TResult>;
|
|
244
|
+
} catch (reason) {
|
|
245
|
+
state.userContinuationFailed = true;
|
|
246
|
+
throw reason;
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function isThenable(value: unknown): value is PromiseLike<unknown> {
|
|
252
|
+
if (value === null || (typeof value !== "object" && typeof value !== "function")) return false;
|
|
253
|
+
return typeof Reflect.get(value, "then") === "function";
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function trackBrowserRunPromise<T>(
|
|
257
|
+
promise: Promise<T>,
|
|
258
|
+
owner?: object,
|
|
259
|
+
onFloatingRejection?: FloatingRejectionHandler,
|
|
260
|
+
): Promise<T> {
|
|
261
|
+
if (!owner) return markHandled(promise);
|
|
262
|
+
const tracked = promise.catch(error => {
|
|
263
|
+
throw markBrowserRunRejection(error, owner);
|
|
264
|
+
});
|
|
265
|
+
return onFloatingRejection ? observeBrowserRunPromise(tracked, owner, onFloatingRejection) : tracked;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Installs worker-realm rejection routing. Consumed browser-run failures stay in
|
|
270
|
+
* the worker; unrelated failures retain the default fatal worker behavior.
|
|
271
|
+
*/
|
|
272
|
+
export function installBrowserWorkerRejectionGuard(consume: (reason: unknown) => boolean): () => void {
|
|
273
|
+
const onRejection = (reason: unknown): void => {
|
|
274
|
+
if (postmortem.isExpectedCleanupError(reason) || consume(reason)) return;
|
|
275
|
+
setTimeout(() => {
|
|
276
|
+
throw reason;
|
|
277
|
+
}, 0);
|
|
278
|
+
};
|
|
279
|
+
process.on("unhandledRejection", onRejection);
|
|
280
|
+
return () => process.off("unhandledRejection", onRejection);
|
|
281
|
+
}
|
|
282
|
+
|
|
4
283
|
/**
|
|
5
284
|
* Marks a run-scoped promise as observed without changing its behavior for awaited callers.
|
|
6
285
|
*
|
|
@@ -83,11 +362,16 @@ export function waitForRun(
|
|
|
83
362
|
await untilAborted(signal, async () => await Bun.sleep(interval));
|
|
84
363
|
}
|
|
85
364
|
})();
|
|
86
|
-
return
|
|
365
|
+
return trackBrowserRunPromise(promise);
|
|
87
366
|
}
|
|
88
367
|
|
|
89
368
|
/** Binds a long-lived scope facade (page/tab/desktop objects) to one evaluated run's abort signal. */
|
|
90
|
-
export function bindRunFacade<T extends object>(
|
|
369
|
+
export function bindRunFacade<T extends object>(
|
|
370
|
+
target: T,
|
|
371
|
+
signal: AbortSignal,
|
|
372
|
+
rejectionOwner?: object,
|
|
373
|
+
onFloatingRejection?: FloatingRejectionHandler,
|
|
374
|
+
): T {
|
|
91
375
|
const cache = new Map<PropertyKey, unknown>();
|
|
92
376
|
return new Proxy(target, {
|
|
93
377
|
get(current, prop) {
|
|
@@ -102,11 +386,13 @@ export function bindRunFacade<T extends object>(target: T, signal: AbortSignal):
|
|
|
102
386
|
if (result && typeof result === "object") {
|
|
103
387
|
const then = Reflect.get(result, "then");
|
|
104
388
|
if (typeof then === "function") {
|
|
105
|
-
return
|
|
389
|
+
return trackBrowserRunPromise(
|
|
106
390
|
Promise.resolve(result).then(resolved => {
|
|
107
391
|
throwIfAborted(signal);
|
|
108
392
|
return resolved;
|
|
109
393
|
}),
|
|
394
|
+
rejectionOwner,
|
|
395
|
+
onFloatingRejection,
|
|
110
396
|
);
|
|
111
397
|
}
|
|
112
398
|
}
|
|
@@ -121,7 +407,7 @@ export function bindRunFacade<T extends object>(target: T, signal: AbortSignal):
|
|
|
121
407
|
// brand-check internal slots that a Proxy cannot forward, and reading a
|
|
122
408
|
// signal needs no abort gating anyway.
|
|
123
409
|
if (value instanceof AbortSignal) return value;
|
|
124
|
-
const wrapped = bindRunFacade(value, signal);
|
|
410
|
+
const wrapped = bindRunFacade(value, signal, rejectionOwner, onFloatingRejection);
|
|
125
411
|
cache.set(prop, wrapped);
|
|
126
412
|
return wrapped;
|
|
127
413
|
}
|
|
@@ -211,3 +211,101 @@ export function extractFlatShellCommandSegments(command: string): FlatShellComma
|
|
|
211
211
|
pushSegment(command.length);
|
|
212
212
|
return segments;
|
|
213
213
|
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Shell metacharacters that end an unquoted `cd` target token. A redirect,
|
|
217
|
+
* extra argument, or any operator in this set means the leading construct is
|
|
218
|
+
* more than a bare `cd <path>`, so extraction must bail.
|
|
219
|
+
*/
|
|
220
|
+
const CD_TARGET_TERMINATORS: Record<string, true> = {
|
|
221
|
+
" ": true,
|
|
222
|
+
"\t": true,
|
|
223
|
+
"\n": true,
|
|
224
|
+
"\r": true,
|
|
225
|
+
"&": true,
|
|
226
|
+
"|": true,
|
|
227
|
+
";": true,
|
|
228
|
+
"<": true,
|
|
229
|
+
">": true,
|
|
230
|
+
"(": true,
|
|
231
|
+
")": true,
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Parses a leading `cd <path> && ...` prefix so the bash tool can route the
|
|
236
|
+
* target through its structured `cwd` parameter when the model omits it.
|
|
237
|
+
*
|
|
238
|
+
* Returns the single path token (quotes and backslash escapes resolved to their
|
|
239
|
+
* literal value) and the command remainder after the top-level `&&`, or `null`
|
|
240
|
+
* when the command does not begin with exactly `cd`, one path token, and a
|
|
241
|
+
* top-level `&&`. The scanner deliberately bails on anything else in the prefix
|
|
242
|
+
* — redirects (`cd /tmp 2>/dev/null && ...`), extra arguments, or paths needing
|
|
243
|
+
* shell expansion (`$`, backticks, `(`) — leaving the whole command for the
|
|
244
|
+
* shell instead of absorbing shell syntax into `cwd`.
|
|
245
|
+
*/
|
|
246
|
+
export function extractLeadingCdTarget(command: string): { path: string; rest: string } | null {
|
|
247
|
+
const prefix = /^cd[ \t]+/.exec(command);
|
|
248
|
+
if (!prefix) return null;
|
|
249
|
+
let i = prefix[0].length;
|
|
250
|
+
let path = "";
|
|
251
|
+
let inSingle = false;
|
|
252
|
+
let inDouble = false;
|
|
253
|
+
for (; i < command.length; i++) {
|
|
254
|
+
const ch = command[i];
|
|
255
|
+
if (inSingle) {
|
|
256
|
+
if (ch === "'") {
|
|
257
|
+
inSingle = false;
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
path += ch;
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
if (inDouble) {
|
|
264
|
+
if (ch === "\\" && i + 1 < command.length) {
|
|
265
|
+
const next = command[i + 1];
|
|
266
|
+
// A line continuation crosses the first physical line. Leave it to
|
|
267
|
+
// the shell rather than turning the escaped newline into cwd text.
|
|
268
|
+
if (next === "\n" || next === "\r") return null;
|
|
269
|
+
if (next === '"' || next === "\\" || next === "$" || next === "`") {
|
|
270
|
+
path += next;
|
|
271
|
+
i++;
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
if (ch === '"') {
|
|
276
|
+
inDouble = false;
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
path += ch;
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
if (ch === "'") {
|
|
283
|
+
inSingle = true;
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
if (ch === '"') {
|
|
287
|
+
inDouble = true;
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
if (ch === "\\" && i + 1 < command.length) {
|
|
291
|
+
// Preserve shell line-continuation semantics by declining extraction.
|
|
292
|
+
if (command[i + 1] === "\n" || command[i + 1] === "\r") return null;
|
|
293
|
+
path += command[i + 1];
|
|
294
|
+
i++;
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
if (CD_TARGET_TERMINATORS[ch]) break;
|
|
298
|
+
path += ch;
|
|
299
|
+
}
|
|
300
|
+
// Unterminated quote or empty target: leave the command for the shell.
|
|
301
|
+
if (inSingle || inDouble || path.length === 0) return null;
|
|
302
|
+
// A path needing shell expansion can't be resolved literally through cwd.
|
|
303
|
+
if (/[$`(]/.test(path)) return null;
|
|
304
|
+
// Skip inter-token whitespace, then require a top-level `&&` (a single `&`,
|
|
305
|
+
// `||`, `;`, `|`, or a redirect all mean this is not a bare `cd <path>`).
|
|
306
|
+
while (command[i] === " " || command[i] === "\t") i++;
|
|
307
|
+
if (command[i] !== "&" || command[i + 1] !== "&") return null;
|
|
308
|
+
i += 2;
|
|
309
|
+
while (command[i] === " " || command[i] === "\t") i++;
|
|
310
|
+
return { path, rest: command.slice(i) };
|
|
311
|
+
}
|
package/src/tools/todo.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { ToolExample } from "@oh-my-pi/pi-ai";
|
|
|
4
4
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
5
5
|
import { Text } from "@oh-my-pi/pi-tui";
|
|
6
6
|
import { isRecord, prompt, sanitizeText } from "@oh-my-pi/pi-utils";
|
|
7
|
-
import chalk from "chalk";
|
|
7
|
+
import chalk from "@oh-my-pi/pi-utils/chalk";
|
|
8
8
|
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
9
9
|
import type { Theme } from "../modes/theme/theme";
|
|
10
10
|
import todoDescription from "../prompts/tools/todo.md" with { type: "text" };
|
package/src/utils/clipboard.ts
CHANGED
|
@@ -259,6 +259,14 @@ async function readTextViaPowerShell(): Promise<string | null> {
|
|
|
259
259
|
}
|
|
260
260
|
}
|
|
261
261
|
|
|
262
|
+
async function readTextFromX11Clipboard(): Promise<string> {
|
|
263
|
+
try {
|
|
264
|
+
return await spawnCapture(["xclip", "-selection", "clipboard", "-o"]);
|
|
265
|
+
} catch {
|
|
266
|
+
return await spawnCapture(["xsel", "--clipboard", "--output"]);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
262
270
|
/**
|
|
263
271
|
* Read an image from the system clipboard.
|
|
264
272
|
*
|
|
@@ -340,11 +348,11 @@ export async function readTextFromClipboard(): Promise<string> {
|
|
|
340
348
|
return await spawnCapture(["wl-paste", "--type", "text/plain", "--no-newline"]);
|
|
341
349
|
} catch {
|
|
342
350
|
if (hasX11Display) {
|
|
343
|
-
return await
|
|
351
|
+
return await readTextFromX11Clipboard();
|
|
344
352
|
}
|
|
345
353
|
}
|
|
346
354
|
} else if (hasX11Display) {
|
|
347
|
-
return await
|
|
355
|
+
return await readTextFromX11Clipboard();
|
|
348
356
|
}
|
|
349
357
|
} catch (error) {
|
|
350
358
|
logger.warn("clipboard: failed to read clipboard text", { error: String(error) });
|
|
@@ -53,8 +53,10 @@ export async function openInEditor(
|
|
|
53
53
|
|
|
54
54
|
const [editor, ...editorArgs] = editorCmd.split(" ");
|
|
55
55
|
const stdio = options?.stdio ?? ["inherit", "inherit", "inherit"];
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
const child =
|
|
57
|
+
process.platform === "win32"
|
|
58
|
+
? spawn(editor, [...editorArgs, tmpFile], { stdio, shell: true })
|
|
59
|
+
: spawn("/bin/sh", ["-c", `${editorCmd} "$1"`, "sh", tmpFile], { stdio });
|
|
58
60
|
const { promise, reject, resolve } = Promise.withResolvers<number>();
|
|
59
61
|
child.once("exit", (code, signal) => resolve(code ?? (signal ? -1 : 0)));
|
|
60
62
|
child.once("error", error => reject(error));
|
package/src/utils/jj.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { $which } from "@oh-my-pi/pi-utils";
|
|
4
|
-
import { LRUCache } from "
|
|
4
|
+
import { LRUCache } from "@oh-my-pi/pi-utils/lru";
|
|
5
5
|
import { withTimeoutSignal } from "./fetch-timeout";
|
|
6
6
|
import * as git from "./git";
|
|
7
7
|
|
package/src/utils/turndown.ts
CHANGED
package/src/vibe/runtime.ts
CHANGED
|
@@ -25,7 +25,6 @@ import { MCPManager } from "../mcp/manager";
|
|
|
25
25
|
import vibeTurnResultTemplate from "../prompts/tools/vibe-turn-result.md" with { type: "text" };
|
|
26
26
|
import { AgentLifecycleManager } from "../registry/agent-lifecycle";
|
|
27
27
|
import { type AgentRef, AgentRegistry, MAIN_AGENT_ID } from "../registry/agent-registry";
|
|
28
|
-
import type { SessionEntry } from "../session/session-entries";
|
|
29
28
|
import { SessionManager, SessionPersistenceIndeterminateError } from "../session/session-manager";
|
|
30
29
|
import { getBundledAgent } from "../task/agents";
|
|
31
30
|
import { type ExecutorOptions, runSubagentFollowUpTurn, runSubprocess } from "../task/executor";
|
|
@@ -363,11 +362,12 @@ function parseLifecycleEvent(value: unknown): VibeLifecycleEvent | undefined {
|
|
|
363
362
|
return undefined;
|
|
364
363
|
}
|
|
365
364
|
|
|
366
|
-
/** Child ids claimed by
|
|
367
|
-
export function persistedVibeChildIds(entries: Iterable<
|
|
365
|
+
/** Child ids claimed by valid Vibe spawn records from untrusted persisted JSON. */
|
|
366
|
+
export function persistedVibeChildIds(entries: Iterable<unknown>): Set<string> {
|
|
368
367
|
const ids = new Set<string>();
|
|
369
|
-
for (const
|
|
370
|
-
|
|
368
|
+
for (const value of entries) {
|
|
369
|
+
const entry = objectRecord(value);
|
|
370
|
+
if (entry?.type !== "custom" || entry.customType !== VIBE_LIFECYCLE_CUSTOM_TYPE) continue;
|
|
371
371
|
const event = parseLifecycleEvent(entry.data);
|
|
372
372
|
if (
|
|
373
373
|
event?.action === "spawn" &&
|
|
@@ -30,7 +30,7 @@ export const handleArxiv: SpecialHandler = async (
|
|
|
30
30
|
if (!result.ok) return null;
|
|
31
31
|
|
|
32
32
|
// Parse the Atom feed response
|
|
33
|
-
const { parseHTML } = await import("
|
|
33
|
+
const { parseHTML } = await import("@oh-my-pi/pi-utils/dom");
|
|
34
34
|
const doc = parseHTML(result.content).document;
|
|
35
35
|
const entry = doc.querySelector("entry");
|
|
36
36
|
|
|
@@ -96,7 +96,7 @@ export const handleGoPkg: SpecialHandler = async (
|
|
|
96
96
|
});
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
const { parseHTML } = await import("
|
|
99
|
+
const { parseHTML } = await import("@oh-my-pi/pi-utils/dom");
|
|
100
100
|
const doc = parseHTML(pageResult.content).document;
|
|
101
101
|
|
|
102
102
|
// Extract actual module path from breadcrumb or header
|
package/src/web/scrapers/iacr.ts
CHANGED
|
@@ -29,7 +29,7 @@ export const handleIacr: SpecialHandler = async (
|
|
|
29
29
|
|
|
30
30
|
if (!result.ok) return null;
|
|
31
31
|
|
|
32
|
-
const { parseHTML } = await import("
|
|
32
|
+
const { parseHTML } = await import("@oh-my-pi/pi-utils/dom");
|
|
33
33
|
const doc = parseHTML(result.content).document;
|
|
34
34
|
|
|
35
35
|
// Extract metadata from the page
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Read the Docs handler for web-fetch
|
|
3
3
|
*/
|
|
4
|
+
import type { Element } from "@oh-my-pi/pi-utils/dom";
|
|
4
5
|
import { buildResult, htmlToBasicMarkdown, loadPage, type RenderResult, type SpecialHandler } from "./types";
|
|
5
6
|
|
|
6
7
|
export const handleReadTheDocs: SpecialHandler = async (
|
|
@@ -38,7 +39,7 @@ export const handleReadTheDocs: SpecialHandler = async (
|
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
// Parse HTML
|
|
41
|
-
const { parseHTML } = await import("
|
|
42
|
+
const { parseHTML } = await import("@oh-my-pi/pi-utils/dom");
|
|
42
43
|
const root = parseHTML(result.content).document;
|
|
43
44
|
|
|
44
45
|
// Extract main content from common Read the Docs selectors
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { HTMLElement } from "
|
|
1
|
+
import type { HTMLElement } from "@oh-my-pi/pi-utils/dom";
|
|
2
2
|
import { ToolAbortError } from "../../tools/tool-errors";
|
|
3
3
|
import type { RenderResult, SpecialHandler } from "./types";
|
|
4
4
|
import { buildResult, loadPage } from "./types";
|
|
@@ -33,7 +33,7 @@ export const handleTwitter: SpecialHandler = async (
|
|
|
33
33
|
|
|
34
34
|
if (result.ok && result.content.length > 500) {
|
|
35
35
|
// Parse the Nitter HTML
|
|
36
|
-
const { parseHTML } = await import("
|
|
36
|
+
const { parseHTML } = await import("@oh-my-pi/pi-utils/dom");
|
|
37
37
|
const doc = parseHTML(result.content).document;
|
|
38
38
|
|
|
39
39
|
// Extract tweet content
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { scheduler } from "node:timers/promises";
|
|
5
5
|
import { ptree } from "@oh-my-pi/pi-utils";
|
|
6
|
-
import type TurndownService from "turndown";
|
|
6
|
+
import type TurndownService from "@oh-my-pi/pi-utils/turndown";
|
|
7
7
|
|
|
8
8
|
import type { AgentStorage } from "../../session/agent-storage";
|
|
9
9
|
import { ToolAbortError } from "../../tools/tool-errors";
|
|
@@ -44,7 +44,7 @@ export const handleWikipedia: SpecialHandler = async (
|
|
|
44
44
|
const contentResult = await loadPage(contentUrl, { timeout, signal });
|
|
45
45
|
|
|
46
46
|
if (contentResult.ok) {
|
|
47
|
-
const { parseHTML } = await import("
|
|
47
|
+
const { parseHTML } = await import("@oh-my-pi/pi-utils/dom");
|
|
48
48
|
const doc = parseHTML(contentResult.content).document;
|
|
49
49
|
|
|
50
50
|
// Extract main content sections
|