@neta-art/neta-search-cli 0.2.18 → 0.2.20
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 -0
- package/neta-search.mjs +335 -221
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,6 +18,8 @@ npx -y @neta-art/neta-search-cli@latest skills init <name> # scaff
|
|
|
18
18
|
|
|
19
19
|
`use` prints the skill directory and the full SKILL.md, so an agent can follow it right away; relative paths in SKILL.md resolve against that directory. If the local entry is a pointer (frontmatter `metadata.neta-skill-id`), `use` fetches the full skill it points to.
|
|
20
20
|
|
|
21
|
+
Each `find --json` item carries a ready-to-run `use` command (`skills use <id> --via find`); prefix it with `npx -y @neta-art/neta-search-cli@latest` or `neta-search`. `--via` only labels where the use came from in usage stats.
|
|
22
|
+
|
|
21
23
|
Use `@latest` (or an exact version): with a range such as `@0.2`, npx keeps running whatever matching version it cached earlier and never checks for a newer one.
|
|
22
24
|
|
|
23
25
|
Inside a Cohub sandbox the CLI picks up the sandbox identity automatically; elsewhere it runs anonymously.
|
package/neta-search.mjs
CHANGED
|
@@ -7021,8 +7021,8 @@ var require_util2 = __commonJS({
|
|
|
7021
7021
|
function createDeferredPromise() {
|
|
7022
7022
|
let res;
|
|
7023
7023
|
let rej;
|
|
7024
|
-
const promise = new Promise((
|
|
7025
|
-
res =
|
|
7024
|
+
const promise = new Promise((resolve2, reject) => {
|
|
7025
|
+
res = resolve2;
|
|
7026
7026
|
rej = reject;
|
|
7027
7027
|
});
|
|
7028
7028
|
return { promise, resolve: res, reject: rej };
|
|
@@ -8526,8 +8526,8 @@ Content-Type: ${value.type || "application/octet-stream"}\r
|
|
|
8526
8526
|
});
|
|
8527
8527
|
}
|
|
8528
8528
|
});
|
|
8529
|
-
const busboyResolve = new Promise((
|
|
8530
|
-
busboy.on("finish",
|
|
8529
|
+
const busboyResolve = new Promise((resolve2, reject) => {
|
|
8530
|
+
busboy.on("finish", resolve2);
|
|
8531
8531
|
busboy.on("error", (err) => reject(new TypeError(err)));
|
|
8532
8532
|
});
|
|
8533
8533
|
if (this.body !== null) for await (const chunk of consumeBody(this[kState].body)) busboy.write(chunk);
|
|
@@ -9061,9 +9061,9 @@ var require_dispatcher_base = __commonJS({
|
|
|
9061
9061
|
}
|
|
9062
9062
|
close(callback) {
|
|
9063
9063
|
if (callback === void 0) {
|
|
9064
|
-
return new Promise((
|
|
9064
|
+
return new Promise((resolve2, reject) => {
|
|
9065
9065
|
this.close((err, data) => {
|
|
9066
|
-
return err ? reject(err) :
|
|
9066
|
+
return err ? reject(err) : resolve2(data);
|
|
9067
9067
|
});
|
|
9068
9068
|
});
|
|
9069
9069
|
}
|
|
@@ -9101,12 +9101,12 @@ var require_dispatcher_base = __commonJS({
|
|
|
9101
9101
|
err = null;
|
|
9102
9102
|
}
|
|
9103
9103
|
if (callback === void 0) {
|
|
9104
|
-
return new Promise((
|
|
9104
|
+
return new Promise((resolve2, reject) => {
|
|
9105
9105
|
this.destroy(err, (err2, data) => {
|
|
9106
9106
|
return err2 ? (
|
|
9107
9107
|
/* istanbul ignore next: should never error */
|
|
9108
9108
|
reject(err2)
|
|
9109
|
-
) :
|
|
9109
|
+
) : resolve2(data);
|
|
9110
9110
|
});
|
|
9111
9111
|
});
|
|
9112
9112
|
}
|
|
@@ -10166,16 +10166,16 @@ var require_client = __commonJS({
|
|
|
10166
10166
|
return this[kNeedDrain] < 2;
|
|
10167
10167
|
}
|
|
10168
10168
|
async [kClose]() {
|
|
10169
|
-
return new Promise((
|
|
10169
|
+
return new Promise((resolve2) => {
|
|
10170
10170
|
if (!this[kSize]) {
|
|
10171
|
-
|
|
10171
|
+
resolve2(null);
|
|
10172
10172
|
} else {
|
|
10173
|
-
this[kClosedResolve] =
|
|
10173
|
+
this[kClosedResolve] = resolve2;
|
|
10174
10174
|
}
|
|
10175
10175
|
});
|
|
10176
10176
|
}
|
|
10177
10177
|
async [kDestroy](err) {
|
|
10178
|
-
return new Promise((
|
|
10178
|
+
return new Promise((resolve2) => {
|
|
10179
10179
|
const requests = this[kQueue].splice(this[kPendingIdx]);
|
|
10180
10180
|
for (let i = 0; i < requests.length; i++) {
|
|
10181
10181
|
const request3 = requests[i];
|
|
@@ -10186,7 +10186,7 @@ var require_client = __commonJS({
|
|
|
10186
10186
|
this[kClosedResolve]();
|
|
10187
10187
|
this[kClosedResolve] = null;
|
|
10188
10188
|
}
|
|
10189
|
-
|
|
10189
|
+
resolve2();
|
|
10190
10190
|
};
|
|
10191
10191
|
if (this[kHTTP2Session] != null) {
|
|
10192
10192
|
util.destroy(this[kHTTP2Session], err);
|
|
@@ -10766,7 +10766,7 @@ var require_client = __commonJS({
|
|
|
10766
10766
|
});
|
|
10767
10767
|
}
|
|
10768
10768
|
try {
|
|
10769
|
-
const socket = await new Promise((
|
|
10769
|
+
const socket = await new Promise((resolve2, reject) => {
|
|
10770
10770
|
client[kConnector]({
|
|
10771
10771
|
host,
|
|
10772
10772
|
hostname,
|
|
@@ -10778,7 +10778,7 @@ var require_client = __commonJS({
|
|
|
10778
10778
|
if (err) {
|
|
10779
10779
|
reject(err);
|
|
10780
10780
|
} else {
|
|
10781
|
-
|
|
10781
|
+
resolve2(socket2);
|
|
10782
10782
|
}
|
|
10783
10783
|
});
|
|
10784
10784
|
});
|
|
@@ -11402,12 +11402,12 @@ upgrade: ${upgrade}\r
|
|
|
11402
11402
|
cb();
|
|
11403
11403
|
}
|
|
11404
11404
|
}
|
|
11405
|
-
const waitForDrain = () => new Promise((
|
|
11405
|
+
const waitForDrain = () => new Promise((resolve2, reject) => {
|
|
11406
11406
|
assert2(callback === null);
|
|
11407
11407
|
if (socket[kError]) {
|
|
11408
11408
|
reject(socket[kError]);
|
|
11409
11409
|
} else {
|
|
11410
|
-
callback =
|
|
11410
|
+
callback = resolve2;
|
|
11411
11411
|
}
|
|
11412
11412
|
});
|
|
11413
11413
|
if (client[kHTTPConnVersion] === "h2") {
|
|
@@ -11752,8 +11752,8 @@ var require_pool_base = __commonJS({
|
|
|
11752
11752
|
if (this[kQueue].isEmpty()) {
|
|
11753
11753
|
return Promise.all(this[kClients].map((c) => c.close()));
|
|
11754
11754
|
} else {
|
|
11755
|
-
return new Promise((
|
|
11756
|
-
this[kClosedResolve] =
|
|
11755
|
+
return new Promise((resolve2) => {
|
|
11756
|
+
this[kClosedResolve] = resolve2;
|
|
11757
11757
|
});
|
|
11758
11758
|
}
|
|
11759
11759
|
}
|
|
@@ -12331,7 +12331,7 @@ var require_readable = __commonJS({
|
|
|
12331
12331
|
if (this.closed) {
|
|
12332
12332
|
return Promise.resolve(null);
|
|
12333
12333
|
}
|
|
12334
|
-
return new Promise((
|
|
12334
|
+
return new Promise((resolve2, reject) => {
|
|
12335
12335
|
const signalListenerCleanup = signal ? util.addAbortListener(signal, () => {
|
|
12336
12336
|
this.destroy();
|
|
12337
12337
|
}) : noop;
|
|
@@ -12340,7 +12340,7 @@ var require_readable = __commonJS({
|
|
|
12340
12340
|
if (signal && signal.aborted) {
|
|
12341
12341
|
reject(signal.reason || Object.assign(new Error("The operation was aborted"), { name: "AbortError" }));
|
|
12342
12342
|
} else {
|
|
12343
|
-
|
|
12343
|
+
resolve2(null);
|
|
12344
12344
|
}
|
|
12345
12345
|
}).on("error", noop).on("data", function(chunk) {
|
|
12346
12346
|
limit -= chunk.length;
|
|
@@ -12362,11 +12362,11 @@ var require_readable = __commonJS({
|
|
|
12362
12362
|
throw new TypeError("unusable");
|
|
12363
12363
|
}
|
|
12364
12364
|
assert2(!stream[kConsume]);
|
|
12365
|
-
return new Promise((
|
|
12365
|
+
return new Promise((resolve2, reject) => {
|
|
12366
12366
|
stream[kConsume] = {
|
|
12367
12367
|
type,
|
|
12368
12368
|
stream,
|
|
12369
|
-
resolve,
|
|
12369
|
+
resolve: resolve2,
|
|
12370
12370
|
reject,
|
|
12371
12371
|
length: 0,
|
|
12372
12372
|
body: []
|
|
@@ -12401,12 +12401,12 @@ var require_readable = __commonJS({
|
|
|
12401
12401
|
}
|
|
12402
12402
|
}
|
|
12403
12403
|
function consumeEnd(consume2) {
|
|
12404
|
-
const { type, body, resolve, stream, length } = consume2;
|
|
12404
|
+
const { type, body, resolve: resolve2, stream, length } = consume2;
|
|
12405
12405
|
try {
|
|
12406
12406
|
if (type === "text") {
|
|
12407
|
-
|
|
12407
|
+
resolve2(toUSVString(Buffer.concat(body)));
|
|
12408
12408
|
} else if (type === "json") {
|
|
12409
|
-
|
|
12409
|
+
resolve2(JSON.parse(Buffer.concat(body)));
|
|
12410
12410
|
} else if (type === "arrayBuffer") {
|
|
12411
12411
|
const dst = new Uint8Array(length);
|
|
12412
12412
|
let pos = 0;
|
|
@@ -12414,12 +12414,12 @@ var require_readable = __commonJS({
|
|
|
12414
12414
|
dst.set(buf, pos);
|
|
12415
12415
|
pos += buf.byteLength;
|
|
12416
12416
|
}
|
|
12417
|
-
|
|
12417
|
+
resolve2(dst.buffer);
|
|
12418
12418
|
} else if (type === "blob") {
|
|
12419
12419
|
if (!Blob2) {
|
|
12420
12420
|
Blob2 = __require("buffer").Blob;
|
|
12421
12421
|
}
|
|
12422
|
-
|
|
12422
|
+
resolve2(new Blob2(body, { type: stream[kContentType] }));
|
|
12423
12423
|
}
|
|
12424
12424
|
consumeFinish(consume2);
|
|
12425
12425
|
} catch (err) {
|
|
@@ -12674,9 +12674,9 @@ var require_api_request = __commonJS({
|
|
|
12674
12674
|
};
|
|
12675
12675
|
function request3(opts, callback) {
|
|
12676
12676
|
if (callback === void 0) {
|
|
12677
|
-
return new Promise((
|
|
12677
|
+
return new Promise((resolve2, reject) => {
|
|
12678
12678
|
request3.call(this, opts, (err, data) => {
|
|
12679
|
-
return err ? reject(err) :
|
|
12679
|
+
return err ? reject(err) : resolve2(data);
|
|
12680
12680
|
});
|
|
12681
12681
|
});
|
|
12682
12682
|
}
|
|
@@ -12849,9 +12849,9 @@ var require_api_stream = __commonJS({
|
|
|
12849
12849
|
};
|
|
12850
12850
|
function stream(opts, factory, callback) {
|
|
12851
12851
|
if (callback === void 0) {
|
|
12852
|
-
return new Promise((
|
|
12852
|
+
return new Promise((resolve2, reject) => {
|
|
12853
12853
|
stream.call(this, opts, factory, (err, data) => {
|
|
12854
|
-
return err ? reject(err) :
|
|
12854
|
+
return err ? reject(err) : resolve2(data);
|
|
12855
12855
|
});
|
|
12856
12856
|
});
|
|
12857
12857
|
}
|
|
@@ -13132,9 +13132,9 @@ var require_api_upgrade = __commonJS({
|
|
|
13132
13132
|
};
|
|
13133
13133
|
function upgrade(opts, callback) {
|
|
13134
13134
|
if (callback === void 0) {
|
|
13135
|
-
return new Promise((
|
|
13135
|
+
return new Promise((resolve2, reject) => {
|
|
13136
13136
|
upgrade.call(this, opts, (err, data) => {
|
|
13137
|
-
return err ? reject(err) :
|
|
13137
|
+
return err ? reject(err) : resolve2(data);
|
|
13138
13138
|
});
|
|
13139
13139
|
});
|
|
13140
13140
|
}
|
|
@@ -13223,9 +13223,9 @@ var require_api_connect = __commonJS({
|
|
|
13223
13223
|
};
|
|
13224
13224
|
function connect3(opts, callback) {
|
|
13225
13225
|
if (callback === void 0) {
|
|
13226
|
-
return new Promise((
|
|
13226
|
+
return new Promise((resolve2, reject) => {
|
|
13227
13227
|
connect3.call(this, opts, (err, data) => {
|
|
13228
|
-
return err ? reject(err) :
|
|
13228
|
+
return err ? reject(err) : resolve2(data);
|
|
13229
13229
|
});
|
|
13230
13230
|
});
|
|
13231
13231
|
}
|
|
@@ -16847,7 +16847,7 @@ var require_fetch = __commonJS({
|
|
|
16847
16847
|
async function dispatch({ body }) {
|
|
16848
16848
|
const url = requestCurrentURL(request3);
|
|
16849
16849
|
const agent = fetchParams.controller.dispatcher;
|
|
16850
|
-
return new Promise((
|
|
16850
|
+
return new Promise((resolve2, reject) => agent.dispatch(
|
|
16851
16851
|
{
|
|
16852
16852
|
path: url.pathname + url.search,
|
|
16853
16853
|
origin: url.origin,
|
|
@@ -16923,7 +16923,7 @@ var require_fetch = __commonJS({
|
|
|
16923
16923
|
}
|
|
16924
16924
|
}
|
|
16925
16925
|
}
|
|
16926
|
-
|
|
16926
|
+
resolve2({
|
|
16927
16927
|
status,
|
|
16928
16928
|
statusText,
|
|
16929
16929
|
headersList: headers[kHeadersList],
|
|
@@ -16966,7 +16966,7 @@ var require_fetch = __commonJS({
|
|
|
16966
16966
|
const val = headersList[n + 1].toString("latin1");
|
|
16967
16967
|
headers[kHeadersList].append(key, val);
|
|
16968
16968
|
}
|
|
16969
|
-
|
|
16969
|
+
resolve2({
|
|
16970
16970
|
status,
|
|
16971
16971
|
statusText: STATUS_CODES[status],
|
|
16972
16972
|
headersList: headers[kHeadersList],
|
|
@@ -23943,14 +23943,14 @@ var __asyncValues = function(o) {
|
|
|
23943
23943
|
}, i);
|
|
23944
23944
|
function verb(n) {
|
|
23945
23945
|
i[n] = o[n] && function(v) {
|
|
23946
|
-
return new Promise(function(
|
|
23947
|
-
v = o[n](v), settle(
|
|
23946
|
+
return new Promise(function(resolve2, reject) {
|
|
23947
|
+
v = o[n](v), settle(resolve2, reject, v.done, v.value);
|
|
23948
23948
|
});
|
|
23949
23949
|
};
|
|
23950
23950
|
}
|
|
23951
|
-
function settle(
|
|
23951
|
+
function settle(resolve2, reject, d, v) {
|
|
23952
23952
|
Promise.resolve(v).then(function(v2) {
|
|
23953
|
-
|
|
23953
|
+
resolve2({ value: v2, done: d });
|
|
23954
23954
|
}, reject);
|
|
23955
23955
|
}
|
|
23956
23956
|
};
|
|
@@ -24475,14 +24475,14 @@ var __asyncValues2 = function(o) {
|
|
|
24475
24475
|
}, i);
|
|
24476
24476
|
function verb(n) {
|
|
24477
24477
|
i[n] = o[n] && function(v) {
|
|
24478
|
-
return new Promise(function(
|
|
24479
|
-
v = o[n](v), settle(
|
|
24478
|
+
return new Promise(function(resolve2, reject) {
|
|
24479
|
+
v = o[n](v), settle(resolve2, reject, v.done, v.value);
|
|
24480
24480
|
});
|
|
24481
24481
|
};
|
|
24482
24482
|
}
|
|
24483
|
-
function settle(
|
|
24483
|
+
function settle(resolve2, reject, d, v) {
|
|
24484
24484
|
Promise.resolve(v).then(function(v2) {
|
|
24485
|
-
|
|
24485
|
+
resolve2({ value: v2, done: d });
|
|
24486
24486
|
}, reject);
|
|
24487
24487
|
}
|
|
24488
24488
|
};
|
|
@@ -25217,14 +25217,14 @@ var __asyncValues3 = function(o) {
|
|
|
25217
25217
|
}, i);
|
|
25218
25218
|
function verb(n) {
|
|
25219
25219
|
i[n] = o[n] && function(v) {
|
|
25220
|
-
return new Promise(function(
|
|
25221
|
-
v = o[n](v), settle(
|
|
25220
|
+
return new Promise(function(resolve2, reject) {
|
|
25221
|
+
v = o[n](v), settle(resolve2, reject, v.done, v.value);
|
|
25222
25222
|
});
|
|
25223
25223
|
};
|
|
25224
25224
|
}
|
|
25225
|
-
function settle(
|
|
25225
|
+
function settle(resolve2, reject, d, v) {
|
|
25226
25226
|
Promise.resolve(v).then(function(v2) {
|
|
25227
|
-
|
|
25227
|
+
resolve2({ value: v2, done: d });
|
|
25228
25228
|
}, reject);
|
|
25229
25229
|
}
|
|
25230
25230
|
};
|
|
@@ -25862,17 +25862,17 @@ function closedOrError(reason) {
|
|
|
25862
25862
|
return isCancel ? closed() : error(reason);
|
|
25863
25863
|
}
|
|
25864
25864
|
function connect2(authority, http2SessionOptions) {
|
|
25865
|
-
let
|
|
25865
|
+
let resolve2;
|
|
25866
25866
|
let reject;
|
|
25867
25867
|
const conn = new Promise((res, rej) => {
|
|
25868
|
-
|
|
25868
|
+
resolve2 = res;
|
|
25869
25869
|
reject = rej;
|
|
25870
25870
|
});
|
|
25871
25871
|
const newConn = http2.connect(authority, http2SessionOptions);
|
|
25872
25872
|
newConn.on("connect", onConnect);
|
|
25873
25873
|
newConn.on("error", onError);
|
|
25874
25874
|
function onConnect() {
|
|
25875
|
-
|
|
25875
|
+
resolve2 === null || resolve2 === void 0 ? void 0 : resolve2(newConn);
|
|
25876
25876
|
cleanup();
|
|
25877
25877
|
}
|
|
25878
25878
|
function onError(err) {
|
|
@@ -25958,13 +25958,13 @@ function ready(conn, options) {
|
|
|
25958
25958
|
},
|
|
25959
25959
|
verify() {
|
|
25960
25960
|
conn.ref();
|
|
25961
|
-
return new Promise((
|
|
25961
|
+
return new Promise((resolve2) => {
|
|
25962
25962
|
commonPing(() => {
|
|
25963
25963
|
if (streamCount == 0)
|
|
25964
25964
|
conn.unref();
|
|
25965
|
-
|
|
25965
|
+
resolve2(true);
|
|
25966
25966
|
});
|
|
25967
|
-
conn.once("error", () =>
|
|
25967
|
+
conn.once("error", () => resolve2(false));
|
|
25968
25968
|
});
|
|
25969
25969
|
},
|
|
25970
25970
|
abort(reason) {
|
|
@@ -26095,7 +26095,7 @@ function createNodeHttpClient(options) {
|
|
|
26095
26095
|
function createNodeHttp1Client(httpOptions) {
|
|
26096
26096
|
return async function request3(req) {
|
|
26097
26097
|
const sentinel = createSentinel(req.signal);
|
|
26098
|
-
return new Promise((
|
|
26098
|
+
return new Promise((resolve2, reject) => {
|
|
26099
26099
|
sentinel.catch((e) => {
|
|
26100
26100
|
reject(e);
|
|
26101
26101
|
});
|
|
@@ -26106,7 +26106,7 @@ function createNodeHttp1Client(httpOptions) {
|
|
|
26106
26106
|
response.on("error", sentinel.reject);
|
|
26107
26107
|
sentinel.catch((reason) => response.destroy(connectErrorFromNodeReason(reason)));
|
|
26108
26108
|
const trailer = new Headers();
|
|
26109
|
-
|
|
26109
|
+
resolve2({
|
|
26110
26110
|
status: (_a = response.statusCode) !== null && _a !== void 0 ? _a : 0,
|
|
26111
26111
|
header: nodeHeaderToWebHeader(response.headers),
|
|
26112
26112
|
body: h1ResponseIterable(sentinel, response, trailer),
|
|
@@ -26121,7 +26121,7 @@ function createNodeHttp2Client(sessionProvider) {
|
|
|
26121
26121
|
return function request3(req) {
|
|
26122
26122
|
const sentinel = createSentinel(req.signal);
|
|
26123
26123
|
const sessionManager = sessionProvider(req.url);
|
|
26124
|
-
return new Promise((
|
|
26124
|
+
return new Promise((resolve2, reject) => {
|
|
26125
26125
|
sentinel.catch((e) => {
|
|
26126
26126
|
reject(e);
|
|
26127
26127
|
});
|
|
@@ -26135,7 +26135,7 @@ function createNodeHttp2Client(sessionProvider) {
|
|
|
26135
26135
|
body: h2ResponseIterable(sentinel, stream, sessionManager),
|
|
26136
26136
|
trailer: h2ResponseTrailer(stream)
|
|
26137
26137
|
};
|
|
26138
|
-
|
|
26138
|
+
resolve2(response);
|
|
26139
26139
|
});
|
|
26140
26140
|
});
|
|
26141
26141
|
});
|
|
@@ -26200,7 +26200,7 @@ function h2Request(sentinel, sm, url, method, headers, options, onStream) {
|
|
|
26200
26200
|
return;
|
|
26201
26201
|
}
|
|
26202
26202
|
const rstCode = reason instanceof ConnectError && reason.code == Code.Canceled ? H2Code.CANCEL : H2Code.INTERNAL_ERROR;
|
|
26203
|
-
return new Promise((
|
|
26203
|
+
return new Promise((resolve2) => stream.close(rstCode, resolve2));
|
|
26204
26204
|
});
|
|
26205
26205
|
stream.on("error", function h2StreamError(e) {
|
|
26206
26206
|
if (stream.writableEnded && unwrapNodeErrorChain(e).map(getNodeErrorProps).some((p) => p.code == "ERR_STREAM_WRITE_AFTER_END")) {
|
|
@@ -26252,11 +26252,11 @@ function h2ResponseIterable(sentinel, response, sm) {
|
|
|
26252
26252
|
}
|
|
26253
26253
|
async function sinkRequest(request3, nodeRequest, sentinel) {
|
|
26254
26254
|
if (request3.body === void 0) {
|
|
26255
|
-
await new Promise((
|
|
26255
|
+
await new Promise((resolve2) => nodeRequest.end(resolve2));
|
|
26256
26256
|
return;
|
|
26257
26257
|
}
|
|
26258
26258
|
const it = request3.body[Symbol.asyncIterator]();
|
|
26259
|
-
return new Promise((
|
|
26259
|
+
return new Promise((resolve2) => {
|
|
26260
26260
|
writeNext();
|
|
26261
26261
|
function writeNext() {
|
|
26262
26262
|
if (sentinel.isRejected()) {
|
|
@@ -26264,7 +26264,7 @@ async function sinkRequest(request3, nodeRequest, sentinel) {
|
|
|
26264
26264
|
}
|
|
26265
26265
|
it.next().then((r) => {
|
|
26266
26266
|
if (r.done === true) {
|
|
26267
|
-
nodeRequest.end(
|
|
26267
|
+
nodeRequest.end(resolve2);
|
|
26268
26268
|
return;
|
|
26269
26269
|
}
|
|
26270
26270
|
nodeRequest.write(r.value, "binary", function(e) {
|
|
@@ -26292,8 +26292,8 @@ function createSentinel(signal) {
|
|
|
26292
26292
|
let rej;
|
|
26293
26293
|
let resolved = false;
|
|
26294
26294
|
let rejected = false;
|
|
26295
|
-
const p = new Promise((
|
|
26296
|
-
res =
|
|
26295
|
+
const p = new Promise((resolve2, reject) => {
|
|
26296
|
+
res = resolve2;
|
|
26297
26297
|
rej = reject;
|
|
26298
26298
|
});
|
|
26299
26299
|
const c = {
|
|
@@ -26906,6 +26906,21 @@ var SkillFeedbackService = {
|
|
|
26906
26906
|
}
|
|
26907
26907
|
};
|
|
26908
26908
|
|
|
26909
|
+
// cli/src/version.ts
|
|
26910
|
+
import { createRequire } from "node:module";
|
|
26911
|
+
var OUR_NAMES = /* @__PURE__ */ new Set(["@neta-search/cli", "@neta-art/neta-search-cli"]);
|
|
26912
|
+
function cliVersion() {
|
|
26913
|
+
const req = createRequire(import.meta.url);
|
|
26914
|
+
for (const p of ["./package.json", "../package.json"]) {
|
|
26915
|
+
try {
|
|
26916
|
+
const pkg = req(p);
|
|
26917
|
+
if (pkg.name && OUR_NAMES.has(pkg.name) && pkg.version) return pkg.version;
|
|
26918
|
+
} catch {
|
|
26919
|
+
}
|
|
26920
|
+
}
|
|
26921
|
+
return "0.0.0-unknown";
|
|
26922
|
+
}
|
|
26923
|
+
|
|
26909
26924
|
// cli/src/env.ts
|
|
26910
26925
|
function detectEnv() {
|
|
26911
26926
|
const actorId = process.env["COHUB_USER_UUID"] ?? "";
|
|
@@ -26925,16 +26940,18 @@ function detectEnv() {
|
|
|
26925
26940
|
anonymous: actorId === "" || spaceId === ""
|
|
26926
26941
|
};
|
|
26927
26942
|
}
|
|
26943
|
+
var SEARCH_TIMEOUT_MS = 15e3;
|
|
26944
|
+
var REPORT_TIMEOUT_MS = 3e3;
|
|
26928
26945
|
function searchClient(env) {
|
|
26929
|
-
const transport = createConnectTransport({ baseUrl: env.apiBase, httpVersion: "1.1" });
|
|
26946
|
+
const transport = createConnectTransport({ baseUrl: env.apiBase, httpVersion: "1.1", defaultTimeoutMs: SEARCH_TIMEOUT_MS });
|
|
26930
26947
|
return createClient(SearchService, transport);
|
|
26931
26948
|
}
|
|
26932
26949
|
function feedbackClient(env) {
|
|
26933
|
-
const transport = createConnectTransport({ baseUrl: env.apiBase, httpVersion: "1.1" });
|
|
26950
|
+
const transport = createConnectTransport({ baseUrl: env.apiBase, httpVersion: "1.1", defaultTimeoutMs: REPORT_TIMEOUT_MS });
|
|
26934
26951
|
return createClient(SkillFeedbackService, transport);
|
|
26935
26952
|
}
|
|
26936
26953
|
function eventContext(env, extra = {}) {
|
|
26937
|
-
const ctx = { source: "cli", ...extra };
|
|
26954
|
+
const ctx = { source: "cli", cli_version: cliVersion(), ...extra };
|
|
26938
26955
|
if (env.sessionId) ctx["session_id"] = env.sessionId;
|
|
26939
26956
|
if (env.turnId) ctx["turn_id"] = env.turnId;
|
|
26940
26957
|
return ctx;
|
|
@@ -26958,7 +26975,7 @@ async function reportSkillEvent(env, event, skillId, digest, skillName, extra =
|
|
|
26958
26975
|
});
|
|
26959
26976
|
return true;
|
|
26960
26977
|
} catch (e) {
|
|
26961
|
-
console.error(
|
|
26978
|
+
console.error(`Note: failed to report the ${event} event (this does not affect the ${event}): ${e instanceof Error ? e.message : e}`);
|
|
26962
26979
|
return false;
|
|
26963
26980
|
}
|
|
26964
26981
|
}
|
|
@@ -26978,7 +26995,8 @@ async function cmdFind(query, opts) {
|
|
|
26978
26995
|
name: c.name,
|
|
26979
26996
|
description: c.summary,
|
|
26980
26997
|
match: c.match,
|
|
26981
|
-
sources: sc.sourceCount || void 0
|
|
26998
|
+
sources: sc.sourceCount || void 0,
|
|
26999
|
+
use: useCommand(c.id)
|
|
26982
27000
|
};
|
|
26983
27001
|
})
|
|
26984
27002
|
);
|
|
@@ -26987,22 +27005,26 @@ async function cmdFind(query, opts) {
|
|
|
26987
27005
|
}
|
|
26988
27006
|
const candidates = res.groups.flatMap((g) => g.candidates);
|
|
26989
27007
|
if (candidates.length === 0) {
|
|
26990
|
-
console.log(
|
|
26991
|
-
console.log(
|
|
27008
|
+
console.log(`No skills found for "${query}".`);
|
|
27009
|
+
console.log(`(This is a useful demand signal: missing capabilities drive what gets added next.)`);
|
|
26992
27010
|
return 0;
|
|
26993
27011
|
}
|
|
26994
|
-
console.log(
|
|
27012
|
+
console.log(`Found ${candidates.length} skill${candidates.length === 1 ? "" : "s"} (query: ${query}):
|
|
26995
27013
|
`);
|
|
26996
27014
|
for (const c of candidates) {
|
|
26997
27015
|
const sc = c;
|
|
26998
27016
|
console.log(` ${c.id}`);
|
|
26999
27017
|
if (c.summary) console.log(` ${trunc(c.summary, 100)}`);
|
|
27000
|
-
if ((sc.sourceCount || 0) > 1) console.log(` \u21B3
|
|
27018
|
+
if ((sc.sourceCount || 0) > 1) console.log(` \u21B3 identical copies merged: ${sc.sourceCount} sources`);
|
|
27001
27019
|
console.log();
|
|
27002
27020
|
}
|
|
27003
|
-
console.log(
|
|
27021
|
+
console.log(`Install: neta-search skills add <id> Try without installing: neta-search ${useCommand("<id>")}`);
|
|
27004
27022
|
return 0;
|
|
27005
27023
|
}
|
|
27024
|
+
function useCommand(id) {
|
|
27025
|
+
return `skills use ${id} --via ${FIND_VIA}`;
|
|
27026
|
+
}
|
|
27027
|
+
var FIND_VIA = "find";
|
|
27006
27028
|
function trunc(s, n) {
|
|
27007
27029
|
return s.length > n ? s.slice(0, n - 1) + "\u2026" : s;
|
|
27008
27030
|
}
|
|
@@ -27065,16 +27087,16 @@ var ArchiveNotFound = class extends Error {
|
|
|
27065
27087
|
async function fetchArchive(env, id) {
|
|
27066
27088
|
const url = `${env.apiBase}${ARCHIVE_PATH}?id=${encodeURIComponent(id)}`;
|
|
27067
27089
|
const res = await fetch(url, { redirect: "manual", signal: AbortSignal.timeout(TIMEOUT_MS) });
|
|
27068
|
-
if (res.status === 404) throw new ArchiveNotFound(`${id}
|
|
27090
|
+
if (res.status === 404) throw new ArchiveNotFound(`${id} does not exist or has no released version`);
|
|
27069
27091
|
const location = res.headers.get("location");
|
|
27070
|
-
if (res.status < 300 || res.status >= 400 || !location) throw new Error(
|
|
27092
|
+
if (res.status < 300 || res.status >= 400 || !location) throw new Error(`failed to download ${id}: HTTP ${res.status}`);
|
|
27071
27093
|
const digest = res.headers.get("x-skill-digest") ?? "";
|
|
27072
27094
|
const name = res.headers.get("x-skill-name") ?? id.split("/").pop();
|
|
27073
|
-
if (!digest) throw new Error(
|
|
27095
|
+
if (!digest) throw new Error(`failed to download ${id}: the server did not return a version (x-skill-digest)`);
|
|
27074
27096
|
const body = await download(new URL(location, url).toString(), id);
|
|
27075
27097
|
const files = untarGz(body);
|
|
27076
27098
|
const got = digestOf(new Map(files.map((f) => [f.path, f.data])));
|
|
27077
|
-
if (got !== digest) throw new Error(
|
|
27099
|
+
if (got !== digest) throw new Error(`downloaded ${id} failed verification (expected ${digest}, got ${got})`);
|
|
27078
27100
|
const handle = res.headers.get("x-skill-handle") || void 0;
|
|
27079
27101
|
return { id, handle, name, digest, files };
|
|
27080
27102
|
}
|
|
@@ -27083,7 +27105,7 @@ async function archiveHead(env, id) {
|
|
|
27083
27105
|
const res = await fetch(url, { method: "HEAD", redirect: "manual", signal: AbortSignal.timeout(1e4) });
|
|
27084
27106
|
if (res.status === 404) return null;
|
|
27085
27107
|
const digest = res.headers.get("x-skill-digest") ?? "";
|
|
27086
|
-
if (res.status < 300 || res.status >= 400 || !digest) throw new Error(
|
|
27108
|
+
if (res.status < 300 || res.status >= 400 || !digest) throw new Error(`failed to look up ${id}: HTTP ${res.status}`);
|
|
27087
27109
|
return {
|
|
27088
27110
|
id: res.headers.get("x-skill-id") ?? id,
|
|
27089
27111
|
handle: res.headers.get("x-skill-handle") || void 0,
|
|
@@ -27099,7 +27121,7 @@ async function download(url, id) {
|
|
|
27099
27121
|
await new Promise((r) => setTimeout(r, Math.min(Math.max(body.retryAfterMs ?? 2e3, 250), 5e3)));
|
|
27100
27122
|
continue;
|
|
27101
27123
|
}
|
|
27102
|
-
if (!res.ok) throw new Error(
|
|
27124
|
+
if (!res.ok) throw new Error(`failed to download ${id}: registry returned HTTP ${res.status}`);
|
|
27103
27125
|
return Buffer.from(await res.arrayBuffer());
|
|
27104
27126
|
}
|
|
27105
27127
|
}
|
|
@@ -27128,7 +27150,7 @@ function untarGz(gz) {
|
|
|
27128
27150
|
const path = paxPath ?? (prefix ? `${prefix}/${name}` : name);
|
|
27129
27151
|
paxPath = null;
|
|
27130
27152
|
if (path.startsWith("/") || path.split("/").some((s) => s === ".." || s === "")) {
|
|
27131
|
-
throw new Error(
|
|
27153
|
+
throw new Error(`unsafe path in archive: ${path}`);
|
|
27132
27154
|
}
|
|
27133
27155
|
const mode = parseOctal(hdr.subarray(100, 108));
|
|
27134
27156
|
out.push({ path, data: Buffer.from(body), exec: (mode & 73) !== 0 });
|
|
@@ -27175,14 +27197,17 @@ function isHandle(s) {
|
|
|
27175
27197
|
return !parseId(s) && HANDLE_RE.test(s);
|
|
27176
27198
|
}
|
|
27177
27199
|
async function resolveRef(env, input) {
|
|
27178
|
-
|
|
27200
|
+
return (await resolveRefDetail(env, input)).ref;
|
|
27201
|
+
}
|
|
27202
|
+
async function resolveRefDetail(env, input) {
|
|
27203
|
+
if (!isHandle(input)) return { ref: input, unreachable: false };
|
|
27179
27204
|
try {
|
|
27180
27205
|
const r = await fetch(`${env.apiBase}/v1/skills/resolve?handle=${encodeURIComponent(input)}`, { signal: AbortSignal.timeout(5e3) });
|
|
27181
|
-
if (!r.ok) return input;
|
|
27206
|
+
if (!r.ok) return { ref: input, unreachable: r.status >= 500 };
|
|
27182
27207
|
const out = await r.json();
|
|
27183
|
-
return typeof out.id === "string" && parseId(out.id) ? out.id : input;
|
|
27208
|
+
return { ref: typeof out.id === "string" && parseId(out.id) ? out.id : input, unreachable: false };
|
|
27184
27209
|
} catch {
|
|
27185
|
-
return input;
|
|
27210
|
+
return { ref: input, unreachable: true };
|
|
27186
27211
|
}
|
|
27187
27212
|
}
|
|
27188
27213
|
function ownId(env, name) {
|
|
@@ -27253,13 +27278,13 @@ function sharedOptOut(dir) {
|
|
|
27253
27278
|
}
|
|
27254
27279
|
function shareNotice(id, dir, draft, reported) {
|
|
27255
27280
|
if (draft) {
|
|
27256
|
-
console.error(
|
|
27281
|
+
console.error(`Note: skills in the drafts directory are not shared. Move it to ${SKILLS_DIR}/ and others will be able to find and install it.`);
|
|
27257
27282
|
} else if (sharedOptOut(dir)) {
|
|
27258
|
-
console.error(
|
|
27283
|
+
console.error(`Note: ${id} sets share: false, so it is not shared with others.`);
|
|
27259
27284
|
} else if (!reported) {
|
|
27260
|
-
console.error(
|
|
27285
|
+
console.error(`Note: could not reach the server this time, so ${id} is not shared yet; it will retry on the next use.`);
|
|
27261
27286
|
} else {
|
|
27262
|
-
console.error(
|
|
27287
|
+
console.error(`Note: the version you just used will be shared with others under your name once the server verifies it: ${id}. To opt out, add share: false to the SKILL.md frontmatter.`);
|
|
27263
27288
|
}
|
|
27264
27289
|
}
|
|
27265
27290
|
|
|
@@ -27274,32 +27299,32 @@ async function cmdAdd(idOrName, opts) {
|
|
|
27274
27299
|
return graduate(env, name, target, opts);
|
|
27275
27300
|
}
|
|
27276
27301
|
if (!parsed) {
|
|
27277
|
-
console.log(`"${idOrName}"
|
|
27302
|
+
console.log(`"${idOrName}" is not an id; searching by name. Pick an id from the results and run add again:`);
|
|
27278
27303
|
await cmdFind(idOrName, { limit: 5, json: false });
|
|
27279
27304
|
return 1;
|
|
27280
27305
|
}
|
|
27281
27306
|
if (parsed.spaceId === env.spaceId) {
|
|
27282
|
-
console.error(`${idOrName}
|
|
27307
|
+
console.error(`${idOrName} is a skill in your own space; no need to install it (it is in ${join3(".agents/skills", name)}/ or your drafts).`);
|
|
27283
27308
|
return 1;
|
|
27284
27309
|
}
|
|
27285
27310
|
let archive;
|
|
27286
27311
|
try {
|
|
27287
27312
|
archive = await fetchArchive(env, idOrName);
|
|
27288
27313
|
} catch (e) {
|
|
27289
|
-
console.error(e instanceof ArchiveNotFound ? `${e.message}
|
|
27314
|
+
console.error(e instanceof ArchiveNotFound ? `${e.message}. Try neta-search skills find first.` : String(e instanceof Error ? e.message : e));
|
|
27290
27315
|
return 1;
|
|
27291
27316
|
}
|
|
27292
27317
|
mkdirSync2(opts.dir, { recursive: true });
|
|
27293
27318
|
writeSkill(target, archive.files, { id: archive.id, digest: archive.digest, handle: archive.handle });
|
|
27294
27319
|
const report = reportSkillEvent(env, "install", archive.id, archive.digest, name);
|
|
27295
27320
|
if (opts.json) console.log(JSON.stringify({ installed: archive.id, handle: archive.handle, path: target, digest: archive.digest }));
|
|
27296
|
-
else console.log(
|
|
27321
|
+
else console.log(`Installed ${displayRef(archive)} \u2192 ${target}`);
|
|
27297
27322
|
await report;
|
|
27298
27323
|
return 0;
|
|
27299
27324
|
}
|
|
27300
27325
|
async function graduate(env, name, target, opts) {
|
|
27301
27326
|
if (existsSync2(target)) {
|
|
27302
|
-
console.error(`${target}
|
|
27327
|
+
console.error(`${target} already exists; draft ${name} was not moved (deal with the existing directory first).`);
|
|
27303
27328
|
return 1;
|
|
27304
27329
|
}
|
|
27305
27330
|
mkdirSync2(opts.dir, { recursive: true });
|
|
@@ -27308,120 +27333,224 @@ async function graduate(env, name, target, opts) {
|
|
|
27308
27333
|
const digest = skillDirDigest(target);
|
|
27309
27334
|
const reported = await reportSkillEvent(env, "install", id, digest, name);
|
|
27310
27335
|
if (opts.json) console.log(JSON.stringify({ graduated: id, path: target, digest }));
|
|
27311
|
-
else console.log(
|
|
27336
|
+
else console.log(`Moved draft ${name} to ${target}`);
|
|
27312
27337
|
if (!env.anonymous) shareNotice(id, target, false, reported);
|
|
27313
27338
|
return 0;
|
|
27314
27339
|
}
|
|
27315
27340
|
|
|
27316
27341
|
// cli/src/skills/use.ts
|
|
27317
|
-
import { existsSync as existsSync3, readdirSync as readdirSync2, readFileSync as
|
|
27342
|
+
import { existsSync as existsSync3, readdirSync as readdirSync2, readFileSync as readFileSync4 } from "node:fs";
|
|
27318
27343
|
import { randomUUID } from "node:crypto";
|
|
27319
|
-
import { join as join4 } from "node:path";
|
|
27344
|
+
import { join as join4, resolve } from "node:path";
|
|
27345
|
+
|
|
27346
|
+
// cli/src/mounts.ts
|
|
27347
|
+
import { readFileSync as readFileSync3 } from "node:fs";
|
|
27348
|
+
var SOURCE_RE = /\/checkpoints\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\/latest\/?$/i;
|
|
27349
|
+
function mountsFile() {
|
|
27350
|
+
return process.env["NETASEARCH_MOUNTS_FILE"] ?? "/proc/mounts";
|
|
27351
|
+
}
|
|
27352
|
+
function unescape(s) {
|
|
27353
|
+
return s.replace(/\\([0-7]{3})/g, (_, o) => String.fromCharCode(parseInt(o, 8)));
|
|
27354
|
+
}
|
|
27355
|
+
function modMounts() {
|
|
27356
|
+
let text;
|
|
27357
|
+
try {
|
|
27358
|
+
text = readFileSync3(mountsFile(), "utf8");
|
|
27359
|
+
} catch {
|
|
27360
|
+
return [];
|
|
27361
|
+
}
|
|
27362
|
+
const out = [];
|
|
27363
|
+
for (const line of text.split("\n")) {
|
|
27364
|
+
const [src, dir] = line.split(" ");
|
|
27365
|
+
if (!src || !dir) continue;
|
|
27366
|
+
const m = SOURCE_RE.exec(unescape(src));
|
|
27367
|
+
if (m) out.push({ spaceId: m[1].toLowerCase(), dir: unescape(dir) });
|
|
27368
|
+
}
|
|
27369
|
+
return out;
|
|
27370
|
+
}
|
|
27371
|
+
|
|
27372
|
+
// cli/src/skills/use.ts
|
|
27320
27373
|
var FETCH_ROOT = process.env["NETASEARCH_FETCH_ROOT"] ?? join4("/tmp", "neta-skills");
|
|
27374
|
+
var WHERE_LABEL = {
|
|
27375
|
+
local: "from this space",
|
|
27376
|
+
mod: "from a mounted mod",
|
|
27377
|
+
cache: "from the local cache",
|
|
27378
|
+
fetched: "downloaded"
|
|
27379
|
+
};
|
|
27321
27380
|
async function cmdUse(idOrName, opts) {
|
|
27322
27381
|
const env = detectEnv();
|
|
27323
27382
|
const input = idOrName;
|
|
27324
|
-
|
|
27325
|
-
|
|
27383
|
+
const resolved = await resolveRefDetail(env, idOrName);
|
|
27384
|
+
idOrName = resolved.ref;
|
|
27326
27385
|
const parsed = parseId(idOrName);
|
|
27327
27386
|
const name = parsed?.name ?? idOrName;
|
|
27328
27387
|
const mine = !parsed || parsed.spaceId === env.spaceId;
|
|
27329
|
-
let
|
|
27330
|
-
|
|
27331
|
-
let
|
|
27388
|
+
let handle = isHandle(input) && parsed ? input.toLowerCase() : void 0;
|
|
27389
|
+
const via = opts.via ? opts.via.slice(0, 32) : null;
|
|
27390
|
+
let viaPointer = false;
|
|
27391
|
+
const entry = opts.entry ? opts.entry.slice(0, 128) : null;
|
|
27332
27392
|
let notice = null;
|
|
27393
|
+
let found = null;
|
|
27333
27394
|
let fetchId = parsed && !mine ? idOrName : null;
|
|
27334
|
-
let via = opts.via ? opts.via.slice(0, 32) : null;
|
|
27335
27395
|
const installed = join4(SKILLS_DIR, name);
|
|
27336
27396
|
const draft = join4(DRAFTS_DIR, name);
|
|
27337
27397
|
if (skillDirExists(installed)) {
|
|
27338
27398
|
const src = readSource(installed);
|
|
27339
27399
|
if (src && (!parsed || src.id === idOrName)) {
|
|
27340
|
-
|
|
27341
|
-
reportId = src.id;
|
|
27400
|
+
found = { path: installed, where: "local", reportId: src.id };
|
|
27342
27401
|
handle = handle ?? src.handle;
|
|
27343
27402
|
} else if (!src && mine) {
|
|
27344
|
-
|
|
27345
|
-
reportId = ownId(env, name);
|
|
27403
|
+
found = { path: installed, where: "local", reportId: ownId(env, name) };
|
|
27346
27404
|
notice = "shared";
|
|
27347
27405
|
}
|
|
27348
27406
|
}
|
|
27349
|
-
if (!
|
|
27350
|
-
|
|
27351
|
-
reportId = ownId(env, name);
|
|
27407
|
+
if (!found && mine && skillDirExists(draft)) {
|
|
27408
|
+
found = { path: draft, where: "local", reportId: ownId(env, name) };
|
|
27352
27409
|
notice = "draft";
|
|
27353
27410
|
}
|
|
27354
|
-
if (!
|
|
27355
|
-
const
|
|
27356
|
-
if (
|
|
27357
|
-
|
|
27358
|
-
where = "mod";
|
|
27359
|
-
}
|
|
27411
|
+
if (!found) {
|
|
27412
|
+
const r = findInMounts(parsed?.spaceId ?? null, name);
|
|
27413
|
+
if (r === "ambiguous") return 1;
|
|
27414
|
+
if (r) found = r;
|
|
27360
27415
|
}
|
|
27361
|
-
if (
|
|
27362
|
-
const target = pointerTarget(path);
|
|
27416
|
+
if (found) {
|
|
27417
|
+
const target = pointerTarget(found.path);
|
|
27363
27418
|
if (target !== null) {
|
|
27364
27419
|
if (!parseId(target)) {
|
|
27365
|
-
console.error(`${join4(path, "SKILL.md")}
|
|
27420
|
+
console.error(`${join4(found.path, "SKILL.md")} is a pointer, but its neta-skill-id is not a valid id: ${target}`);
|
|
27366
27421
|
return 1;
|
|
27367
27422
|
}
|
|
27368
|
-
|
|
27423
|
+
viaPointer = true;
|
|
27369
27424
|
fetchId = target;
|
|
27370
|
-
|
|
27371
|
-
reportId = null;
|
|
27425
|
+
found = null;
|
|
27372
27426
|
notice = null;
|
|
27427
|
+
const p = parseId(target);
|
|
27428
|
+
const r = findInMounts(p.spaceId, p.name);
|
|
27429
|
+
if (r && r !== "ambiguous" && pointerTarget(r.path) === null) {
|
|
27430
|
+
found = r;
|
|
27431
|
+
fetchId = null;
|
|
27432
|
+
}
|
|
27373
27433
|
}
|
|
27374
27434
|
}
|
|
27375
|
-
if (!
|
|
27376
|
-
|
|
27377
|
-
|
|
27378
|
-
|
|
27379
|
-
|
|
27380
|
-
|
|
27381
|
-
|
|
27382
|
-
|
|
27383
|
-
|
|
27384
|
-
path = join4(FETCH_ROOT, p.spaceId, p.name);
|
|
27385
|
-
const have = readSource(path);
|
|
27386
|
-
if (!skillDirExists(path) || have?.digest !== a.digest) writeSkill(path, a.files, { id: a.id, digest: a.digest, handle: a.handle });
|
|
27387
|
-
reportId = a.id;
|
|
27388
|
-
handle = a.handle ?? handle;
|
|
27389
|
-
where = "fetched";
|
|
27390
|
-
} catch (e) {
|
|
27391
|
-
console.error(e instanceof ArchiveNotFound ? `${e.message}\u3002` : String(e instanceof Error ? e.message : e));
|
|
27435
|
+
if (!found && fetchId) {
|
|
27436
|
+
const r = await fromCacheOrDownload(env, fetchId);
|
|
27437
|
+
if (!r) return 1;
|
|
27438
|
+
found = r.found;
|
|
27439
|
+
handle = r.handle ?? handle;
|
|
27440
|
+
}
|
|
27441
|
+
if (!found) {
|
|
27442
|
+
if (resolved.unreachable) {
|
|
27443
|
+
console.error(`Cannot reach the server (${env.apiBase}), so handle "${input}" could not be resolved. Try again later; if the mod is mounted here, you can read /mods/<mod>/.agents/skills/<name>/SKILL.md directly.`);
|
|
27392
27444
|
return 1;
|
|
27393
27445
|
}
|
|
27394
|
-
|
|
27395
|
-
if (!path) {
|
|
27396
|
-
console.error(`skill "${idOrName}" \u672C\u5730\u6CA1\u6709\u2014\u2014\u5148 neta-search skills find "${name}" \u62FF\u5230 id\u3002`);
|
|
27446
|
+
console.error(`Skill "${idOrName}" is not available locally. Run neta-search skills find "${name}" to get its id.`);
|
|
27397
27447
|
return 1;
|
|
27398
27448
|
}
|
|
27399
27449
|
const useId = randomUUID();
|
|
27400
|
-
const extra = { use_id: useId };
|
|
27450
|
+
const extra = { use_id: useId, where: found.where };
|
|
27401
27451
|
if (via) extra["via"] = via;
|
|
27402
|
-
|
|
27403
|
-
const
|
|
27452
|
+
if (entry) extra["entry"] = entry;
|
|
27453
|
+
const digest = found.where === "mod" ? "" : found.digest ?? skillDirDigest(found.path);
|
|
27454
|
+
const reported = found.reportId ? await reportSkillEvent(env, "use", found.reportId, digest, name, extra) : false;
|
|
27455
|
+
const skillMd = readFileSync4(join4(found.path, "SKILL.md"), "utf8");
|
|
27456
|
+
const dir = resolve(found.path);
|
|
27457
|
+
const shown = handle ?? found.reportId ?? name;
|
|
27404
27458
|
if (opts.json) {
|
|
27405
|
-
console.log(
|
|
27459
|
+
console.log(
|
|
27460
|
+
JSON.stringify({
|
|
27461
|
+
skill: found.reportId ?? name,
|
|
27462
|
+
handle,
|
|
27463
|
+
path: dir,
|
|
27464
|
+
where: found.where,
|
|
27465
|
+
entry: entry ?? void 0,
|
|
27466
|
+
use_id: found.reportId ? useId : void 0,
|
|
27467
|
+
skill_md: skillMd
|
|
27468
|
+
})
|
|
27469
|
+
);
|
|
27406
27470
|
} else {
|
|
27407
|
-
|
|
27408
|
-
console.log(
|
|
27409
|
-
|
|
27410
|
-
console.log(
|
|
27411
|
-
|
|
27412
|
-
|
|
27413
|
-
|
|
27414
|
-
|
|
27415
|
-
|
|
27471
|
+
console.log(`You are being given a skill to execute for the user's request: ${shown} (${WHERE_LABEL[found.where]}${viaPointer ? ", via a pointer" : ""}).`);
|
|
27472
|
+
console.log(`Use the following SKILL.md as your instructions:
|
|
27473
|
+
`);
|
|
27474
|
+
console.log(`<SKILL.md>
|
|
27475
|
+
${skillMd}${skillMd.endsWith("\n") ? "" : "\n"}</SKILL.md>
|
|
27476
|
+
`);
|
|
27477
|
+
console.log(`Skill directory: ${dir}`);
|
|
27478
|
+
console.log(`When the SKILL.md references relative paths, read them from that directory.`);
|
|
27479
|
+
}
|
|
27480
|
+
if (notice && found.reportId && !env.anonymous) shareNotice(found.reportId, found.path, notice === "draft", reported);
|
|
27416
27481
|
return 0;
|
|
27417
27482
|
}
|
|
27418
|
-
function
|
|
27419
|
-
if (
|
|
27420
|
-
|
|
27421
|
-
|
|
27422
|
-
|
|
27483
|
+
function findInMounts(spaceId, name) {
|
|
27484
|
+
if (name.includes("/") || name.startsWith(".")) return null;
|
|
27485
|
+
const mounts = modMounts();
|
|
27486
|
+
if (spaceId) {
|
|
27487
|
+
for (const m of mounts) {
|
|
27488
|
+
const p = join4(m.dir, ".agents/skills", name);
|
|
27489
|
+
if (m.spaceId === spaceId && skillDirExists(p)) return { path: p, where: "mod", reportId: `cohub:${spaceId}/${name}` };
|
|
27490
|
+
}
|
|
27491
|
+
return null;
|
|
27492
|
+
}
|
|
27493
|
+
const hits = [];
|
|
27494
|
+
const seen = /* @__PURE__ */ new Set();
|
|
27495
|
+
for (const m of mounts) {
|
|
27496
|
+
seen.add(resolve(m.dir));
|
|
27497
|
+
const p = join4(m.dir, ".agents/skills", name);
|
|
27498
|
+
if (skillDirExists(p)) hits.push({ path: p, where: "mod", reportId: `cohub:${m.spaceId}/${name}` });
|
|
27499
|
+
}
|
|
27500
|
+
if (existsSync3("/mods")) {
|
|
27501
|
+
for (const d of readdirSync2("/mods")) {
|
|
27502
|
+
const dir = join4("/mods", d);
|
|
27503
|
+
if (seen.has(resolve(dir))) continue;
|
|
27504
|
+
const p = join4(dir, ".agents/skills", name);
|
|
27505
|
+
if (skillDirExists(p)) hits.push({ path: p, where: "mod", reportId: null });
|
|
27506
|
+
}
|
|
27507
|
+
}
|
|
27508
|
+
if (hits.length > 1) {
|
|
27509
|
+
console.error(`${hits.length} mounted mods each have a different skill named ${name}:`);
|
|
27510
|
+
for (const h of hits) console.error(` ${h.path}${h.reportId ? ` (${h.reportId})` : ""}`);
|
|
27511
|
+
console.error(`Use a handle (<prefix>/${name}) to pick one; neta-search skills find "${name}" shows each handle.`);
|
|
27512
|
+
return "ambiguous";
|
|
27513
|
+
}
|
|
27514
|
+
return hits[0] ?? null;
|
|
27515
|
+
}
|
|
27516
|
+
async function fromCacheOrDownload(env, fetchId) {
|
|
27517
|
+
const p = parseId(fetchId);
|
|
27518
|
+
const cacheDir = join4(FETCH_ROOT, p.spaceId, p.name);
|
|
27519
|
+
const have = skillDirExists(cacheDir) ? readSource(cacheDir) : null;
|
|
27520
|
+
let head;
|
|
27521
|
+
try {
|
|
27522
|
+
head = await archiveHead(env, fetchId);
|
|
27523
|
+
} catch (e) {
|
|
27524
|
+
if (have) {
|
|
27525
|
+
console.error(`Note: cannot reach the server (${e instanceof Error ? e.message : e}); using the cached copy, which may not be the latest.`);
|
|
27526
|
+
return { found: { path: cacheDir, where: "cache", reportId: have.id, digest: have.digest }, handle: have.handle };
|
|
27527
|
+
}
|
|
27528
|
+
console.error(String(e instanceof Error ? e.message : e));
|
|
27529
|
+
return null;
|
|
27530
|
+
}
|
|
27531
|
+
if (head === null) {
|
|
27532
|
+
console.error(`${fetchId} does not exist or has no released version.`);
|
|
27533
|
+
return null;
|
|
27534
|
+
}
|
|
27535
|
+
if (have && have.digest === head.digest) {
|
|
27536
|
+
if (head.handle && head.handle !== have.handle) writeSource(cacheDir, { ...have, handle: head.handle });
|
|
27537
|
+
return { found: { path: cacheDir, where: "cache", reportId: have.id, digest: have.digest }, handle: head.handle ?? have.handle };
|
|
27538
|
+
}
|
|
27539
|
+
try {
|
|
27540
|
+
const a = await fetchArchive(env, fetchId);
|
|
27541
|
+
const skillMd = a.files.find((f) => f.path === "SKILL.md");
|
|
27542
|
+
if (skillMd && pointerTargetOf(skillMd.data.toString("utf8")) !== null) {
|
|
27543
|
+
console.error(`${fetchId} downloaded as another pointer; stopping here (pointers are followed only one level, to avoid loops).`);
|
|
27544
|
+
return null;
|
|
27545
|
+
}
|
|
27546
|
+
const q = parseId(a.id);
|
|
27547
|
+
const path = join4(FETCH_ROOT, q.spaceId, q.name);
|
|
27548
|
+
writeSkill(path, a.files, { id: a.id, digest: a.digest, handle: a.handle });
|
|
27549
|
+
return { found: { path, where: "fetched", reportId: a.id, digest: a.digest }, handle: a.handle };
|
|
27550
|
+
} catch (e) {
|
|
27551
|
+
console.error(e instanceof ArchiveNotFound ? `${e.message}.` : String(e instanceof Error ? e.message : e));
|
|
27552
|
+
return null;
|
|
27423
27553
|
}
|
|
27424
|
-
return null;
|
|
27425
27554
|
}
|
|
27426
27555
|
|
|
27427
27556
|
// cli/src/skills/init.ts
|
|
@@ -27429,50 +27558,50 @@ import { existsSync as existsSync4, mkdirSync as mkdirSync3, writeFileSync as wr
|
|
|
27429
27558
|
import { join as join5 } from "node:path";
|
|
27430
27559
|
async function cmdInit(name, opts) {
|
|
27431
27560
|
if (!name) {
|
|
27432
|
-
console.error(
|
|
27561
|
+
console.error(`Usage: neta-search skills init <name> (kebab-case, e.g. brawl-creator).`);
|
|
27433
27562
|
return 1;
|
|
27434
27563
|
}
|
|
27435
27564
|
const slug = name;
|
|
27436
27565
|
if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(slug)) {
|
|
27437
|
-
console.error(`
|
|
27566
|
+
console.error(`Skill names must be kebab-case (e.g. brawl-creator), got "${slug}".`);
|
|
27438
27567
|
return 1;
|
|
27439
27568
|
}
|
|
27440
27569
|
const dir = opts.here ? "." : join5(".agents", "skills-drafts", slug);
|
|
27441
27570
|
const target = join5(dir, "SKILL.md");
|
|
27442
27571
|
if (existsSync4(target)) {
|
|
27443
|
-
console.error(`${target}
|
|
27572
|
+
console.error(`${target} already exists; init does not overwrite it.`);
|
|
27444
27573
|
return 1;
|
|
27445
27574
|
}
|
|
27446
27575
|
mkdirSync3(dir, { recursive: true });
|
|
27447
27576
|
writeFileSync2(target, template(slug));
|
|
27448
|
-
console.log(
|
|
27577
|
+
console.log(`Created ${target} (drafts directory: not loaded into the agent's skills while you write it)`);
|
|
27449
27578
|
console.log(`
|
|
27450
|
-
|
|
27451
|
-
console.log(` 1.
|
|
27452
|
-
console.log(` 2. neta-search skills use ${slug}
|
|
27453
|
-
console.log(` 3.
|
|
27454
|
-
console.log(`
|
|
27579
|
+
Next steps:`);
|
|
27580
|
+
console.log(` 1. Edit SKILL.md. Make the description say when to use this skill; agents decide by it, and search matches on it.`);
|
|
27581
|
+
console.log(` 2. Try it: neta-search skills use ${slug} (drafts work directly and are not shared)`);
|
|
27582
|
+
console.log(` 3. When it is ready: neta-search skills add ${slug} moves it to .agents/skills/; versions you use from there are shared with others`);
|
|
27583
|
+
console.log(` (under your name; to opt out, add share: false to the frontmatter)`);
|
|
27455
27584
|
return 0;
|
|
27456
27585
|
}
|
|
27457
27586
|
function template(slug) {
|
|
27458
27587
|
return `---
|
|
27459
27588
|
name: ${slug}
|
|
27460
|
-
description:
|
|
27589
|
+
description: One sentence on when to use this skill (what a user would search for). Search matches on this field.
|
|
27461
27590
|
metadata:
|
|
27462
27591
|
neta-scope: universal # character|world|image|video|audio|text|universal
|
|
27463
|
-
# neta-tags: [] #
|
|
27464
|
-
# disable-model-invocation: true #
|
|
27592
|
+
# neta-tags: [] # optional: your own tags (the server adds coarse tags too)
|
|
27593
|
+
# disable-model-invocation: true # optional: hide from the agent's skill list; only runs when named explicitly or via use
|
|
27465
27594
|
---
|
|
27466
27595
|
|
|
27467
27596
|
# ${slug}
|
|
27468
27597
|
|
|
27469
|
-
##
|
|
27598
|
+
## What it does
|
|
27470
27599
|
|
|
27471
|
-
|
|
27600
|
+
(What it does and who it is for.)
|
|
27472
27601
|
|
|
27473
|
-
##
|
|
27602
|
+
## How to use it
|
|
27474
27603
|
|
|
27475
|
-
|
|
27604
|
+
(How to call it, inputs and outputs, examples.)
|
|
27476
27605
|
`;
|
|
27477
27606
|
}
|
|
27478
27607
|
|
|
@@ -27515,8 +27644,8 @@ async function statusOf(env, s) {
|
|
|
27515
27644
|
return { status: "unknown", error: e instanceof Error ? e.message : String(e) };
|
|
27516
27645
|
}
|
|
27517
27646
|
}
|
|
27518
|
-
var KIND_LABEL = { installed: "
|
|
27519
|
-
var STATUS_LABEL = { latest: "
|
|
27647
|
+
var KIND_LABEL = { installed: "installed", pointer: "pointer", own: "your own" };
|
|
27648
|
+
var STATUS_LABEL = { latest: "latest", outdated: "update available", unavailable: "no longer available", unknown: "" };
|
|
27520
27649
|
async function cmdList(opts) {
|
|
27521
27650
|
const env = detectEnv();
|
|
27522
27651
|
const local = scanLocal(opts.dir);
|
|
@@ -27531,10 +27660,10 @@ async function cmdList(opts) {
|
|
|
27531
27660
|
return 0;
|
|
27532
27661
|
}
|
|
27533
27662
|
if (rows.length === 0) {
|
|
27534
|
-
console.log(
|
|
27663
|
+
console.log(`No skills in ${opts.dir}/. Find one with neta-search skills find <what you want>, then add it.`);
|
|
27535
27664
|
return 0;
|
|
27536
27665
|
}
|
|
27537
|
-
console.log(`${opts.dir}
|
|
27666
|
+
console.log(`${opts.dir}/ (${rows.length}):`);
|
|
27538
27667
|
for (const r of rows) {
|
|
27539
27668
|
const st = STATUS_LABEL[r.status] ? ` [${STATUS_LABEL[r.status]}]` : "";
|
|
27540
27669
|
const from = r.id ? ` ${displayRef(r)}` : "";
|
|
@@ -27542,7 +27671,7 @@ async function cmdList(opts) {
|
|
|
27542
27671
|
}
|
|
27543
27672
|
const outdated = rows.filter((r) => r.status === "outdated").length;
|
|
27544
27673
|
if (outdated > 0) console.log(`
|
|
27545
|
-
${outdated}
|
|
27674
|
+
${outdated} with updates available: neta-search skills update`);
|
|
27546
27675
|
return 0;
|
|
27547
27676
|
}
|
|
27548
27677
|
async function cmdUpdate(names, opts) {
|
|
@@ -27596,15 +27725,15 @@ async function cmdUpdate(names, opts) {
|
|
|
27596
27725
|
console.log(JSON.stringify({ results }));
|
|
27597
27726
|
return failed > 0 ? 1 : 0;
|
|
27598
27727
|
}
|
|
27599
|
-
if (results.length === 0) console.log(
|
|
27728
|
+
if (results.length === 0) console.log(`No installed skills in ${opts.dir}/; nothing to update.`);
|
|
27600
27729
|
const say = {
|
|
27601
|
-
updated: (r) =>
|
|
27602
|
-
latest: (r) => `${r.name}
|
|
27603
|
-
unavailable: (r) => `${r.name}
|
|
27604
|
-
own_skipped: (r) => `${r.name}
|
|
27605
|
-
pointer_skipped: (r) => `${r.name}
|
|
27606
|
-
not_found: (r) => `${opts.dir}/${r.name}
|
|
27607
|
-
error: (r) =>
|
|
27730
|
+
updated: (r) => `Updated ${r.name} (${short(r.from)} \u2192 ${short(r.to)})`,
|
|
27731
|
+
latest: (r) => `${r.name} is up to date`,
|
|
27732
|
+
unavailable: (r) => `${r.name} is no longer available from its source; keeping the local copy`,
|
|
27733
|
+
own_skipped: (r) => `${r.name} is your own skill; nothing to update`,
|
|
27734
|
+
pointer_skipped: (r) => `${r.name} is a pointer; use always fetches the latest, nothing to update`,
|
|
27735
|
+
not_found: (r) => `${opts.dir}/${r.name} does not exist`,
|
|
27736
|
+
error: (r) => `Failed to update ${r.name}: ${r.from ?? ""}`
|
|
27608
27737
|
};
|
|
27609
27738
|
for (const r of results) console.log(say[r.result](r));
|
|
27610
27739
|
return failed > 0 ? 1 : 0;
|
|
@@ -27632,51 +27761,36 @@ async function cmdRemove(names, opts) {
|
|
|
27632
27761
|
if (opts.json) console.log(JSON.stringify({ results }));
|
|
27633
27762
|
else
|
|
27634
27763
|
for (const r of results) {
|
|
27635
|
-
if (r.result === "removed") console.log(
|
|
27636
|
-
else if (r.result === "not_found") console.error(`${join6(opts.dir, r.name)}
|
|
27637
|
-
else console.error(`${r.name}
|
|
27764
|
+
if (r.result === "removed") console.log(`Removed ${join6(opts.dir, r.name)}`);
|
|
27765
|
+
else if (r.result === "not_found") console.error(`${join6(opts.dir, r.name)} does not exist`);
|
|
27766
|
+
else console.error(`${r.name} is a skill you wrote yourself (no install source), so it was not removed. Add --force if you really want to delete it.`);
|
|
27638
27767
|
}
|
|
27639
27768
|
return failed > 0 ? 1 : 0;
|
|
27640
27769
|
}
|
|
27641
27770
|
|
|
27642
|
-
// cli/src/version.ts
|
|
27643
|
-
import { createRequire } from "node:module";
|
|
27644
|
-
var OUR_NAMES = /* @__PURE__ */ new Set(["@neta-search/cli", "@neta-art/neta-search-cli"]);
|
|
27645
|
-
function cliVersion() {
|
|
27646
|
-
const req = createRequire(import.meta.url);
|
|
27647
|
-
for (const p of ["./package.json", "../package.json"]) {
|
|
27648
|
-
try {
|
|
27649
|
-
const pkg = req(p);
|
|
27650
|
-
if (pkg.name && OUR_NAMES.has(pkg.name) && pkg.version) return pkg.version;
|
|
27651
|
-
} catch {
|
|
27652
|
-
}
|
|
27653
|
-
}
|
|
27654
|
-
return "0.0.0-unknown";
|
|
27655
|
-
}
|
|
27656
|
-
|
|
27657
27771
|
// cli/src/cli.ts
|
|
27658
27772
|
var program2 = new Command();
|
|
27659
|
-
program2.name("neta-search").description("neta-search
|
|
27660
|
-
var skills = program2.command("skills").description("
|
|
27661
|
-
skills.command("find").description("
|
|
27773
|
+
program2.name("neta-search").description("neta-search: search the Cohub skill ecosystem").version(cliVersion());
|
|
27774
|
+
var skills = program2.command("skills").description("skills: find / add / use / list / update / remove / init");
|
|
27775
|
+
skills.command("find").description("search the ecosystem for skills").argument("<query>", "what you want to do (natural language or keywords)").option("-n, --limit <n>", "max results", "20").option("--json", "compact JSON output (for agents)").action(async (query, opts) => {
|
|
27662
27776
|
await run(cmdFind(query, { limit: Number(opts.limit) || 20, json: opts.json }));
|
|
27663
27777
|
});
|
|
27664
|
-
skills.command("add").description("
|
|
27778
|
+
skills.command("add").description("install a skill: an id or handle from find downloads its current release; a name from your drafts moves it into .agents/skills/").argument("<id-or-name>", "skill id or handle from find (e.g. neta-skills/holo-pack-opening), or the name of one of your drafts").option("--dir <dir>", "install directory", ".agents/skills").option("--json", "compact JSON output (for agents)").action(async (idOrName, opts) => {
|
|
27665
27779
|
await run(cmdAdd(idOrName, opts));
|
|
27666
27780
|
});
|
|
27667
|
-
skills.command("use").description("
|
|
27781
|
+
skills.command("use").description("use a skill without installing it: prints the full SKILL.md and the skill directory (local copy, mounted mod, cache, or download)").argument("<id-or-name>", "skill id, handle (e.g. neta-skills/holo-pack-opening), or local skill name").option("--json", "compact JSON output (for agents)").option("--via <channel>", "where this use came from, recorded in usage stats (site / board-menu / picker / find)").option("--entry <id>", "entry id (picker / menu entry), recorded in usage stats").action(async (idOrName, opts) => {
|
|
27668
27782
|
await run(cmdUse(idOrName, opts));
|
|
27669
27783
|
});
|
|
27670
|
-
skills.command("list").alias("ls").description("
|
|
27784
|
+
skills.command("list").alias("ls").description("list local skills (installed / pointer / your own) and check installed ones for updates").option("--dir <dir>", "skills directory", ".agents/skills").option("--offline", "do not check for updates online").option("--json", "compact JSON output (for agents)").action(async (opts) => {
|
|
27671
27785
|
await run(cmdList({ dir: opts.dir, offline: !!opts.offline, json: !!opts.json }));
|
|
27672
27786
|
});
|
|
27673
|
-
skills.command("update").description("
|
|
27787
|
+
skills.command("update").description("update installed skills to their current release (no names = all; your own skills and pointers are left alone)").argument("[names...]", "skills to update: directory name, handle (e.g. neta-skills/holo-pack-opening), or id").option("--dir <dir>", "skills directory", ".agents/skills").option("--json", "compact JSON output (for agents)").action(async (names, opts) => {
|
|
27674
27788
|
await run(cmdUpdate(names, { dir: opts.dir, json: !!opts.json }));
|
|
27675
27789
|
});
|
|
27676
|
-
skills.command("remove").alias("rm").description("
|
|
27790
|
+
skills.command("remove").alias("rm").description("remove local skills (installed / pointer; your own need --force)").argument("<names...>", "skills to remove: directory name, handle, or id").option("--dir <dir>", "skills directory", ".agents/skills").option("--force", "also remove skills you wrote yourself").option("--json", "compact JSON output (for agents)").action(async (names, opts) => {
|
|
27677
27791
|
await run(cmdRemove(names, { dir: opts.dir, force: !!opts.force, json: !!opts.json }));
|
|
27678
27792
|
});
|
|
27679
|
-
skills.command("init").description("
|
|
27793
|
+
skills.command("init").description("scaffold a new skill (SKILL.md with frontmatter)").argument("[name]", "skill name (kebab-case)").option("--here", "create SKILL.md in the current directory instead of the drafts directory").action(async (name, opts) => {
|
|
27680
27794
|
await run(cmdInit(name, opts));
|
|
27681
27795
|
});
|
|
27682
27796
|
async function run(p) {
|
|
@@ -27684,7 +27798,7 @@ async function run(p) {
|
|
|
27684
27798
|
process.exit(code);
|
|
27685
27799
|
}
|
|
27686
27800
|
process.on("unhandledRejection", (err) => {
|
|
27687
|
-
console.error(import_picocolors.default.red(
|
|
27801
|
+
console.error(import_picocolors.default.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
27688
27802
|
process.exit(1);
|
|
27689
27803
|
});
|
|
27690
27804
|
program2.parseAsync();
|