@trim21/personal-pi-extensions 0.1.20261012000609 → 0.1.20261012003405

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
@@ -475,7 +475,7 @@ GitHub 只读工具集。取数全部走 octokit REST(`src/lib/github-reads.ts
475
475
  - **CI**:`read-github-ci-logs`、`list-github-workflow-runs`、`get-github-workflow-jobs`、`wait-github-pr-checks`、`wait-github-commit-checks`、`watch-github-run`
476
476
  - **仓库 / 发布**:`read-github-repo`、`list-github-releases`、`read-github-release`、`download-github-release-assets`
477
477
 
478
- `list-github-issues` / `list-github-prs` 带 `keywords` 时走 GitHub search API,不带 `keywords` 时走 REST 列表端点(state 缺省只搜 open,`state: "all"` 不加 state qualifier 覆盖 open + closed),输出 TSV,默认列 `number,state,title,labels,updatedAt`,可用 `fields` 白名单指定列。`wait-github-pr-checks` / `wait-github-commit-checks` 30 秒轮询、600 秒截止:任一 fail 即返回,全部 pass / skipped 才算通过,超时返回快照不抛错;检查快照还包含「已结束但没有 check run」的 check suite——fork PR 上等待维护者批准的 workflow 只存在于这一层,遇到它立即返回 `awaiting_approval`(不会自行开始,轮询无意义),条目名字取自对应的 workflow run。
478
+ `list-github-issues` / `list-github-prs` 带 `keywords` 时走 GitHub search API,不带 `keywords` 时走 REST 列表端点(state 缺省只搜 open,`state: "all"` 不加 state qualifier 覆盖 open + closed),输出 TSV,固定列 `number,state,title,labels,updatedAt`(未给 `repo` 时最前面多一列 `repo`),默认列之外的字段从结构化载荷 `items` 里取。`wait-github-pr-checks` / `wait-github-commit-checks` 30 秒轮询、600 秒截止:任一 fail 即返回,全部 pass / skipped 才算通过,超时返回快照不抛错;检查快照还包含「已结束但没有 check run」的 check suite——fork PR 上等待维护者批准的 workflow 只存在于这一层,遇到它立即返回 `awaiting_approval`(不会自行开始,轮询无意义),条目名字取自对应的 workflow run。
479
479
 
480
480
  出网代理:`~/.pi/agent/proxy.json`(`{ "proxy": "http://127.0.0.1:7890", "noProxy": "localhost" }`),缺省字段回退 `HTTPS_PROXY` / `HTTP_PROXY` / `ALL_PROXY` / `NO_PROXY` 环境变量。
481
481
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trim21/personal-pi-extensions",
3
- "version": "0.1.20261012000609",
3
+ "version": "0.1.20261012003405",
4
4
  "type": "module",
5
5
  "description": "Custom pi coding-agent extensions: bwrap sandbox, workspace guard, opencode edit, and more",
6
6
  "keywords": [
package/src/gh/base.ts CHANGED
@@ -334,8 +334,9 @@ export function withPendant<T extends ToolResult, IdKey extends string = never>(
334
334
  }
335
335
 
336
336
  /**
337
- * `list-github-issues` / `list-github-prs` 共用的一套过滤参数,只有 `state` 与 `fields`
338
- * 的说明文案按 kind 不同。
337
+ * `list-github-issues` / `list-github-prs` 共用的一套过滤参数,只有 `state` 的说明文案按
338
+ * kind 不同。文本列是固定的(见 `renderHits`),因此没有列选择参数:默认列之外的字段
339
+ * 从结构化载荷里取。
339
340
  */
340
341
  export function listFilterParameters(kind: "issue" | "pr") {
341
342
  const isPr = kind === "pr";
@@ -364,11 +365,6 @@ export function listFilterParameters(kind: "issue" | "pr") {
364
365
  ),
365
366
  milestone: Type.Optional(Type.String({ description: "Filter by milestone" })),
366
367
  limit: Type.Optional(Type.Number({ description: "Max results (default 30, max 100)" })),
367
- fields: Type.Optional(
368
- Type.String({
369
- description: `Comma-separated columns for the rows (default: number,state,title,labels,updatedAt; adds repo when no repo given). Valid: number,state,title,url,author,labels,milestone,assignees,comments,repo,createdAt,updatedAt,closedAt${isPr ? ",mergedAt" : ""}`,
370
- }),
371
- ),
372
368
  });
373
369
  }
374
370
 
@@ -381,8 +377,6 @@ export interface ListFilters {
381
377
  assignee?: string;
382
378
  milestone?: string;
383
379
  limit?: number;
384
- /** Comma-separated field names for the keyword-search result rows. */
385
- fields?: string;
386
380
  }
387
381
 
388
382
  /**
@@ -415,11 +409,11 @@ export async function browseList(
415
409
  return { repo, hits: normalizeRestList(items, repo) };
416
410
  }
417
411
 
418
- /** 行列表的文本:两条分支共用一套 TSV 渲染;空结果是成功结果。 */
412
+ /** 行列表的文本:两条分支共用一套 TSV 渲染(列为固定默认列);空结果是成功结果。 */
419
413
  export function renderHitList(
420
414
  kind: "issue" | "pr",
421
415
  hits: SearchHit[],
422
- options: { repo?: string; fields?: string },
416
+ options: { repo?: string },
423
417
  ): string {
424
418
  if (hits.length === 0) {
425
419
  return `(no matching ${kind === "issue" ? "issues" : "pull requests"})`;
@@ -26,7 +26,7 @@ async function listIssues(
26
26
  const { repo, hits } = params.keywords
27
27
  ? { repo: params.repo, hits: await gh.search.search("issue", params) }
28
28
  : await browseList(gh, "issue", params, { cwd: ctx.cwd, signal, input: params });
29
- const text = renderHitList("issue", hits, { repo, fields: params.fields });
29
+ const text = renderHitList("issue", hits, { repo });
30
30
  const result = toToolResult(text, params);
31
31
  // 文本可能被行数/字节预算截断,载荷给全部命中
32
32
  return withStructuredResult(withPendant(result, params), { text, items: hits });
@@ -26,7 +26,7 @@ async function listPrs(
26
26
  const { repo, hits } = params.keywords
27
27
  ? { repo: params.repo, hits: await gh.search.search("pr", params) }
28
28
  : await browseList(gh, "pr", params, { cwd: ctx.cwd, signal, input: params });
29
- const text = renderHitList("pr", hits, { repo, fields: params.fields });
29
+ const text = renderHitList("pr", hits, { repo });
30
30
  const result = toToolResult(text, params);
31
31
  // 文本可能被行数/字节预算截断,载荷给全部命中
32
32
  return withStructuredResult(withPendant(result, params), { text, items: hits });
package/src/lib/github.ts CHANGED
@@ -146,42 +146,19 @@ function quoteQualifier(value: string): string {
146
146
  return `"${value.replaceAll('"', String.raw`\"`)}"`;
147
147
  }
148
148
 
149
- const FIELD_EXTRACTORS: Record<string, (hit: SearchHit) => string> = {
150
- number: (h) => String(h.number),
151
- state: (h) => h.state,
152
- title: (h) => h.title,
153
- url: (h) => h.url,
154
- repo: (h) => h.repo,
155
- author: (h) => h.author,
156
- labels: (h) => h.labels.join(","),
157
- milestone: (h) => h.milestone,
158
- assignees: (h) => h.assignees.join(","),
159
- comments: (h) => String(h.comments),
160
- createdAt: (h) => h.createdAt,
161
- updatedAt: (h) => h.updatedAt,
162
- closedAt: (h) => h.closedAt,
163
- mergedAt: (h) => h.mergedAt,
164
- };
165
-
166
- export const SEARCH_FIELDS: readonly string[] = Object.keys(FIELD_EXTRACTORS);
167
-
168
- /** Render search hits as tab-separated rows; one row per hit, one column per field. */
169
- export function renderHits(hits: SearchHit[], options: { repo?: string; fields?: string }): string {
170
- const requested = options.fields
171
- ? options.fields
172
- .split(",")
173
- .map((f) => f.trim())
174
- .filter(Boolean)
175
- : options.repo
176
- ? ["number", "state", "title", "labels", "updatedAt"]
177
- : ["repo", "number", "state", "title", "labels", "updatedAt"];
178
- const unknown = requested.filter((f) => !(f in FIELD_EXTRACTORS));
179
- if (unknown.length > 0) {
180
- throw new Error(
181
- `unknown field${unknown.length > 1 ? "s" : ""}: ${unknown.join(", ")} (valid: ${SEARCH_FIELDS.join(", ")})`,
182
- );
183
- }
184
- return hits.map((hit) => requested.map((f) => FIELD_EXTRACTORS[f](hit)).join("\t")).join("\n");
149
+ /**
150
+ * Render search hits as tab-separated rows: one row per hit, fixed columns
151
+ * `number,state,title,labels,updatedAt`, plus a leading `repo` column when no
152
+ * repo is given (cross-repo search). Other fields of a hit reach the caller
153
+ * through the structured payload, not through the text.
154
+ */
155
+ export function renderHits(hits: SearchHit[], options: { repo?: string }): string {
156
+ return hits
157
+ .map((hit) => {
158
+ const columns = [hit.number, hit.state, hit.title, hit.labels.join(","), hit.updatedAt];
159
+ return (options.repo ? columns : [hit.repo, ...columns]).join("\t");
160
+ })
161
+ .join("\n");
185
162
  }
186
163
 
187
164
  function toDate(iso: string | null | undefined): string {