allagents 1.10.0-next.1 → 1.11.0-next.1
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 +2 -2
- package/dist/index.js +263 -188
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ AllAgents keeps your AI tooling (skills, agents, hooks, MCP servers) in one work
|
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
14
|
# Create a workspace from a shared template
|
|
15
|
-
npx allagents
|
|
15
|
+
npx allagents init my-workspace --from myorg/templates/nodejs
|
|
16
16
|
cd my-workspace
|
|
17
17
|
|
|
18
18
|
# Install plugins
|
|
@@ -89,7 +89,7 @@ clients:
|
|
|
89
89
|
|
|
90
90
|
| Command | Description |
|
|
91
91
|
|---|---|
|
|
92
|
-
| `allagents
|
|
92
|
+
| `allagents init <path>` | Create a workspace (optionally `--from owner/repo`) |
|
|
93
93
|
| `allagents update` | Sync all plugins to workspace |
|
|
94
94
|
| `allagents plugin install <spec>` | Install a plugin |
|
|
95
95
|
| `allagents plugin uninstall <spec>` | Remove a plugin |
|
package/dist/index.js
CHANGED
|
@@ -29053,6 +29053,15 @@ var init_sync_state2 = __esm(() => {
|
|
|
29053
29053
|
// src/core/vscode-workspace.ts
|
|
29054
29054
|
import { createHash as createHash2 } from "node:crypto";
|
|
29055
29055
|
import { resolve as resolve9, basename as basename6, isAbsolute as isAbsolute3, relative as relative4 } from "node:path";
|
|
29056
|
+
function normalizeWorkspacePath(path) {
|
|
29057
|
+
return path.replace(/\\/g, "/");
|
|
29058
|
+
}
|
|
29059
|
+
function resolveFolderAbsolutePath(workspacePath, folderPath) {
|
|
29060
|
+
return (isAbsolute3(folderPath) ? folderPath : resolve9(workspacePath, folderPath)).replace(/\\/g, "/");
|
|
29061
|
+
}
|
|
29062
|
+
function resolveFolderDisplayPath(folderPath) {
|
|
29063
|
+
return normalizeWorkspacePath(folderPath);
|
|
29064
|
+
}
|
|
29056
29065
|
function buildPathPlaceholderMap(repositories, workspacePath) {
|
|
29057
29066
|
const map2 = new Map;
|
|
29058
29067
|
for (const repo of repositories) {
|
|
@@ -29093,8 +29102,8 @@ function generateVscodeWorkspace(input) {
|
|
|
29093
29102
|
folders.push({ path: "." });
|
|
29094
29103
|
seenPaths.add(resolve9(workspacePath, "."));
|
|
29095
29104
|
for (const repo of repositories) {
|
|
29096
|
-
const absolutePath =
|
|
29097
|
-
const entry = { path:
|
|
29105
|
+
const absolutePath = resolveFolderAbsolutePath(workspacePath, repo.path);
|
|
29106
|
+
const entry = { path: resolveFolderDisplayPath(repo.path) };
|
|
29098
29107
|
if (repo.name)
|
|
29099
29108
|
entry.name = repo.name;
|
|
29100
29109
|
folders.push(entry);
|
|
@@ -29103,9 +29112,9 @@ function generateVscodeWorkspace(input) {
|
|
|
29103
29112
|
if (resolvedTemplate && Array.isArray(resolvedTemplate.folders)) {
|
|
29104
29113
|
for (const folder of resolvedTemplate.folders) {
|
|
29105
29114
|
const rawPath = folder.path;
|
|
29106
|
-
const normalizedPath = (
|
|
29115
|
+
const normalizedPath = resolveFolderAbsolutePath(workspacePath, rawPath);
|
|
29107
29116
|
if (!seenPaths.has(normalizedPath)) {
|
|
29108
|
-
const entry = { path:
|
|
29117
|
+
const entry = { path: resolveFolderDisplayPath(rawPath) };
|
|
29109
29118
|
if (folder.name)
|
|
29110
29119
|
entry.name = folder.name;
|
|
29111
29120
|
folders.push(entry);
|
|
@@ -34698,6 +34707,182 @@ var init_skills = __esm(() => {
|
|
|
34698
34707
|
init_skill();
|
|
34699
34708
|
});
|
|
34700
34709
|
|
|
34710
|
+
// src/core/skill-search.ts
|
|
34711
|
+
function validateSkillSearchArgs(query, options2) {
|
|
34712
|
+
if (query.trim().length < 2) {
|
|
34713
|
+
throw new SkillSearchError("Search query must be at least 2 characters.", "validation");
|
|
34714
|
+
}
|
|
34715
|
+
if (options2.page !== undefined && options2.page < 1) {
|
|
34716
|
+
throw new SkillSearchError("--page must be >= 1.", "validation");
|
|
34717
|
+
}
|
|
34718
|
+
if (options2.limit !== undefined && (options2.limit < 1 || options2.limit > 100)) {
|
|
34719
|
+
throw new SkillSearchError("--limit must be between 1 and 100.", "validation");
|
|
34720
|
+
}
|
|
34721
|
+
if (options2.owner !== undefined && !OWNER_REGEX.test(options2.owner)) {
|
|
34722
|
+
throw new SkillSearchError(`Invalid --owner "${options2.owner}": GitHub owners are alphanumeric + dashes, ≤ 39 chars.`, "validation");
|
|
34723
|
+
}
|
|
34724
|
+
}
|
|
34725
|
+
function couldBeOwner(query) {
|
|
34726
|
+
return COULD_BE_OWNER_REGEX.test(query);
|
|
34727
|
+
}
|
|
34728
|
+
function buildSearchQueries(query, owner) {
|
|
34729
|
+
const trimmed2 = query.trim();
|
|
34730
|
+
const pathTerm = trimmed2.replace(/ /g, "-");
|
|
34731
|
+
const userClause = owner ? `user:${owner}` : "";
|
|
34732
|
+
const join26 = (...parts) => parts.filter(Boolean).join(" ");
|
|
34733
|
+
const queries = [
|
|
34734
|
+
{ priority: 1, label: "path", q: join26("filename:SKILL.md", `in:path ${pathTerm}`, userClause) }
|
|
34735
|
+
];
|
|
34736
|
+
if (pathTerm !== trimmed2) {
|
|
34737
|
+
queries.push({ priority: 2, label: "hyphen", q: join26("filename:SKILL.md", pathTerm, userClause) });
|
|
34738
|
+
}
|
|
34739
|
+
if (!owner && couldBeOwner(trimmed2)) {
|
|
34740
|
+
queries.push({ priority: 3, label: "owner", q: `filename:SKILL.md user:${trimmed2}` });
|
|
34741
|
+
}
|
|
34742
|
+
queries.push({ priority: 4, label: "primary", q: join26("filename:SKILL.md", trimmed2, userClause) });
|
|
34743
|
+
return queries;
|
|
34744
|
+
}
|
|
34745
|
+
function classifyApiError(status, body) {
|
|
34746
|
+
const msg = typeof body === "object" && body !== null && "message" in body ? String(body.message ?? "") : "";
|
|
34747
|
+
if (status === 403 && /rate limit/i.test(msg)) {
|
|
34748
|
+
return new SkillSearchError("GitHub Code Search rate limit exceeded. Authenticate with `gh auth login` or set GITHUB_TOKEN to raise the quota.", "rate-limit");
|
|
34749
|
+
}
|
|
34750
|
+
if (status === 422) {
|
|
34751
|
+
return new SkillSearchError(`GitHub rejected the search query: ${msg || "unprocessable entity"}.`, "api");
|
|
34752
|
+
}
|
|
34753
|
+
return new SkillSearchError(`GitHub Code Search returned ${status}${msg ? `: ${msg}` : ""}.`, "api");
|
|
34754
|
+
}
|
|
34755
|
+
function qualifiedName(item) {
|
|
34756
|
+
return item.namespace ? `${item.namespace}/${item.name}` : item.name;
|
|
34757
|
+
}
|
|
34758
|
+
function parseSkillPath(path, repoFallback) {
|
|
34759
|
+
const parts = path.split("/").filter(Boolean);
|
|
34760
|
+
const skillsIdx = parts.lastIndexOf("skills");
|
|
34761
|
+
if (skillsIdx !== -1) {
|
|
34762
|
+
const afterSkills = parts.slice(skillsIdx + 1);
|
|
34763
|
+
const meaningful = afterSkills[afterSkills.length - 1] === "SKILL.md" ? afterSkills.slice(0, -1) : afterSkills;
|
|
34764
|
+
if (meaningful.length >= 2) {
|
|
34765
|
+
const namespace = meaningful[0] ?? "";
|
|
34766
|
+
const name = meaningful[1] ?? "";
|
|
34767
|
+
if (namespace && name)
|
|
34768
|
+
return { namespace, name };
|
|
34769
|
+
}
|
|
34770
|
+
if (meaningful.length === 1 && meaningful[0]) {
|
|
34771
|
+
return { namespace: "", name: meaningful[0] };
|
|
34772
|
+
}
|
|
34773
|
+
}
|
|
34774
|
+
if (parts.length >= 2) {
|
|
34775
|
+
const parent = parts[parts.length - 2];
|
|
34776
|
+
if (parent)
|
|
34777
|
+
return { namespace: "", name: parent };
|
|
34778
|
+
}
|
|
34779
|
+
return { namespace: "", name: repoFallback };
|
|
34780
|
+
}
|
|
34781
|
+
async function runOneQuery(q3, page, limit, token, fetchFn) {
|
|
34782
|
+
const url = new URL("https://api.github.com/search/code");
|
|
34783
|
+
url.searchParams.set("q", q3);
|
|
34784
|
+
url.searchParams.set("per_page", String(limit));
|
|
34785
|
+
url.searchParams.set("page", String(page));
|
|
34786
|
+
const headers = {
|
|
34787
|
+
Accept: "application/vnd.github+json",
|
|
34788
|
+
"X-GitHub-Api-Version": "2022-11-28",
|
|
34789
|
+
"User-Agent": "allagents-cli"
|
|
34790
|
+
};
|
|
34791
|
+
if (token)
|
|
34792
|
+
headers.Authorization = `token ${token}`;
|
|
34793
|
+
const response = await fetchFn(url.toString(), { headers });
|
|
34794
|
+
let body = null;
|
|
34795
|
+
try {
|
|
34796
|
+
body = await response.json();
|
|
34797
|
+
} catch {}
|
|
34798
|
+
if (!response.ok) {
|
|
34799
|
+
throw classifyApiError(response.status, body);
|
|
34800
|
+
}
|
|
34801
|
+
const parsed = body;
|
|
34802
|
+
const items = (parsed.items ?? []).map((item) => {
|
|
34803
|
+
const path = item.path ?? "";
|
|
34804
|
+
const repo = item.repository?.full_name ?? "";
|
|
34805
|
+
const repoFallback = repo.split("/").pop() ?? "";
|
|
34806
|
+
const { namespace, name } = parseSkillPath(path, repoFallback);
|
|
34807
|
+
return {
|
|
34808
|
+
name,
|
|
34809
|
+
namespace,
|
|
34810
|
+
repo,
|
|
34811
|
+
path,
|
|
34812
|
+
description: item.repository?.description ?? "",
|
|
34813
|
+
sha: item.sha ?? ""
|
|
34814
|
+
};
|
|
34815
|
+
});
|
|
34816
|
+
return {
|
|
34817
|
+
items,
|
|
34818
|
+
total: parsed.total_count ?? items.length,
|
|
34819
|
+
truncated: Boolean(parsed.incomplete_results)
|
|
34820
|
+
};
|
|
34821
|
+
}
|
|
34822
|
+
async function searchSkills(query, options2 = {}, deps = {}) {
|
|
34823
|
+
validateSkillSearchArgs(query, options2);
|
|
34824
|
+
const fetchFn = deps.fetch ?? fetch;
|
|
34825
|
+
const logger = deps.logger ?? ((msg) => process.stderr.write(`${msg}
|
|
34826
|
+
`));
|
|
34827
|
+
const page = options2.page ?? 1;
|
|
34828
|
+
const limit = options2.limit ?? 30;
|
|
34829
|
+
const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
|
|
34830
|
+
const queries = buildSearchQueries(query, options2.owner);
|
|
34831
|
+
const settled = await Promise.allSettled(queries.map((entry) => runOneQuery(entry.q, page, limit, token, fetchFn)));
|
|
34832
|
+
const primaryIdx = queries.findIndex((q3) => q3.priority === 4);
|
|
34833
|
+
const primarySettled = settled[primaryIdx];
|
|
34834
|
+
if (primarySettled?.status === "rejected") {
|
|
34835
|
+
throw primarySettled.reason;
|
|
34836
|
+
}
|
|
34837
|
+
const buckets = [];
|
|
34838
|
+
for (let i2 = 0;i2 < queries.length; i2++) {
|
|
34839
|
+
const entry = queries[i2];
|
|
34840
|
+
const outcome = settled[i2];
|
|
34841
|
+
if (!entry || !outcome)
|
|
34842
|
+
continue;
|
|
34843
|
+
if (outcome.status === "fulfilled") {
|
|
34844
|
+
buckets.push({ priority: entry.priority, result: outcome.value });
|
|
34845
|
+
} else {
|
|
34846
|
+
const reason = outcome.reason instanceof Error ? outcome.reason.message : String(outcome.reason);
|
|
34847
|
+
logger(`Warning: skill search "${entry.label}" query failed: ${reason}`);
|
|
34848
|
+
}
|
|
34849
|
+
}
|
|
34850
|
+
buckets.sort((a, b) => a.priority - b.priority);
|
|
34851
|
+
const mergedItems = buckets.flatMap((b) => b.result.items);
|
|
34852
|
+
const deduped = dedupeItems(mergedItems);
|
|
34853
|
+
return {
|
|
34854
|
+
query,
|
|
34855
|
+
items: deduped,
|
|
34856
|
+
total: deduped.length,
|
|
34857
|
+
truncated: buckets.some((b) => b.result.truncated)
|
|
34858
|
+
};
|
|
34859
|
+
}
|
|
34860
|
+
function dedupeItems(items) {
|
|
34861
|
+
const seen = new Set;
|
|
34862
|
+
const out = [];
|
|
34863
|
+
for (const item of items) {
|
|
34864
|
+
const key = `${item.repo}#${qualifiedName(item)}`;
|
|
34865
|
+
if (seen.has(key))
|
|
34866
|
+
continue;
|
|
34867
|
+
seen.add(key);
|
|
34868
|
+
out.push(item);
|
|
34869
|
+
}
|
|
34870
|
+
return out;
|
|
34871
|
+
}
|
|
34872
|
+
var OWNER_REGEX, COULD_BE_OWNER_REGEX, SkillSearchError;
|
|
34873
|
+
var init_skill_search = __esm(() => {
|
|
34874
|
+
OWNER_REGEX = /^[A-Za-z0-9-]{1,39}$/;
|
|
34875
|
+
COULD_BE_OWNER_REGEX = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,37}[a-zA-Z0-9])?$/;
|
|
34876
|
+
SkillSearchError = class SkillSearchError extends Error {
|
|
34877
|
+
kind;
|
|
34878
|
+
constructor(message, kind) {
|
|
34879
|
+
super(message);
|
|
34880
|
+
this.kind = kind;
|
|
34881
|
+
this.name = "SkillSearchError";
|
|
34882
|
+
}
|
|
34883
|
+
};
|
|
34884
|
+
});
|
|
34885
|
+
|
|
34701
34886
|
// node_modules/ajv/dist/compile/codegen/code.js
|
|
34702
34887
|
var require_code = __commonJS((exports) => {
|
|
34703
34888
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -41668,7 +41853,7 @@ var package_default;
|
|
|
41668
41853
|
var init_package = __esm(() => {
|
|
41669
41854
|
package_default = {
|
|
41670
41855
|
name: "allagents",
|
|
41671
|
-
version: "1.
|
|
41856
|
+
version: "1.11.0-next.1",
|
|
41672
41857
|
packageManager: "bun@1.3.12",
|
|
41673
41858
|
description: "CLI tool for managing multi-repo AI agent workspaces with plugin synchronization",
|
|
41674
41859
|
type: "module",
|
|
@@ -42956,6 +43141,7 @@ async function runSkills(context, cache2) {
|
|
|
42956
43141
|
options: [
|
|
42957
43142
|
{ label: "Toggle installed skills", value: "toggle" },
|
|
42958
43143
|
{ label: "Browse marketplace skills...", value: "browse" },
|
|
43144
|
+
{ label: "Search online...", value: "search" },
|
|
42959
43145
|
{ label: "Back", value: "back" }
|
|
42960
43146
|
]
|
|
42961
43147
|
});
|
|
@@ -42966,6 +43152,10 @@ async function runSkills(context, cache2) {
|
|
|
42966
43152
|
await runBrowseMarketplaceSkills(context, cache2);
|
|
42967
43153
|
continue;
|
|
42968
43154
|
}
|
|
43155
|
+
if (action === "search") {
|
|
43156
|
+
await runSearchOnlineSkills(context, cache2);
|
|
43157
|
+
continue;
|
|
43158
|
+
}
|
|
42969
43159
|
await runToggleSkills(skills, context, cache2);
|
|
42970
43160
|
return;
|
|
42971
43161
|
}
|
|
@@ -43122,7 +43312,60 @@ Use "Manage marketplaces" to add one first.`, "Skills");
|
|
|
43122
43312
|
await runBrowsePluginSkills(selected, scope, context, cache2);
|
|
43123
43313
|
}
|
|
43124
43314
|
}
|
|
43125
|
-
|
|
43315
|
+
async function runSearchOnlineSkills(context, cache2) {
|
|
43316
|
+
const query = await text3({
|
|
43317
|
+
message: "Search for skills on GitHub",
|
|
43318
|
+
placeholder: "e.g. commit, deploy, aws"
|
|
43319
|
+
});
|
|
43320
|
+
if (Ct(query) || !query || query.trim().length === 0) {
|
|
43321
|
+
return;
|
|
43322
|
+
}
|
|
43323
|
+
const s = Ie();
|
|
43324
|
+
s.start("Searching GitHub...");
|
|
43325
|
+
let items;
|
|
43326
|
+
try {
|
|
43327
|
+
const result = await searchSkills(query.trim());
|
|
43328
|
+
items = result.items;
|
|
43329
|
+
} catch (error2) {
|
|
43330
|
+
s.stop("Search failed");
|
|
43331
|
+
kt2(error2 instanceof Error ? error2.message : String(error2), "Search Error");
|
|
43332
|
+
return;
|
|
43333
|
+
}
|
|
43334
|
+
s.stop(`Found ${items.length} skill${items.length !== 1 ? "s" : ""}`);
|
|
43335
|
+
if (items.length === 0) {
|
|
43336
|
+
kt2(`No skills found for "${query.trim()}".`, "Search");
|
|
43337
|
+
return;
|
|
43338
|
+
}
|
|
43339
|
+
const options2 = items.map((item) => ({
|
|
43340
|
+
label: qualifiedName(item),
|
|
43341
|
+
value: item.repo,
|
|
43342
|
+
hint: item.repo + (item.description ? ` · ${item.description}` : "")
|
|
43343
|
+
}));
|
|
43344
|
+
options2.push({ label: "Back", value: "__back__" });
|
|
43345
|
+
const selected = await autocomplete2({
|
|
43346
|
+
message: `Results for "${query.trim()}"`,
|
|
43347
|
+
options: options2,
|
|
43348
|
+
placeholder: "Type to filter..."
|
|
43349
|
+
});
|
|
43350
|
+
if (Ct(selected) || selected === "__back__") {
|
|
43351
|
+
return;
|
|
43352
|
+
}
|
|
43353
|
+
const workspacePath = context.workspacePath ?? process.cwd();
|
|
43354
|
+
const isInstalledProject = context.workspacePath ? await hasPlugin(selected, workspacePath) : false;
|
|
43355
|
+
const isInstalledUser = await hasUserPlugin(selected);
|
|
43356
|
+
if (isInstalledProject || isInstalledUser) {
|
|
43357
|
+
const scope = isInstalledUser ? "user" : "project";
|
|
43358
|
+
await runBrowsePluginSkills(selected, scope, context, cache2);
|
|
43359
|
+
return;
|
|
43360
|
+
}
|
|
43361
|
+
const installed = await installSelectedPlugin(selected, context, cache2);
|
|
43362
|
+
if (installed) {
|
|
43363
|
+
const nowInstalledUser = await hasUserPlugin(selected);
|
|
43364
|
+
const scope = nowInstalledUser ? "user" : "project";
|
|
43365
|
+
await runBrowsePluginSkills(selected, scope, context, cache2);
|
|
43366
|
+
}
|
|
43367
|
+
}
|
|
43368
|
+
var multiselect2, select4, autocomplete2, text3;
|
|
43126
43369
|
var init_skills2 = __esm(() => {
|
|
43127
43370
|
init_dist2();
|
|
43128
43371
|
init_skills();
|
|
@@ -43130,9 +43373,10 @@ var init_skills2 = __esm(() => {
|
|
|
43130
43373
|
init_user_workspace();
|
|
43131
43374
|
init_sync();
|
|
43132
43375
|
init_marketplace();
|
|
43376
|
+
init_skill_search();
|
|
43133
43377
|
init_constants();
|
|
43134
43378
|
init_plugins();
|
|
43135
|
-
({ multiselect: multiselect2, select: select4, autocomplete: autocomplete2 } = exports_dist);
|
|
43379
|
+
({ multiselect: multiselect2, select: select4, autocomplete: autocomplete2, text: text3 } = exports_dist);
|
|
43136
43380
|
});
|
|
43137
43381
|
|
|
43138
43382
|
// src/cli/tui/wizard.ts
|
|
@@ -43488,14 +43732,14 @@ function validateJsonFields(fields, meta) {
|
|
|
43488
43732
|
|
|
43489
43733
|
// src/cli/metadata/workspace.ts
|
|
43490
43734
|
var initMeta = {
|
|
43491
|
-
command: "
|
|
43735
|
+
command: "init",
|
|
43492
43736
|
description: "Create new workspace and sync plugins",
|
|
43493
43737
|
whenToUse: "When starting a new project or adding allagents to an existing repo for the first time",
|
|
43494
43738
|
examples: [
|
|
43495
|
-
"allagents
|
|
43496
|
-
"allagents
|
|
43497
|
-
"allagents
|
|
43498
|
-
"allagents
|
|
43739
|
+
"allagents init",
|
|
43740
|
+
"allagents init ./my-project",
|
|
43741
|
+
"allagents init --from ../template-workspace/.allagents/workspace.yaml",
|
|
43742
|
+
"allagents init --client claude,copilot,cursor"
|
|
43499
43743
|
],
|
|
43500
43744
|
expectedOutput: "Creates .allagents/workspace.yaml and syncs plugins. Shows sync results per plugin. Exit 0 on success, exit 1 on failure.",
|
|
43501
43745
|
positionals: [
|
|
@@ -44534,181 +44778,8 @@ var skillsAddMeta = {
|
|
|
44534
44778
|
}
|
|
44535
44779
|
};
|
|
44536
44780
|
|
|
44537
|
-
// src/core/skill-search.ts
|
|
44538
|
-
var OWNER_REGEX = /^[A-Za-z0-9-]{1,39}$/;
|
|
44539
|
-
var COULD_BE_OWNER_REGEX = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,37}[a-zA-Z0-9])?$/;
|
|
44540
|
-
|
|
44541
|
-
class SkillSearchError extends Error {
|
|
44542
|
-
kind;
|
|
44543
|
-
constructor(message, kind) {
|
|
44544
|
-
super(message);
|
|
44545
|
-
this.kind = kind;
|
|
44546
|
-
this.name = "SkillSearchError";
|
|
44547
|
-
}
|
|
44548
|
-
}
|
|
44549
|
-
function validateSkillSearchArgs(query, options2) {
|
|
44550
|
-
if (query.trim().length < 2) {
|
|
44551
|
-
throw new SkillSearchError("Search query must be at least 2 characters.", "validation");
|
|
44552
|
-
}
|
|
44553
|
-
if (options2.page !== undefined && options2.page < 1) {
|
|
44554
|
-
throw new SkillSearchError("--page must be >= 1.", "validation");
|
|
44555
|
-
}
|
|
44556
|
-
if (options2.limit !== undefined && (options2.limit < 1 || options2.limit > 100)) {
|
|
44557
|
-
throw new SkillSearchError("--limit must be between 1 and 100.", "validation");
|
|
44558
|
-
}
|
|
44559
|
-
if (options2.owner !== undefined && !OWNER_REGEX.test(options2.owner)) {
|
|
44560
|
-
throw new SkillSearchError(`Invalid --owner "${options2.owner}": GitHub owners are alphanumeric + dashes, ≤ 39 chars.`, "validation");
|
|
44561
|
-
}
|
|
44562
|
-
}
|
|
44563
|
-
function couldBeOwner(query) {
|
|
44564
|
-
return COULD_BE_OWNER_REGEX.test(query);
|
|
44565
|
-
}
|
|
44566
|
-
function buildSearchQueries(query, owner) {
|
|
44567
|
-
const trimmed2 = query.trim();
|
|
44568
|
-
const pathTerm = trimmed2.replace(/ /g, "-");
|
|
44569
|
-
const userClause = owner ? `user:${owner}` : "";
|
|
44570
|
-
const join26 = (...parts) => parts.filter(Boolean).join(" ");
|
|
44571
|
-
const queries = [
|
|
44572
|
-
{ priority: 1, label: "path", q: join26("filename:SKILL.md", `in:path ${pathTerm}`, userClause) }
|
|
44573
|
-
];
|
|
44574
|
-
if (pathTerm !== trimmed2) {
|
|
44575
|
-
queries.push({ priority: 2, label: "hyphen", q: join26("filename:SKILL.md", pathTerm, userClause) });
|
|
44576
|
-
}
|
|
44577
|
-
if (!owner && couldBeOwner(trimmed2)) {
|
|
44578
|
-
queries.push({ priority: 3, label: "owner", q: `filename:SKILL.md user:${trimmed2}` });
|
|
44579
|
-
}
|
|
44580
|
-
queries.push({ priority: 4, label: "primary", q: join26("filename:SKILL.md", trimmed2, userClause) });
|
|
44581
|
-
return queries;
|
|
44582
|
-
}
|
|
44583
|
-
function classifyApiError(status, body) {
|
|
44584
|
-
const msg = typeof body === "object" && body !== null && "message" in body ? String(body.message ?? "") : "";
|
|
44585
|
-
if (status === 403 && /rate limit/i.test(msg)) {
|
|
44586
|
-
return new SkillSearchError("GitHub Code Search rate limit exceeded. Authenticate with `gh auth login` or set GITHUB_TOKEN to raise the quota.", "rate-limit");
|
|
44587
|
-
}
|
|
44588
|
-
if (status === 422) {
|
|
44589
|
-
return new SkillSearchError(`GitHub rejected the search query: ${msg || "unprocessable entity"}.`, "api");
|
|
44590
|
-
}
|
|
44591
|
-
return new SkillSearchError(`GitHub Code Search returned ${status}${msg ? `: ${msg}` : ""}.`, "api");
|
|
44592
|
-
}
|
|
44593
|
-
function qualifiedName(item) {
|
|
44594
|
-
return item.namespace ? `${item.namespace}/${item.name}` : item.name;
|
|
44595
|
-
}
|
|
44596
|
-
function parseSkillPath(path, repoFallback) {
|
|
44597
|
-
const parts = path.split("/").filter(Boolean);
|
|
44598
|
-
const skillsIdx = parts.lastIndexOf("skills");
|
|
44599
|
-
if (skillsIdx !== -1) {
|
|
44600
|
-
const afterSkills = parts.slice(skillsIdx + 1);
|
|
44601
|
-
const meaningful = afterSkills[afterSkills.length - 1] === "SKILL.md" ? afterSkills.slice(0, -1) : afterSkills;
|
|
44602
|
-
if (meaningful.length >= 2) {
|
|
44603
|
-
const namespace = meaningful[0] ?? "";
|
|
44604
|
-
const name = meaningful[1] ?? "";
|
|
44605
|
-
if (namespace && name)
|
|
44606
|
-
return { namespace, name };
|
|
44607
|
-
}
|
|
44608
|
-
if (meaningful.length === 1 && meaningful[0]) {
|
|
44609
|
-
return { namespace: "", name: meaningful[0] };
|
|
44610
|
-
}
|
|
44611
|
-
}
|
|
44612
|
-
if (parts.length >= 2) {
|
|
44613
|
-
const parent = parts[parts.length - 2];
|
|
44614
|
-
if (parent)
|
|
44615
|
-
return { namespace: "", name: parent };
|
|
44616
|
-
}
|
|
44617
|
-
return { namespace: "", name: repoFallback };
|
|
44618
|
-
}
|
|
44619
|
-
async function runOneQuery(q3, page, limit, token, fetchFn) {
|
|
44620
|
-
const url = new URL("https://api.github.com/search/code");
|
|
44621
|
-
url.searchParams.set("q", q3);
|
|
44622
|
-
url.searchParams.set("per_page", String(limit));
|
|
44623
|
-
url.searchParams.set("page", String(page));
|
|
44624
|
-
const headers = {
|
|
44625
|
-
Accept: "application/vnd.github+json",
|
|
44626
|
-
"X-GitHub-Api-Version": "2022-11-28",
|
|
44627
|
-
"User-Agent": "allagents-cli"
|
|
44628
|
-
};
|
|
44629
|
-
if (token)
|
|
44630
|
-
headers.Authorization = `token ${token}`;
|
|
44631
|
-
const response = await fetchFn(url.toString(), { headers });
|
|
44632
|
-
let body = null;
|
|
44633
|
-
try {
|
|
44634
|
-
body = await response.json();
|
|
44635
|
-
} catch {}
|
|
44636
|
-
if (!response.ok) {
|
|
44637
|
-
throw classifyApiError(response.status, body);
|
|
44638
|
-
}
|
|
44639
|
-
const parsed = body;
|
|
44640
|
-
const items = (parsed.items ?? []).map((item) => {
|
|
44641
|
-
const path = item.path ?? "";
|
|
44642
|
-
const repo = item.repository?.full_name ?? "";
|
|
44643
|
-
const repoFallback = repo.split("/").pop() ?? "";
|
|
44644
|
-
const { namespace, name } = parseSkillPath(path, repoFallback);
|
|
44645
|
-
return {
|
|
44646
|
-
name,
|
|
44647
|
-
namespace,
|
|
44648
|
-
repo,
|
|
44649
|
-
path,
|
|
44650
|
-
description: item.repository?.description ?? "",
|
|
44651
|
-
sha: item.sha ?? ""
|
|
44652
|
-
};
|
|
44653
|
-
});
|
|
44654
|
-
return {
|
|
44655
|
-
items,
|
|
44656
|
-
total: parsed.total_count ?? items.length,
|
|
44657
|
-
truncated: Boolean(parsed.incomplete_results)
|
|
44658
|
-
};
|
|
44659
|
-
}
|
|
44660
|
-
async function searchSkills(query, options2 = {}, deps = {}) {
|
|
44661
|
-
validateSkillSearchArgs(query, options2);
|
|
44662
|
-
const fetchFn = deps.fetch ?? fetch;
|
|
44663
|
-
const logger = deps.logger ?? ((msg) => process.stderr.write(`${msg}
|
|
44664
|
-
`));
|
|
44665
|
-
const page = options2.page ?? 1;
|
|
44666
|
-
const limit = options2.limit ?? 30;
|
|
44667
|
-
const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
|
|
44668
|
-
const queries = buildSearchQueries(query, options2.owner);
|
|
44669
|
-
const settled = await Promise.allSettled(queries.map((entry) => runOneQuery(entry.q, page, limit, token, fetchFn)));
|
|
44670
|
-
const primaryIdx = queries.findIndex((q3) => q3.priority === 4);
|
|
44671
|
-
const primarySettled = settled[primaryIdx];
|
|
44672
|
-
if (primarySettled?.status === "rejected") {
|
|
44673
|
-
throw primarySettled.reason;
|
|
44674
|
-
}
|
|
44675
|
-
const buckets = [];
|
|
44676
|
-
for (let i2 = 0;i2 < queries.length; i2++) {
|
|
44677
|
-
const entry = queries[i2];
|
|
44678
|
-
const outcome = settled[i2];
|
|
44679
|
-
if (!entry || !outcome)
|
|
44680
|
-
continue;
|
|
44681
|
-
if (outcome.status === "fulfilled") {
|
|
44682
|
-
buckets.push({ priority: entry.priority, result: outcome.value });
|
|
44683
|
-
} else {
|
|
44684
|
-
const reason = outcome.reason instanceof Error ? outcome.reason.message : String(outcome.reason);
|
|
44685
|
-
logger(`Warning: skill search "${entry.label}" query failed: ${reason}`);
|
|
44686
|
-
}
|
|
44687
|
-
}
|
|
44688
|
-
buckets.sort((a, b) => a.priority - b.priority);
|
|
44689
|
-
const mergedItems = buckets.flatMap((b) => b.result.items);
|
|
44690
|
-
const deduped = dedupeItems(mergedItems);
|
|
44691
|
-
return {
|
|
44692
|
-
query,
|
|
44693
|
-
items: deduped,
|
|
44694
|
-
total: deduped.length,
|
|
44695
|
-
truncated: buckets.some((b) => b.result.truncated)
|
|
44696
|
-
};
|
|
44697
|
-
}
|
|
44698
|
-
function dedupeItems(items) {
|
|
44699
|
-
const seen = new Set;
|
|
44700
|
-
const out = [];
|
|
44701
|
-
for (const item of items) {
|
|
44702
|
-
const key = `${item.repo}#${qualifiedName(item)}`;
|
|
44703
|
-
if (seen.has(key))
|
|
44704
|
-
continue;
|
|
44705
|
-
seen.add(key);
|
|
44706
|
-
out.push(item);
|
|
44707
|
-
}
|
|
44708
|
-
return out;
|
|
44709
|
-
}
|
|
44710
|
-
|
|
44711
44781
|
// src/cli/commands/plugin-skills.ts
|
|
44782
|
+
init_skill_search();
|
|
44712
44783
|
init_constants();
|
|
44713
44784
|
init_plugin_path();
|
|
44714
44785
|
init_plugin();
|
|
@@ -55416,11 +55487,14 @@ function findFreePort() {
|
|
|
55416
55487
|
});
|
|
55417
55488
|
});
|
|
55418
55489
|
}
|
|
55419
|
-
function
|
|
55420
|
-
|
|
55490
|
+
function getBrowserOpenCommands(url2, platform2 = process.platform) {
|
|
55491
|
+
return platform2 === "darwin" ? [{ command: "open", args: [url2] }] : platform2 === "win32" ? [{ command: "explorer.exe", args: [url2] }] : [
|
|
55421
55492
|
{ command: "xdg-open", args: [url2] },
|
|
55422
55493
|
{ command: "gio", args: ["open", url2] }
|
|
55423
55494
|
];
|
|
55495
|
+
}
|
|
55496
|
+
function tryOpenBrowser(url2) {
|
|
55497
|
+
const commands = getBrowserOpenCommands(url2);
|
|
55424
55498
|
return new Promise((resolve15) => {
|
|
55425
55499
|
const tryCommand = (index) => {
|
|
55426
55500
|
if (index >= commands.length) {
|
|
@@ -57923,6 +57997,7 @@ var app = conciseSubcommands({
|
|
|
57923
57997
|
` + "For AI agents: use --agent-help for machine-readable help, or --json for structured output",
|
|
57924
57998
|
version: package_default.version,
|
|
57925
57999
|
cmds: {
|
|
58000
|
+
init: initCmd,
|
|
57926
58001
|
update: syncCmd,
|
|
57927
58002
|
workspace: workspaceCmd,
|
|
57928
58003
|
plugin: pluginCmd,
|
package/package.json
CHANGED