@oh-my-pi/pi-coding-agent 17.2.11 → 17.2.12
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 +13 -0
- package/dist/{CHANGELOG-d9xenpn9.md → CHANGELOG-k9ghy5sn.md} +13 -0
- package/dist/cli.js +10795 -10791
- package/dist/types/advisor/runtime.d.ts +1 -1
- package/dist/types/config/custom-models.d.ts +31 -0
- package/dist/types/config/model-config-values.d.ts +19 -0
- package/dist/types/config/model-patch.d.ts +93 -0
- package/dist/types/config/model-provider-discovery.d.ts +51 -0
- package/dist/types/config/model-registry.d.ts +5 -52
- package/dist/types/config/settings.d.ts +5 -3
- package/dist/types/debug/raw-sse-buffer.d.ts +9 -0
- package/dist/types/discovery/agent-plugin-format.d.ts +6 -13
- package/dist/types/discovery/contained-path.d.ts +2 -3
- package/dist/types/eval/executor-base.d.ts +8 -2
- package/dist/types/eval/kernel-session-registry.d.ts +60 -0
- package/dist/types/export/share.d.ts +1 -1
- package/dist/types/lsp/diagnostics.d.ts +96 -0
- package/dist/types/lsp/index.d.ts +7 -128
- package/dist/types/lsp/servers.d.ts +72 -0
- package/dist/types/lsp/tool.d.ts +42 -0
- package/dist/types/lsp/workspace-diagnostics.d.ts +12 -0
- package/dist/types/lsp/writethrough.d.ts +33 -0
- package/dist/types/mcp/transports/header-policy.d.ts +2 -1
- package/dist/types/modes/components/agent-hub-projection.d.ts +2 -7
- package/dist/types/modes/components/agent-hub-renderer.d.ts +0 -7
- package/dist/types/modes/theme/color.d.ts +19 -0
- package/dist/types/modes/theme/loader.d.ts +19 -0
- package/dist/types/modes/theme/schema.d.ts +175 -0
- package/dist/types/modes/theme/symbols.d.ts +28 -0
- package/dist/types/modes/theme/theme-class.d.ts +244 -0
- package/dist/types/modes/theme/theme.d.ts +9 -280
- package/dist/types/modes/theme/tui-adapters.d.ts +13 -0
- package/dist/types/registry/agent-registry.d.ts +1 -3
- package/dist/types/secrets/index.d.ts +3 -1
- package/dist/types/secrets/message-transform.d.ts +40 -0
- package/dist/types/secrets/obfuscator.d.ts +0 -108
- package/dist/types/secrets/placeholder-scan.d.ts +95 -0
- package/dist/types/secrets/placeholder.d.ts +94 -0
- package/dist/types/secrets/replacement.d.ts +82 -0
- package/dist/types/session/agent-session-types.d.ts +6 -0
- package/dist/types/session/agent-session.d.ts +1 -1
- package/dist/types/session/session-handoff.d.ts +3 -3
- package/dist/types/session/session-manager.d.ts +32 -0
- package/dist/types/session/session-provider-boundary.d.ts +1 -1
- package/dist/types/session/turn-recovery.d.ts +2 -2
- package/dist/types/slash-commands/builtin-collaboration.d.ts +2 -0
- package/dist/types/slash-commands/builtin-completions.d.ts +36 -0
- package/dist/types/slash-commands/builtin-control.d.ts +2 -0
- package/dist/types/slash-commands/builtin-lifecycle.d.ts +3 -0
- package/dist/types/slash-commands/builtin-marketplace.d.ts +11 -0
- package/dist/types/slash-commands/builtin-modes.d.ts +5 -0
- package/dist/types/slash-commands/builtin-registry.d.ts +1 -1
- package/dist/types/slash-commands/builtin-session.d.ts +2 -0
- package/dist/types/tools/gh-common.d.ts +69 -0
- package/dist/types/tools/gh-pr-checkout.d.ts +84 -0
- package/dist/types/tools/gh-pr-diff.d.ts +102 -0
- package/dist/types/tools/gh-run-watch.d.ts +78 -0
- package/dist/types/tools/gh-search.d.ts +61 -0
- package/dist/types/tools/gh-types.d.ts +340 -0
- package/dist/types/tools/gh-view.d.ts +88 -0
- package/dist/types/tools/gh.d.ts +4 -201
- package/dist/types/tools/read-archive.d.ts +16 -0
- package/dist/types/tools/read-format.d.ts +104 -0
- package/dist/types/tools/read-path-resolution.d.ts +19 -0
- package/dist/types/tools/read-pdf-images.d.ts +12 -0
- package/dist/types/tools/read-renderer.d.ts +24 -0
- package/dist/types/tools/read-selector.d.ts +27 -0
- package/dist/types/tools/read-sqlite.d.ts +16 -0
- package/dist/types/tools/read-summary.d.ts +19 -0
- package/dist/types/tools/read.d.ts +1 -23
- package/dist/types/tools/shell-tokenize.d.ts +2 -1
- package/dist/types/utils/changelog.d.ts +0 -5
- package/package.json +13 -13
- package/src/advisor/runtime.ts +12 -7
- package/src/config/custom-models.ts +188 -0
- package/src/config/model-config-values.ts +128 -0
- package/src/config/model-patch.ts +252 -0
- package/src/config/model-provider-discovery.ts +132 -0
- package/src/config/model-registry.ts +64 -704
- package/src/config/settings.ts +7 -3
- package/src/debug/raw-sse-buffer.ts +20 -0
- package/src/discovery/agent-plugin-format.ts +7 -7
- package/src/discovery/contained-path.ts +2 -5
- package/src/edit/hashline/diff.ts +5 -1
- package/src/eval/executor-base.ts +39 -6
- package/src/eval/jl/executor.ts +82 -371
- package/src/eval/kernel-session-registry.ts +398 -0
- package/src/eval/py/executor.ts +53 -261
- package/src/eval/rb/executor.ts +36 -279
- package/src/export/share.ts +2 -1
- package/src/lsp/diagnostics.ts +516 -0
- package/src/lsp/index.ts +20 -2819
- package/src/lsp/servers.ts +296 -0
- package/src/lsp/tool.ts +1352 -0
- package/src/lsp/workspace-diagnostics.ts +170 -0
- package/src/lsp/writethrough.ts +561 -0
- package/src/mcp/transports/header-policy.ts +1 -1
- package/src/modes/components/agent-hub-projection.ts +2 -2
- package/src/modes/components/agent-hub-renderer.ts +3 -7
- package/src/modes/controllers/command-controller.ts +4 -1
- package/src/modes/theme/color.ts +133 -0
- package/src/modes/theme/loader.ts +178 -0
- package/src/modes/theme/schema.ts +263 -0
- package/src/modes/theme/symbols.ts +1000 -0
- package/src/modes/theme/theme-class.ts +611 -0
- package/src/modes/theme/theme.ts +27 -2453
- package/src/modes/theme/tui-adapters.ts +279 -0
- package/src/registry/agent-registry.ts +2 -2
- package/src/secrets/index.ts +6 -12
- package/src/secrets/message-transform.ts +287 -0
- package/src/secrets/obfuscator.ts +39 -1303
- package/src/secrets/placeholder-scan.ts +506 -0
- package/src/secrets/placeholder.ts +309 -0
- package/src/secrets/replacement.ts +216 -0
- package/src/session/agent-session-types.ts +6 -0
- package/src/session/agent-session.ts +113 -7
- package/src/session/indexed-session-storage.ts +7 -2
- package/src/session/session-advisors.ts +32 -34
- package/src/session/session-handoff.ts +39 -20
- package/src/session/session-manager.ts +67 -3
- package/src/session/session-provider-boundary.ts +3 -6
- package/src/session/turn-recovery.ts +21 -12
- package/src/slash-commands/builtin-collaboration.ts +504 -0
- package/src/slash-commands/builtin-completions.ts +291 -0
- package/src/slash-commands/builtin-control.ts +78 -0
- package/src/slash-commands/builtin-lifecycle.ts +506 -0
- package/src/slash-commands/builtin-marketplace.ts +567 -0
- package/src/slash-commands/builtin-modes.ts +518 -0
- package/src/slash-commands/builtin-registry.ts +21 -3000
- package/src/slash-commands/builtin-session.ts +592 -0
- package/src/task/executor.ts +17 -14
- package/src/tools/gh-common.ts +288 -0
- package/src/tools/gh-pr-checkout.ts +679 -0
- package/src/tools/gh-pr-diff.ts +473 -0
- package/src/tools/gh-run-watch.ts +1015 -0
- package/src/tools/gh-search.ts +500 -0
- package/src/tools/gh-types.ts +379 -0
- package/src/tools/gh-view.ts +612 -0
- package/src/tools/gh.ts +109 -3821
- package/src/tools/read-archive.ts +209 -0
- package/src/tools/read-format.ts +593 -0
- package/src/tools/read-path-resolution.ts +36 -0
- package/src/tools/read-pdf-images.ts +250 -0
- package/src/tools/read-renderer.ts +289 -0
- package/src/tools/read-selector.ts +84 -0
- package/src/tools/read-sqlite.ts +215 -0
- package/src/tools/read-summary.ts +199 -0
- package/src/tools/read.ts +77 -1820
- package/src/tools/shell-tokenize.ts +1 -1
- package/src/utils/changelog.ts +1 -1
- package/src/utils/title-generator.ts +3 -1
- package/src/web/search/providers/zai.ts +12 -3
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import * as path from "node:path";
|
|
2
|
+
import type { AgentToolResult } from "@oh-my-pi/pi-agent-core";
|
|
3
|
+
import { untilAborted } from "@oh-my-pi/pi-utils";
|
|
4
|
+
import * as git from "../utils/git";
|
|
5
|
+
import type { ToolSession } from ".";
|
|
6
|
+
import type { GhToolDetails } from "./gh";
|
|
7
|
+
import type { GhLabel, GhUser } from "./gh-types";
|
|
8
|
+
import { ToolError } from "./tool-errors";
|
|
9
|
+
import { toolResult } from "./tool-result";
|
|
10
|
+
|
|
11
|
+
export function normalizeText(value: string | null | undefined): string {
|
|
12
|
+
return (value ?? "").replaceAll("\r\n", "\n").replaceAll("\r", "\n").replaceAll("\t", " ").trim();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function normalizeBlock(value: string | null | undefined): string {
|
|
16
|
+
return (value ?? "").replaceAll("\r\n", "\n").replaceAll("\r", "\n").replaceAll("\t", " ").trimEnd();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function looksLikeGitHubUrl(value: string | undefined): boolean {
|
|
20
|
+
return value?.startsWith("https://github.com/") ?? false;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function normalizeOptionalString(value: string | null | undefined): string | undefined {
|
|
24
|
+
const normalized = value?.trim();
|
|
25
|
+
return normalized ? normalized : undefined;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function normalizePrIdentifierList(value: string | string[] | undefined): string[] {
|
|
29
|
+
if (value === undefined) return [];
|
|
30
|
+
const raw = typeof value === "string" ? [value] : value;
|
|
31
|
+
const cleaned: string[] = [];
|
|
32
|
+
for (const entry of raw) {
|
|
33
|
+
const trimmed = entry?.trim();
|
|
34
|
+
if (trimmed) cleaned.push(trimmed);
|
|
35
|
+
}
|
|
36
|
+
return cleaned;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function requireNonEmpty(value: string | null | undefined, label: string): string {
|
|
40
|
+
const normalized = normalizeOptionalString(value);
|
|
41
|
+
if (!normalized) {
|
|
42
|
+
throw new ToolError(`${label} must not be empty`);
|
|
43
|
+
}
|
|
44
|
+
return normalized;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function appendRepoFlag(args: string[], repo: string | undefined, identifier?: string): void {
|
|
48
|
+
if (!repo || looksLikeGitHubUrl(identifier)) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
args.push("--repo", repo);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export const REPO_API_URL_PREFIX = "https://api.github.com/repos/";
|
|
56
|
+
|
|
57
|
+
export const PR_URL_PATTERN = /^https:\/\/github\.com\/([^/]+\/[^/]+)\/pull\/(\d+)(?:\/.*)?$/;
|
|
58
|
+
export const ISSUE_URL_PATTERN = /^https:\/\/github\.com\/([^/]+\/[^/]+)\/issues\/(\d+)(?:\/.*)?$/;
|
|
59
|
+
|
|
60
|
+
export async function requireCurrentGitBranch(cwd: string, signal?: AbortSignal): Promise<string> {
|
|
61
|
+
const branch = await git.branch.current(cwd, signal);
|
|
62
|
+
if (!branch) {
|
|
63
|
+
throw new ToolError("Current git branch is unavailable. Pass `branch` or `run` explicitly.");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return branch;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export async function requireCurrentGitHead(cwd: string, signal?: AbortSignal): Promise<string> {
|
|
70
|
+
const headSha = await git.head.sha(cwd, signal);
|
|
71
|
+
if (!headSha) {
|
|
72
|
+
throw new ToolError("Current git HEAD is unavailable. Pass `run` explicitly.");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return headSha;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function formatAuthor(author: GhUser | null | undefined): string | undefined {
|
|
79
|
+
if (!author) return undefined;
|
|
80
|
+
if (author.login) return `@${author.login}`;
|
|
81
|
+
if (author.name) return author.name;
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function formatLabels(labels: GhLabel[] | undefined): string | undefined {
|
|
86
|
+
const names = labels?.map(label => label.name).filter((value): value is string => Boolean(value)) ?? [];
|
|
87
|
+
if (names.length === 0) return undefined;
|
|
88
|
+
return names.join(", ");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function pushLine(lines: string[], label: string, value: string | number | boolean | undefined): void {
|
|
92
|
+
if (value === undefined || value === "") return;
|
|
93
|
+
lines.push(`${label}: ${value}`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function parsePullRequestUrl(value: string | undefined): { repo?: string; prNumber?: number } {
|
|
97
|
+
const normalized = normalizeOptionalString(value);
|
|
98
|
+
if (!normalized) {
|
|
99
|
+
return {};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const match = normalized.match(PR_URL_PATTERN);
|
|
103
|
+
if (!match) {
|
|
104
|
+
return {};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
repo: match[1],
|
|
109
|
+
prNumber: Number(match[2]),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Parse a digit-only decimal positive integer or return undefined. Rejects
|
|
115
|
+
* `1e2`, `0x10`, `12.0`, leading +/-, or any other shape `Number()` would
|
|
116
|
+
* accept — those would otherwise key the cache against the wrong row.
|
|
117
|
+
*/
|
|
118
|
+
export function parsePositiveDecimalInt(value: string | undefined): number | undefined {
|
|
119
|
+
if (!value || !/^\d+$/.test(value)) return undefined;
|
|
120
|
+
const num = Number(value);
|
|
121
|
+
if (!Number.isSafeInteger(num) || num <= 0) return undefined;
|
|
122
|
+
return num;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function parseIssueUrl(value: string | undefined): { repo?: string; issueNumber?: number } {
|
|
126
|
+
const normalized = normalizeOptionalString(value);
|
|
127
|
+
if (!normalized) return {};
|
|
128
|
+
const match = normalized.match(ISSUE_URL_PATTERN);
|
|
129
|
+
if (!match) return {};
|
|
130
|
+
return {
|
|
131
|
+
repo: match[1],
|
|
132
|
+
issueNumber: Number(match[2]),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function githubRepoSlugEquals(left: string | undefined, right: string): boolean {
|
|
137
|
+
if (left === undefined || left.length !== right.length) return false;
|
|
138
|
+
for (let idx = 0; idx < left.length; idx += 1) {
|
|
139
|
+
let leftCode = left.charCodeAt(idx);
|
|
140
|
+
let rightCode = right.charCodeAt(idx);
|
|
141
|
+
if (leftCode >= 65 && leftCode <= 90) leftCode += 32;
|
|
142
|
+
if (rightCode >= 65 && rightCode <= 90) rightCode += 32;
|
|
143
|
+
if (leftCode !== rightCode) return false;
|
|
144
|
+
}
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export async function resolveGitHubRepo(
|
|
149
|
+
cwd: string,
|
|
150
|
+
repo: string | undefined,
|
|
151
|
+
runRepo: string | undefined,
|
|
152
|
+
signal?: AbortSignal,
|
|
153
|
+
): Promise<string> {
|
|
154
|
+
if (repo && runRepo && !githubRepoSlugEquals(repo, runRepo)) {
|
|
155
|
+
throw new ToolError("run URL repository does not match the provided repo");
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (repo) {
|
|
159
|
+
return repo;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (runRepo) {
|
|
163
|
+
return runRepo;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const resolved = await git.github.text(
|
|
167
|
+
cwd,
|
|
168
|
+
["repo", "view", "--json", "nameWithOwner", "-q", ".nameWithOwner"],
|
|
169
|
+
signal,
|
|
170
|
+
);
|
|
171
|
+
return requireNonEmpty(resolved, "repo");
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Process-lifetime cache of `gh repo view --json nameWithOwner` lookups keyed
|
|
176
|
+
* by absolute cwd. Avoids repeated `gh` chatter when the same protocol handler
|
|
177
|
+
* or tool call resolves the default repo many times in a row.
|
|
178
|
+
*
|
|
179
|
+
* The shared lookup is intentionally **not** bound to any caller's
|
|
180
|
+
* AbortSignal. Cancelling one caller would otherwise kill the underlying
|
|
181
|
+
* `gh repo view` for every concurrent waiter on the same cwd. Each caller's
|
|
182
|
+
* signal is honored at the wait point via `untilAborted` instead, so an abort
|
|
183
|
+
* unwinds only that caller.
|
|
184
|
+
*/
|
|
185
|
+
export const DEFAULT_REPO_RESOLVED = new Map<string, string>();
|
|
186
|
+
export const DEFAULT_REPO_INFLIGHT = new Map<string, Promise<string>>();
|
|
187
|
+
|
|
188
|
+
export async function resolveDefaultRepoMemoized(cwd: string, signal?: AbortSignal): Promise<string> {
|
|
189
|
+
const key = path.resolve(cwd);
|
|
190
|
+
const ready = DEFAULT_REPO_RESOLVED.get(key);
|
|
191
|
+
if (ready) return ready;
|
|
192
|
+
let pending = DEFAULT_REPO_INFLIGHT.get(key);
|
|
193
|
+
if (!pending) {
|
|
194
|
+
pending = (async () => {
|
|
195
|
+
// No caller signal: this lookup is shared across every concurrent
|
|
196
|
+
// waiter on the same cwd.
|
|
197
|
+
const resolved = await git.github.text(cwd, [
|
|
198
|
+
"repo",
|
|
199
|
+
"view",
|
|
200
|
+
"--json",
|
|
201
|
+
"nameWithOwner",
|
|
202
|
+
"-q",
|
|
203
|
+
".nameWithOwner",
|
|
204
|
+
]);
|
|
205
|
+
const value = requireNonEmpty(resolved, "repo");
|
|
206
|
+
DEFAULT_REPO_RESOLVED.set(key, value);
|
|
207
|
+
return value;
|
|
208
|
+
})();
|
|
209
|
+
// Drop the in-flight slot on settle so failures don't poison the cache
|
|
210
|
+
// and so a successful resolution survives only in `DEFAULT_REPO_RESOLVED`.
|
|
211
|
+
void pending.then(
|
|
212
|
+
() => DEFAULT_REPO_INFLIGHT.delete(key),
|
|
213
|
+
() => DEFAULT_REPO_INFLIGHT.delete(key),
|
|
214
|
+
);
|
|
215
|
+
DEFAULT_REPO_INFLIGHT.set(key, pending);
|
|
216
|
+
}
|
|
217
|
+
return untilAborted(signal, pending);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Best-effort cached cwd → `owner/repo` resolution that swallows any failure
|
|
222
|
+
* (not a git checkout, no GitHub remote, `gh` unauthenticated, …) into
|
|
223
|
+
* `undefined`. Use where the cwd repo is a convenience fallback, not a safety
|
|
224
|
+
* check.
|
|
225
|
+
*/
|
|
226
|
+
export async function tryResolveCurrentRepo(cwd: string, signal: AbortSignal | undefined): Promise<string | undefined> {
|
|
227
|
+
try {
|
|
228
|
+
return await resolveDefaultRepoMemoized(cwd, signal);
|
|
229
|
+
} catch {
|
|
230
|
+
return undefined;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Best-effort fresh cwd → `owner/repo` resolution for safety checks that must
|
|
236
|
+
* reflect the repository currently mounted at `cwd`, not the process-lifetime
|
|
237
|
+
* default-repo cache.
|
|
238
|
+
*/
|
|
239
|
+
export async function tryResolveCurrentRepoFresh(
|
|
240
|
+
cwd: string,
|
|
241
|
+
signal: AbortSignal | undefined,
|
|
242
|
+
): Promise<string | undefined> {
|
|
243
|
+
try {
|
|
244
|
+
return await resolveGitHubRepo(cwd, undefined, undefined, signal);
|
|
245
|
+
} catch {
|
|
246
|
+
return undefined;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export async function saveArtifactText(
|
|
251
|
+
session: ToolSession,
|
|
252
|
+
toolType: string,
|
|
253
|
+
text: string,
|
|
254
|
+
): Promise<string | undefined> {
|
|
255
|
+
const { path: artifactPath, id: artifactId } = (await session.allocateOutputArtifact?.(toolType)) ?? {};
|
|
256
|
+
if (!artifactPath || !artifactId) {
|
|
257
|
+
return undefined;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
await Bun.write(artifactPath, text);
|
|
261
|
+
return artifactId;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export function appendArtifactReference(text: string, artifactId: string | undefined, label: string): string {
|
|
265
|
+
if (!artifactId) {
|
|
266
|
+
return text;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return `${text}\n\n${label}: artifact://${artifactId}`;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export function buildTextResult(
|
|
273
|
+
text: string,
|
|
274
|
+
sourceUrl?: string,
|
|
275
|
+
details?: GhToolDetails,
|
|
276
|
+
options?: { artifactId?: string; artifactLabel?: string; useless?: boolean },
|
|
277
|
+
): AgentToolResult<GhToolDetails> {
|
|
278
|
+
const builder = toolResult<GhToolDetails>(details).text(
|
|
279
|
+
appendArtifactReference(text, options?.artifactId, options?.artifactLabel ?? "Saved artifact"),
|
|
280
|
+
);
|
|
281
|
+
if (sourceUrl) {
|
|
282
|
+
builder.sourceUrl(sourceUrl);
|
|
283
|
+
}
|
|
284
|
+
if (options?.useless) {
|
|
285
|
+
builder.useless();
|
|
286
|
+
}
|
|
287
|
+
return builder.done();
|
|
288
|
+
}
|