@cydm/pie 1.0.7 → 1.0.8

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/README.md CHANGED
@@ -92,6 +92,7 @@ Validate the file explicitly:
92
92
  ```bash
93
93
  pie models validate
94
94
  pie models validate --path /abs/path/to/models.json
95
+ pie models validate --probe web_search
95
96
  ```
96
97
 
97
98
  Generate a starter template:
@@ -249,13 +250,15 @@ node <resolvedPath for browser-tools/playwright-cli.js> install-browser chromium
249
250
 
250
251
  Run `pie doctor` to check whether Playwright CLI and its browser runtime are discoverable.
251
252
 
252
- ## Web Search
253
+ ## Web Research
253
254
 
254
- Pie exposes a canonical `web_search` tool for public web research, current information, online documentation, and internet inspiration. Workspace search remains separate: use `grep_text`, `find_files`, and `list_dir` for local repository content.
255
+ Pie exposes a canonical `web_research` tool for public web research, current information, online documentation, and internet inspiration. It plans search variants, uses provider-native search, fetches credible sources, and returns citations. Workspace search remains separate: use `grep_text`, `find_files`, and `list_dir` for local repository content.
255
256
 
256
- `web_search` uses provider-native web search where supported. It does not scrape DuckDuckGo or fall back to `bash` with `curl` or Python HTTP scripts. If the current provider/model cannot perform native web search, the tool returns a clear unavailable result with provider/configuration details.
257
+ `web_search` remains available as the lower-level provider-native search tool. It does not scrape DuckDuckGo or fall back to `bash` with `curl` or Python HTTP scripts. If the configured provider/model cannot perform native web search, the tool returns a clear unavailable result with provider/configuration details.
257
258
 
258
- Use `web_fetch` after search when the agent needs to read a specific URL, documentation page, changelog, issue, or PDF. `web_fetch` follows redirects, extracts readable text/markdown, returns citation anchors and extraction diagnostics, and reports `requires_browser` for JavaScript-heavy pages instead of pretending the content was read.
259
+ Use `web_fetch` directly when the agent needs to read a specific URL, documentation page, changelog, issue, or PDF. `web_fetch` follows redirects, extracts readable text/markdown, returns citation anchors and extraction diagnostics, and reports `requires_browser` for JavaScript-heavy pages instead of pretending the content was read. In the CLI, `web_research` can use browser-tools for browser-rendered sources when the Playwright runtime is available; Unity reports those pages as `requires_browser`.
260
+
261
+ `web_research` records route health and latency in Pie's state directory so later runs can prefer providers with better source quality, fewer timeouts, and lower rate-limit pressure. `pie doctor --json` reports the recorded provider health, and `verify:web` writes web metrics including p50/p95 latency, failure categories, and citation quality artifacts.
259
262
 
260
263
  ## Permissions
261
264
 
@@ -305,8 +308,10 @@ npm run verify:terminal:matrix
305
308
  ```
306
309
 
307
310
  Use `npm run verify:agent` when model credentials are available and you want the real daily agent gate.
308
- Use `npm run verify:agent:nightly` and `npm run verify:unity:reliability` before release candidates that claim real-provider or Unity reliability.
311
+ Use `npm run verify:agent:nightly` before release candidates that claim real-provider reliability.
312
+ Use `UNITY_EDITOR="/path/to/Unity" npm run verify:unity:reliability` before Unity release candidates. For live Unity Dev RPC coverage, run `PIE_UNITY_REAL_RPC=1 UNITY_EDITOR="/path/to/Unity" npm run verify:unity:reliability`.
309
313
  Set `PIE_REAL_BROWSER=1` when you want `verify:browser` to open a real browser session instead of only checking the Playwright CLI contract.
314
+ Set `PIE_REAL_WEB=1` when you want `verify:web` to run real provider web research smoke with fetched or browser-read citations.
310
315
 
311
316
  ## Publishing
312
317
 
@@ -1,7 +1,7 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  createAskUserCapability
4
- } from "../../../chunks/chunk-BHNULR7U.js";
4
+ } from "../../../chunks/chunk-6WD2NFIC.js";
5
5
  import "../../../chunks/chunk-A5JSJAPK.js";
6
6
  import "../../../chunks/chunk-TG2EQLX2.js";
7
7
 
@@ -1,136 +1,138 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
+ import {
3
+ resolveCliProjectRoot
4
+ } from "../../../chunks/chunk-NTYHFBUA.js";
2
5
  import "../../../chunks/chunk-TG2EQLX2.js";
3
6
 
4
7
  // builtin/extensions/init/index.ts
8
+ import fs from "node:fs";
9
+ import path from "node:path";
10
+ function resolveProjectAgentsTarget(cwd) {
11
+ const projectRoot = resolveCliProjectRoot(cwd);
12
+ return {
13
+ projectRoot,
14
+ agentsPath: path.join(projectRoot, "AGENTS.md")
15
+ };
16
+ }
5
17
  async function loadExistingKnowledge(cwd) {
18
+ const target = resolveProjectAgentsTarget(cwd);
6
19
  try {
7
- const fs = await import("fs");
8
- const path = await import("path");
9
- const agentsPath = path.join(cwd, ".pie", "agents.md");
10
- if (fs.existsSync(agentsPath)) {
11
- return fs.readFileSync(agentsPath, "utf-8");
20
+ if (fs.existsSync(target.agentsPath)) {
21
+ return { target, content: fs.readFileSync(target.agentsPath, "utf-8") };
12
22
  }
13
23
  } catch {
14
24
  }
15
- return null;
16
- }
17
- async function ensurePieDir(cwd) {
18
- const fs = await import("fs");
19
- const path = await import("path");
20
- const pieDir = path.join(cwd, ".pie");
21
- if (!fs.existsSync(pieDir)) {
22
- fs.mkdirSync(pieDir, { recursive: true });
23
- }
25
+ return { target, content: null };
24
26
  }
25
27
  function buildResearchPrompt(params) {
26
- const { isUpdate, existingContent, userIntent, cwd } = params;
28
+ const { isUpdate, existingContent, userIntent, cwd, projectRoot, agentsPath } = params;
27
29
  if (isUpdate && existingContent) {
28
30
  const truncatedContent = existingContent.length > 4e3 ? existingContent.slice(0, 4e3) + "\n... (truncated)" : existingContent;
29
- return `\u{1F4DD} \u66F4\u65B0\u9879\u76EE\u77E5\u8BC6\u6587\u6863
31
+ return `\u{1F4DD} \u66F4\u65B0 root AGENTS.md \u9879\u76EE\u4E0A\u4E0B\u6587
32
+
33
+ \u76EE\u6807\u6587\u4EF6\uFF1A${agentsPath}
34
+ \u9879\u76EE\u6839\u76EE\u5F55\uFF1A${projectRoot}
35
+ \u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\uFF1A${cwd}
30
36
 
31
- \u5F53\u524D .pie/agents.md \u5185\u5BB9\uFF1A
37
+ \u5F53\u524D root AGENTS.md \u5185\u5BB9\uFF1A
32
38
  \`\`\`
33
39
  ${truncatedContent}
34
40
  \`\`\`
35
41
 
36
42
  ${userIntent ? `\u{1F4CC} \u7528\u6237\u66F4\u65B0\u610F\u56FE\uFF1A${userIntent}
37
43
 
38
- ` : ""}\u8BF7\u91CD\u65B0\u7814\u7A76\u9879\u76EE\u5E76\u66F4\u65B0\u77E5\u8BC6\u6587\u6863\uFF1A
44
+ ` : ""}\u8BF7\u91CD\u65B0\u7814\u7A76\u9879\u76EE\u5E76\u66F4\u65B0 root AGENTS.md\uFF1A
39
45
 
40
- 1. \u63A2\u7D22\u5F53\u524D\u4EE3\u7801\u7ED3\u6784\uFF0C\u5BF9\u6BD4\u73B0\u6709\u6587\u6863
41
- 2. \u8BC6\u522B\u65B0\u589E/\u53D8\u66F4/\u79FB\u9664\u7684\u6A21\u5757\u548C\u6587\u4EF6
42
- 3. ${userIntent ? `\u91CD\u70B9\u5173\u6CE8\uFF1A${userIntent}` : "\u8865\u5145\u7F3A\u5931\u7684\u7EC6\u8282\u548C\u67B6\u6784\u8BF4\u660E\uFF0C\u66F4\u65B0\u8FC7\u65F6\u7684\u4FE1\u606F"}
43
- 4. \u4FDD\u6301\u6587\u6863\u7ED3\u6784\u6E05\u6670\uFF0C\u7EF4\u62A4\u7AE0\u8282\u5B8C\u6574\u6027
44
- 5. \u66F4\u65B0\u540E\u786E\u4FDD agents.md \u4ECD\u7136\u6709\u7528\u4E14\u51C6\u786E
46
+ 1. \u4FDD\u6301 AGENTS.md \u662F progressive disclosure index\uFF0C\u4E0D\u8981\u5199\u6210\u957F\u7BC7\u9879\u76EE\u767E\u79D1
47
+ 2. \u4FDD\u7559\u7B80\u77ED root instructions\uFF0C\u7136\u540E\u7EF4\u62A4 Repo Map
48
+ 3. Repo Map \u91CC\u7684\u6BCF\u4E2A\u91CD\u8981\u76EE\u5F55\u90FD\u8981\u6709 desc\uFF0C\u8BF4\u660E\u4EC0\u4E48\u65F6\u5019\u9700\u8981\u8BFB\u8BE5\u76EE\u5F55\u6216\u76F8\u5173\u6587\u6863
49
+ 4. \u53EA\u8865\u5145\u7A33\u5B9A\u89C4\u5219\u3001\u76EE\u5F55\u8DEF\u7531\u3001\u9A8C\u8BC1\u95E8\u7981\u548C\u751F\u6210\u7269\u89C4\u5219
50
+ 5. \u5220\u9664\u8FC7\u65F6\u6216\u91CD\u590D README/ARCHITECTURE \u7684\u5927\u6BB5\u5185\u5BB9
45
51
 
46
- \u8BF7\u4F7F\u7528 write \u5DE5\u5177\u66F4\u65B0 \`.pie/agents.md\` \u6587\u4EF6\u3002
47
-
48
- \u5DE5\u4F5C\u76EE\u5F55\uFF1A${cwd}`;
52
+ \u8BF7\u4F7F\u7528 write_file \u5DE5\u5177\u66F4\u65B0\u76EE\u6807\u6587\u4EF6\uFF1A${agentsPath}
53
+ CLI \u6587\u4EF6\u5DE5\u5177\u4F1A\u4EE5\u9879\u76EE\u6839\u76EE\u5F55\u4F5C\u4E3A\u8BBF\u95EE\u8FB9\u754C\uFF1B\u4E0D\u8981\u4F7F\u7528\u989D\u5916\u7684 root \u53C2\u6570\u3002`;
49
54
  }
50
- return `\u{1F50D} \u521D\u59CB\u5316\u9879\u76EE\u7814\u7A76
55
+ return `\u{1F50D} \u521D\u59CB\u5316 root AGENTS.md \u9879\u76EE\u4E0A\u4E0B\u6587
56
+
57
+ \u76EE\u6807\u6587\u4EF6\uFF1A${agentsPath}
58
+ \u9879\u76EE\u6839\u76EE\u5F55\uFF1A${projectRoot}
59
+ \u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\uFF1A${cwd}
51
60
 
52
61
  ${userIntent ? `\u{1F4CC} \u7528\u6237\u7814\u7A76\u610F\u56FE\uFF1A${userIntent}
53
62
 
54
- ` : ""}\u8BF7\u5E2E\u6211\u5168\u9762\u7814\u7A76\u5F53\u524D\u9879\u76EE\u5E76\u521B\u5EFA \`.pie/agents.md\` \u77E5\u8BC6\u6587\u6863\u3002
63
+ ` : ""}\u8BF7\u7814\u7A76\u5F53\u524D\u9879\u76EE\u5E76\u521B\u5EFA root \`AGENTS.md\`\u3002\u8FD9\u4E2A\u6587\u4EF6\u5E94\u8BE5\u662F progressive disclosure index\uFF0C\u7528\u6765\u6307\u5BFC\u540E\u7EED agent \u6309\u9700\u8BFB\u53D6\u76F8\u5173\u6587\u6863\uFF0C\u800C\u4E0D\u662F\u4E00\u6B21\u6027\u603B\u7ED3\u6574\u4E2A\u4ED3\u5E93\u3002
55
64
 
56
65
  \u7814\u7A76\u4EFB\u52A1\uFF1A
57
66
  1. \u8BC6\u522B\u9879\u76EE\u7C7B\u578B\u548C\u6280\u672F\u6808\uFF08\u67E5\u770B package.json, Cargo.toml, go.mod, requirements.txt, pyproject.toml \u7B49\uFF09
58
- 2. \u63A2\u7D22\u6E90\u4EE3\u7801\u76EE\u5F55\u7ED3\u6784\uFF08src/, lib/, app/ \u7B49\u5E38\u89C1\u76EE\u5F55\uFF09
59
- 3. \u8BFB\u53D6\u5173\u952E\u914D\u7F6E\u6587\u4EF6\u7406\u89E3\u9879\u76EE\u8BBE\u7F6E
60
- 4. \u8BC6\u522B\u4E3B\u8981\u6A21\u5757\u3001\u5165\u53E3\u70B9\u3001\u6838\u5FC3\u7C7B/\u51FD\u6570
61
- 5. \u5206\u6790\u67B6\u6784\u6A21\u5F0F\u548C\u8BBE\u8BA1\u51B3\u7B56
62
- 6. \u63A8\u65AD\u5F00\u53D1\u89C4\u8303\uFF08\u4EE3\u7801\u98CE\u683C\u3001\u6D4B\u8BD5\u3001\u6784\u5EFA\u6D41\u7A0B\uFF09
67
+ 2. \u63A2\u7D22\u9876\u5C42\u76EE\u5F55\u7ED3\u6784\u548C\u5173\u952E package/product \u8FB9\u754C
68
+ 3. \u8BFB\u53D6 README\u3001ARCHITECTURE\u3001docs/public-api \u7B49\u5DF2\u6709\u6587\u6863\uFF0C\u907F\u514D\u91CD\u590D\u7C98\u8D34
69
+ 4. \u8BC6\u522B\u751F\u6210\u7269\u89C4\u5219\u3001\u6D4B\u8BD5\u95E8\u7981\u3001\u4EE3\u7801\u5206\u5C42\u548C\u9AD8\u98CE\u9669\u6539\u52A8\u8FB9\u754C
70
+ 5. \u751F\u6210\u7B80\u77ED\u3001\u7A33\u5B9A\u3001\u53EF\u7EF4\u62A4\u7684\u76EE\u5F55\u8DEF\u7531\u8BF4\u660E
63
71
 
64
- \u8BF7\u751F\u6210\u5305\u542B\u4EE5\u4E0B\u7AE0\u8282\u7684 agents.md\uFF1A
72
+ \u8BF7\u751F\u6210\u5305\u542B\u4EE5\u4E0B\u7AE0\u8282\u7684 AGENTS.md\uFF1A
65
73
 
66
74
  \`\`\`
67
- # Project: <\u9879\u76EE\u540D\u79F0>
75
+ # AGENTS.md
68
76
 
69
- ## \u6982\u89C8
70
- - \u7C7B\u578B\uFF1A<\u9879\u76EE\u7C7B\u578B>
71
- - \u6280\u672F\u6808\uFF1A<\u4E3B\u8981\u6280\u672F>
72
- - \u4E00\u53E5\u8BDD\u63CF\u8FF0\uFF1A<\u9879\u76EE\u7528\u9014>
77
+ ## How To Use This File
78
+ Briefly explain that this file is an index/router. Agents should read linked docs on demand.
73
79
 
74
- ## \u67B6\u6784\u5206\u6790
75
- - \u6A21\u5757\u5212\u5206
76
- - \u5173\u952E\u7EC4\u4EF6\u8BF4\u660E
77
- - \u4F9D\u8D56\u5173\u7CFB
80
+ ## Repo Map
81
+ - \`path\`
82
+ desc: When to read this directory and what it owns.
78
83
 
79
- ## \u6838\u5FC3\u6587\u4EF6
80
- | \u7528\u9014 | \u8DEF\u5F84 | \u8BF4\u660E |
81
- |------|------|------|
84
+ ## Architecture Rules
85
+ Stable cross-package boundaries only.
82
86
 
83
- ## \u5F00\u53D1\u89C4\u8303
84
- - \u4EE3\u7801\u98CE\u683C
85
- - \u6D4B\u8BD5\u6A21\u5F0F
86
- - \u6784\u5EFA/\u8FD0\u884C\u65B9\u5F0F
87
+ ## Context And Generated Artifacts
88
+ Rules for AGENTS.md, generated bundles, and source-of-truth files.
87
89
 
88
- ## \u63A2\u7D22\u6E05\u5355\uFF08\u5F85\u6DF1\u5165\u7814\u7A76\uFF09
89
- - [ ]
90
+ ## Verification Map
91
+ Which focused tests/checks to run by touched area.
90
92
  \`\`\`
91
93
 
92
- \u8BF7\u4F7F\u7528 write \u5DE5\u5177\u521B\u5EFA \`.pie/agents.md\` \u6587\u4EF6\u3002
93
-
94
- \u5DE5\u4F5C\u76EE\u5F55\uFF1A${cwd}`;
94
+ \u8BF7\u4F7F\u7528 write_file \u5DE5\u5177\u521B\u5EFA\u76EE\u6807\u6587\u4EF6\uFF1A${agentsPath}
95
+ CLI \u6587\u4EF6\u5DE5\u5177\u4F1A\u4EE5\u9879\u76EE\u6839\u76EE\u5F55\u4F5C\u4E3A\u8BBF\u95EE\u8FB9\u754C\uFF1B\u4E0D\u8981\u4F7F\u7528\u989D\u5916\u7684 root \u53C2\u6570\u3002`;
95
96
  }
96
97
  async function initExtension(ctx) {
97
98
  ctx.log("Init extension loaded");
98
99
  let cachedKnowledge = null;
99
100
  try {
100
- cachedKnowledge = await loadExistingKnowledge(ctx.cwd);
101
+ const existing = await loadExistingKnowledge(ctx.cwd);
102
+ cachedKnowledge = existing.content;
101
103
  if (cachedKnowledge) {
102
- const firstLine = cachedKnowledge.split("\n")[0] || "";
103
- const projectName = firstLine.replace(/^#\s*/, "").trim() || "\u9879\u76EE";
104
- ctx.log(`Pre-loaded agents.md (${cachedKnowledge.length} chars)`);
104
+ ctx.log(`Pre-loaded root AGENTS.md (${cachedKnowledge.length} chars) from ${existing.target.agentsPath}`);
105
105
  } else {
106
- ctx.log("No existing agents.md found");
106
+ ctx.log(`No existing root AGENTS.md found at ${existing.target.agentsPath}`);
107
107
  }
108
108
  } catch (err) {
109
- ctx.log(`Failed to pre-load agents.md: ${err}`);
109
+ ctx.log(`Failed to pre-load root AGENTS.md: ${err}`);
110
110
  }
111
111
  ctx.registerCommand({
112
112
  path: ["tools", "init"],
113
- description: "\u7814\u7A76\u9879\u76EE\u5E76\u751F\u6210/\u66F4\u65B0 agents.md \u77E5\u8BC6\u6587\u6863",
113
+ description: "\u7814\u7A76\u9879\u76EE\u5E76\u751F\u6210/\u66F4\u65B0 root AGENTS.md \u9879\u76EE\u4E0A\u4E0B\u6587\u7D22\u5F15",
114
114
  handler: async (ctx2, args) => {
115
- await ensurePieDir(ctx2.cwd);
116
- const existingContent = await loadExistingKnowledge(ctx2.cwd);
117
- const isUpdate = !!existingContent;
115
+ const existing = await loadExistingKnowledge(ctx2.cwd);
116
+ const existingContent = existing.content;
117
+ const isUpdate = !!existing.content;
118
118
  const userIntent = args?.trim();
119
119
  cachedKnowledge = existingContent;
120
120
  if (isUpdate) {
121
121
  if (userIntent) {
122
122
  ctx2.ui.notify(`\u{1F4DD} \u6B63\u5728\u66F4\u65B0\u9879\u76EE\u77E5\u8BC6\uFF08${userIntent}\uFF09...`, "info");
123
123
  } else {
124
- ctx2.ui.notify("\u{1F4DD} \u6B63\u5728\u66F4\u65B0\u9879\u76EE\u77E5\u8BC6...", "info");
124
+ ctx2.ui.notify("\u{1F4DD} \u6B63\u5728\u66F4\u65B0 root AGENTS.md...", "info");
125
125
  }
126
126
  } else {
127
- ctx2.ui.notify("\u{1F50D} \u6B63\u5728\u521D\u59CB\u5316\u9879\u76EE\u7814\u7A76...", "info");
127
+ ctx2.ui.notify("\u{1F50D} \u6B63\u5728\u521D\u59CB\u5316 root AGENTS.md...", "info");
128
128
  }
129
129
  const researchPrompt = buildResearchPrompt({
130
130
  isUpdate,
131
131
  existingContent,
132
132
  userIntent,
133
- cwd: ctx2.cwd
133
+ cwd: ctx2.cwd,
134
+ projectRoot: existing.target.projectRoot,
135
+ agentsPath: existing.target.agentsPath
134
136
  });
135
137
  return researchPrompt;
136
138
  }
@@ -7,7 +7,7 @@ import {
7
7
  isPlanModeSafeCommand,
8
8
  markCompletedPlanSteps,
9
9
  restoreExecutionState
10
- } from "../../../chunks/chunk-BHNULR7U.js";
10
+ } from "../../../chunks/chunk-6WD2NFIC.js";
11
11
  import "../../../chunks/chunk-A5JSJAPK.js";
12
12
  import "../../../chunks/chunk-TG2EQLX2.js";
13
13
 
@@ -1,14 +1,11 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  createCliHostCapabilities
4
- } from "../../../chunks/chunk-GDTN4UPJ.js";
4
+ } from "../../../chunks/chunk-ZRONUKTW.js";
5
5
  import {
6
- createReadResourceCapability,
7
- createReadSkillCapability,
8
- createResolveResourceCapability,
9
6
  createSharedFileSystemTools,
10
7
  createSubagentCapability
11
- } from "../../../chunks/chunk-BHNULR7U.js";
8
+ } from "../../../chunks/chunk-6WD2NFIC.js";
12
9
  import "../../../chunks/chunk-A5JSJAPK.js";
13
10
  import "../../../chunks/chunk-TG2EQLX2.js";
14
11
 
@@ -65,68 +62,16 @@ function subagentExtension(ctx) {
65
62
  return parentRuntimeTools.filter((tool) => tool?.name !== "spawn_subagents_parallel");
66
63
  }
67
64
  const configDir = path.join(os.homedir(), ".pie");
68
- const fsOptions = ctx.yoloMode ? { allowlistedDirs: ["/"] } : { allowlistedDirs: [configDir] };
65
+ const fsOptions = ctx.yoloMode ? { allowlistedDirs: ["/"] } : {
66
+ accessRoots: [
67
+ ctx.cwd,
68
+ configDir,
69
+ ...skills.map((skill) => skill.baseDir).filter((entry) => entry && entry.length > 0)
70
+ ]
71
+ };
69
72
  const fsTools = createSharedFileSystemTools(ctx.cwd, fsOptions);
70
- const readSkillTool = createReadSkillCapability({
71
- resolveSkill(name) {
72
- const skill = skills.find((entry) => entry.name === name);
73
- if (!skill || !skill.filePath) {
74
- return null;
75
- }
76
- const content = skill.content ?? fs.readFileSync(skill.filePath, "utf8");
77
- return {
78
- name: skill.name,
79
- content,
80
- resources: skill.resourceRefs
81
- };
82
- }
83
- }).tool;
84
- const readResourceTool = createReadResourceCapability({
85
- resolveResource(owner, resourcePath) {
86
- const skill = skills.find((entry) => entry.name === owner);
87
- if (!skill) {
88
- return null;
89
- }
90
- const trimmed = String(resourcePath || "").trim().replace(/\\/g, "/");
91
- if (!trimmed || trimmed.startsWith("/") || /^[A-Za-z]:\//.test(trimmed)) {
92
- return null;
93
- }
94
- const segments = trimmed.split("/").filter(Boolean);
95
- if (segments.some((segment) => segment === "..")) {
96
- return null;
97
- }
98
- const absolutePath = path.resolve(skill.baseDir, ...segments);
99
- const relativePath = path.relative(skill.baseDir, absolutePath).replace(/\\/g, "/");
100
- if (relativePath.startsWith("../") || relativePath === ".." || !fs.existsSync(absolutePath)) {
101
- return null;
102
- }
103
- return {
104
- owner: skill.name,
105
- path: trimmed.replace(/^\.\/+/, ""),
106
- content: fs.readFileSync(absolutePath, "utf8")
107
- };
108
- }
109
- }).tool;
110
- const resolveResourceTool = createResolveResourceCapability({
111
- resolveResource(owner, resourcePath) {
112
- const skill = skills.find((entry) => entry.name === owner);
113
- if (!skill) return null;
114
- const trimmed = String(resourcePath || "").trim().replace(/\\/g, "/");
115
- if (!trimmed || trimmed.startsWith("/") || /^[A-Za-z]:\//.test(trimmed)) return null;
116
- const segments = trimmed.split("/").filter(Boolean);
117
- if (segments.some((segment) => segment === "..")) return null;
118
- const absolutePath = path.resolve(skill.baseDir, ...segments);
119
- const relativePath = path.relative(skill.baseDir, absolutePath).replace(/\\/g, "/");
120
- if (relativePath.startsWith("../") || relativePath === ".." || !fs.existsSync(absolutePath)) return null;
121
- return {
122
- owner: skill.name,
123
- path: trimmed.replace(/^\.\/+/, ""),
124
- resolvedPath: absolutePath
125
- };
126
- }
127
- }).tool;
128
73
  const cliHostCapabilities = createCliHostCapabilities(ctx.cwd);
129
- return [...fsTools, readSkillTool, readResourceTool, resolveResourceTool, ...cliHostCapabilities.tools];
74
+ return [...fsTools, ...cliHostCapabilities.tools];
130
75
  }
131
76
  });
132
77
  for (const tool of capability.tools) {
@@ -7,7 +7,7 @@ import {
7
7
  executeManageTodoList,
8
8
  executionStateToTodos,
9
9
  restoreExecutionState
10
- } from "../../../chunks/chunk-BHNULR7U.js";
10
+ } from "../../../chunks/chunk-6WD2NFIC.js";
11
11
  import "../../../chunks/chunk-A5JSJAPK.js";
12
12
  import "../../../chunks/chunk-TG2EQLX2.js";
13
13
 
@@ -5,25 +5,25 @@ description: Interactive browser automation via Microsoft Playwright CLI. Use wh
5
5
 
6
6
  # Browser Tools
7
7
 
8
- Use Pie's packaged Microsoft Playwright CLI wrapper. Scripts live next to this skill; use `read_resource("browser-tools", "playwright-cli.js")` or `resolve_resource("browser-tools", "playwright-cli.js")` to get the executable path.
8
+ Use Pie's packaged Microsoft Playwright CLI wrapper. Scripts live next to this skill; resolve `playwright-cli.js` against this skill's `baseDir` and use the resulting ordinary path with `bash`.
9
9
 
10
10
  No manual dependency install is required when this skill is shipped with Pie.
11
11
 
12
12
  ## Common Commands
13
13
 
14
14
  ```bash
15
- node <resolvedPath for playwright-cli.js> open https://example.com
16
- node <resolvedPath for playwright-cli.js> goto https://example.com
17
- node <resolvedPath for playwright-cli.js> snapshot
18
- node <resolvedPath for playwright-cli.js> click "Submit"
19
- node <resolvedPath for playwright-cli.js> type "hello"
20
- node <resolvedPath for playwright-cli.js> screenshot
21
- node <resolvedPath for playwright-cli.js> console
22
- node <resolvedPath for playwright-cli.js> network
23
- node <resolvedPath for playwright-cli.js> close
15
+ node <baseDir>/playwright-cli.js open https://example.com
16
+ node <baseDir>/playwright-cli.js goto https://example.com
17
+ node <baseDir>/playwright-cli.js snapshot
18
+ node <baseDir>/playwright-cli.js click "Submit"
19
+ node <baseDir>/playwright-cli.js type "hello"
20
+ node <baseDir>/playwright-cli.js screenshot
21
+ node <baseDir>/playwright-cli.js console
22
+ node <baseDir>/playwright-cli.js network
23
+ node <baseDir>/playwright-cli.js close
24
24
  ```
25
25
 
26
- Use `node <resolvedPath for playwright-cli.js> --help` for the full command list.
26
+ Use `node <baseDir>/playwright-cli.js --help` for the full command list.
27
27
 
28
28
  ## Workflow
29
29
 
@@ -32,12 +32,12 @@ Start with `open` or `goto`, then use `snapshot` before interacting. Prefer snap
32
32
  If the browser is not installed, run:
33
33
 
34
34
  ```bash
35
- node <resolvedPath for playwright-cli.js> install-browser chromium
35
+ node <baseDir>/playwright-cli.js install-browser chromium
36
36
  ```
37
37
 
38
38
  If a session gets stuck, use:
39
39
 
40
40
  ```bash
41
- node <resolvedPath for playwright-cli.js> close
42
- node <resolvedPath for playwright-cli.js> kill-all
41
+ node <baseDir>/playwright-cli.js close
42
+ node <baseDir>/playwright-cli.js kill-all
43
43
  ```