Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,17 @@ pi install npm:@tt-a1i/openpi
重启 Pi,或在当前 Session 运行 `/reload`。然后直接描述真实任务:

```text
启动前端 dev server;并行检查 API 主链路和测试覆盖;
在后台启动前端 dev server;用子代理并行检查 API 主链路和测试覆盖;
结果回来后汇总风险,主会话不要原地等待。
```

OpenPI 会把长期进程放到后台,把独立任务交给隔离 Context 的 Pi Subagent,把多阶段依赖组织成 Workflow。状态会持续显示;完整运行可从 `/ps`、`/subagents` 和 `/workflows` 检查或终止。

> [!TIP]
> Capability discovery 默认 `explicit`:明确说出能力意图才会加载对应组。
> 例如「在后台运行 dev server」→ 后台终端;「用/使用子代理检查」→ Subagent;「用工作流编排」→ Workflow;「用 fd/rg 搜索」→ 搜索工具。
> 关键是把意图说清楚(说「用子代理」「后台运行」这类带动作的短语),不需要记住任何工具名。

> [!IMPORTANT]
> 默认安装是安静的:不改主题、不绑定 Provider 或模型、不开启下一步预测,也不执行 post-edit 命令。Capability discovery 默认 `explicit`;只有用户通过 `/openpi-setup` 选择 `adaptive` 后,模型才会常驻看到一个小型发现网关并可自主加载额外能力。

Expand Down Expand Up @@ -570,4 +575,4 @@ npm 仍用于发布包的 `pack` / clean-install 验证,因为用户通过 npm

`extensions/sessions/` 改编自 [jayshah5696/pi-agent-extensions](https://github.com/jayshah5696/pi-agent-extensions)。可选的顶层 Session 通信由 [pi-intercom](https://github.com/nicobailon/pi-intercom) 提供。完整第三方说明见 [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md)。

本仓库目前没有项目级开源许可证;`THIRD_PARTY_NOTICES.md` 只记录第三方来源与各自许可,不等同于授予本项目使用许可
本项目以 MIT 许可证发布(见 [`LICENSE`](LICENSE));`THIRD_PARTY_NOTICES.md` 记录第三方来源与各自许可
2 changes: 1 addition & 1 deletion SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Pi installs the package dependencies automatically. Restart Pi or run `/reload`

## fd and rg tools

The `file-search` extension registers `fd` and `rg` as model tools. They stay outside an ordinary parent turn until the user explicitly asks to use `fd`/`rg` or structured file search, or the model loads the `search` group through `openpi_load_tools`. The gateway is shown after an explicit OpenPI-capability request, or remains visible when the user opts into adaptive discovery; child sessions may still receive `fd` and `rg` through the reviewed child-safe allowlist. No setup is normally needed: at startup it silently uses a system-installed `fd` (or `fdfind` on Debian/Ubuntu) and `rg` when available, or an existing fallback in this package's private `bin/` directory. Only when neither exists does it download an official release binary (macOS/Linux, arm64/x64, over HTTPS) into that package-local directory and show a one-time notification. If your platform is unsupported, install `fd` and `rg` with your package manager and restart Pi.
The `file-search` extension registers `fd` and `rg` as model tools. They stay outside an ordinary parent turn until the user explicitly asks to use `fd`/`rg` or structured file search, or the model loads the `search` group through `openpi_load_tools`. The gateway is shown after an explicit OpenPI-capability request, or remains visible when the user opts into adaptive discovery; child sessions may still receive `fd` and `rg` through the reviewed child-safe allowlist. No setup is normally needed: at startup it silently uses a system-installed `fd` (or `fdfind` on Debian/Ubuntu) and `rg` when available, or an existing binary in the agent's private managed bin directory (`~/.pi/agent/bin`). Only when neither exists does it download an official release binary (macOS/Linux, arm64/x64, over HTTPS) into that directory — a persistent cache that survives package updates — and show a one-time notification. If your platform is unsupported, install `fd` and `rg` with your package manager and restart Pi.

## Theme

Expand Down
2 changes: 1 addition & 1 deletion extensions/background-terminals/src/prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ export function buildTerminalResultMessage(snap: TerminalSnapshot) {
if (snap.stderr.totalBytes > 0) {
text += `\n\n${outputSection("stderr", snap.stderr, RESULT_STDERR_MAX, RESULT_STDERR_MAX_LINES)}`;
}
return text;
return `${text}\n\n(This result is already shown to the user. Act on it and relay only the decisions or next steps — do not repeat it verbatim.)`;
}

/** Preserve every retained terminal identity while globally bounding batch logs. */
Expand Down
49 changes: 49 additions & 0 deletions extensions/capabilities/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ function harness(options: { discovery?: "explicit" | "adaptive" } = {}) {
"subagent_send",
"subagent_check",
"subagent_list",
"workflow",
"workflow_stop",
"workflow_status",
"bg_start",
"bg_status",
"bg_list",
"bg_kill",
"bg_watch",
];
let active = [...available];
const tools = new Map<string, CapturedTool>();
Expand Down Expand Up @@ -89,6 +97,15 @@ function harness(options: { discovery?: "explicit" | "adaptive" } = {}) {
patchOwnedTools(pi, "subagents", {
enable: OPENPI_TOOL_SURFACE.subagents.entry,
});
// The real extensions disable their deferred lifecycle tools on
// session_start (hideLifecycleTools); replicate that so the harness
// matches production wiring and tools only appear via capability loads.
patchOwnedTools(pi, "workflows", {
disable: OPENPI_TOOL_SURFACE.workflows.deferred,
});
patchOwnedTools(pi, "background", {
disable: OPENPI_TOOL_SURFACE.background.deferred,
});
});
return {
active: () => [...active],
Expand Down Expand Up @@ -223,6 +240,38 @@ test("common Chinese and multi-agent delegation requests are explicit intent", (
}
});

test("the README quick-start example and its advertised phrases load capabilities", () => {
// The flagship README example: both clauses must be explicit intent.
const example = harness();
example.start();
example.before(
"在后台启动前端 dev server;用子代理并行检查 API 主链路和测试覆盖;\n结果回来后汇总风险,主会话不要原地等待。",
);
const active = example.active();
assert.ok(active.includes("bg_start"), "example loads background terminals");
assert.ok(active.includes("subagent_spawn"), "example loads subagents");

// Every phrase the README TIP advertises as a trigger must actually match.
const advertised: Array<[string, string]> = [
["在后台运行 dev server", "bg_start"],
["用子代理检查", "subagent_spawn"],
["使用子代理检查", "subagent_spawn"],
["用工作流编排", "workflow"],
["使用工作流编排", "workflow"],
["用 fd 搜索", "fd"],
["使用 rg 搜索", "rg"],
];
for (const [phrase, tool] of advertised) {
const h = harness();
h.start();
h.before(phrase);
assert.ok(
h.active().includes(tool),
`README-advertised phrase ${JSON.stringify(phrase)} should load ${tool}, got: ${h.active().join(",")}`,
);
}
});

test("the gateway returns progressive skill guidance for a loaded group", async () => {
const h = harness();
h.start();
Expand Down
8 changes: 4 additions & 4 deletions extensions/capabilities/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ type OpenPiLoadToolsInput = Static<typeof OpenPiLoadToolsParameters>;

const CAPABILITY_INTENT = {
search:
/\b(?:use|run)\s+(?:fd|rg)\b|\buse\s+(?:structured\s+)?(?:(?:file|code|content)\s+)?search\b|\b(?:structured|fast)\s+(?:file|code|content)\s+search\b|(?:使用|运行).{0,8}(?:fd|rg)|结构化(?:文件|代码|内容)搜索/iu,
/\b(?:use|run)\s+(?:fd|rg)\b|\buse\s+(?:structured\s+)?(?:(?:file|code|content)\s+)?search\b|\b(?:structured|fast)\s+(?:file|code|content)\s+search\b|(?:使用|用|运行).{0,8}(?:fd|rg)|结构化(?:文件|代码|内容)搜索/iu,
delegate:
/\b(?:use|spawn|run)\s+(?:an?\s+|multiple\s+|several\s+|two\s+)?(?:pi\s+)?subagents?\b|(?:^|[.!?]\s+)(?:please\s+)?(?:delegate|parallelize)\s+(?:this|the)\s+(?:task|work)\b|\b(?:can|could|would)\s+you\s+(?:please\s+)?(?:delegate|parallelize)\s+(?:this|the)\s+(?:task|work)\b|\bparallel\s+agents?\b|(?:使用|启动|调用|来|开).{0,8}子代理|(?:多个?|多路)子代理|并行.{0,8}(?:代理|agent)|委派.{0,6}任务/iu,
/\b(?:use|spawn|run)\s+(?:an?\s+|multiple\s+|several\s+|two\s+)?(?:pi\s+)?subagents?\b|(?:^|[.!?]\s+)(?:please\s+)?(?:delegate|parallelize)\s+(?:this|the)\s+(?:task|work)\b|\b(?:can|could|would)\s+you\s+(?:please\s+)?(?:delegate|parallelize)\s+(?:this|the)\s+(?:task|work)\b|\bparallel\s+agents?\b|(?:使用|用|启动|调用|来|开).{0,8}子代理|(?:多个?|多路)子代理|并行.{0,8}(?:代理|agent)|委派.{0,6}(?:任务|给|出去)/iu,
workflow:
/\b(?:use|run|create|build)\s+(?:(?:an?|the)\s+)?(?:openpi\s+)?workflow\b|(?:使用|运行|创建|构建).{0,8}工作流/iu,
/\b(?:use|run|create|build)\s+(?:(?:an?|the)\s+)?(?:openpi\s+)?workflow\b|(?:使用|用|运行|创建|构建).{0,8}工作流|用.{0,4}workflow/iu,
background:
/\b(?:run|start|keep)\b.{0,40}\b(?:in the background|background\s+(?:process|terminal|job))\b|后台.{0,8}(?:运行|进程|终端|任务)/iu,
/\b(?:run|start|keep)\b.{0,40}\b(?:in the background|background\s+(?:process|terminal|job))\b|后台.{0,8}(?:运行|启动|进程|终端|任务)/iu,
session:
/\b(?:create|set|update|track)\s+(?:an?\s+)?(?:session\s+)?(?:goal|task list|tasks)\b|(?:设置|创建|更新|跟踪|追踪).{0,8}(?:目标|任务)/iu,
} as const satisfies Record<OpenPiCapability, RegExp>;
Expand Down
33 changes: 24 additions & 9 deletions extensions/file-search/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as NodeServices from "@effect/platform-node/NodeServices";
import { assert, it } from "@effect/vitest";
import { randomUUID } from "node:crypto";
import { mkdtempSync, rmSync } from "node:fs";
import { homedir, tmpdir } from "node:os";
import { dirname, join } from "node:path";
import { Writable } from "node:stream";
Expand All @@ -15,6 +16,7 @@ import {
import {
FD_INTEL_DARWIN_VERSION,
InstallError,
managedBinDir,
readBoundedResponse,
releaseAsset,
resolveBinary,
Expand Down Expand Up @@ -228,20 +230,20 @@ it.effect("binary resolution: fdfind is accepted as a system fd", () =>
}),
);

it.effect("binary resolution: existing bin fallback is used silently", () =>
it.effect("binary resolution: an existing cached binary is used silently", () =>
Effect.gen(function* () {
const env = makeEnv({ available: ["/repo/bin/rg"] });
const env = makeEnv({ available: ["/cache/bin/rg"] });
const resolved = yield* resolveBinary(
TOOL_SPECS.rg,
"/repo/bin",
"/cache/bin",
darwinArm,
env,
);

assert.deepEqual(resolved, {
tool: "rg",
command: "/repo/bin/rg",
source: "bundled",
command: "/cache/bin/rg",
source: "cached",
});
assert.equal(env.installs.length, 0);
}),
Expand Down Expand Up @@ -316,6 +318,19 @@ it.effect("binary resolution: one failed tool does not disable the other", () =>
}),
);

it("managed bin directory lives inside the agent directory", () => {
const agentDir = mkdtempSync(join(tmpdir(), "my-pi-setup-bins-"));
const previous = process.env.PI_CODING_AGENT_DIR;
process.env.PI_CODING_AGENT_DIR = agentDir;
try {
assert.equal(managedBinDir(), join(agentDir, "bin"));
} finally {
if (previous === undefined) delete process.env.PI_CODING_AGENT_DIR;
else process.env.PI_CODING_AGENT_DIR = previous;
rmSync(agentDir, { recursive: true, force: true });
}
});

it("release assets cover macOS and Linux on arm64 and x64 over HTTPS", () => {
for (const os of ["darwin", "linux"] as const) {
for (const arch of ["arm64", "x64"] as const) {
Expand Down Expand Up @@ -377,10 +392,10 @@ it("notifications: only fresh installs notify", () => {
command: "fd",
source: "system",
};
const bundled: ResolvedBinary = {
const cached: ResolvedBinary = {
tool: "rg",
command: "/repo/bin/rg",
source: "bundled",
command: "/cache/bin/rg",
source: "cached",
};
const installed: ResolvedBinary = {
tool: "rg",
Expand All @@ -389,7 +404,7 @@ it("notifications: only fresh installs notify", () => {
version: "15.2.0",
};

assert.deepEqual(installNotifications([system, bundled]), []);
assert.deepEqual(installNotifications([system, cached]), []);
const messages = installNotifications([system, installed]);
assert.equal(messages.length, 1);
assert.match(messages[0], /downloaded rg 15\.2\.0/);
Expand Down
15 changes: 8 additions & 7 deletions extensions/file-search/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
*
* On session start the extension resolves a usable binary for each tool:
* a normally installed system binary is preferred (silently), then an
* existing fallback in this repo's `bin/` directory (silently), and only
* when neither exists is an official release downloaded into `bin/` — the
* single case that shows a UI notification. Tools await that initialization
* before executing, and report a clear error if it failed.
* existing binary in the agent's managed bin directory (`~/.pi/agent/bin`,
* silently — e.g. cached by an earlier download), and only when neither
* exists is an official release downloaded into that directory — the single
* case that shows a UI notification. Tools await that initialization before
* executing, and report a clear error if it failed.
*/

import * as NodeServices from "@effect/platform-node/NodeServices";
Expand All @@ -33,7 +34,7 @@ import {
import {
currentTarget,
liveBinaryEnv,
repositoryBinDir,
managedBinDir,
resolveBinary,
TOOL_SPECS,
type BinaryEnv,
Expand Down Expand Up @@ -80,7 +81,7 @@ export function installNotifications(binaries: readonly ResolvedBinary[]) {
.map(
(binary) =>
`file-search: no system ${binary.tool} found — downloaded ${binary.tool} ${binary.version ?? ""}`.trimEnd() +
` to ${repositoryBinDir()}`,
` to ${managedBinDir()}`,
);
}

Expand Down Expand Up @@ -136,7 +137,7 @@ export default function fileSearchTools(pi: ExtensionAPI) {
}
};

const binDir = repositoryBinDir();
const binDir = managedBinDir();
const target = currentTarget();
const initializers = makeBinaryInitializers(binDir, target, liveBinaryEnv);

Expand Down
36 changes: 18 additions & 18 deletions extensions/file-search/src/binaries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,22 @@
*
* Resolution order (per tool, first usable wins):
* 1. A normally installed system binary (`fd`/`fdfind`, `rg`) — used silently.
* 2. An existing fallback in this repository's `bin/` directory — used silently.
* 3. A fresh download of an official release into `bin/` — the only case that
* should surface a UI notification.
* 2. An existing binary in the agent's managed bin directory
* (`~/.pi/agent/bin`), cached by an earlier download — used silently.
* 3. A fresh download of an official release into that directory — the only
* case that should surface a UI notification.
*
* The decision logic is an Effect over a small injectable environment
* (`BinaryEnv`) so tests can drive it without touching the filesystem or the
* network. `liveBinaryEnv` is the real implementation.
*/

import { getAgentDir } from "@earendil-works/pi-coding-agent";
import * as NodeHttpClient from "@effect/platform-node/NodeHttpClient";
import * as NodeServices from "@effect/platform-node/NodeServices";
import { execFile } from "node:child_process";
import { tmpdir } from "node:os";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { promisify } from "node:util";
import { Crypto, Data, Effect, Encoding, FileSystem, Stream } from "effect";
import { FetchHttpClient, HttpClient } from "effect/unstable/http";
Expand Down Expand Up @@ -56,13 +57,13 @@
};

export type ToolName = "fd" | "rg";
export type BinarySource = "system" | "bundled" | "installed";
export type BinarySource = "system" | "cached" | "installed";

export interface ToolSpec {
readonly tool: ToolName;
/** Commands probed on PATH, in order. Debian/Ubuntu install fd as `fdfind`. */
readonly systemCommands: readonly string[];
/** Executable name used inside release archives and the repo bin directory. */
/** Executable name used inside release archives and the managed bin directory. */
readonly binaryName: string;
}

Expand Down Expand Up @@ -144,10 +145,9 @@
return { os: process.platform, arch: process.arch };
}

/** Repository root (`~/.pi/agent`) resolved from this module's location. */
export function repositoryBinDir() {
const moduleDir = dirname(fileURLToPath(import.meta.url));
return join(moduleDir, "..", "..", "..", "bin");
/** Pi agent's managed binaries directory (`~/.pi/agent/bin`). */
export function managedBinDir() {
return join(getAgentDir(), "bin");
}

export class UnsupportedPlatformError extends Data.TaggedError(
Expand Down Expand Up @@ -179,7 +179,7 @@
readonly version?: string;
}

/** Resolve one tool: system binary, existing bin fallback, or fresh install. */
/** Resolve one tool: system binary, cached fallback, or fresh install. */
export function resolveBinary(
spec: ToolSpec,
binDir: string,
Expand All @@ -193,9 +193,9 @@
}
}

const bundled = join(binDir, spec.binaryName);
if (yield* env.probe(bundled, spec.tool)) {
return { tool: spec.tool, command: bundled, source: "bundled" as const };
const cached = join(binDir, spec.binaryName);
if (yield* env.probe(cached, spec.tool)) {
return { tool: spec.tool, command: cached, source: "cached" as const };
}

const asset = releaseAsset(spec.tool, target);
Expand All @@ -205,17 +205,17 @@
});
}

yield* env.install(asset, bundled);
yield* env.install(asset, cached);

if (!(yield* env.probe(bundled, spec.tool))) {
if (!(yield* env.probe(cached, spec.tool))) {
return yield* new InstallError({
message: `${spec.tool} ${asset.version} was installed to ${bundled} but failed to run.`,
message: `${spec.tool} ${asset.version} was installed to ${cached} but failed to run.`,
});
}

return {
tool: spec.tool,
command: bundled,
command: cached,
source: "installed" as const,
version: asset.version,
};
Expand All @@ -238,7 +238,7 @@
const declaredLength = Number(response.headers["content-length"]);
if (Number.isFinite(declaredLength) && declaredLength > maxBytes) {
return yield* Effect.fail(
new Error(`download exceeds the ${maxBytes}-byte size limit`),

Check warning on line 241 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 22.19.0

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 241 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 24

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 241 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 22.19.0

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 241 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 24

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)
);
}

Expand All @@ -249,7 +249,7 @@
const totalBytes = accumulator.totalBytes + chunk.byteLength;
if (totalBytes > maxBytes) {
return Effect.fail(
new Error(`download exceeds the ${maxBytes}-byte size limit`),

Check warning on line 252 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 22.19.0

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 252 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 24

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 252 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 22.19.0

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 252 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 24

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)
);
}
return Effect.sync(() => {
Expand All @@ -273,7 +273,7 @@
for (let redirects = 0; redirects <= MAX_DOWNLOAD_REDIRECTS; redirects++) {
if (url.protocol !== "https:") {
return yield* Effect.fail(
new Error(`refusing non-HTTPS download URL: ${url.href}`),

Check warning on line 276 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 22.19.0

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 276 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 24

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 276 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 22.19.0

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 276 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 24

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)
);
}

Expand All @@ -284,19 +284,19 @@
const location = response.headers.location;
if (!location) {
return yield* Effect.fail(
new Error(`redirect from ${url.href} had no location header`),

Check warning on line 287 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 22.19.0

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 287 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 24

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 287 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 22.19.0

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 287 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 24

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)
);
}
if (redirects === MAX_DOWNLOAD_REDIRECTS) {
return yield* Effect.fail(
new Error(

Check warning on line 292 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 22.19.0

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 292 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 24

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 292 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 22.19.0

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 292 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 24

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)
`download exceeded ${MAX_DOWNLOAD_REDIRECTS} redirects`,
),
);
}
if (!URL.canParse(location, url)) {
return yield* Effect.fail(
new Error(

Check warning on line 299 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 22.19.0

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 299 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 24

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 299 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 22.19.0

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 299 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 24

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)
`download returned an invalid redirect URL: ${location}`,
),
);
Expand All @@ -306,7 +306,7 @@

if (response.status < 200 || response.status >= 300) {
return yield* Effect.fail(
new Error(`download failed with HTTP ${response.status}`),

Check warning on line 309 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 22.19.0

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 309 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 24

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 309 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 22.19.0

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 309 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 24

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)
);
}
return {
Expand All @@ -320,7 +320,7 @@
url = result.url;
}

return yield* Effect.fail(new Error("download redirect handling failed"));

Check warning on line 323 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 22.19.0

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 323 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 24

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 323 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 22.19.0

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 323 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 24

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)
});
}

Expand All @@ -345,7 +345,7 @@
const install = Effect.gen(function* () {
if (!URL.canParse(asset.url)) {
return yield* Effect.fail(
new Error(`invalid download URL: ${asset.url}`),

Check warning on line 348 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 22.19.0

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 348 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 24

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 348 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 22.19.0

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 348 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 24

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)
);
}

Expand All @@ -361,7 +361,7 @@
const digest = Encoding.encodeHex(digestBytes);
if (digest !== asset.sha256) {
return yield* Effect.fail(
new Error(

Check warning on line 364 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 22.19.0

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 364 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 24

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 364 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 22.19.0

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)

Check warning on line 364 in extensions/file-search/src/binaries.ts

View workflow job for this annotation

GitHub Actions / Node 24

Global 'Error' loses type safety as untagged errors merge together in the Effect failure channel. Consider using a tagged error and optionally wrapping the original in a 'cause' property. effect(globalErrorInEffectFailure)
`SHA-256 mismatch for ${asset.fileName}: expected ${asset.sha256}, received ${digest}`,
),
);
Expand Down
2 changes: 1 addition & 1 deletion extensions/subagents/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ import {
registerEditorLayer,
removeEditorLayer,
} from "../shared/editor-layers.ts";
import { formatContextUtilization } from "./src/format.ts";
import { formatContextUtilization } from "../shared/context-utilization.ts";
import { SubagentManager, type SubagentManagerShape } from "./src/manager.ts";
import {
buildSubagentResultMessage,
Expand Down
Loading
Loading