@geminixiang/mikan 1.0.0-beta.12 → 1.0.0-beta.2
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 +0 -161
- package/dist/adapter.d.ts +1 -1
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js.map +1 -1
- package/dist/adapters/discord/bot.d.ts +0 -1
- package/dist/adapters/discord/bot.d.ts.map +1 -1
- package/dist/adapters/discord/bot.js +0 -9
- package/dist/adapters/discord/bot.js.map +1 -1
- package/dist/adapters/slack/bot.d.ts +0 -1
- package/dist/adapters/slack/bot.d.ts.map +1 -1
- package/dist/adapters/slack/bot.js +1 -18
- package/dist/adapters/slack/bot.js.map +1 -1
- package/dist/adapters/slack/response-lifecycle.d.ts.map +1 -1
- package/dist/adapters/slack/response-lifecycle.js +0 -6
- package/dist/adapters/slack/response-lifecycle.js.map +1 -1
- package/dist/adapters/telegram/bot.d.ts +0 -1
- package/dist/adapters/telegram/bot.d.ts.map +1 -1
- package/dist/adapters/telegram/bot.js +0 -10
- package/dist/adapters/telegram/bot.js.map +1 -1
- package/dist/agent.d.ts +2 -2
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +11 -39
- package/dist/agent.js.map +1 -1
- package/dist/commands/extensions.d.ts.map +1 -1
- package/dist/commands/extensions.js +5 -14
- package/dist/commands/extensions.js.map +1 -1
- package/dist/execution-resolver.d.ts.map +1 -1
- package/dist/execution-resolver.js +2 -11
- package/dist/execution-resolver.js.map +1 -1
- package/dist/harness/extensions/loader.d.ts +9 -33
- package/dist/harness/extensions/loader.d.ts.map +1 -1
- package/dist/harness/extensions/loader.js +50 -226
- package/dist/harness/extensions/loader.js.map +1 -1
- package/dist/harness/extensions/types.d.ts +4 -27
- package/dist/harness/extensions/types.d.ts.map +1 -1
- package/dist/harness/extensions/types.js.map +1 -1
- package/dist/harness/index.d.ts +1 -1
- package/dist/harness/index.d.ts.map +1 -1
- package/dist/harness/index.js +1 -1
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/runner.d.ts.map +1 -1
- package/dist/harness/runner.js +1 -5
- package/dist/harness/runner.js.map +1 -1
- package/dist/main.js +8 -84
- package/dist/main.js.map +1 -1
- package/dist/runtime/conversation-runtime.js +1 -1
- package/dist/runtime/conversation-runtime.js.map +1 -1
- package/dist/runtime/types.d.ts +1 -5
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/types.js.map +1 -1
- package/dist/sessions/policy.d.ts.map +1 -1
- package/dist/sessions/policy.js +0 -1
- package/dist/sessions/policy.js.map +1 -1
- package/dist/tools/index.d.ts +1 -5
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +0 -12
- package/dist/tools/index.js.map +1 -1
- package/dist/types.d.ts +1 -57
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -2
- package/dist/adapters/github/bot.d.ts +0 -76
- package/dist/adapters/github/bot.d.ts.map +0 -1
- package/dist/adapters/github/bot.js +0 -639
- package/dist/adapters/github/bot.js.map +0 -1
- package/dist/adapters/github/client.d.ts +0 -87
- package/dist/adapters/github/client.d.ts.map +0 -1
- package/dist/adapters/github/client.js +0 -230
- package/dist/adapters/github/client.js.map +0 -1
- package/dist/adapters/github/context.d.ts +0 -9
- package/dist/adapters/github/context.d.ts.map +0 -1
- package/dist/adapters/github/context.js +0 -171
- package/dist/adapters/github/context.js.map +0 -1
- package/dist/adapters/github/ids.d.ts +0 -25
- package/dist/adapters/github/ids.d.ts.map +0 -1
- package/dist/adapters/github/ids.js +0 -39
- package/dist/adapters/github/ids.js.map +0 -1
- package/dist/adapters/github/repo.d.ts +0 -19
- package/dist/adapters/github/repo.d.ts.map +0 -1
- package/dist/adapters/github/repo.js +0 -58
- package/dist/adapters/github/repo.js.map +0 -1
- package/dist/adapters/github/types.d.ts +0 -125
- package/dist/adapters/github/types.d.ts.map +0 -1
- package/dist/adapters/github/types.js +0 -2
- package/dist/adapters/github/types.js.map +0 -1
- package/dist/cli/ext-git.d.ts +0 -22
- package/dist/cli/ext-git.d.ts.map +0 -1
- package/dist/cli/ext-git.js +0 -76
- package/dist/cli/ext-git.js.map +0 -1
- package/dist/cli/ext.d.ts +0 -2
- package/dist/cli/ext.d.ts.map +0 -1
- package/dist/cli/ext.js +0 -217
- package/dist/cli/ext.js.map +0 -1
- package/dist/tools/github-checks.d.ts +0 -22
- package/dist/tools/github-checks.d.ts.map +0 -1
- package/dist/tools/github-checks.js +0 -88
- package/dist/tools/github-checks.js.map +0 -1
- package/dist/tools/github-pr.d.ts +0 -22
- package/dist/tools/github-pr.d.ts.map +0 -1
- package/dist/tools/github-pr.js +0 -55
- package/dist/tools/github-pr.js.map +0 -1
- package/dist/tools/react.d.ts +0 -15
- package/dist/tools/react.d.ts.map +0 -1
- package/dist/tools/react.js +0 -40
- package/dist/tools/react.js.map +0 -1
package/dist/cli/ext-git.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ext-git.js","sourceRoot":"","sources":["../../src/cli/ext-git.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Resolve a `mikan ext install` source that points at a git repository into a\n * local directory: clone it, descend into an optional `#subpath`, and run\n * `npm install --omit=dev` when the extension declares dependencies. The\n * caller validates + copies the returned directory, then calls cleanup().\n */\nimport { execFileSync } from \"node:child_process\";\nimport { existsSync, mkdtempSync, readFileSync, rmSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport interface ResolvedGitSource {\n /** Local directory holding the extension (clone root or a subpath within). */\n dir: string;\n /** Remove the temporary clone. */\n cleanup: () => void;\n}\n\ninterface GitSpec {\n url: string;\n subpath?: string;\n}\n\n/**\n * Recognize a git source and split off an optional `#subpath`:\n * https://host/owner/repo.git#dir/ext → { url, subpath }\n * git@host:owner/repo.git → { url }\n * github:owner/repo → expands to https clone URL\n * Returns undefined for anything that looks like a local path.\n */\nexport function parseGitSource(source: string): GitSpec | undefined {\n const [locator, subpath] = splitSubpath(source);\n\n if (locator.startsWith(\"github:\")) {\n const repo = locator.slice(\"github:\".length).replace(/\\.git$/, \"\");\n return { url: `https://github.com/${repo}.git`, subpath };\n }\n if (\n locator.startsWith(\"https://\") ||\n locator.startsWith(\"http://\") ||\n locator.startsWith(\"git://\") ||\n locator.startsWith(\"ssh://\") ||\n locator.startsWith(\"file://\") ||\n /^git@[^:]+:/.test(locator)\n ) {\n return { url: locator, subpath };\n }\n return undefined;\n}\n\nfunction splitSubpath(source: string): [string, string | undefined] {\n const hash = source.indexOf(\"#\");\n if (hash === -1) return [source, undefined];\n return [source.slice(0, hash), source.slice(hash + 1) || undefined];\n}\n\n/** Clone a git source (shallow) and resolve the extension directory within it. */\nexport function resolveGitSource(spec: GitSpec): ResolvedGitSource {\n const tempRoot = mkdtempSync(join(tmpdir(), \"mikan-ext-git-\"));\n const cleanup = () => rmSync(tempRoot, { recursive: true, force: true });\n try {\n execFileSync(\"git\", [\"clone\", \"--depth\", \"1\", spec.url, tempRoot], { stdio: \"inherit\" });\n\n const dir = spec.subpath ? join(tempRoot, spec.subpath) : tempRoot;\n if (!existsSync(dir)) {\n throw new Error(`Subpath not found in repository: ${spec.subpath}`);\n }\n\n // Install runtime dependencies only when the extension declares any.\n if (hasDependencies(dir)) {\n execFileSync(\"npm\", [\"install\", \"--omit=dev\", \"--no-audit\", \"--no-fund\"], {\n cwd: dir,\n stdio: \"inherit\",\n });\n }\n return { dir, cleanup };\n } catch (err) {\n cleanup();\n throw err;\n }\n}\n\nfunction hasDependencies(dir: string): boolean {\n const packageJsonPath = join(dir, \"package.json\");\n if (!existsSync(packageJsonPath)) return false;\n try {\n const pkg = JSON.parse(readFileSync(packageJsonPath, \"utf-8\")) as {\n dependencies?: Record<string, string>;\n };\n return Boolean(pkg.dependencies && Object.keys(pkg.dependencies).length > 0);\n } catch {\n return false;\n }\n}\n"]}
|
package/dist/cli/ext.d.ts
DELETED
package/dist/cli/ext.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ext.d.ts","sourceRoot":"","sources":["../../src/cli/ext.ts"],"names":[],"mappings":"AA2EA,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBnE"}
|
package/dist/cli/ext.js
DELETED
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `mikan ext` — manage extensions from the CLI.
|
|
3
|
-
*
|
|
4
|
-
* mikan ext install <source> [--global | --conversation <id>] [--state-dir <dir>]
|
|
5
|
-
* mikan ext validate <path>
|
|
6
|
-
* mikan ext list [--conversation <id>] [--state-dir <dir>]
|
|
7
|
-
* mikan ext remove <slug> (--global | --conversation <id>) [--state-dir <dir>]
|
|
8
|
-
*
|
|
9
|
-
* `<source>` is a local path or a git URL (https://…, git@…, or github:owner/repo)
|
|
10
|
-
* with an optional `#subpath` for extensions inside a repo. Reinstalling over an
|
|
11
|
-
* existing extension updates it (data is preserved). Extensions install into the
|
|
12
|
-
* host-only state dir (never the workspace); see src/harness/extensions/LAYOUT.md.
|
|
13
|
-
*/
|
|
14
|
-
import { cpSync, existsSync, mkdirSync, rmSync } from "node:fs";
|
|
15
|
-
import { homedir } from "node:os";
|
|
16
|
-
import { basename, join, resolve } from "node:path";
|
|
17
|
-
import { defaultExtensionDirs, listInstalledExtensions, validateExtension, } from "../harness/index.js";
|
|
18
|
-
import { parseGitSource, resolveGitSource } from "./ext-git.js";
|
|
19
|
-
function parseExtArgs(argv) {
|
|
20
|
-
let stateDir = join(homedir(), ".mikan");
|
|
21
|
-
let scope;
|
|
22
|
-
let conversationId;
|
|
23
|
-
const positional = [];
|
|
24
|
-
for (let i = 0; i < argv.length; i++) {
|
|
25
|
-
const arg = argv[i];
|
|
26
|
-
if (arg === "--global")
|
|
27
|
-
scope = "global";
|
|
28
|
-
else if (arg === "--conversation") {
|
|
29
|
-
scope = "conversation";
|
|
30
|
-
conversationId = argv[++i];
|
|
31
|
-
}
|
|
32
|
-
else if (arg.startsWith("--conversation=")) {
|
|
33
|
-
scope = "conversation";
|
|
34
|
-
conversationId = arg.slice("--conversation=".length);
|
|
35
|
-
}
|
|
36
|
-
else if (arg === "--state-dir")
|
|
37
|
-
stateDir = resolve(argv[++i] ?? "");
|
|
38
|
-
else if (arg.startsWith("--state-dir="))
|
|
39
|
-
stateDir = resolve(arg.slice("--state-dir=".length));
|
|
40
|
-
else
|
|
41
|
-
positional.push(arg);
|
|
42
|
-
}
|
|
43
|
-
return { action: positional[0], target: positional[1], stateDir, scope, conversationId };
|
|
44
|
-
}
|
|
45
|
-
/** Directory that extension CODE for the chosen scope lives in. */
|
|
46
|
-
function scopeExtensionsDir(args) {
|
|
47
|
-
if (args.scope === "global")
|
|
48
|
-
return join(args.stateDir, "global", "extensions");
|
|
49
|
-
if (args.scope === "conversation" && args.conversationId) {
|
|
50
|
-
// defaultExtensionDirs returns [global, conversation]; take the conversation one.
|
|
51
|
-
return defaultExtensionDirs(args.conversationId, args.stateDir)[1];
|
|
52
|
-
}
|
|
53
|
-
throw new Error("Specify a scope: --global or --conversation <id>");
|
|
54
|
-
}
|
|
55
|
-
const USAGE = `Usage:
|
|
56
|
-
mikan ext install <source> (--global | --conversation <id>) [--state-dir <dir>]
|
|
57
|
-
<source>: a local path, or a git URL / github:owner/repo with optional #subpath
|
|
58
|
-
e.g. github:geminixiang/mikan#examples/extensions/agent-pm
|
|
59
|
-
Reinstalling over an existing extension updates it (data preserved).
|
|
60
|
-
mikan ext validate <path>
|
|
61
|
-
mikan ext list [--conversation <id>] [--state-dir <dir>]
|
|
62
|
-
mikan ext remove <slug> (--global | --conversation <id>) [--state-dir <dir>]`;
|
|
63
|
-
function noop() { }
|
|
64
|
-
export async function runExtCommand(argv) {
|
|
65
|
-
const args = parseExtArgs(argv);
|
|
66
|
-
switch (args.action) {
|
|
67
|
-
case "validate":
|
|
68
|
-
return validateAction(args);
|
|
69
|
-
case "install":
|
|
70
|
-
return installAction(args);
|
|
71
|
-
case "list":
|
|
72
|
-
return listAction(args);
|
|
73
|
-
case "remove":
|
|
74
|
-
return removeAction(args);
|
|
75
|
-
default:
|
|
76
|
-
console.error(USAGE);
|
|
77
|
-
return 1;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
async function validateAction(args) {
|
|
81
|
-
if (!args.target) {
|
|
82
|
-
console.error("ext validate: missing <path>");
|
|
83
|
-
return 1;
|
|
84
|
-
}
|
|
85
|
-
const result = await validateExtension(resolve(args.target));
|
|
86
|
-
printValidation(result);
|
|
87
|
-
return result.ok ? 0 : 1;
|
|
88
|
-
}
|
|
89
|
-
async function installAction(args) {
|
|
90
|
-
if (!args.target) {
|
|
91
|
-
console.error("ext install: missing <path>");
|
|
92
|
-
return 1;
|
|
93
|
-
}
|
|
94
|
-
let destDir;
|
|
95
|
-
try {
|
|
96
|
-
destDir = scopeExtensionsDir(args);
|
|
97
|
-
}
|
|
98
|
-
catch (err) {
|
|
99
|
-
console.error(err instanceof Error ? err.message : String(err));
|
|
100
|
-
return 1;
|
|
101
|
-
}
|
|
102
|
-
// Resolve the source: a git URL (optionally with #subpath) is cloned to a
|
|
103
|
-
// temp dir; a local path is used directly.
|
|
104
|
-
const gitSpec = parseGitSource(args.target);
|
|
105
|
-
let source;
|
|
106
|
-
let cleanup = noop;
|
|
107
|
-
if (gitSpec) {
|
|
108
|
-
try {
|
|
109
|
-
const resolved = resolveGitSource(gitSpec);
|
|
110
|
-
source = resolved.dir;
|
|
111
|
-
cleanup = resolved.cleanup;
|
|
112
|
-
}
|
|
113
|
-
catch (err) {
|
|
114
|
-
console.error(`Failed to fetch ${gitSpec.url}: ${err instanceof Error ? err.message : err}`);
|
|
115
|
-
return 1;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
119
|
-
source = resolve(args.target);
|
|
120
|
-
}
|
|
121
|
-
try {
|
|
122
|
-
return await installResolved(args, source, destDir);
|
|
123
|
-
}
|
|
124
|
-
finally {
|
|
125
|
-
cleanup();
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
async function installResolved(args, source, destDir) {
|
|
129
|
-
const result = await validateExtension(source);
|
|
130
|
-
printValidation(result);
|
|
131
|
-
if (!result.ok) {
|
|
132
|
-
console.error("Refusing to install: fix the errors above.");
|
|
133
|
-
return 1;
|
|
134
|
-
}
|
|
135
|
-
// Install into a named subdirectory so the slug never degenerates to the
|
|
136
|
-
// scope name. A bare file installs as <name>.<ext>; a directory as <name>/.
|
|
137
|
-
const destName = basename(source);
|
|
138
|
-
const dest = join(destDir, destName);
|
|
139
|
-
mkdirSync(destDir, { recursive: true });
|
|
140
|
-
// Reinstalling over an existing install is how updates work: replace it.
|
|
141
|
-
const replaced = existsSync(dest);
|
|
142
|
-
if (replaced)
|
|
143
|
-
rmSync(dest, { recursive: true, force: true });
|
|
144
|
-
cpSync(source, dest, { recursive: true });
|
|
145
|
-
const scopeLabel = args.scope === "global" ? "all conversations" : `conversation ${args.conversationId}`;
|
|
146
|
-
const dataDir = args.scope === "global"
|
|
147
|
-
? join(args.stateDir, "global", "extension-data", result.slug)
|
|
148
|
-
: join(args.stateDir, "conversations", args.conversationId, "extension-data", result.slug);
|
|
149
|
-
const verb = replaced ? "Reinstalled" : "Installed";
|
|
150
|
-
console.log(`\n${verb} ${result.name} (slug: ${result.slug}) for ${scopeLabel}.`);
|
|
151
|
-
console.log(` code: ${dest}`);
|
|
152
|
-
console.log(` data: ${dataDir} (created on first use, preserved on reinstall)`);
|
|
153
|
-
console.log("Run /pi-new in the conversation to activate.");
|
|
154
|
-
return 0;
|
|
155
|
-
}
|
|
156
|
-
function listAction(args) {
|
|
157
|
-
// List the requested scope, or both when no conversation is given.
|
|
158
|
-
const dirs = args.conversationId
|
|
159
|
-
? defaultExtensionDirs(args.conversationId, args.stateDir)
|
|
160
|
-
: [join(args.stateDir, "global", "extensions")];
|
|
161
|
-
const installed = listInstalledExtensions(dirs);
|
|
162
|
-
if (installed.length === 0) {
|
|
163
|
-
console.log("No extensions installed.");
|
|
164
|
-
return 0;
|
|
165
|
-
}
|
|
166
|
-
for (const info of installed) {
|
|
167
|
-
const scope = basename(resolve(info.dir, "..")) === "global" ? "global" : "conversation";
|
|
168
|
-
const version = info.version ? `@${info.version}` : "";
|
|
169
|
-
console.log(`${info.name}${version} [${scope}] slug=${info.slug}`);
|
|
170
|
-
if (info.description)
|
|
171
|
-
console.log(` ${info.description}`);
|
|
172
|
-
if (info.skillNames.length > 0)
|
|
173
|
-
console.log(` skills: ${info.skillNames.join(", ")}`);
|
|
174
|
-
}
|
|
175
|
-
return 0;
|
|
176
|
-
}
|
|
177
|
-
function removeAction(args) {
|
|
178
|
-
if (!args.target) {
|
|
179
|
-
console.error("ext remove: missing <slug>");
|
|
180
|
-
return 1;
|
|
181
|
-
}
|
|
182
|
-
let destDir;
|
|
183
|
-
try {
|
|
184
|
-
destDir = scopeExtensionsDir(args);
|
|
185
|
-
}
|
|
186
|
-
catch (err) {
|
|
187
|
-
console.error(err instanceof Error ? err.message : String(err));
|
|
188
|
-
return 1;
|
|
189
|
-
}
|
|
190
|
-
// Match by installed slug so the caller doesn't need the exact dir name.
|
|
191
|
-
const match = listInstalledExtensions([destDir]).find((info) => info.slug === args.target);
|
|
192
|
-
if (!match) {
|
|
193
|
-
console.error(`No extension with slug '${args.target}' in ${destDir}`);
|
|
194
|
-
return 1;
|
|
195
|
-
}
|
|
196
|
-
// match.path is the entrypoint. Dir-form: its parent is the extension dir to
|
|
197
|
-
// remove. Bare-file: the parent is the scan dir, so remove the file itself.
|
|
198
|
-
const parent = resolve(match.path, "..");
|
|
199
|
-
const removeTarget = parent === resolve(destDir) ? match.path : parent;
|
|
200
|
-
rmSync(removeTarget, { recursive: true, force: true });
|
|
201
|
-
console.log(`Removed ${match.name} (slug: ${match.slug}). Data left in place.`);
|
|
202
|
-
console.log("Run /pi-new in the conversation to apply.");
|
|
203
|
-
return 0;
|
|
204
|
-
}
|
|
205
|
-
function printValidation(result) {
|
|
206
|
-
console.log(`${result.name}${result.version ? `@${result.version}` : ""} (slug: ${result.slug})`);
|
|
207
|
-
if (result.entrypoint)
|
|
208
|
-
console.log(` entrypoint: ${result.entrypoint}`);
|
|
209
|
-
if (result.skillNames.length > 0)
|
|
210
|
-
console.log(` skills: ${result.skillNames.join(", ")}`);
|
|
211
|
-
for (const warning of result.warnings)
|
|
212
|
-
console.log(` warning: ${warning}`);
|
|
213
|
-
for (const error of result.errors)
|
|
214
|
-
console.error(` error: ${error}`);
|
|
215
|
-
console.log(result.ok ? " ✓ valid" : " ✗ invalid");
|
|
216
|
-
}
|
|
217
|
-
//# sourceMappingURL=ext.js.map
|
package/dist/cli/ext.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ext.js","sourceRoot":"","sources":["../../src/cli/ext.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `mikan ext` — manage extensions from the CLI.\n *\n * mikan ext install <source> [--global | --conversation <id>] [--state-dir <dir>]\n * mikan ext validate <path>\n * mikan ext list [--conversation <id>] [--state-dir <dir>]\n * mikan ext remove <slug> (--global | --conversation <id>) [--state-dir <dir>]\n *\n * `<source>` is a local path or a git URL (https://…, git@…, or github:owner/repo)\n * with an optional `#subpath` for extensions inside a repo. Reinstalling over an\n * existing extension updates it (data is preserved). Extensions install into the\n * host-only state dir (never the workspace); see src/harness/extensions/LAYOUT.md.\n */\nimport { cpSync, existsSync, mkdirSync, rmSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, join, resolve } from \"node:path\";\nimport {\n defaultExtensionDirs,\n listInstalledExtensions,\n validateExtension,\n} from \"../harness/index.js\";\nimport { parseGitSource, resolveGitSource } from \"./ext-git.js\";\n\ninterface ExtArgs {\n action?: string;\n target?: string;\n stateDir: string;\n scope: \"global\" | \"conversation\" | undefined;\n conversationId?: string;\n}\n\nfunction parseExtArgs(argv: string[]): ExtArgs {\n let stateDir = join(homedir(), \".mikan\");\n let scope: ExtArgs[\"scope\"];\n let conversationId: string | undefined;\n const positional: string[] = [];\n\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n if (arg === \"--global\") scope = \"global\";\n else if (arg === \"--conversation\") {\n scope = \"conversation\";\n conversationId = argv[++i];\n } else if (arg.startsWith(\"--conversation=\")) {\n scope = \"conversation\";\n conversationId = arg.slice(\"--conversation=\".length);\n } else if (arg === \"--state-dir\") stateDir = resolve(argv[++i] ?? \"\");\n else if (arg.startsWith(\"--state-dir=\")) stateDir = resolve(arg.slice(\"--state-dir=\".length));\n else positional.push(arg);\n }\n\n return { action: positional[0], target: positional[1], stateDir, scope, conversationId };\n}\n\n/** Directory that extension CODE for the chosen scope lives in. */\nfunction scopeExtensionsDir(args: ExtArgs): string {\n if (args.scope === \"global\") return join(args.stateDir, \"global\", \"extensions\");\n if (args.scope === \"conversation\" && args.conversationId) {\n // defaultExtensionDirs returns [global, conversation]; take the conversation one.\n return defaultExtensionDirs(args.conversationId, args.stateDir)[1];\n }\n throw new Error(\"Specify a scope: --global or --conversation <id>\");\n}\n\nconst USAGE = `Usage:\n mikan ext install <source> (--global | --conversation <id>) [--state-dir <dir>]\n <source>: a local path, or a git URL / github:owner/repo with optional #subpath\n e.g. github:geminixiang/mikan#examples/extensions/agent-pm\n Reinstalling over an existing extension updates it (data preserved).\n mikan ext validate <path>\n mikan ext list [--conversation <id>] [--state-dir <dir>]\n mikan ext remove <slug> (--global | --conversation <id>) [--state-dir <dir>]`;\n\nfunction noop(): void {}\n\nexport async function runExtCommand(argv: string[]): Promise<number> {\n const args = parseExtArgs(argv);\n\n switch (args.action) {\n case \"validate\":\n return validateAction(args);\n case \"install\":\n return installAction(args);\n case \"list\":\n return listAction(args);\n case \"remove\":\n return removeAction(args);\n default:\n console.error(USAGE);\n return 1;\n }\n}\n\nasync function validateAction(args: ExtArgs): Promise<number> {\n if (!args.target) {\n console.error(\"ext validate: missing <path>\");\n return 1;\n }\n const result = await validateExtension(resolve(args.target));\n printValidation(result);\n return result.ok ? 0 : 1;\n}\n\nasync function installAction(args: ExtArgs): Promise<number> {\n if (!args.target) {\n console.error(\"ext install: missing <path>\");\n return 1;\n }\n let destDir: string;\n try {\n destDir = scopeExtensionsDir(args);\n } catch (err) {\n console.error(err instanceof Error ? err.message : String(err));\n return 1;\n }\n\n // Resolve the source: a git URL (optionally with #subpath) is cloned to a\n // temp dir; a local path is used directly.\n const gitSpec = parseGitSource(args.target);\n let source: string;\n let cleanup = noop;\n if (gitSpec) {\n try {\n const resolved = resolveGitSource(gitSpec);\n source = resolved.dir;\n cleanup = resolved.cleanup;\n } catch (err) {\n console.error(`Failed to fetch ${gitSpec.url}: ${err instanceof Error ? err.message : err}`);\n return 1;\n }\n } else {\n source = resolve(args.target);\n }\n\n try {\n return await installResolved(args, source, destDir);\n } finally {\n cleanup();\n }\n}\n\nasync function installResolved(args: ExtArgs, source: string, destDir: string): Promise<number> {\n const result = await validateExtension(source);\n printValidation(result);\n if (!result.ok) {\n console.error(\"Refusing to install: fix the errors above.\");\n return 1;\n }\n\n // Install into a named subdirectory so the slug never degenerates to the\n // scope name. A bare file installs as <name>.<ext>; a directory as <name>/.\n const destName = basename(source);\n const dest = join(destDir, destName);\n mkdirSync(destDir, { recursive: true });\n // Reinstalling over an existing install is how updates work: replace it.\n const replaced = existsSync(dest);\n if (replaced) rmSync(dest, { recursive: true, force: true });\n cpSync(source, dest, { recursive: true });\n\n const scopeLabel =\n args.scope === \"global\" ? \"all conversations\" : `conversation ${args.conversationId}`;\n const dataDir =\n args.scope === \"global\"\n ? join(args.stateDir, \"global\", \"extension-data\", result.slug)\n : join(args.stateDir, \"conversations\", args.conversationId!, \"extension-data\", result.slug);\n const verb = replaced ? \"Reinstalled\" : \"Installed\";\n console.log(`\\n${verb} ${result.name} (slug: ${result.slug}) for ${scopeLabel}.`);\n console.log(` code: ${dest}`);\n console.log(` data: ${dataDir} (created on first use, preserved on reinstall)`);\n console.log(\"Run /pi-new in the conversation to activate.\");\n return 0;\n}\n\nfunction listAction(args: ExtArgs): number {\n // List the requested scope, or both when no conversation is given.\n const dirs = args.conversationId\n ? defaultExtensionDirs(args.conversationId, args.stateDir)\n : [join(args.stateDir, \"global\", \"extensions\")];\n const installed = listInstalledExtensions(dirs);\n if (installed.length === 0) {\n console.log(\"No extensions installed.\");\n return 0;\n }\n for (const info of installed) {\n const scope = basename(resolve(info.dir, \"..\")) === \"global\" ? \"global\" : \"conversation\";\n const version = info.version ? `@${info.version}` : \"\";\n console.log(`${info.name}${version} [${scope}] slug=${info.slug}`);\n if (info.description) console.log(` ${info.description}`);\n if (info.skillNames.length > 0) console.log(` skills: ${info.skillNames.join(\", \")}`);\n }\n return 0;\n}\n\nfunction removeAction(args: ExtArgs): number {\n if (!args.target) {\n console.error(\"ext remove: missing <slug>\");\n return 1;\n }\n let destDir: string;\n try {\n destDir = scopeExtensionsDir(args);\n } catch (err) {\n console.error(err instanceof Error ? err.message : String(err));\n return 1;\n }\n // Match by installed slug so the caller doesn't need the exact dir name.\n const match = listInstalledExtensions([destDir]).find((info) => info.slug === args.target);\n if (!match) {\n console.error(`No extension with slug '${args.target}' in ${destDir}`);\n return 1;\n }\n // match.path is the entrypoint. Dir-form: its parent is the extension dir to\n // remove. Bare-file: the parent is the scan dir, so remove the file itself.\n const parent = resolve(match.path, \"..\");\n const removeTarget = parent === resolve(destDir) ? match.path : parent;\n rmSync(removeTarget, { recursive: true, force: true });\n console.log(`Removed ${match.name} (slug: ${match.slug}). Data left in place.`);\n console.log(\"Run /pi-new in the conversation to apply.\");\n return 0;\n}\n\nfunction printValidation(result: {\n ok: boolean;\n name: string;\n slug: string;\n version?: string;\n entrypoint?: string;\n skillNames: string[];\n errors: string[];\n warnings: string[];\n}): void {\n console.log(`${result.name}${result.version ? `@${result.version}` : \"\"} (slug: ${result.slug})`);\n if (result.entrypoint) console.log(` entrypoint: ${result.entrypoint}`);\n if (result.skillNames.length > 0) console.log(` skills: ${result.skillNames.join(\", \")}`);\n for (const warning of result.warnings) console.log(` warning: ${warning}`);\n for (const error of result.errors) console.error(` error: ${error}`);\n console.log(result.ok ? \" ✓ valid\" : \" ✗ invalid\");\n}\n"]}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { AgentTool } from "@earendil-works/pi-agent-core";
|
|
2
|
-
import type { GithubCheckSummary } from "../adapter.js";
|
|
3
|
-
declare const githubChecksSchema: import("@sinclair/typebox").TObject<{
|
|
4
|
-
branch: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
5
|
-
job_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
6
|
-
}>;
|
|
7
|
-
export interface GithubChecksFns {
|
|
8
|
-
getChecks: (branch?: string) => Promise<GithubCheckSummary[]>;
|
|
9
|
-
getJobLog: (jobId: number) => Promise<string>;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* The `github_checks` tool reads CI check runs (GitHub Actions and other
|
|
13
|
-
* check-reporting apps) for a branch or the conversation's PR head, and can
|
|
14
|
-
* fetch one job's log tail so the agent can diagnose failures and iterate.
|
|
15
|
-
* Read-only, host-side; wired per run and only for GitHub conversations.
|
|
16
|
-
*/
|
|
17
|
-
export declare function createGithubChecksTool(): {
|
|
18
|
-
tool: AgentTool<typeof githubChecksSchema>;
|
|
19
|
-
setGithubChecksFunction: (fns: GithubChecksFns | null) => void;
|
|
20
|
-
};
|
|
21
|
-
export {};
|
|
22
|
-
//# sourceMappingURL=github-checks.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"github-checks.d.ts","sourceRoot":"","sources":["../../src/tools/github-checks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAExD,QAAA,MAAM,kBAAkB;;;EAetB,CAAC;AAkBH,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAC9D,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAC/C;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,IAAI;IACxC,IAAI,EAAE,SAAS,CAAC,OAAO,kBAAkB,CAAC,CAAC;IAC3C,uBAAuB,EAAE,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI,KAAK,IAAI,CAAC;CAChE,CAmEA"}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { Type } from "@sinclair/typebox";
|
|
2
|
-
const githubChecksSchema = Type.Object({
|
|
3
|
-
branch: Type.Optional(Type.String({
|
|
4
|
-
description: "Branch whose CI checks to read (e.g. a pi/<name> branch you pushed). " +
|
|
5
|
-
"Omit in a pull-request conversation to read the PR head's checks.",
|
|
6
|
-
})),
|
|
7
|
-
job_id: Type.Optional(Type.Number({
|
|
8
|
-
description: "A check's job id from the summary output — returns that CI job's log " +
|
|
9
|
-
"(tail) instead of the summary, for diagnosing a failing check.",
|
|
10
|
-
})),
|
|
11
|
-
});
|
|
12
|
-
/** Conclusions that mean "this check did not pass and needs attention". */
|
|
13
|
-
const FAILING_CONCLUSIONS = new Set(["failure", "timed_out", "action_required", "cancelled"]);
|
|
14
|
-
function formatCheckLine(run) {
|
|
15
|
-
const state = run.status === "completed" ? (run.conclusion ?? "unknown") : run.status;
|
|
16
|
-
const marker = run.conclusion === null
|
|
17
|
-
? "…"
|
|
18
|
-
: FAILING_CONCLUSIONS.has(run.conclusion)
|
|
19
|
-
? "✗"
|
|
20
|
-
: run.conclusion === "success"
|
|
21
|
-
? "✓"
|
|
22
|
-
: "−";
|
|
23
|
-
return `${marker} ${run.name}: ${state} [job ${run.id}]${run.url ? ` (${run.url})` : ""}`;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* The `github_checks` tool reads CI check runs (GitHub Actions and other
|
|
27
|
-
* check-reporting apps) for a branch or the conversation's PR head, and can
|
|
28
|
-
* fetch one job's log tail so the agent can diagnose failures and iterate.
|
|
29
|
-
* Read-only, host-side; wired per run and only for GitHub conversations.
|
|
30
|
-
*/
|
|
31
|
-
export function createGithubChecksTool() {
|
|
32
|
-
let checksFns = null;
|
|
33
|
-
const tool = {
|
|
34
|
-
name: "github_checks",
|
|
35
|
-
label: "github_checks",
|
|
36
|
-
description: "Read CI status (check runs) for a branch you pushed with github_pr, or for this " +
|
|
37
|
-
"conversation's pull request when branch is omitted. Pass job_id (from the summary) " +
|
|
38
|
-
"to fetch that job's log and diagnose a failing check. Re-run while checks are in " +
|
|
39
|
-
"progress. Only available in GitHub conversations.",
|
|
40
|
-
parameters: githubChecksSchema,
|
|
41
|
-
execute: async (_toolCallId, args, signal) => {
|
|
42
|
-
if (!checksFns) {
|
|
43
|
-
throw new Error("github_checks is only available in GitHub conversations.");
|
|
44
|
-
}
|
|
45
|
-
if (signal?.aborted) {
|
|
46
|
-
throw new Error("Operation aborted");
|
|
47
|
-
}
|
|
48
|
-
if (args.job_id !== undefined) {
|
|
49
|
-
const logText = await checksFns.getJobLog(args.job_id);
|
|
50
|
-
return {
|
|
51
|
-
content: [{ type: "text", text: logText || "(empty log)" }],
|
|
52
|
-
details: undefined,
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
const runs = await checksFns.getChecks(args.branch);
|
|
56
|
-
if (runs.length === 0) {
|
|
57
|
-
return {
|
|
58
|
-
content: [
|
|
59
|
-
{
|
|
60
|
-
type: "text",
|
|
61
|
-
text: "No check runs found — CI may not have started yet; try again shortly.",
|
|
62
|
-
},
|
|
63
|
-
],
|
|
64
|
-
details: undefined,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
const completed = runs.filter((run) => run.status === "completed");
|
|
68
|
-
const failing = completed.filter((run) => run.conclusion !== null && FAILING_CONCLUSIONS.has(run.conclusion));
|
|
69
|
-
const summary = `${runs.length} check(s): ${completed.length} completed, ${runs.length - completed.length} running, ${failing.length} failing`;
|
|
70
|
-
return {
|
|
71
|
-
content: [
|
|
72
|
-
{
|
|
73
|
-
type: "text",
|
|
74
|
-
text: [summary, ...runs.map(formatCheckLine)].join("\n"),
|
|
75
|
-
},
|
|
76
|
-
],
|
|
77
|
-
details: undefined,
|
|
78
|
-
};
|
|
79
|
-
},
|
|
80
|
-
};
|
|
81
|
-
return {
|
|
82
|
-
tool,
|
|
83
|
-
setGithubChecksFunction: (fns) => {
|
|
84
|
-
checksFns = fns;
|
|
85
|
-
},
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
//# sourceMappingURL=github-checks.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"github-checks.js","sourceRoot":"","sources":["../../src/tools/github-checks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAGzC,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM,CAAC;IACrC,MAAM,EAAE,IAAI,CAAC,QAAQ,CACnB,IAAI,CAAC,MAAM,CAAC;QACV,WAAW,EACT,uEAAuE;YACvE,mEAAmE;KACtE,CAAC,CACH;IACD,MAAM,EAAE,IAAI,CAAC,QAAQ,CACnB,IAAI,CAAC,MAAM,CAAC;QACV,WAAW,EACT,uEAAuE;YACvE,gEAAgE;KACnE,CAAC,CACH;CACF,CAAC,CAAC;AAEH,2EAA2E;AAC3E,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,WAAW,EAAE,iBAAiB,EAAE,WAAW,CAAC,CAAC,CAAC;AAE9F,SAAS,eAAe,CAAC,GAAuB;IAC9C,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;IACtF,MAAM,MAAM,GACV,GAAG,CAAC,UAAU,KAAK,IAAI;QACrB,CAAC,CAAC,GAAG;QACL,CAAC,CAAC,mBAAmB,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC;YACvC,CAAC,CAAC,GAAG;YACL,CAAC,CAAC,GAAG,CAAC,UAAU,KAAK,SAAS;gBAC5B,CAAC,CAAC,GAAG;gBACL,CAAC,CAAC,GAAG,CAAC;IACd,OAAO,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,KAAK,KAAK,SAAS,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AAC5F,CAAC;AAOD;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB;IAIpC,IAAI,SAAS,GAA2B,IAAI,CAAC;IAE7C,MAAM,IAAI,GAAyC;QACjD,IAAI,EAAE,eAAe;QACrB,KAAK,EAAE,eAAe;QACtB,WAAW,EACT,kFAAkF;YAClF,qFAAqF;YACrF,mFAAmF;YACnF,mDAAmD;QACrD,UAAU,EAAE,kBAAkB;QAC9B,OAAO,EAAE,KAAK,EACZ,WAAmB,EACnB,IAA0C,EAC1C,MAAoB,EACpB,EAAE;YACF,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;YAC9E,CAAC;YACD,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;gBACpB,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACvC,CAAC;YAED,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC9B,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACvD,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,OAAO,IAAI,aAAa,EAAE,CAAC;oBACpE,OAAO,EAAE,SAAS;iBACnB,CAAC;YACJ,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACpD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACtB,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAe;4BACrB,IAAI,EAAE,uEAAuE;yBAC9E;qBACF;oBACD,OAAO,EAAE,SAAS;iBACnB,CAAC;YACJ,CAAC;YACD,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC;YACnE,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAC9B,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,KAAK,IAAI,IAAI,mBAAmB,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAC5E,CAAC;YACF,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,MAAM,cAAc,SAAS,CAAC,MAAM,eAAe,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,aAAa,OAAO,CAAC,MAAM,UAAU,CAAC;YAC/I,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;qBACzD;iBACF;gBACD,OAAO,EAAE,SAAS;aACnB,CAAC;QACJ,CAAC;KACF,CAAC;IAEF,OAAO;QACL,IAAI;QACJ,uBAAuB,EAAE,CAAC,GAAG,EAAE,EAAE;YAC/B,SAAS,GAAG,GAAG,CAAC;QAClB,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { Type } from \"@sinclair/typebox\";\nimport type { GithubCheckSummary } from \"../adapter.js\";\n\nconst githubChecksSchema = Type.Object({\n branch: Type.Optional(\n Type.String({\n description:\n \"Branch whose CI checks to read (e.g. a pi/<name> branch you pushed). \" +\n \"Omit in a pull-request conversation to read the PR head's checks.\",\n }),\n ),\n job_id: Type.Optional(\n Type.Number({\n description:\n \"A check's job id from the summary output — returns that CI job's log \" +\n \"(tail) instead of the summary, for diagnosing a failing check.\",\n }),\n ),\n});\n\n/** Conclusions that mean \"this check did not pass and needs attention\". */\nconst FAILING_CONCLUSIONS = new Set([\"failure\", \"timed_out\", \"action_required\", \"cancelled\"]);\n\nfunction formatCheckLine(run: GithubCheckSummary): string {\n const state = run.status === \"completed\" ? (run.conclusion ?? \"unknown\") : run.status;\n const marker =\n run.conclusion === null\n ? \"…\"\n : FAILING_CONCLUSIONS.has(run.conclusion)\n ? \"✗\"\n : run.conclusion === \"success\"\n ? \"✓\"\n : \"−\";\n return `${marker} ${run.name}: ${state} [job ${run.id}]${run.url ? ` (${run.url})` : \"\"}`;\n}\n\nexport interface GithubChecksFns {\n getChecks: (branch?: string) => Promise<GithubCheckSummary[]>;\n getJobLog: (jobId: number) => Promise<string>;\n}\n\n/**\n * The `github_checks` tool reads CI check runs (GitHub Actions and other\n * check-reporting apps) for a branch or the conversation's PR head, and can\n * fetch one job's log tail so the agent can diagnose failures and iterate.\n * Read-only, host-side; wired per run and only for GitHub conversations.\n */\nexport function createGithubChecksTool(): {\n tool: AgentTool<typeof githubChecksSchema>;\n setGithubChecksFunction: (fns: GithubChecksFns | null) => void;\n} {\n let checksFns: GithubChecksFns | null = null;\n\n const tool: AgentTool<typeof githubChecksSchema> = {\n name: \"github_checks\",\n label: \"github_checks\",\n description:\n \"Read CI status (check runs) for a branch you pushed with github_pr, or for this \" +\n \"conversation's pull request when branch is omitted. Pass job_id (from the summary) \" +\n \"to fetch that job's log and diagnose a failing check. Re-run while checks are in \" +\n \"progress. Only available in GitHub conversations.\",\n parameters: githubChecksSchema,\n execute: async (\n _toolCallId: string,\n args: { branch?: string; job_id?: number },\n signal?: AbortSignal,\n ) => {\n if (!checksFns) {\n throw new Error(\"github_checks is only available in GitHub conversations.\");\n }\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n\n if (args.job_id !== undefined) {\n const logText = await checksFns.getJobLog(args.job_id);\n return {\n content: [{ type: \"text\" as const, text: logText || \"(empty log)\" }],\n details: undefined,\n };\n }\n\n const runs = await checksFns.getChecks(args.branch);\n if (runs.length === 0) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"No check runs found — CI may not have started yet; try again shortly.\",\n },\n ],\n details: undefined,\n };\n }\n const completed = runs.filter((run) => run.status === \"completed\");\n const failing = completed.filter(\n (run) => run.conclusion !== null && FAILING_CONCLUSIONS.has(run.conclusion),\n );\n const summary = `${runs.length} check(s): ${completed.length} completed, ${runs.length - completed.length} running, ${failing.length} failing`;\n return {\n content: [\n {\n type: \"text\" as const,\n text: [summary, ...runs.map(formatCheckLine)].join(\"\\n\"),\n },\n ],\n details: undefined,\n };\n },\n };\n\n return {\n tool,\n setGithubChecksFunction: (fns) => {\n checksFns = fns;\n },\n };\n}\n"]}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { AgentTool } from "@earendil-works/pi-agent-core";
|
|
2
|
-
import type { GithubPrRequest, GithubPrResult } from "../adapter.js";
|
|
3
|
-
declare const githubPrSchema: import("@sinclair/typebox").TObject<{
|
|
4
|
-
branch: import("@sinclair/typebox").TString;
|
|
5
|
-
title: import("@sinclair/typebox").TString;
|
|
6
|
-
body: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
7
|
-
base: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
8
|
-
draft: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
9
|
-
}>;
|
|
10
|
-
/**
|
|
11
|
-
* The `github_pr` tool pushes a branch the agent prepared in the
|
|
12
|
-
* conversation's ./repo clone and opens a pull request as the GitHub App.
|
|
13
|
-
* The push and API calls run host-side with an ephemeral repo-scoped token;
|
|
14
|
-
* the sandbox never holds credentials. Wired per run via the setter, and only
|
|
15
|
-
* for GitHub conversations.
|
|
16
|
-
*/
|
|
17
|
-
export declare function createGithubPrTool(): {
|
|
18
|
-
tool: AgentTool<typeof githubPrSchema>;
|
|
19
|
-
setGithubPrFunction: (fn: ((request: GithubPrRequest) => Promise<GithubPrResult>) | null) => void;
|
|
20
|
-
};
|
|
21
|
-
export {};
|
|
22
|
-
//# sourceMappingURL=github-pr.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"github-pr.d.ts","sourceRoot":"","sources":["../../src/tools/github-pr.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAErE,QAAA,MAAM,cAAc;;;;;;EAWlB,CAAC;AAIH;;;;;;GAMG;AACH,wBAAgB,kBAAkB,IAAI;IACpC,IAAI,EAAE,SAAS,CAAC,OAAO,cAAc,CAAC,CAAC;IACvC,mBAAmB,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC;CACnG,CAuCA"}
|
package/dist/tools/github-pr.js
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { Type } from "@sinclair/typebox";
|
|
2
|
-
const githubPrSchema = Type.Object({
|
|
3
|
-
branch: Type.String({
|
|
4
|
-
description: 'Local branch inside ./repo to push. Must be named pi/<something> (e.g. "pi/fix-42"); the default branch is never pushable.',
|
|
5
|
-
}),
|
|
6
|
-
title: Type.String({ description: "Pull request title." }),
|
|
7
|
-
body: Type.Optional(Type.String({ description: "Pull request description (Markdown)." })),
|
|
8
|
-
base: Type.Optional(Type.String({ description: "Target branch; defaults to the repository's default branch." })),
|
|
9
|
-
draft: Type.Optional(Type.Boolean({ description: "Open as a draft pull request." })),
|
|
10
|
-
});
|
|
11
|
-
/**
|
|
12
|
-
* The `github_pr` tool pushes a branch the agent prepared in the
|
|
13
|
-
* conversation's ./repo clone and opens a pull request as the GitHub App.
|
|
14
|
-
* The push and API calls run host-side with an ephemeral repo-scoped token;
|
|
15
|
-
* the sandbox never holds credentials. Wired per run via the setter, and only
|
|
16
|
-
* for GitHub conversations.
|
|
17
|
-
*/
|
|
18
|
-
export function createGithubPrTool() {
|
|
19
|
-
let prFn = null;
|
|
20
|
-
const tool = {
|
|
21
|
-
name: "github_pr",
|
|
22
|
-
label: "github_pr",
|
|
23
|
-
description: "Push a pi/<name> branch you committed inside ./repo and open a GitHub pull request " +
|
|
24
|
-
"(or draft) for it. Only available in GitHub issue/PR conversations. You cannot push " +
|
|
25
|
-
"to the default branch and you cannot merge — humans review and merge the PR.",
|
|
26
|
-
parameters: githubPrSchema,
|
|
27
|
-
execute: async (_toolCallId, args, signal) => {
|
|
28
|
-
if (!prFn) {
|
|
29
|
-
throw new Error("github_pr is only available in GitHub conversations.");
|
|
30
|
-
}
|
|
31
|
-
if (signal?.aborted) {
|
|
32
|
-
throw new Error("Operation aborted");
|
|
33
|
-
}
|
|
34
|
-
const result = await prFn(args);
|
|
35
|
-
return {
|
|
36
|
-
content: [
|
|
37
|
-
{
|
|
38
|
-
type: "text",
|
|
39
|
-
text: result.updatedExisting
|
|
40
|
-
? `Pushed to existing PR #${result.number}: ${result.url}`
|
|
41
|
-
: `Opened ${args.draft ? "draft " : ""}PR #${result.number}: ${result.url}`,
|
|
42
|
-
},
|
|
43
|
-
],
|
|
44
|
-
details: undefined,
|
|
45
|
-
};
|
|
46
|
-
},
|
|
47
|
-
};
|
|
48
|
-
return {
|
|
49
|
-
tool,
|
|
50
|
-
setGithubPrFunction: (fn) => {
|
|
51
|
-
prFn = fn;
|
|
52
|
-
},
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
//# sourceMappingURL=github-pr.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"github-pr.js","sourceRoot":"","sources":["../../src/tools/github-pr.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAGzC,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC;IACjC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;QAClB,WAAW,EACT,4HAA4H;KAC/H,CAAC;IACF,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,qBAAqB,EAAE,CAAC;IAC1D,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,sCAAsC,EAAE,CAAC,CAAC;IACzF,IAAI,EAAE,IAAI,CAAC,QAAQ,CACjB,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,6DAA6D,EAAE,CAAC,CAC5F;IACD,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,+BAA+B,EAAE,CAAC,CAAC;CACrF,CAAC,CAAC;AAIH;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB;IAIhC,IAAI,IAAI,GAAmE,IAAI,CAAC;IAEhF,MAAM,IAAI,GAAqC;QAC7C,IAAI,EAAE,WAAW;QACjB,KAAK,EAAE,WAAW;QAClB,WAAW,EACT,qFAAqF;YACrF,sFAAsF;YACtF,8EAA8E;QAChF,UAAU,EAAE,cAAc;QAC1B,OAAO,EAAE,KAAK,EAAE,WAAmB,EAAE,IAAkB,EAAE,MAAoB,EAAE,EAAE;YAC/E,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;YAC1E,CAAC;YACD,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;gBACpB,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACvC,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;YAChC,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,MAAM,CAAC,eAAe;4BAC1B,CAAC,CAAC,0BAA0B,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,GAAG,EAAE;4BAC1D,CAAC,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,GAAG,EAAE;qBAC9E;iBACF;gBACD,OAAO,EAAE,SAAS;aACnB,CAAC;QACJ,CAAC;KACF,CAAC;IAEF,OAAO;QACL,IAAI;QACJ,mBAAmB,EAAE,CAAC,EAAE,EAAE,EAAE;YAC1B,IAAI,GAAG,EAAE,CAAC;QACZ,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { Type } from \"@sinclair/typebox\";\nimport type { GithubPrRequest, GithubPrResult } from \"../adapter.js\";\n\nconst githubPrSchema = Type.Object({\n branch: Type.String({\n description:\n 'Local branch inside ./repo to push. Must be named pi/<something> (e.g. \"pi/fix-42\"); the default branch is never pushable.',\n }),\n title: Type.String({ description: \"Pull request title.\" }),\n body: Type.Optional(Type.String({ description: \"Pull request description (Markdown).\" })),\n base: Type.Optional(\n Type.String({ description: \"Target branch; defaults to the repository's default branch.\" }),\n ),\n draft: Type.Optional(Type.Boolean({ description: \"Open as a draft pull request.\" })),\n});\n\ntype GithubPrArgs = GithubPrRequest;\n\n/**\n * The `github_pr` tool pushes a branch the agent prepared in the\n * conversation's ./repo clone and opens a pull request as the GitHub App.\n * The push and API calls run host-side with an ephemeral repo-scoped token;\n * the sandbox never holds credentials. Wired per run via the setter, and only\n * for GitHub conversations.\n */\nexport function createGithubPrTool(): {\n tool: AgentTool<typeof githubPrSchema>;\n setGithubPrFunction: (fn: ((request: GithubPrRequest) => Promise<GithubPrResult>) | null) => void;\n} {\n let prFn: ((request: GithubPrRequest) => Promise<GithubPrResult>) | null = null;\n\n const tool: AgentTool<typeof githubPrSchema> = {\n name: \"github_pr\",\n label: \"github_pr\",\n description:\n \"Push a pi/<name> branch you committed inside ./repo and open a GitHub pull request \" +\n \"(or draft) for it. Only available in GitHub issue/PR conversations. You cannot push \" +\n \"to the default branch and you cannot merge — humans review and merge the PR.\",\n parameters: githubPrSchema,\n execute: async (_toolCallId: string, args: GithubPrArgs, signal?: AbortSignal) => {\n if (!prFn) {\n throw new Error(\"github_pr is only available in GitHub conversations.\");\n }\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n const result = await prFn(args);\n return {\n content: [\n {\n type: \"text\" as const,\n text: result.updatedExisting\n ? `Pushed to existing PR #${result.number}: ${result.url}`\n : `Opened ${args.draft ? \"draft \" : \"\"}PR #${result.number}: ${result.url}`,\n },\n ],\n details: undefined,\n };\n },\n };\n\n return {\n tool,\n setGithubPrFunction: (fn) => {\n prFn = fn;\n },\n };\n}\n"]}
|
package/dist/tools/react.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { AgentTool } from "@earendil-works/pi-agent-core";
|
|
2
|
-
declare const reactSchema: import("@sinclair/typebox").TObject<{
|
|
3
|
-
emoji: import("@sinclair/typebox").TString;
|
|
4
|
-
}>;
|
|
5
|
-
/**
|
|
6
|
-
* The `react` tool adds an emoji reaction to the message that triggered the
|
|
7
|
-
* current run. The channel and message timestamp are captured per run via
|
|
8
|
-
* {@link createReactTool}'s setter; the model only supplies the emoji.
|
|
9
|
-
*/
|
|
10
|
-
export declare function createReactTool(): {
|
|
11
|
-
tool: AgentTool<typeof reactSchema>;
|
|
12
|
-
setReactFunction: (fn: ((emoji: string) => Promise<void>) | null) => void;
|
|
13
|
-
};
|
|
14
|
-
export {};
|
|
15
|
-
//# sourceMappingURL=react.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../src/tools/react.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAG/D,QAAA,MAAM,WAAW;;EAKf,CAAC;AAEH;;;;GAIG;AACH,wBAAgB,eAAe,IAAI;IACjC,IAAI,EAAE,SAAS,CAAC,OAAO,WAAW,CAAC,CAAC;IACpC,gBAAgB,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC;CAC3E,CA8BA"}
|
package/dist/tools/react.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { Type } from "@sinclair/typebox";
|
|
2
|
-
const reactSchema = Type.Object({
|
|
3
|
-
emoji: Type.String({
|
|
4
|
-
description: "Emoji to react with. Use a short name without colons (e.g. eyes, white_check_mark, +1) on Slack, or a Unicode emoji on Discord/Telegram.",
|
|
5
|
-
}),
|
|
6
|
-
});
|
|
7
|
-
/**
|
|
8
|
-
* The `react` tool adds an emoji reaction to the message that triggered the
|
|
9
|
-
* current run. The channel and message timestamp are captured per run via
|
|
10
|
-
* {@link createReactTool}'s setter; the model only supplies the emoji.
|
|
11
|
-
*/
|
|
12
|
-
export function createReactTool() {
|
|
13
|
-
let reactFn = null;
|
|
14
|
-
const tool = {
|
|
15
|
-
name: "react",
|
|
16
|
-
label: "react",
|
|
17
|
-
description: "Add an emoji reaction to the message you are responding to. Useful for a lightweight acknowledgement (e.g. eyes to show you saw a request, white_check_mark when done) instead of a full reply.",
|
|
18
|
-
parameters: reactSchema,
|
|
19
|
-
execute: async (_toolCallId, { emoji }, signal) => {
|
|
20
|
-
if (!reactFn) {
|
|
21
|
-
throw new Error("Reactions are not supported in this conversation.");
|
|
22
|
-
}
|
|
23
|
-
if (signal?.aborted) {
|
|
24
|
-
throw new Error("Operation aborted");
|
|
25
|
-
}
|
|
26
|
-
await reactFn(emoji);
|
|
27
|
-
return {
|
|
28
|
-
content: [{ type: "text", text: `Reacted with :${emoji.replace(/^:|:$/g, "")}:` }],
|
|
29
|
-
details: undefined,
|
|
30
|
-
};
|
|
31
|
-
},
|
|
32
|
-
};
|
|
33
|
-
return {
|
|
34
|
-
tool,
|
|
35
|
-
setReactFunction: (fn) => {
|
|
36
|
-
reactFn = fn;
|
|
37
|
-
},
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
//# sourceMappingURL=react.js.map
|
package/dist/tools/react.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"react.js","sourceRoot":"","sources":["../../src/tools/react.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC;IAC9B,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC;QACjB,WAAW,EACT,0IAA0I;KAC7I,CAAC;CACH,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,UAAU,eAAe;IAI7B,IAAI,OAAO,GAA8C,IAAI,CAAC;IAE9D,MAAM,IAAI,GAAkC;QAC1C,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,OAAO;QACd,WAAW,EACT,iMAAiM;QACnM,UAAU,EAAE,WAAW;QACvB,OAAO,EAAE,KAAK,EAAE,WAAmB,EAAE,EAAE,KAAK,EAAqB,EAAE,MAAoB,EAAE,EAAE;YACzF,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;YACvE,CAAC;YACD,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;gBACpB,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACvC,CAAC;YACD,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC;YACrB,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,iBAAiB,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC;gBAC3F,OAAO,EAAE,SAAS;aACnB,CAAC;QACJ,CAAC;KACF,CAAC;IAEF,OAAO;QACL,IAAI;QACJ,gBAAgB,EAAE,CAAC,EAAE,EAAE,EAAE;YACvB,OAAO,GAAG,EAAE,CAAC;QACf,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { Type } from \"@sinclair/typebox\";\n\nconst reactSchema = Type.Object({\n emoji: Type.String({\n description:\n \"Emoji to react with. Use a short name without colons (e.g. eyes, white_check_mark, +1) on Slack, or a Unicode emoji on Discord/Telegram.\",\n }),\n});\n\n/**\n * The `react` tool adds an emoji reaction to the message that triggered the\n * current run. The channel and message timestamp are captured per run via\n * {@link createReactTool}'s setter; the model only supplies the emoji.\n */\nexport function createReactTool(): {\n tool: AgentTool<typeof reactSchema>;\n setReactFunction: (fn: ((emoji: string) => Promise<void>) | null) => void;\n} {\n let reactFn: ((emoji: string) => Promise<void>) | null = null;\n\n const tool: AgentTool<typeof reactSchema> = {\n name: \"react\",\n label: \"react\",\n description:\n \"Add an emoji reaction to the message you are responding to. Useful for a lightweight acknowledgement (e.g. eyes to show you saw a request, white_check_mark when done) instead of a full reply.\",\n parameters: reactSchema,\n execute: async (_toolCallId: string, { emoji }: { emoji: string }, signal?: AbortSignal) => {\n if (!reactFn) {\n throw new Error(\"Reactions are not supported in this conversation.\");\n }\n if (signal?.aborted) {\n throw new Error(\"Operation aborted\");\n }\n await reactFn(emoji);\n return {\n content: [{ type: \"text\" as const, text: `Reacted with :${emoji.replace(/^:|:$/g, \"\")}:` }],\n details: undefined,\n };\n },\n };\n\n return {\n tool,\n setReactFunction: (fn) => {\n reactFn = fn;\n },\n };\n}\n"]}
|