@lobehub/cli 0.0.1-canary.8 → 0.0.1-canary.9
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/dist/index.js +996 -249
- package/package.json +7 -5
package/dist/index.js
CHANGED
|
@@ -348,27 +348,27 @@ var noop = () => {
|
|
|
348
348
|
var freezeIfAvailable = (obj) => {
|
|
349
349
|
if (Object.freeze) Object.freeze(obj);
|
|
350
350
|
};
|
|
351
|
-
function createInnerProxy(callback,
|
|
351
|
+
function createInnerProxy(callback, path13, memo) {
|
|
352
352
|
var _memo$cacheKey;
|
|
353
|
-
const cacheKey =
|
|
353
|
+
const cacheKey = path13.join(".");
|
|
354
354
|
(_memo$cacheKey = memo[cacheKey]) !== null && _memo$cacheKey !== void 0 || (memo[cacheKey] = new Proxy(noop, {
|
|
355
355
|
get(_obj, key) {
|
|
356
356
|
if (typeof key !== "string" || key === "then") return void 0;
|
|
357
|
-
return createInnerProxy(callback, [...
|
|
357
|
+
return createInnerProxy(callback, [...path13, key], memo);
|
|
358
358
|
},
|
|
359
359
|
apply(_1, _2, args) {
|
|
360
|
-
const lastOfPath =
|
|
360
|
+
const lastOfPath = path13[path13.length - 1];
|
|
361
361
|
let opts = {
|
|
362
362
|
args,
|
|
363
|
-
path:
|
|
363
|
+
path: path13
|
|
364
364
|
};
|
|
365
365
|
if (lastOfPath === "call") opts = {
|
|
366
366
|
args: args.length >= 2 ? [args[1]] : [],
|
|
367
|
-
path:
|
|
367
|
+
path: path13.slice(0, -1)
|
|
368
368
|
};
|
|
369
369
|
else if (lastOfPath === "apply") opts = {
|
|
370
370
|
args: args.length >= 2 ? args[1] : [],
|
|
371
|
-
path:
|
|
371
|
+
path: path13.slice(0, -1)
|
|
372
372
|
};
|
|
373
373
|
freezeIfAvailable(opts.args);
|
|
374
374
|
freezeIfAvailable(opts.path);
|
|
@@ -700,11 +700,11 @@ function httpLink(opts) {
|
|
|
700
700
|
return (operationOpts) => {
|
|
701
701
|
const { op } = operationOpts;
|
|
702
702
|
return observable((observer) => {
|
|
703
|
-
const { path:
|
|
703
|
+
const { path: path13, input, type } = op;
|
|
704
704
|
if (type === "subscription") throw new Error("Subscriptions are unsupported by `httpLink` - use `httpSubscriptionLink` or `wsLink`");
|
|
705
705
|
const request = universalRequester((0, import_objectSpread25.default)((0, import_objectSpread25.default)({}, resolvedOpts), {}, {
|
|
706
706
|
type,
|
|
707
|
-
path:
|
|
707
|
+
path: path13,
|
|
708
708
|
input,
|
|
709
709
|
signal: op.signal,
|
|
710
710
|
headers() {
|
|
@@ -925,28 +925,28 @@ var TRPCUntypedClient = class {
|
|
|
925
925
|
throw TRPCClientError.from(err);
|
|
926
926
|
}
|
|
927
927
|
}
|
|
928
|
-
query(
|
|
928
|
+
query(path13, input, opts) {
|
|
929
929
|
return this.requestAsPromise({
|
|
930
930
|
type: "query",
|
|
931
|
-
path:
|
|
931
|
+
path: path13,
|
|
932
932
|
input,
|
|
933
933
|
context: opts === null || opts === void 0 ? void 0 : opts.context,
|
|
934
934
|
signal: opts === null || opts === void 0 ? void 0 : opts.signal
|
|
935
935
|
});
|
|
936
936
|
}
|
|
937
|
-
mutation(
|
|
937
|
+
mutation(path13, input, opts) {
|
|
938
938
|
return this.requestAsPromise({
|
|
939
939
|
type: "mutation",
|
|
940
|
-
path:
|
|
940
|
+
path: path13,
|
|
941
941
|
input,
|
|
942
942
|
context: opts === null || opts === void 0 ? void 0 : opts.context,
|
|
943
943
|
signal: opts === null || opts === void 0 ? void 0 : opts.signal
|
|
944
944
|
});
|
|
945
945
|
}
|
|
946
|
-
subscription(
|
|
946
|
+
subscription(path13, input, opts) {
|
|
947
947
|
const observable$ = this.$request({
|
|
948
948
|
type: "subscription",
|
|
949
|
-
path:
|
|
949
|
+
path: path13,
|
|
950
950
|
input,
|
|
951
951
|
context: opts.context,
|
|
952
952
|
signal: opts.signal
|
|
@@ -998,8 +998,8 @@ var clientCallTypeToProcedureType = (clientCallType) => {
|
|
|
998
998
|
return clientCallTypeMap[clientCallType];
|
|
999
999
|
};
|
|
1000
1000
|
function createTRPCClientProxy(client) {
|
|
1001
|
-
const proxy = createRecursiveProxy(({ path:
|
|
1002
|
-
const pathCopy = [...
|
|
1001
|
+
const proxy = createRecursiveProxy(({ path: path13, args }) => {
|
|
1002
|
+
const pathCopy = [...path13];
|
|
1003
1003
|
const procedureType = clientCallTypeToProcedureType(pathCopy.pop());
|
|
1004
1004
|
const fullPath = pathCopy.join(".");
|
|
1005
1005
|
return client[procedureType](fullPath, ...args);
|
|
@@ -1367,7 +1367,7 @@ var isURL = (payload) => payload instanceof URL;
|
|
|
1367
1367
|
|
|
1368
1368
|
// node_modules/.pnpm/superjson@2.2.6/node_modules/superjson/dist/pathstringifier.js
|
|
1369
1369
|
var escapeKey = (key) => key.replace(/\\/g, "\\\\").replace(/\./g, "\\.");
|
|
1370
|
-
var stringifyPath = (
|
|
1370
|
+
var stringifyPath = (path13) => path13.map(String).map(escapeKey).join(".");
|
|
1371
1371
|
var parsePath = (string, legacyPaths) => {
|
|
1372
1372
|
const result = [];
|
|
1373
1373
|
let segment = "";
|
|
@@ -1614,26 +1614,26 @@ var getNthKey = (value, n) => {
|
|
|
1614
1614
|
}
|
|
1615
1615
|
return keys.next().value;
|
|
1616
1616
|
};
|
|
1617
|
-
function validatePath(
|
|
1618
|
-
if (includes(
|
|
1617
|
+
function validatePath(path13) {
|
|
1618
|
+
if (includes(path13, "__proto__")) {
|
|
1619
1619
|
throw new Error("__proto__ is not allowed as a property");
|
|
1620
1620
|
}
|
|
1621
|
-
if (includes(
|
|
1621
|
+
if (includes(path13, "prototype")) {
|
|
1622
1622
|
throw new Error("prototype is not allowed as a property");
|
|
1623
1623
|
}
|
|
1624
|
-
if (includes(
|
|
1624
|
+
if (includes(path13, "constructor")) {
|
|
1625
1625
|
throw new Error("constructor is not allowed as a property");
|
|
1626
1626
|
}
|
|
1627
1627
|
}
|
|
1628
|
-
var getDeep = (object,
|
|
1629
|
-
validatePath(
|
|
1630
|
-
for (let i = 0; i <
|
|
1631
|
-
const key =
|
|
1628
|
+
var getDeep = (object, path13) => {
|
|
1629
|
+
validatePath(path13);
|
|
1630
|
+
for (let i = 0; i < path13.length; i++) {
|
|
1631
|
+
const key = path13[i];
|
|
1632
1632
|
if (isSet(object)) {
|
|
1633
1633
|
object = getNthKey(object, +key);
|
|
1634
1634
|
} else if (isMap(object)) {
|
|
1635
1635
|
const row = +key;
|
|
1636
|
-
const type = +
|
|
1636
|
+
const type = +path13[++i] === 0 ? "key" : "value";
|
|
1637
1637
|
const keyOfRow = getNthKey(object, row);
|
|
1638
1638
|
switch (type) {
|
|
1639
1639
|
case "key":
|
|
@@ -1649,14 +1649,14 @@ var getDeep = (object, path12) => {
|
|
|
1649
1649
|
}
|
|
1650
1650
|
return object;
|
|
1651
1651
|
};
|
|
1652
|
-
var setDeep = (object,
|
|
1653
|
-
validatePath(
|
|
1654
|
-
if (
|
|
1652
|
+
var setDeep = (object, path13, mapper) => {
|
|
1653
|
+
validatePath(path13);
|
|
1654
|
+
if (path13.length === 0) {
|
|
1655
1655
|
return mapper(object);
|
|
1656
1656
|
}
|
|
1657
1657
|
let parent = object;
|
|
1658
|
-
for (let i = 0; i <
|
|
1659
|
-
const key =
|
|
1658
|
+
for (let i = 0; i < path13.length - 1; i++) {
|
|
1659
|
+
const key = path13[i];
|
|
1660
1660
|
if (isArray(parent)) {
|
|
1661
1661
|
const index = +key;
|
|
1662
1662
|
parent = parent[index];
|
|
@@ -1666,12 +1666,12 @@ var setDeep = (object, path12, mapper) => {
|
|
|
1666
1666
|
const row = +key;
|
|
1667
1667
|
parent = getNthKey(parent, row);
|
|
1668
1668
|
} else if (isMap(parent)) {
|
|
1669
|
-
const isEnd = i ===
|
|
1669
|
+
const isEnd = i === path13.length - 2;
|
|
1670
1670
|
if (isEnd) {
|
|
1671
1671
|
break;
|
|
1672
1672
|
}
|
|
1673
1673
|
const row = +key;
|
|
1674
|
-
const type = +
|
|
1674
|
+
const type = +path13[++i] === 0 ? "key" : "value";
|
|
1675
1675
|
const keyOfRow = getNthKey(parent, row);
|
|
1676
1676
|
switch (type) {
|
|
1677
1677
|
case "key":
|
|
@@ -1683,7 +1683,7 @@ var setDeep = (object, path12, mapper) => {
|
|
|
1683
1683
|
}
|
|
1684
1684
|
}
|
|
1685
1685
|
}
|
|
1686
|
-
const lastKey =
|
|
1686
|
+
const lastKey = path13[path13.length - 1];
|
|
1687
1687
|
if (isArray(parent)) {
|
|
1688
1688
|
parent[+lastKey] = mapper(parent[+lastKey]);
|
|
1689
1689
|
} else if (isPlainObject(parent)) {
|
|
@@ -1698,7 +1698,7 @@ var setDeep = (object, path12, mapper) => {
|
|
|
1698
1698
|
}
|
|
1699
1699
|
}
|
|
1700
1700
|
if (isMap(parent)) {
|
|
1701
|
-
const row = +
|
|
1701
|
+
const row = +path13[path13.length - 2];
|
|
1702
1702
|
const keyToRow = getNthKey(parent, row);
|
|
1703
1703
|
const type = +lastKey === 0 ? "key" : "value";
|
|
1704
1704
|
switch (type) {
|
|
@@ -1745,16 +1745,16 @@ function traverse(tree, walker2, version2, origin = []) {
|
|
|
1745
1745
|
walker2(nodeValue, origin);
|
|
1746
1746
|
}
|
|
1747
1747
|
function applyValueAnnotations(plain, annotations, version2, superJson) {
|
|
1748
|
-
traverse(annotations, (type,
|
|
1749
|
-
plain = setDeep(plain,
|
|
1748
|
+
traverse(annotations, (type, path13) => {
|
|
1749
|
+
plain = setDeep(plain, path13, (v) => untransformValue(v, type, superJson));
|
|
1750
1750
|
}, version2);
|
|
1751
1751
|
return plain;
|
|
1752
1752
|
}
|
|
1753
1753
|
function applyReferentialEqualityAnnotations(plain, annotations, version2) {
|
|
1754
1754
|
const legacyPaths = enableLegacyPaths(version2);
|
|
1755
|
-
function apply(identicalPaths,
|
|
1756
|
-
const object = getDeep(plain, parsePath(
|
|
1757
|
-
identicalPaths.map((
|
|
1755
|
+
function apply(identicalPaths, path13) {
|
|
1756
|
+
const object = getDeep(plain, parsePath(path13, legacyPaths));
|
|
1757
|
+
identicalPaths.map((path14) => parsePath(path14, legacyPaths)).forEach((identicalObjectPath) => {
|
|
1758
1758
|
plain = setDeep(plain, identicalObjectPath, () => object);
|
|
1759
1759
|
});
|
|
1760
1760
|
}
|
|
@@ -1772,12 +1772,12 @@ function applyReferentialEqualityAnnotations(plain, annotations, version2) {
|
|
|
1772
1772
|
return plain;
|
|
1773
1773
|
}
|
|
1774
1774
|
var isDeep = (object, superJson) => isPlainObject(object) || isArray(object) || isMap(object) || isSet(object) || isError(object) || isInstanceOfRegisteredClass(object, superJson);
|
|
1775
|
-
function addIdentity(object,
|
|
1775
|
+
function addIdentity(object, path13, identities) {
|
|
1776
1776
|
const existingSet = identities.get(object);
|
|
1777
1777
|
if (existingSet) {
|
|
1778
|
-
existingSet.push(
|
|
1778
|
+
existingSet.push(path13);
|
|
1779
1779
|
} else {
|
|
1780
|
-
identities.set(object, [
|
|
1780
|
+
identities.set(object, [path13]);
|
|
1781
1781
|
}
|
|
1782
1782
|
}
|
|
1783
1783
|
function generateReferentialEqualityAnnotations(identitites, dedupe) {
|
|
@@ -1788,7 +1788,7 @@ function generateReferentialEqualityAnnotations(identitites, dedupe) {
|
|
|
1788
1788
|
return;
|
|
1789
1789
|
}
|
|
1790
1790
|
if (!dedupe) {
|
|
1791
|
-
paths = paths.map((
|
|
1791
|
+
paths = paths.map((path13) => path13.map(String)).sort((a, b) => a.length - b.length);
|
|
1792
1792
|
}
|
|
1793
1793
|
const [representativePath, ...identicalPaths] = paths;
|
|
1794
1794
|
if (representativePath.length === 0) {
|
|
@@ -1807,10 +1807,10 @@ function generateReferentialEqualityAnnotations(identitites, dedupe) {
|
|
|
1807
1807
|
return isEmptyObject(result) ? void 0 : result;
|
|
1808
1808
|
}
|
|
1809
1809
|
}
|
|
1810
|
-
var walker = (object, identities, superJson, dedupe,
|
|
1810
|
+
var walker = (object, identities, superJson, dedupe, path13 = [], objectsInThisPath = [], seenObjects = /* @__PURE__ */ new Map()) => {
|
|
1811
1811
|
const primitive = isPrimitive(object);
|
|
1812
1812
|
if (!primitive) {
|
|
1813
|
-
addIdentity(object,
|
|
1813
|
+
addIdentity(object, path13, identities);
|
|
1814
1814
|
const seen = seenObjects.get(object);
|
|
1815
1815
|
if (seen) {
|
|
1816
1816
|
return dedupe ? {
|
|
@@ -1844,7 +1844,7 @@ var walker = (object, identities, superJson, dedupe, path12 = [], objectsInThisP
|
|
|
1844
1844
|
if (index === "__proto__" || index === "constructor" || index === "prototype") {
|
|
1845
1845
|
throw new Error(`Detected property ${index}. This is a prototype pollution risk, please remove it from your object.`);
|
|
1846
1846
|
}
|
|
1847
|
-
const recursiveResult = walker(value, identities, superJson, dedupe, [...
|
|
1847
|
+
const recursiveResult = walker(value, identities, superJson, dedupe, [...path13, index], [...objectsInThisPath, object], seenObjects);
|
|
1848
1848
|
transformedValue[index] = recursiveResult.transformedValue;
|
|
1849
1849
|
if (isArray(recursiveResult.annotations)) {
|
|
1850
1850
|
innerAnnotations[escapeKey(index)] = recursiveResult.annotations;
|
|
@@ -2072,7 +2072,8 @@ var log = {
|
|
|
2072
2072
|
};
|
|
2073
2073
|
|
|
2074
2074
|
// src/settings/index.ts
|
|
2075
|
-
var
|
|
2075
|
+
var LOBEHUB_DIR_NAME = process.env.LOBEHUB_CLI_HOME || ".lobehub";
|
|
2076
|
+
var SETTINGS_DIR = path.join(os.homedir(), LOBEHUB_DIR_NAME);
|
|
2076
2077
|
var SETTINGS_FILE = path.join(SETTINGS_DIR, "settings.json");
|
|
2077
2078
|
function normalizeUrl(url) {
|
|
2078
2079
|
return url ? url.replace(/\/$/, "") : void 0;
|
|
@@ -2120,7 +2121,8 @@ import crypto from "crypto";
|
|
|
2120
2121
|
import fs2 from "fs";
|
|
2121
2122
|
import os2 from "os";
|
|
2122
2123
|
import path2 from "path";
|
|
2123
|
-
var
|
|
2124
|
+
var LOBEHUB_DIR_NAME2 = process.env.LOBEHUB_CLI_HOME || ".lobehub";
|
|
2125
|
+
var CREDENTIALS_DIR = path2.join(os2.homedir(), LOBEHUB_DIR_NAME2);
|
|
2124
2126
|
var CREDENTIALS_FILE = path2.join(CREDENTIALS_DIR, "credentials.json");
|
|
2125
2127
|
function deriveKey() {
|
|
2126
2128
|
const material = `lobehub-cli:${os2.hostname()}:${os2.userInfo().username}`;
|
|
@@ -2718,6 +2720,20 @@ function confirm(message) {
|
|
|
2718
2720
|
}
|
|
2719
2721
|
|
|
2720
2722
|
// src/commands/agent.ts
|
|
2723
|
+
async function resolveAgentId(client, opts) {
|
|
2724
|
+
if (opts.agentId) return opts.agentId;
|
|
2725
|
+
if (opts.slug) {
|
|
2726
|
+
const agent = await client.agent.getBuiltinAgent.query({ slug: opts.slug });
|
|
2727
|
+
if (!agent) {
|
|
2728
|
+
log.error(`Agent not found for slug: ${opts.slug}`);
|
|
2729
|
+
process.exit(1);
|
|
2730
|
+
}
|
|
2731
|
+
return agent.id || agent.agentId;
|
|
2732
|
+
}
|
|
2733
|
+
log.error("Either <agentId> or --slug is required.");
|
|
2734
|
+
process.exit(1);
|
|
2735
|
+
return "";
|
|
2736
|
+
}
|
|
2721
2737
|
function registerAgentCommand(program2) {
|
|
2722
2738
|
const agent = program2.command("agent").description("Manage agents");
|
|
2723
2739
|
agent.command("list").description("List agents").option("-L, --limit <n>", "Maximum number of items", "30").option("-k, --keyword <keyword>", "Filter by keyword").option("--json [fields]", "Output JSON, optionally specify fields (comma-separated)").action(async (options) => {
|
|
@@ -2744,32 +2760,35 @@ function registerAgentCommand(program2) {
|
|
|
2744
2760
|
]);
|
|
2745
2761
|
printTable(rows, ["ID", "TITLE", "DESCRIPTION", "MODEL"]);
|
|
2746
2762
|
});
|
|
2747
|
-
agent.command("view
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
console.log();
|
|
2769
|
-
|
|
2770
|
-
|
|
2763
|
+
agent.command("view [agentId]").description("View agent configuration").option("-s, --slug <slug>", "Agent slug (e.g. inbox)").option("--json [fields]", "Output JSON, optionally specify fields (comma-separated)").action(
|
|
2764
|
+
async (agentIdArg, options) => {
|
|
2765
|
+
const client = await getTrpcClient();
|
|
2766
|
+
const agentId = await resolveAgentId(client, { agentId: agentIdArg, slug: options.slug });
|
|
2767
|
+
const result = await client.agent.getAgentConfigById.query({ agentId });
|
|
2768
|
+
if (!result) {
|
|
2769
|
+
log.error(`Agent not found: ${agentId}`);
|
|
2770
|
+
process.exit(1);
|
|
2771
|
+
return;
|
|
2772
|
+
}
|
|
2773
|
+
if (options.json !== void 0) {
|
|
2774
|
+
const fields = typeof options.json === "string" ? options.json : void 0;
|
|
2775
|
+
outputJson(result, fields);
|
|
2776
|
+
return;
|
|
2777
|
+
}
|
|
2778
|
+
const r = result;
|
|
2779
|
+
console.log(pc4.bold(r.title || r.meta?.title || "Untitled"));
|
|
2780
|
+
const meta = [];
|
|
2781
|
+
if (r.description || r.meta?.description) meta.push(r.description || r.meta.description);
|
|
2782
|
+
if (r.model) meta.push(`Model: ${r.model}`);
|
|
2783
|
+
if (r.provider) meta.push(`Provider: ${r.provider}`);
|
|
2784
|
+
if (meta.length > 0) console.log(pc4.dim(meta.join(" \xB7 ")));
|
|
2785
|
+
if (r.systemRole) {
|
|
2786
|
+
console.log();
|
|
2787
|
+
console.log(pc4.bold("System Role:"));
|
|
2788
|
+
console.log(r.systemRole);
|
|
2789
|
+
}
|
|
2771
2790
|
}
|
|
2772
|
-
|
|
2791
|
+
);
|
|
2773
2792
|
agent.command("create").description("Create a new agent").option("-t, --title <title>", "Agent title").option("-d, --description <desc>", "Agent description").option("-m, --model <model>", "Model ID").option("-p, --provider <provider>", "Provider ID").option("-s, --system-role <role>", "System role prompt").option("--group <groupId>", "Group ID").action(
|
|
2774
2793
|
async (options) => {
|
|
2775
2794
|
const client = await getTrpcClient();
|
|
@@ -2787,8 +2806,8 @@ function registerAgentCommand(program2) {
|
|
|
2787
2806
|
if (r.sessionId) console.log(` Session: ${r.sessionId}`);
|
|
2788
2807
|
}
|
|
2789
2808
|
);
|
|
2790
|
-
agent.command("edit
|
|
2791
|
-
async (
|
|
2809
|
+
agent.command("edit [agentId]").description("Update agent configuration").option("--slug <slug>", "Agent slug (e.g. inbox)").option("-t, --title <title>", "New title").option("-d, --description <desc>", "New description").option("-m, --model <model>", "New model ID").option("-p, --provider <provider>", "New provider ID").option("-s, --system-role <role>", "New system role prompt").action(
|
|
2810
|
+
async (agentIdArg, options) => {
|
|
2792
2811
|
const value = {};
|
|
2793
2812
|
if (options.title) value.title = options.title;
|
|
2794
2813
|
if (options.description) value.description = options.description;
|
|
@@ -2802,6 +2821,7 @@ function registerAgentCommand(program2) {
|
|
|
2802
2821
|
process.exit(1);
|
|
2803
2822
|
}
|
|
2804
2823
|
const client = await getTrpcClient();
|
|
2824
|
+
const agentId = await resolveAgentId(client, { agentId: agentIdArg, slug: options.slug });
|
|
2805
2825
|
await client.agent.updateAgentConfig.mutate({ agentId, value });
|
|
2806
2826
|
console.log(`${pc4.green("\u2713")} Updated agent ${pc4.bold(agentId)}`);
|
|
2807
2827
|
}
|
|
@@ -3018,13 +3038,33 @@ function registerConfigCommand(program2) {
|
|
|
3018
3038
|
const monthLabel = options.month || (/* @__PURE__ */ new Date()).toISOString().slice(0, 7);
|
|
3019
3039
|
const mode = options.daily ? "Daily" : "Monthly";
|
|
3020
3040
|
printBoxTable(columns, rows, `LobeHub Token Usage Report - ${mode} (${monthLabel})`);
|
|
3021
|
-
const
|
|
3022
|
-
|
|
3041
|
+
const now = /* @__PURE__ */ new Date();
|
|
3042
|
+
const rangeStart = new Date(now.getFullYear() - 1, now.getMonth(), now.getDate() + 1);
|
|
3043
|
+
let yearLogs;
|
|
3044
|
+
try {
|
|
3045
|
+
yearLogs = await client.usage.findAndGroupByDateRange.query({
|
|
3046
|
+
endAt: now.toISOString().slice(0, 10),
|
|
3047
|
+
startAt: rangeStart.toISOString().slice(0, 10)
|
|
3048
|
+
});
|
|
3049
|
+
} catch {
|
|
3050
|
+
const monthKeys = [];
|
|
3051
|
+
for (let i = 11; i >= 0; i--) {
|
|
3052
|
+
const d = new Date(now.getFullYear(), now.getMonth() - i, 1);
|
|
3053
|
+
monthKeys.push(d.toISOString().slice(0, 7));
|
|
3054
|
+
}
|
|
3055
|
+
const results = await Promise.all(
|
|
3056
|
+
monthKeys.map((mo) => client.usage.findAndGroupByDay.query({ mo }))
|
|
3057
|
+
);
|
|
3058
|
+
yearLogs = results.flat();
|
|
3059
|
+
}
|
|
3060
|
+
const calendarData = (Array.isArray(yearLogs) ? yearLogs : []).filter((log3) => log3.day).map((log3) => ({
|
|
3061
|
+
day: log3.day,
|
|
3023
3062
|
value: log3.totalTokens || 0
|
|
3024
3063
|
}));
|
|
3064
|
+
const yearTotal = calendarData.reduce((acc, d) => acc + d.value, 0);
|
|
3025
3065
|
printCalendarHeatmap(calendarData, {
|
|
3026
|
-
label: `
|
|
3027
|
-
title: "Activity"
|
|
3066
|
+
label: `Past 12 months: ${formatNumber(yearTotal)} tokens`,
|
|
3067
|
+
title: "Activity (past 12 months)"
|
|
3028
3068
|
});
|
|
3029
3069
|
});
|
|
3030
3070
|
}
|
|
@@ -4150,15 +4190,16 @@ var ShellProcessManager = class {
|
|
|
4150
4190
|
// ../../packages/local-file-shell/src/shell/runner.ts
|
|
4151
4191
|
import { spawn as spawn3 } from "child_process";
|
|
4152
4192
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
4153
|
-
async function runCommand({ command, description, run_in_background, timeout = 12e4 }, { processManager: processManager2, logger }) {
|
|
4193
|
+
async function runCommand({ command, cwd, description, run_in_background, timeout = 12e4 }, { processManager: processManager2, logger }) {
|
|
4154
4194
|
const logPrefix = `[runCommand: ${description || command.slice(0, 50)}]`;
|
|
4155
|
-
logger?.debug(`${logPrefix} Starting`, { background: run_in_background, timeout });
|
|
4195
|
+
logger?.debug(`${logPrefix} Starting`, { background: run_in_background, cwd, timeout });
|
|
4156
4196
|
const effectiveTimeout = Math.min(Math.max(timeout, 1e3), 6e5);
|
|
4157
4197
|
const shellConfig = getShellConfig(command);
|
|
4158
4198
|
try {
|
|
4159
4199
|
if (run_in_background) {
|
|
4160
4200
|
const shellId = randomUUID2();
|
|
4161
4201
|
const childProcess = spawn3(shellConfig.cmd, shellConfig.args, {
|
|
4202
|
+
cwd,
|
|
4162
4203
|
env: process.env,
|
|
4163
4204
|
shell: false
|
|
4164
4205
|
});
|
|
@@ -4184,6 +4225,7 @@ async function runCommand({ command, description, run_in_background, timeout = 1
|
|
|
4184
4225
|
} else {
|
|
4185
4226
|
return new Promise((resolve) => {
|
|
4186
4227
|
const childProcess = spawn3(shellConfig.cmd, shellConfig.args, {
|
|
4228
|
+
cwd,
|
|
4187
4229
|
env: process.env,
|
|
4188
4230
|
shell: false
|
|
4189
4231
|
});
|
|
@@ -4210,6 +4252,7 @@ async function runCommand({ command, description, run_in_background, timeout = 1
|
|
|
4210
4252
|
if (!killed) {
|
|
4211
4253
|
clearTimeout(timeoutHandle);
|
|
4212
4254
|
const success = code === 0;
|
|
4255
|
+
logger?.info?.(`${logPrefix} Command completed`, { code, success });
|
|
4213
4256
|
resolve({
|
|
4214
4257
|
exit_code: code || 0,
|
|
4215
4258
|
output: truncateOutput(stdout + stderr),
|
|
@@ -4221,6 +4264,7 @@ async function runCommand({ command, description, run_in_background, timeout = 1
|
|
|
4221
4264
|
});
|
|
4222
4265
|
childProcess.on("error", (error) => {
|
|
4223
4266
|
clearTimeout(timeoutHandle);
|
|
4267
|
+
logger?.error(`${logPrefix} Command failed:`, error);
|
|
4224
4268
|
resolve({
|
|
4225
4269
|
error: error.message,
|
|
4226
4270
|
stderr: truncateOutput(stderr),
|
|
@@ -4542,30 +4586,35 @@ function readBodyContent(options) {
|
|
|
4542
4586
|
}
|
|
4543
4587
|
function registerDocCommand(program2) {
|
|
4544
4588
|
const doc = program2.command("doc").description("Manage documents");
|
|
4545
|
-
doc.command("list").description("List documents").option("-L, --limit <n>", "Maximum number of items to fetch", "30").option("--file-type <type>", "Filter by file type").option("--json [fields]", "Output JSON, optionally specify fields (comma-separated)").action(
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
4589
|
+
doc.command("list").description("List documents").option("-L, --limit <n>", "Maximum number of items to fetch", "30").option("--file-type <type>", "Filter by file type").option("--source-type <type>", "Filter by source type (file, web, api, topic)").option("--json [fields]", "Output JSON, optionally specify fields (comma-separated)").action(
|
|
4590
|
+
async (options) => {
|
|
4591
|
+
const client = await getTrpcClient();
|
|
4592
|
+
const pageSize = Number.parseInt(options.limit || "30", 10);
|
|
4593
|
+
const query = {
|
|
4594
|
+
pageSize
|
|
4595
|
+
};
|
|
4596
|
+
if (options.fileType) query.fileTypes = [options.fileType];
|
|
4597
|
+
if (options.sourceType) query.sourceTypes = [options.sourceType];
|
|
4598
|
+
const result = await client.document.queryDocuments.query(query);
|
|
4599
|
+
const docs = Array.isArray(result) ? result : result.items ?? [];
|
|
4600
|
+
if (options.json !== void 0) {
|
|
4601
|
+
const fields = typeof options.json === "string" ? options.json : void 0;
|
|
4602
|
+
outputJson(docs, fields);
|
|
4603
|
+
return;
|
|
4604
|
+
}
|
|
4605
|
+
if (docs.length === 0) {
|
|
4606
|
+
console.log("No documents found.");
|
|
4607
|
+
return;
|
|
4608
|
+
}
|
|
4609
|
+
const rows = docs.map((d) => [
|
|
4610
|
+
d.id,
|
|
4611
|
+
truncate(d.title || d.filename || "Untitled", 120),
|
|
4612
|
+
d.fileType || "",
|
|
4613
|
+
d.updatedAt ? timeAgo(d.updatedAt) : ""
|
|
4614
|
+
]);
|
|
4615
|
+
printTable(rows, ["ID", "TITLE", "TYPE", "UPDATED"]);
|
|
4560
4616
|
}
|
|
4561
|
-
|
|
4562
|
-
d.id,
|
|
4563
|
-
truncate(d.title || d.filename || "Untitled", 120),
|
|
4564
|
-
d.fileType || "",
|
|
4565
|
-
d.updatedAt ? timeAgo(d.updatedAt) : ""
|
|
4566
|
-
]);
|
|
4567
|
-
printTable(rows, ["ID", "TITLE", "TYPE", "UPDATED"]);
|
|
4568
|
-
});
|
|
4617
|
+
);
|
|
4569
4618
|
doc.command("view <id>").description("View a document").option("--json [fields]", "Output JSON, optionally specify fields (comma-separated)").action(async (id, options) => {
|
|
4570
4619
|
const client = await getTrpcClient();
|
|
4571
4620
|
const document = await client.document.getDocumentById.query({ id });
|
|
@@ -4582,6 +4631,7 @@ function registerDocCommand(program2) {
|
|
|
4582
4631
|
console.log(pc6.bold(document.title || "Untitled"));
|
|
4583
4632
|
const meta = [];
|
|
4584
4633
|
if (document.fileType) meta.push(document.fileType);
|
|
4634
|
+
if (document.knowledgeBaseId) meta.push(`KB: ${document.knowledgeBaseId}`);
|
|
4585
4635
|
if (document.updatedAt) meta.push(`Updated ${timeAgo(document.updatedAt)}`);
|
|
4586
4636
|
if (meta.length > 0) console.log(pc6.dim(meta.join(" \xB7 ")));
|
|
4587
4637
|
console.log();
|
|
@@ -4591,13 +4641,15 @@ function registerDocCommand(program2) {
|
|
|
4591
4641
|
console.log(pc6.dim("(no content)"));
|
|
4592
4642
|
}
|
|
4593
4643
|
});
|
|
4594
|
-
doc.command("create").description("Create a new document").requiredOption("-t, --title <title>", "Document title").option("-b, --body <content>", "Document content").option("-F, --body-file <path>", "Read content from file").option("--parent <id>", "Parent document or folder ID").option("--slug <slug>", "Custom slug").action(
|
|
4644
|
+
doc.command("create").description("Create a new document").requiredOption("-t, --title <title>", "Document title").option("-b, --body <content>", "Document content").option("-F, --body-file <path>", "Read content from file").option("--parent <id>", "Parent document or folder ID").option("--slug <slug>", "Custom slug").option("--kb <id>", "Knowledge base ID to associate with").option("--file-type <type>", "File type (e.g. custom/document, custom/folder)").action(
|
|
4595
4645
|
async (options) => {
|
|
4596
4646
|
const content = readBodyContent(options);
|
|
4597
4647
|
const client = await getTrpcClient();
|
|
4598
4648
|
const result = await client.document.createDocument.mutate({
|
|
4599
4649
|
content,
|
|
4600
4650
|
editorData: JSON.stringify({ content: content || "", type: "doc" }),
|
|
4651
|
+
fileType: options.fileType,
|
|
4652
|
+
knowledgeBaseId: options.kb,
|
|
4601
4653
|
parentId: options.parent,
|
|
4602
4654
|
slug: options.slug,
|
|
4603
4655
|
title: options.title
|
|
@@ -4605,11 +4657,50 @@ function registerDocCommand(program2) {
|
|
|
4605
4657
|
console.log(`${pc6.green("\u2713")} Created document ${pc6.bold(result.id)}`);
|
|
4606
4658
|
}
|
|
4607
4659
|
);
|
|
4608
|
-
doc.command("
|
|
4660
|
+
doc.command("batch-create <file>").description("Batch create documents from a JSON file").action(async (file) => {
|
|
4661
|
+
if (!fs5.existsSync(file)) {
|
|
4662
|
+
log.error(`File not found: ${file}`);
|
|
4663
|
+
process.exit(1);
|
|
4664
|
+
return;
|
|
4665
|
+
}
|
|
4666
|
+
let documents;
|
|
4667
|
+
try {
|
|
4668
|
+
const raw = fs5.readFileSync(file, "utf8");
|
|
4669
|
+
documents = JSON.parse(raw);
|
|
4670
|
+
} catch {
|
|
4671
|
+
log.error("Failed to parse JSON file. Expected an array of document objects.");
|
|
4672
|
+
process.exit(1);
|
|
4673
|
+
return;
|
|
4674
|
+
}
|
|
4675
|
+
if (!Array.isArray(documents) || documents.length === 0) {
|
|
4676
|
+
log.error("JSON file must contain a non-empty array of document objects.");
|
|
4677
|
+
process.exit(1);
|
|
4678
|
+
return;
|
|
4679
|
+
}
|
|
4680
|
+
const client = await getTrpcClient();
|
|
4681
|
+
const items = documents.map((d) => ({
|
|
4682
|
+
content: d.content,
|
|
4683
|
+
editorData: JSON.stringify({ content: d.content || "", type: "doc" }),
|
|
4684
|
+
fileType: d.fileType,
|
|
4685
|
+
knowledgeBaseId: d.knowledgeBaseId,
|
|
4686
|
+
parentId: d.parentId,
|
|
4687
|
+
slug: d.slug,
|
|
4688
|
+
title: d.title
|
|
4689
|
+
}));
|
|
4690
|
+
const result = await client.document.createDocuments.mutate({ documents: items });
|
|
4691
|
+
const created = Array.isArray(result) ? result : [result];
|
|
4692
|
+
console.log(`${pc6.green("\u2713")} Created ${created.length} document(s)`);
|
|
4693
|
+
for (const doc2 of created) {
|
|
4694
|
+
console.log(` ${pc6.dim("\u2022")} ${doc2.id} \u2014 ${doc2.title || "Untitled"}`);
|
|
4695
|
+
}
|
|
4696
|
+
});
|
|
4697
|
+
doc.command("edit <id>").description("Edit a document").option("-t, --title <title>", "New title").option("-b, --body <content>", "New content").option("-F, --body-file <path>", "Read new content from file").option("--parent <id>", "Move to parent document (empty string for root)").option("--file-type <type>", "Change file type").action(
|
|
4609
4698
|
async (id, options) => {
|
|
4610
4699
|
const content = readBodyContent(options);
|
|
4611
|
-
if (!options.title && !content && options.parent === void 0) {
|
|
4612
|
-
log.error(
|
|
4700
|
+
if (!options.title && !content && options.parent === void 0 && !options.fileType) {
|
|
4701
|
+
log.error(
|
|
4702
|
+
"No changes specified. Use --title, --body, --body-file, --parent, or --file-type."
|
|
4703
|
+
);
|
|
4613
4704
|
process.exit(1);
|
|
4614
4705
|
}
|
|
4615
4706
|
const client = await getTrpcClient();
|
|
@@ -4622,6 +4713,7 @@ function registerDocCommand(program2) {
|
|
|
4622
4713
|
if (options.parent !== void 0) {
|
|
4623
4714
|
params.parentId = options.parent || null;
|
|
4624
4715
|
}
|
|
4716
|
+
if (options.fileType) params.fileType = options.fileType;
|
|
4625
4717
|
await client.document.updateDocument.mutate(params);
|
|
4626
4718
|
console.log(`${pc6.green("\u2713")} Updated document ${pc6.bold(id)}`);
|
|
4627
4719
|
}
|
|
@@ -4644,6 +4736,62 @@ function registerDocCommand(program2) {
|
|
|
4644
4736
|
}
|
|
4645
4737
|
console.log(`${pc6.green("\u2713")} Deleted ${ids.length} document(s)`);
|
|
4646
4738
|
});
|
|
4739
|
+
doc.command("parse <fileId>").description("Parse an uploaded file into a document").option("--with-pages", "Preserve page structure").option("--json [fields]", "Output JSON, optionally specify fields (comma-separated)").action(async (fileId, options) => {
|
|
4740
|
+
const client = await getTrpcClient();
|
|
4741
|
+
const result = options.withPages ? await client.document.parseFileContent.mutate({ id: fileId }) : await client.document.parseDocument.mutate({ id: fileId });
|
|
4742
|
+
if (options.json !== void 0) {
|
|
4743
|
+
const fields = typeof options.json === "string" ? options.json : void 0;
|
|
4744
|
+
outputJson(result, fields);
|
|
4745
|
+
return;
|
|
4746
|
+
}
|
|
4747
|
+
console.log(`${pc6.green("\u2713")} Parsed file ${pc6.bold(fileId)}`);
|
|
4748
|
+
if (result.title) console.log(` Title: ${result.title}`);
|
|
4749
|
+
if (result.content) {
|
|
4750
|
+
const preview = truncate(result.content, 200);
|
|
4751
|
+
console.log(` Content: ${pc6.dim(preview)}`);
|
|
4752
|
+
}
|
|
4753
|
+
});
|
|
4754
|
+
doc.command("link-topic <docId> <topicId>").description("Associate a document with a topic").action(async (docId, topicId) => {
|
|
4755
|
+
const client = await getTrpcClient();
|
|
4756
|
+
const document = await client.document.getDocumentById.query({ id: docId });
|
|
4757
|
+
if (!document) {
|
|
4758
|
+
log.error(`Document not found: ${docId}`);
|
|
4759
|
+
process.exit(1);
|
|
4760
|
+
return;
|
|
4761
|
+
}
|
|
4762
|
+
const result = await client.notebook.createDocument.mutate({
|
|
4763
|
+
content: document.content || "",
|
|
4764
|
+
description: document.description || "",
|
|
4765
|
+
title: document.title || "Untitled",
|
|
4766
|
+
topicId
|
|
4767
|
+
});
|
|
4768
|
+
console.log(
|
|
4769
|
+
`${pc6.green("\u2713")} Linked document ${pc6.bold(result.id)} to topic ${pc6.bold(topicId)}`
|
|
4770
|
+
);
|
|
4771
|
+
});
|
|
4772
|
+
doc.command("topic-docs <topicId>").description("List documents associated with a topic").option("--type <type>", "Filter by document type (article, markdown, note, report)").option("--json [fields]", "Output JSON, optionally specify fields (comma-separated)").action(async (topicId, options) => {
|
|
4773
|
+
const client = await getTrpcClient();
|
|
4774
|
+
const query = { topicId };
|
|
4775
|
+
if (options.type) query.type = options.type;
|
|
4776
|
+
const result = await client.notebook.listDocuments.query(query);
|
|
4777
|
+
const docs = Array.isArray(result) ? result : result.data ?? [];
|
|
4778
|
+
if (options.json !== void 0) {
|
|
4779
|
+
const fields = typeof options.json === "string" ? options.json : void 0;
|
|
4780
|
+
outputJson(docs, fields);
|
|
4781
|
+
return;
|
|
4782
|
+
}
|
|
4783
|
+
if (docs.length === 0) {
|
|
4784
|
+
console.log("No documents found for this topic.");
|
|
4785
|
+
return;
|
|
4786
|
+
}
|
|
4787
|
+
const rows = docs.map((d) => [
|
|
4788
|
+
d.id,
|
|
4789
|
+
truncate(d.title || "Untitled", 120),
|
|
4790
|
+
d.fileType || "",
|
|
4791
|
+
d.updatedAt ? timeAgo(d.updatedAt) : ""
|
|
4792
|
+
]);
|
|
4793
|
+
printTable(rows, ["ID", "TITLE", "TYPE", "UPDATED"]);
|
|
4794
|
+
});
|
|
4647
4795
|
}
|
|
4648
4796
|
|
|
4649
4797
|
// src/commands/file.ts
|
|
@@ -4867,6 +5015,9 @@ ${stdinContent}`;
|
|
|
4867
5015
|
const payload = {
|
|
4868
5016
|
messages,
|
|
4869
5017
|
model,
|
|
5018
|
+
// For non-streaming, use responseMode 'json' to get a plain JSON response
|
|
5019
|
+
// instead of SSE (the backend converts non-stream to SSE by default)
|
|
5020
|
+
responseMode: useStream ? "stream" : "json",
|
|
4870
5021
|
stream: useStream
|
|
4871
5022
|
};
|
|
4872
5023
|
if (options.temperature) payload.temperature = Number.parseFloat(options.temperature);
|
|
@@ -4888,7 +5039,7 @@ ${stdinContent}`;
|
|
|
4888
5039
|
if (options.json) {
|
|
4889
5040
|
console.log(JSON.stringify(body, null, 2));
|
|
4890
5041
|
} else {
|
|
4891
|
-
const content = body.choices?.[0]?.message?.content || JSON.stringify(body);
|
|
5042
|
+
const content = body.choices?.[0]?.message?.content || body.content?.[0]?.text || JSON.stringify(body);
|
|
4892
5043
|
process.stdout.write(content);
|
|
4893
5044
|
process.stdout.write("\n");
|
|
4894
5045
|
}
|
|
@@ -4925,9 +5076,10 @@ async function streamSSEResponse(body, json) {
|
|
|
4925
5076
|
const parsed = JSON.parse(data);
|
|
4926
5077
|
if (json) {
|
|
4927
5078
|
console.log(JSON.stringify(parsed));
|
|
4928
|
-
} else {
|
|
4929
|
-
|
|
4930
|
-
|
|
5079
|
+
} else if (typeof parsed === "string" && parsed !== "stop") {
|
|
5080
|
+
process.stdout.write(parsed);
|
|
5081
|
+
} else if (parsed?.choices?.[0]?.delta?.content) {
|
|
5082
|
+
process.stdout.write(parsed.choices[0].delta.content);
|
|
4931
5083
|
}
|
|
4932
5084
|
} catch {
|
|
4933
5085
|
if (!json) process.stdout.write(data);
|
|
@@ -5008,12 +5160,19 @@ function registerVideoCommand(parent) {
|
|
|
5008
5160
|
}
|
|
5009
5161
|
const data = r.data || r;
|
|
5010
5162
|
console.log(`${pc10.green("\u2713")} Video generation started`);
|
|
5011
|
-
if (data.
|
|
5012
|
-
|
|
5163
|
+
if (data.batch?.id) console.log(` Batch ID: ${pc10.bold(data.batch.id)}`);
|
|
5164
|
+
const generations = data.generations || [];
|
|
5165
|
+
if (generations.length > 0) {
|
|
5166
|
+
for (const gen of generations) {
|
|
5167
|
+
if (gen.asyncTaskId) {
|
|
5168
|
+
console.log(` Generation ${pc10.bold(gen.id)} \u2192 Task ${pc10.dim(gen.asyncTaskId)}`);
|
|
5169
|
+
}
|
|
5170
|
+
}
|
|
5171
|
+
console.log();
|
|
5172
|
+
console.log(
|
|
5173
|
+
pc10.dim('Use "lh generate status <generationId> <taskId>" to check progress.')
|
|
5174
|
+
);
|
|
5013
5175
|
}
|
|
5014
|
-
console.log(
|
|
5015
|
-
pc10.dim("Video generation runs asynchronously. Check status or wait for notification.")
|
|
5016
|
-
);
|
|
5017
5176
|
}
|
|
5018
5177
|
);
|
|
5019
5178
|
}
|
|
@@ -5048,6 +5207,63 @@ function registerGenerateCommand(program2) {
|
|
|
5048
5207
|
if (gen.asset?.thumbnailUrl) console.log(` Thumb: ${gen.asset.thumbnailUrl}`);
|
|
5049
5208
|
}
|
|
5050
5209
|
});
|
|
5210
|
+
generate.command("download <generationId> <taskId>").description("Wait for generation to complete and download the result").option("-o, --output <path>", "Output file path (default: auto-detect from asset)").option("--interval <sec>", "Polling interval in seconds", "5").option("--timeout <sec>", "Timeout in seconds (0 = no timeout)", "300").action(
|
|
5211
|
+
async (generationId, taskId, options) => {
|
|
5212
|
+
const client = await getTrpcClient();
|
|
5213
|
+
const interval = Number.parseInt(options.interval || "5", 10) * 1e3;
|
|
5214
|
+
const timeout = Number.parseInt(options.timeout || "300", 10) * 1e3;
|
|
5215
|
+
const startTime = Date.now();
|
|
5216
|
+
console.log(`${pc11.yellow("\u22EF")} Waiting for generation ${pc11.bold(generationId)}...`);
|
|
5217
|
+
while (true) {
|
|
5218
|
+
const result = await client.generation.getGenerationStatus.query({
|
|
5219
|
+
asyncTaskId: taskId,
|
|
5220
|
+
generationId
|
|
5221
|
+
});
|
|
5222
|
+
if (result.status === "success" && result.generation) {
|
|
5223
|
+
const gen = result.generation;
|
|
5224
|
+
const url = gen.asset?.url;
|
|
5225
|
+
if (!url) {
|
|
5226
|
+
console.log(`${pc11.red("\u2717")} Generation succeeded but no asset URL found.`);
|
|
5227
|
+
process.exit(1);
|
|
5228
|
+
}
|
|
5229
|
+
const ext = url.split("?")[0].split(".").pop() || "bin";
|
|
5230
|
+
const outputPath = options.output || `${generationId}.${ext}`;
|
|
5231
|
+
console.log(`${pc11.green("\u2713")} Generation complete. Downloading...`);
|
|
5232
|
+
const res = await fetch(url);
|
|
5233
|
+
if (!res.ok) {
|
|
5234
|
+
console.log(`${pc11.red("\u2717")} Download failed: ${res.status} ${res.statusText}`);
|
|
5235
|
+
process.exit(1);
|
|
5236
|
+
}
|
|
5237
|
+
const { writeFile: writeFile3 } = await import("fs/promises");
|
|
5238
|
+
const buffer = Buffer.from(await res.arrayBuffer());
|
|
5239
|
+
await writeFile3(outputPath, buffer);
|
|
5240
|
+
console.log(
|
|
5241
|
+
`${pc11.green("\u2713")} Saved to ${pc11.bold(outputPath)} (${(buffer.length / 1024).toFixed(1)} KB)`
|
|
5242
|
+
);
|
|
5243
|
+
if (gen.asset?.thumbnailUrl) {
|
|
5244
|
+
console.log(` Thumbnail: ${pc11.dim(gen.asset.thumbnailUrl)}`);
|
|
5245
|
+
}
|
|
5246
|
+
return;
|
|
5247
|
+
}
|
|
5248
|
+
if (result.status === "error") {
|
|
5249
|
+
const errMsg = result.error?.body?.detail || result.error?.message || JSON.stringify(result.error);
|
|
5250
|
+
console.log(`${pc11.red("\u2717")} Generation failed: ${errMsg}`);
|
|
5251
|
+
process.exit(1);
|
|
5252
|
+
}
|
|
5253
|
+
if (timeout > 0 && Date.now() - startTime > timeout) {
|
|
5254
|
+
console.log(
|
|
5255
|
+
`${pc11.red("\u2717")} Timed out after ${options.timeout}s. Task still ${result.status}.`
|
|
5256
|
+
);
|
|
5257
|
+
console.log(pc11.dim(`Run "lh gen status ${generationId} ${taskId}" to check later.`));
|
|
5258
|
+
process.exit(1);
|
|
5259
|
+
}
|
|
5260
|
+
process.stdout.write(
|
|
5261
|
+
`\r${pc11.yellow("\u22EF")} Status: ${colorStatus2(result.status)}... (${Math.round((Date.now() - startTime) / 1e3)}s)`
|
|
5262
|
+
);
|
|
5263
|
+
await new Promise((r) => setTimeout(r, interval));
|
|
5264
|
+
}
|
|
5265
|
+
}
|
|
5266
|
+
);
|
|
5051
5267
|
generate.command("list").description("List generation topics").option("--json [fields]", "Output JSON, optionally specify fields (comma-separated)").action(async (options) => {
|
|
5052
5268
|
const client = await getTrpcClient();
|
|
5053
5269
|
const result = await client.generationTopic.getAllGenerationTopics.query();
|
|
@@ -5091,9 +5307,28 @@ function colorStatus2(status) {
|
|
|
5091
5307
|
}
|
|
5092
5308
|
|
|
5093
5309
|
// src/commands/kb.ts
|
|
5310
|
+
import crypto2 from "crypto";
|
|
5311
|
+
import fs6 from "fs";
|
|
5312
|
+
import path11 from "path";
|
|
5094
5313
|
import pc12 from "picocolors";
|
|
5314
|
+
function formatFileType(fileType) {
|
|
5315
|
+
if (!fileType) return "";
|
|
5316
|
+
const map2 = {
|
|
5317
|
+
"application/msword": "doc",
|
|
5318
|
+
"application/pdf": "pdf",
|
|
5319
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation": "pptx",
|
|
5320
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
|
|
5321
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
|
|
5322
|
+
"custom/folder": "folder",
|
|
5323
|
+
"text/markdown": "md",
|
|
5324
|
+
"text/plain": "txt"
|
|
5325
|
+
};
|
|
5326
|
+
if (map2[fileType]) return map2[fileType];
|
|
5327
|
+
const parts = fileType.split("/");
|
|
5328
|
+
return parts.length > 1 ? parts[1] : fileType;
|
|
5329
|
+
}
|
|
5095
5330
|
function registerKbCommand(program2) {
|
|
5096
|
-
const kb = program2.command("kb").description("Manage knowledge bases");
|
|
5331
|
+
const kb = program2.command("kb").description("Manage knowledge bases, folders, documents, and files");
|
|
5097
5332
|
kb.command("list").description("List knowledge bases").option("--json [fields]", "Output JSON, optionally specify fields (comma-separated)").action(async (options) => {
|
|
5098
5333
|
const client = await getTrpcClient();
|
|
5099
5334
|
const result = await client.knowledgeBase.getKnowledgeBases.query();
|
|
@@ -5123,9 +5358,33 @@ function registerKbCommand(program2) {
|
|
|
5123
5358
|
process.exit(1);
|
|
5124
5359
|
return;
|
|
5125
5360
|
}
|
|
5361
|
+
const allItems = [];
|
|
5362
|
+
async function fetchItems(parentId, depth = 0) {
|
|
5363
|
+
const PAGE_SIZE = 100;
|
|
5364
|
+
let offset = 0;
|
|
5365
|
+
let hasMore = true;
|
|
5366
|
+
while (hasMore) {
|
|
5367
|
+
const query = { knowledgeBaseId: id, limit: PAGE_SIZE, offset, parentId };
|
|
5368
|
+
const result2 = await client.file.getKnowledgeItems.query(query);
|
|
5369
|
+
const list = Array.isArray(result2) ? result2 : result2.items ?? [];
|
|
5370
|
+
hasMore = Array.isArray(result2) ? false : result2.hasMore ?? false;
|
|
5371
|
+
offset += list.length;
|
|
5372
|
+
const folders = [];
|
|
5373
|
+
for (const item of list) {
|
|
5374
|
+
allItems.push({ ...item, _depth: depth });
|
|
5375
|
+
if (item.fileType === "custom/folder") {
|
|
5376
|
+
folders.push(item);
|
|
5377
|
+
}
|
|
5378
|
+
}
|
|
5379
|
+
if (folders.length > 0) {
|
|
5380
|
+
await Promise.all(folders.map((f) => fetchItems(f.id, depth + 1)));
|
|
5381
|
+
}
|
|
5382
|
+
}
|
|
5383
|
+
}
|
|
5384
|
+
await fetchItems(null);
|
|
5126
5385
|
if (options.json !== void 0) {
|
|
5127
5386
|
const fields = typeof options.json === "string" ? options.json : void 0;
|
|
5128
|
-
outputJson(result, fields);
|
|
5387
|
+
outputJson({ ...result, files: allItems }, fields);
|
|
5129
5388
|
return;
|
|
5130
5389
|
}
|
|
5131
5390
|
console.log(pc12.bold(result.name || "Untitled"));
|
|
@@ -5133,18 +5392,23 @@ function registerKbCommand(program2) {
|
|
|
5133
5392
|
if (result.description) meta.push(result.description);
|
|
5134
5393
|
if (result.updatedAt) meta.push(`Updated ${timeAgo(result.updatedAt)}`);
|
|
5135
5394
|
if (meta.length > 0) console.log(pc12.dim(meta.join(" \xB7 ")));
|
|
5136
|
-
if (
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
const
|
|
5395
|
+
if (allItems.length > 0) {
|
|
5396
|
+
console.log();
|
|
5397
|
+
console.log(pc12.bold(`Items (${allItems.length}):`));
|
|
5398
|
+
const rows = allItems.map((f) => {
|
|
5399
|
+
const indent = " ".repeat(f._depth);
|
|
5400
|
+
const name = f.name || f.filename || "";
|
|
5401
|
+
return [
|
|
5142
5402
|
f.id,
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5403
|
+
f.sourceType === "document" ? "Doc" : "File",
|
|
5404
|
+
truncate(`${indent}${name}`, 45),
|
|
5405
|
+
formatFileType(f.fileType || ""),
|
|
5406
|
+
f.size ? `${Math.round(f.size / 1024)}KB` : ""
|
|
5407
|
+
];
|
|
5408
|
+
});
|
|
5409
|
+
printTable(rows, ["ID", "SOURCE", "NAME", "TYPE", "SIZE"]);
|
|
5410
|
+
} else {
|
|
5411
|
+
console.log(pc12.dim("\nNo files in this knowledge base."));
|
|
5148
5412
|
}
|
|
5149
5413
|
});
|
|
5150
5414
|
kb.command("create").description("Create a knowledge base").requiredOption("-n, --name <name>", "Knowledge base name").option("-d, --description <desc>", "Description").option("--avatar <url>", "Avatar URL").action(async (options) => {
|
|
@@ -5154,8 +5418,8 @@ function registerKbCommand(program2) {
|
|
|
5154
5418
|
};
|
|
5155
5419
|
if (options.description) input.description = options.description;
|
|
5156
5420
|
if (options.avatar) input.avatar = options.avatar;
|
|
5157
|
-
const
|
|
5158
|
-
console.log(`${pc12.green("\u2713")} Created knowledge base ${pc12.bold(
|
|
5421
|
+
const id = await client.knowledgeBase.createKnowledgeBase.mutate(input);
|
|
5422
|
+
console.log(`${pc12.green("\u2713")} Created knowledge base ${pc12.bold(String(id))}`);
|
|
5159
5423
|
});
|
|
5160
5424
|
kb.command("edit <id>").description("Update a knowledge base").option("-n, --name <name>", "New name").option("-d, --description <desc>", "New description").option("--avatar <url>", "New avatar URL").action(
|
|
5161
5425
|
async (id, options) => {
|
|
@@ -5216,12 +5480,285 @@ function registerKbCommand(program2) {
|
|
|
5216
5480
|
`${pc12.green("\u2713")} Removed ${options.ids.length} file(s) from knowledge base ${pc12.bold(knowledgeBaseId)}`
|
|
5217
5481
|
);
|
|
5218
5482
|
});
|
|
5483
|
+
kb.command("mkdir <knowledgeBaseId>").description("Create a folder in a knowledge base").requiredOption("-n, --name <name>", "Folder name").option("--parent <parentId>", "Parent folder ID").action(async (knowledgeBaseId, options) => {
|
|
5484
|
+
const client = await getTrpcClient();
|
|
5485
|
+
const result = await client.document.createDocument.mutate({
|
|
5486
|
+
editorData: JSON.stringify({}),
|
|
5487
|
+
fileType: "custom/folder",
|
|
5488
|
+
knowledgeBaseId,
|
|
5489
|
+
parentId: options.parent,
|
|
5490
|
+
title: options.name
|
|
5491
|
+
});
|
|
5492
|
+
console.log(`${pc12.green("\u2713")} Created folder ${pc12.bold(result.id)}`);
|
|
5493
|
+
});
|
|
5494
|
+
kb.command("create-doc <knowledgeBaseId>").description("Create a document in a knowledge base").requiredOption("-t, --title <title>", "Document title").option("-c, --content <content>", "Document content (text)").option("--parent <parentId>", "Parent folder ID").action(
|
|
5495
|
+
async (knowledgeBaseId, options) => {
|
|
5496
|
+
const client = await getTrpcClient();
|
|
5497
|
+
const result = await client.document.createDocument.mutate({
|
|
5498
|
+
content: options.content,
|
|
5499
|
+
editorData: JSON.stringify({}),
|
|
5500
|
+
fileType: "custom/document",
|
|
5501
|
+
knowledgeBaseId,
|
|
5502
|
+
parentId: options.parent,
|
|
5503
|
+
title: options.title
|
|
5504
|
+
});
|
|
5505
|
+
console.log(`${pc12.green("\u2713")} Created document ${pc12.bold(result.id)}`);
|
|
5506
|
+
}
|
|
5507
|
+
);
|
|
5508
|
+
kb.command("move <id>").description("Move a file or document to a different folder").option("--parent <parentId>", "Target folder ID (omit to move to root)").option("--type <type>", "Item type: file or doc", "file").action(async (id, options) => {
|
|
5509
|
+
const client = await getTrpcClient();
|
|
5510
|
+
const parentId = options.parent ?? null;
|
|
5511
|
+
if (options.type === "doc") {
|
|
5512
|
+
await client.document.updateDocument.mutate({ id, parentId });
|
|
5513
|
+
} else {
|
|
5514
|
+
await client.file.updateFile.mutate({ id, parentId });
|
|
5515
|
+
}
|
|
5516
|
+
const dest = parentId ? `folder ${pc12.bold(parentId)}` : "root";
|
|
5517
|
+
console.log(`${pc12.green("\u2713")} Moved ${pc12.bold(id)} to ${dest}`);
|
|
5518
|
+
});
|
|
5519
|
+
kb.command("upload <knowledgeBaseId> <filePath>").description("Upload a file to a knowledge base").option("--parent <parentId>", "Parent folder ID").action(async (knowledgeBaseId, filePath, options) => {
|
|
5520
|
+
const resolved = path11.resolve(filePath);
|
|
5521
|
+
if (!fs6.existsSync(resolved)) {
|
|
5522
|
+
log.error(`File not found: ${resolved}`);
|
|
5523
|
+
process.exit(1);
|
|
5524
|
+
}
|
|
5525
|
+
const stat4 = fs6.statSync(resolved);
|
|
5526
|
+
const fileName = path11.basename(resolved);
|
|
5527
|
+
const fileBuffer = fs6.readFileSync(resolved);
|
|
5528
|
+
const hash = crypto2.createHash("sha256").update(fileBuffer).digest("hex");
|
|
5529
|
+
const ext = path11.extname(fileName).toLowerCase().slice(1);
|
|
5530
|
+
const mimeMap = {
|
|
5531
|
+
csv: "text/csv",
|
|
5532
|
+
doc: "application/msword",
|
|
5533
|
+
docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
5534
|
+
gif: "image/gif",
|
|
5535
|
+
jpeg: "image/jpeg",
|
|
5536
|
+
jpg: "image/jpeg",
|
|
5537
|
+
json: "application/json",
|
|
5538
|
+
md: "text/markdown",
|
|
5539
|
+
mp3: "audio/mpeg",
|
|
5540
|
+
mp4: "video/mp4",
|
|
5541
|
+
pdf: "application/pdf",
|
|
5542
|
+
png: "image/png",
|
|
5543
|
+
pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
5544
|
+
svg: "image/svg+xml",
|
|
5545
|
+
txt: "text/plain",
|
|
5546
|
+
webp: "image/webp",
|
|
5547
|
+
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
5548
|
+
};
|
|
5549
|
+
const fileType = mimeMap[ext] || "application/octet-stream";
|
|
5550
|
+
const client = await getTrpcClient();
|
|
5551
|
+
const { serverUrl, headers } = await getAuthInfo();
|
|
5552
|
+
const date = (/* @__PURE__ */ new Date()).toLocaleDateString("en-CA");
|
|
5553
|
+
const pathname = `files/${date}/${hash}.${ext}`;
|
|
5554
|
+
const presigned = await client.upload.createS3PreSignedUrl.mutate({ pathname });
|
|
5555
|
+
const presignedUrl = typeof presigned === "string" ? presigned : presigned.url;
|
|
5556
|
+
const uploadRes = await fetch(presignedUrl, {
|
|
5557
|
+
body: fileBuffer,
|
|
5558
|
+
headers: { "Content-Type": fileType },
|
|
5559
|
+
method: "PUT"
|
|
5560
|
+
});
|
|
5561
|
+
if (!uploadRes.ok) {
|
|
5562
|
+
log.error(`Upload failed: ${uploadRes.status} ${uploadRes.statusText}`);
|
|
5563
|
+
process.exit(1);
|
|
5564
|
+
}
|
|
5565
|
+
const result = await client.file.createFile.mutate({
|
|
5566
|
+
fileType,
|
|
5567
|
+
hash,
|
|
5568
|
+
knowledgeBaseId,
|
|
5569
|
+
metadata: {
|
|
5570
|
+
date,
|
|
5571
|
+
dirname: "",
|
|
5572
|
+
filename: fileName,
|
|
5573
|
+
path: pathname
|
|
5574
|
+
},
|
|
5575
|
+
name: fileName,
|
|
5576
|
+
parentId: options.parent,
|
|
5577
|
+
size: stat4.size,
|
|
5578
|
+
url: pathname
|
|
5579
|
+
});
|
|
5580
|
+
console.log(
|
|
5581
|
+
`${pc12.green("\u2713")} Uploaded ${pc12.bold(fileName)} \u2192 ${pc12.bold(result.id)}`
|
|
5582
|
+
);
|
|
5583
|
+
});
|
|
5584
|
+
}
|
|
5585
|
+
|
|
5586
|
+
// src/commands/eval.ts
|
|
5587
|
+
import { InvalidArgumentError } from "commander";
|
|
5588
|
+
import pc13 from "picocolors";
|
|
5589
|
+
var JSON_VERSION = "v1";
|
|
5590
|
+
var printJson = (data) => {
|
|
5591
|
+
console.log(JSON.stringify(data, null, 2));
|
|
5592
|
+
};
|
|
5593
|
+
var outputJsonSuccess = (data) => {
|
|
5594
|
+
const payload = {
|
|
5595
|
+
data,
|
|
5596
|
+
error: null,
|
|
5597
|
+
ok: true,
|
|
5598
|
+
version: JSON_VERSION
|
|
5599
|
+
};
|
|
5600
|
+
printJson(payload);
|
|
5601
|
+
};
|
|
5602
|
+
var isRecord = (value) => typeof value === "object" && value !== null;
|
|
5603
|
+
var toJsonError = (error) => {
|
|
5604
|
+
if (error instanceof Error) {
|
|
5605
|
+
const maybeData = error.data;
|
|
5606
|
+
const code = maybeData?.code;
|
|
5607
|
+
return {
|
|
5608
|
+
code: typeof code === "string" ? code : void 0,
|
|
5609
|
+
message: error.message
|
|
5610
|
+
};
|
|
5611
|
+
}
|
|
5612
|
+
if (isRecord(error)) {
|
|
5613
|
+
const code = typeof error.code === "string" ? error.code : void 0;
|
|
5614
|
+
const message = typeof error.message === "string" ? error.message : "Unknown error";
|
|
5615
|
+
return { code, message };
|
|
5616
|
+
}
|
|
5617
|
+
return { message: String(error) };
|
|
5618
|
+
};
|
|
5619
|
+
var handleCommandError = (error, json) => {
|
|
5620
|
+
const normalized = toJsonError(error);
|
|
5621
|
+
if (json) {
|
|
5622
|
+
const payload = {
|
|
5623
|
+
data: null,
|
|
5624
|
+
error: normalized,
|
|
5625
|
+
ok: false,
|
|
5626
|
+
version: JSON_VERSION
|
|
5627
|
+
};
|
|
5628
|
+
printJson(payload);
|
|
5629
|
+
} else {
|
|
5630
|
+
log.error(normalized.message);
|
|
5631
|
+
}
|
|
5632
|
+
process.exit(1);
|
|
5633
|
+
};
|
|
5634
|
+
var parseScore = (value) => {
|
|
5635
|
+
const score = Number(value);
|
|
5636
|
+
if (!Number.isFinite(score)) {
|
|
5637
|
+
throw new InvalidArgumentError(`Invalid score: ${value}`);
|
|
5638
|
+
}
|
|
5639
|
+
return score;
|
|
5640
|
+
};
|
|
5641
|
+
var parseBoolean = (value) => {
|
|
5642
|
+
const normalized = value.trim().toLowerCase();
|
|
5643
|
+
if (["1", "true", "yes"].includes(normalized)) return true;
|
|
5644
|
+
if (["0", "false", "no"].includes(normalized)) return false;
|
|
5645
|
+
throw new InvalidArgumentError(`Invalid boolean value: ${value}`);
|
|
5646
|
+
};
|
|
5647
|
+
var parseResultJson = (value) => {
|
|
5648
|
+
let parsed;
|
|
5649
|
+
try {
|
|
5650
|
+
parsed = JSON.parse(value);
|
|
5651
|
+
} catch {
|
|
5652
|
+
throw new InvalidArgumentError("Invalid JSON value for --result-json");
|
|
5653
|
+
}
|
|
5654
|
+
if (!isRecord(parsed) || Array.isArray(parsed)) {
|
|
5655
|
+
throw new InvalidArgumentError("--result-json must be a JSON object");
|
|
5656
|
+
}
|
|
5657
|
+
return parsed;
|
|
5658
|
+
};
|
|
5659
|
+
var parseRunStatus = (value) => {
|
|
5660
|
+
if (value !== "completed" && value !== "external") {
|
|
5661
|
+
throw new InvalidArgumentError("Only 'completed' and 'external' are supported");
|
|
5662
|
+
}
|
|
5663
|
+
return value;
|
|
5664
|
+
};
|
|
5665
|
+
var executeCommand = async (options, action, successMessage) => {
|
|
5666
|
+
try {
|
|
5667
|
+
const data = await action();
|
|
5668
|
+
if (options.json) {
|
|
5669
|
+
outputJsonSuccess(data);
|
|
5670
|
+
return;
|
|
5671
|
+
}
|
|
5672
|
+
if (successMessage) {
|
|
5673
|
+
console.log(`${pc13.green("OK")} ${successMessage}`);
|
|
5674
|
+
return;
|
|
5675
|
+
}
|
|
5676
|
+
printJson(data);
|
|
5677
|
+
} catch (error) {
|
|
5678
|
+
handleCommandError(error, Boolean(options.json));
|
|
5679
|
+
}
|
|
5680
|
+
};
|
|
5681
|
+
function registerEvalCommand(program2) {
|
|
5682
|
+
const evalCmd = program2.command("eval").description("Manage external evaluation workflows");
|
|
5683
|
+
const runCmd = evalCmd.command("run").description("Manage evaluation runs");
|
|
5684
|
+
runCmd.command("get").description("Get run information").requiredOption("--run-id <id>", "Run ID").option("--json", "Output JSON envelope").action(
|
|
5685
|
+
async (options) => executeCommand(options, async () => {
|
|
5686
|
+
const client = await getTrpcClient();
|
|
5687
|
+
return client.agentEvalExternal.runGet.query({ runId: options.runId });
|
|
5688
|
+
})
|
|
5689
|
+
);
|
|
5690
|
+
runCmd.command("set-status").description("Set run status (external API supports completed or external)").requiredOption("--run-id <id>", "Run ID").requiredOption("--status <status>", "Status (completed | external)", parseRunStatus).option("--json", "Output JSON envelope").action(
|
|
5691
|
+
async (options) => executeCommand(
|
|
5692
|
+
options,
|
|
5693
|
+
async () => {
|
|
5694
|
+
const client = await getTrpcClient();
|
|
5695
|
+
return client.agentEvalExternal.runSetStatus.mutate({
|
|
5696
|
+
runId: options.runId,
|
|
5697
|
+
status: options.status
|
|
5698
|
+
});
|
|
5699
|
+
},
|
|
5700
|
+
`Run ${pc13.bold(options.runId)} status updated to ${pc13.bold(options.status)}`
|
|
5701
|
+
)
|
|
5702
|
+
);
|
|
5703
|
+
evalCmd.command("dataset").description("Manage evaluation datasets").command("get").description("Get dataset information").requiredOption("--dataset-id <id>", "Dataset ID").option("--json", "Output JSON envelope").action(
|
|
5704
|
+
async (options) => executeCommand(options, async () => {
|
|
5705
|
+
const client = await getTrpcClient();
|
|
5706
|
+
return client.agentEvalExternal.datasetGet.query({ datasetId: options.datasetId });
|
|
5707
|
+
})
|
|
5708
|
+
);
|
|
5709
|
+
evalCmd.command("run-topics").description("Manage run topics").command("list").description("List topics in a run").requiredOption("--run-id <id>", "Run ID").option("--only-external", "Only return topics pending external evaluation").option("--json", "Output JSON envelope").action(
|
|
5710
|
+
async (options) => executeCommand(options, async () => {
|
|
5711
|
+
const client = await getTrpcClient();
|
|
5712
|
+
return client.agentEvalExternal.runTopicsList.query({
|
|
5713
|
+
onlyExternal: Boolean(options.onlyExternal),
|
|
5714
|
+
runId: options.runId
|
|
5715
|
+
});
|
|
5716
|
+
})
|
|
5717
|
+
);
|
|
5718
|
+
evalCmd.command("threads").description("Manage evaluation threads").command("list").description("List threads by topic").requiredOption("--topic-id <id>", "Topic ID").option("--json", "Output JSON envelope").action(
|
|
5719
|
+
async (options) => executeCommand(options, async () => {
|
|
5720
|
+
const client = await getTrpcClient();
|
|
5721
|
+
return client.agentEvalExternal.threadsList.query({ topicId: options.topicId });
|
|
5722
|
+
})
|
|
5723
|
+
);
|
|
5724
|
+
evalCmd.command("messages").description("Manage evaluation messages").command("list").description("List messages by topic and optional thread").requiredOption("--topic-id <id>", "Topic ID").option("--thread-id <id>", "Thread ID").option("--json", "Output JSON envelope").action(
|
|
5725
|
+
async (options) => executeCommand(options, async () => {
|
|
5726
|
+
const client = await getTrpcClient();
|
|
5727
|
+
return client.agentEvalExternal.messagesList.query({
|
|
5728
|
+
threadId: options.threadId,
|
|
5729
|
+
topicId: options.topicId
|
|
5730
|
+
});
|
|
5731
|
+
})
|
|
5732
|
+
);
|
|
5733
|
+
evalCmd.command("test-cases").description("Manage evaluation test cases").command("count").description("Count test cases by dataset").requiredOption("--dataset-id <id>", "Dataset ID").option("--json", "Output JSON envelope").action(
|
|
5734
|
+
async (options) => executeCommand(options, async () => {
|
|
5735
|
+
const client = await getTrpcClient();
|
|
5736
|
+
return client.agentEvalExternal.testCasesCount.query({ datasetId: options.datasetId });
|
|
5737
|
+
})
|
|
5738
|
+
);
|
|
5739
|
+
evalCmd.command("run-topic").description("Manage evaluation run-topic reporting").command("report-result").description("Report one evaluation result for a run topic").requiredOption("--run-id <id>", "Run ID").requiredOption("--topic-id <id>", "Topic ID").option("--thread-id <id>", "Thread ID (required for k > 1)").requiredOption("--score <score>", "Evaluation score", parseScore).requiredOption("--correct <boolean>", "Whether the result is correct", parseBoolean).requiredOption("--result-json <json>", "Raw evaluation result JSON object", parseResultJson).option("--json", "Output JSON envelope").action(
|
|
5740
|
+
async (options) => executeCommand(
|
|
5741
|
+
options,
|
|
5742
|
+
async () => {
|
|
5743
|
+
const client = await getTrpcClient();
|
|
5744
|
+
return client.agentEvalExternal.runTopicReportResult.mutate({
|
|
5745
|
+
correct: options.correct,
|
|
5746
|
+
result: options.resultJson,
|
|
5747
|
+
runId: options.runId,
|
|
5748
|
+
score: options.score,
|
|
5749
|
+
threadId: options.threadId,
|
|
5750
|
+
topicId: options.topicId
|
|
5751
|
+
});
|
|
5752
|
+
},
|
|
5753
|
+
`Reported result for topic ${pc13.bold(options.topicId)}`
|
|
5754
|
+
)
|
|
5755
|
+
);
|
|
5219
5756
|
}
|
|
5220
5757
|
|
|
5221
5758
|
// src/commands/login.ts
|
|
5222
5759
|
import { execFile } from "child_process";
|
|
5223
|
-
import
|
|
5224
|
-
import
|
|
5760
|
+
import fs7 from "fs";
|
|
5761
|
+
import path12 from "path";
|
|
5225
5762
|
var CLIENT_ID2 = "lobehub-cli";
|
|
5226
5763
|
var SCOPES = "openid profile email offline_access";
|
|
5227
5764
|
async function parseJsonResponse(res, endpoint) {
|
|
@@ -5352,31 +5889,31 @@ function sleep2(ms) {
|
|
|
5352
5889
|
function resolveCommandExecutable(cmd, platform = process.platform) {
|
|
5353
5890
|
if (!cmd) return void 0;
|
|
5354
5891
|
if (cmd.includes("/") || cmd.includes("\\")) {
|
|
5355
|
-
return
|
|
5892
|
+
return fs7.existsSync(cmd) ? cmd : void 0;
|
|
5356
5893
|
}
|
|
5357
5894
|
const pathValue = process.env.PATH || "";
|
|
5358
5895
|
if (!pathValue) return void 0;
|
|
5359
5896
|
if (platform === "win32") {
|
|
5360
5897
|
const pathEntries2 = pathValue.split(";").filter(Boolean);
|
|
5361
5898
|
const pathext = (process.env.PATHEXT || ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean);
|
|
5362
|
-
const hasExtension =
|
|
5899
|
+
const hasExtension = path12.win32.extname(cmd).length > 0;
|
|
5363
5900
|
const candidateNames = hasExtension ? [cmd] : [cmd, ...pathext.map((ext) => `${cmd}${ext}`)];
|
|
5364
5901
|
const systemRoot = process.env.SystemRoot || process.env.WINDIR;
|
|
5365
5902
|
if (systemRoot) {
|
|
5366
|
-
pathEntries2.push(
|
|
5903
|
+
pathEntries2.push(path12.win32.join(systemRoot, "System32"));
|
|
5367
5904
|
}
|
|
5368
5905
|
for (const entry of pathEntries2) {
|
|
5369
5906
|
for (const candidate of candidateNames) {
|
|
5370
|
-
const resolved =
|
|
5371
|
-
if (
|
|
5907
|
+
const resolved = path12.win32.join(entry, candidate);
|
|
5908
|
+
if (fs7.existsSync(resolved)) return resolved;
|
|
5372
5909
|
}
|
|
5373
5910
|
}
|
|
5374
5911
|
return void 0;
|
|
5375
5912
|
}
|
|
5376
|
-
const pathEntries = pathValue.split(
|
|
5913
|
+
const pathEntries = pathValue.split(path12.delimiter).filter(Boolean);
|
|
5377
5914
|
for (const entry of pathEntries) {
|
|
5378
|
-
const resolved =
|
|
5379
|
-
if (
|
|
5915
|
+
const resolved = path12.join(entry, cmd);
|
|
5916
|
+
if (fs7.existsSync(resolved)) return resolved;
|
|
5380
5917
|
}
|
|
5381
5918
|
return void 0;
|
|
5382
5919
|
}
|
|
@@ -5422,7 +5959,7 @@ function registerLogoutCommand(program2) {
|
|
|
5422
5959
|
}
|
|
5423
5960
|
|
|
5424
5961
|
// src/commands/memory.ts
|
|
5425
|
-
import
|
|
5962
|
+
import pc14 from "picocolors";
|
|
5426
5963
|
var CATEGORIES = ["identity", "activity", "context", "experience", "preference"];
|
|
5427
5964
|
function capitalize(s) {
|
|
5428
5965
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
@@ -5438,18 +5975,8 @@ function registerMemoryCommand(program2) {
|
|
|
5438
5975
|
const categoriesToFetch = category ? [category] : [...CATEGORIES];
|
|
5439
5976
|
const allResults = {};
|
|
5440
5977
|
for (const cat of categoriesToFetch) {
|
|
5441
|
-
const getter = `get${capitalize(cat)}`;
|
|
5442
|
-
const getterPlural = `${getter}s`;
|
|
5443
|
-
const router = client.userMemory;
|
|
5444
5978
|
try {
|
|
5445
|
-
|
|
5446
|
-
allResults[cat] = await router[getterPlural].query();
|
|
5447
|
-
} else if (router[getter]) {
|
|
5448
|
-
allResults[cat] = await router[getter].query();
|
|
5449
|
-
} else {
|
|
5450
|
-
const items = await fetchCategory(client, cat);
|
|
5451
|
-
allResults[cat] = items;
|
|
5452
|
-
}
|
|
5979
|
+
allResults[cat] = await fetchCategory(client, cat);
|
|
5453
5980
|
} catch {
|
|
5454
5981
|
allResults[cat] = [];
|
|
5455
5982
|
}
|
|
@@ -5465,7 +5992,7 @@ function registerMemoryCommand(program2) {
|
|
|
5465
5992
|
continue;
|
|
5466
5993
|
}
|
|
5467
5994
|
console.log();
|
|
5468
|
-
console.log(
|
|
5995
|
+
console.log(pc14.bold(pc14.cyan(`\u2500\u2500 ${capitalize(cat)} (${items.length}) \u2500\u2500`)));
|
|
5469
5996
|
const rows = items.map((item) => {
|
|
5470
5997
|
const desc = item.description || item.narrative || item.title || item.situation || item.conclusionDirectives || item.content || "";
|
|
5471
5998
|
return [
|
|
@@ -5487,8 +6014,11 @@ function registerMemoryCommand(program2) {
|
|
|
5487
6014
|
if (options.labels) input.extractedLabels = options.labels;
|
|
5488
6015
|
try {
|
|
5489
6016
|
const result = await client.userMemory.createIdentity.mutate(input);
|
|
5490
|
-
const
|
|
5491
|
-
|
|
6017
|
+
const memoryId = result?.userMemoryId || "unknown";
|
|
6018
|
+
const identityId = result?.identityId || "unknown";
|
|
6019
|
+
console.log(
|
|
6020
|
+
`${pc14.green("\u2713")} Created identity memory ${pc14.bold(memoryId)} (identity: ${pc14.bold(identityId)})`
|
|
6021
|
+
);
|
|
5492
6022
|
} catch (error) {
|
|
5493
6023
|
log.error(`Failed to create identity: ${error.message}`);
|
|
5494
6024
|
process.exit(1);
|
|
@@ -5506,7 +6036,7 @@ function registerMemoryCommand(program2) {
|
|
|
5506
6036
|
const data = buildCategoryInput(category, options);
|
|
5507
6037
|
try {
|
|
5508
6038
|
await router[mutationName].mutate({ data, id });
|
|
5509
|
-
console.log(`${
|
|
6039
|
+
console.log(`${pc14.green("\u2713")} Updated ${category} memory ${pc14.bold(id)}`);
|
|
5510
6040
|
} catch (error) {
|
|
5511
6041
|
log.error(`Failed to update ${category}: ${error.message}`);
|
|
5512
6042
|
process.exit(1);
|
|
@@ -5530,7 +6060,7 @@ function registerMemoryCommand(program2) {
|
|
|
5530
6060
|
const mutationName = `delete${capitalize(category)}`;
|
|
5531
6061
|
try {
|
|
5532
6062
|
await router[mutationName].mutate({ id });
|
|
5533
|
-
console.log(`${
|
|
6063
|
+
console.log(`${pc14.green("\u2713")} Deleted ${category} memory ${pc14.bold(id)}`);
|
|
5534
6064
|
} catch (error) {
|
|
5535
6065
|
log.error(`Failed to delete ${category}: ${error.message}`);
|
|
5536
6066
|
process.exit(1);
|
|
@@ -5549,7 +6079,7 @@ function registerMemoryCommand(program2) {
|
|
|
5549
6079
|
console.log("No persona data available.");
|
|
5550
6080
|
return;
|
|
5551
6081
|
}
|
|
5552
|
-
console.log(
|
|
6082
|
+
console.log(pc14.bold("User Persona"));
|
|
5553
6083
|
console.log();
|
|
5554
6084
|
console.log(typeof persona === "string" ? persona : JSON.stringify(persona, null, 2));
|
|
5555
6085
|
});
|
|
@@ -5559,11 +6089,11 @@ function registerMemoryCommand(program2) {
|
|
|
5559
6089
|
if (options.from) input.fromDate = new Date(options.from);
|
|
5560
6090
|
if (options.to) input.toDate = new Date(options.to);
|
|
5561
6091
|
const result = await client.userMemory.requestMemoryFromChatTopic.mutate(input);
|
|
5562
|
-
console.log(`${
|
|
6092
|
+
console.log(`${pc14.green("\u2713")} Memory extraction started`);
|
|
5563
6093
|
if (result?.id) {
|
|
5564
|
-
console.log(`Task ID: ${
|
|
6094
|
+
console.log(`Task ID: ${pc14.bold(result.id)}`);
|
|
5565
6095
|
}
|
|
5566
|
-
console.log(
|
|
6096
|
+
console.log(pc14.dim('Use "lh memory extract-status" to check progress.'));
|
|
5567
6097
|
});
|
|
5568
6098
|
memory.command("extract-status").description("Check memory extraction task status").option("--task-id <id>", "Specific task ID to check").option("--json [fields]", "Output JSON, optionally specify fields (comma-separated)").action(async (options) => {
|
|
5569
6099
|
const client = await getTrpcClient();
|
|
@@ -5580,7 +6110,7 @@ function registerMemoryCommand(program2) {
|
|
|
5580
6110
|
return;
|
|
5581
6111
|
}
|
|
5582
6112
|
const r = result;
|
|
5583
|
-
console.log(
|
|
6113
|
+
console.log(pc14.bold("Memory Extraction Task"));
|
|
5584
6114
|
if (r.id) console.log(` ID: ${r.id}`);
|
|
5585
6115
|
if (r.status) console.log(` Status: ${r.status}`);
|
|
5586
6116
|
if (r.metadata) console.log(` Detail: ${JSON.stringify(r.metadata)}`);
|
|
@@ -5648,20 +6178,34 @@ function buildCategoryInput(category, options) {
|
|
|
5648
6178
|
}
|
|
5649
6179
|
|
|
5650
6180
|
// src/commands/message.ts
|
|
5651
|
-
import
|
|
6181
|
+
import pc15 from "picocolors";
|
|
5652
6182
|
function registerMessageCommand(program2) {
|
|
5653
6183
|
const message = program2.command("message").description("Manage messages");
|
|
5654
|
-
message.command("list").description("List messages").option("--topic-id <id>", "Filter by topic ID").option("--agent-id <id>", "Filter by agent ID").option("
|
|
6184
|
+
message.command("list").description("List messages").option("--topic-id <id>", "Filter by topic ID").option("--agent-id <id>", "Filter by agent ID").option("-L, --limit <n>", "Page size", "30").option("--page <n>", "Page number", "1").option("--user", "Only show user messages").option("--json [fields]", "Output JSON, optionally specify fields (comma-separated)").action(
|
|
5655
6185
|
async (options) => {
|
|
5656
6186
|
const client = await getTrpcClient();
|
|
5657
|
-
const
|
|
5658
|
-
|
|
5659
|
-
|
|
5660
|
-
|
|
5661
|
-
if (
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
|
|
6187
|
+
const hasFilter = options.topicId || options.agentId;
|
|
6188
|
+
const pageSize = options.limit ? Number.parseInt(options.limit, 10) : void 0;
|
|
6189
|
+
const current = options.page ? Number.parseInt(options.page, 10) : void 0;
|
|
6190
|
+
let items;
|
|
6191
|
+
if (hasFilter) {
|
|
6192
|
+
const input = {};
|
|
6193
|
+
if (options.topicId) input.topicId = options.topicId;
|
|
6194
|
+
if (options.agentId) input.agentId = options.agentId;
|
|
6195
|
+
if (pageSize) input.pageSize = pageSize;
|
|
6196
|
+
if (current) input.current = current;
|
|
6197
|
+
const result = await client.message.getMessages.query(input);
|
|
6198
|
+
items = Array.isArray(result) ? result : result.items ?? [];
|
|
6199
|
+
} else {
|
|
6200
|
+
const input = {};
|
|
6201
|
+
if (pageSize) input.pageSize = pageSize;
|
|
6202
|
+
if (current) input.current = current;
|
|
6203
|
+
const result = await client.message.listAll.query(input);
|
|
6204
|
+
items = Array.isArray(result) ? result : [];
|
|
6205
|
+
}
|
|
6206
|
+
if (options.user) {
|
|
6207
|
+
items = items.filter((m) => m.role === "user");
|
|
6208
|
+
}
|
|
5665
6209
|
if (options.json !== void 0) {
|
|
5666
6210
|
const fields = typeof options.json === "string" ? options.json : void 0;
|
|
5667
6211
|
outputJson(items, fields);
|
|
@@ -5712,7 +6256,7 @@ function registerMessageCommand(program2) {
|
|
|
5712
6256
|
} else {
|
|
5713
6257
|
await client.message.removeMessages.mutate({ ids });
|
|
5714
6258
|
}
|
|
5715
|
-
console.log(`${
|
|
6259
|
+
console.log(`${pc15.green("\u2713")} Deleted ${ids.length} message(s)`);
|
|
5716
6260
|
});
|
|
5717
6261
|
message.command("count").description("Count messages").option("--start <date>", "Start date (ISO format)").option("--end <date>", "End date (ISO format)").option("--json", "Output JSON").action(async (options) => {
|
|
5718
6262
|
const client = await getTrpcClient();
|
|
@@ -5724,7 +6268,7 @@ function registerMessageCommand(program2) {
|
|
|
5724
6268
|
console.log(JSON.stringify({ count }));
|
|
5725
6269
|
return;
|
|
5726
6270
|
}
|
|
5727
|
-
console.log(`Messages: ${
|
|
6271
|
+
console.log(`Messages: ${pc15.bold(String(count))}`);
|
|
5728
6272
|
});
|
|
5729
6273
|
message.command("heatmap").description("Get message activity heatmap").option("--json", "Output JSON").action(async (options) => {
|
|
5730
6274
|
const client = await getTrpcClient();
|
|
@@ -5740,23 +6284,30 @@ function registerMessageCommand(program2) {
|
|
|
5740
6284
|
const items = Array.isArray(result) ? result : [result];
|
|
5741
6285
|
for (const entry of items) {
|
|
5742
6286
|
const e = entry;
|
|
5743
|
-
console.log(`${e.date || e.day || ""}: ${
|
|
6287
|
+
console.log(`${e.date || e.day || ""}: ${pc15.bold(String(e.count || e.value || 0))}`);
|
|
5744
6288
|
}
|
|
5745
6289
|
});
|
|
5746
6290
|
}
|
|
5747
6291
|
|
|
5748
6292
|
// src/commands/model.ts
|
|
5749
|
-
import
|
|
6293
|
+
import pc16 from "picocolors";
|
|
5750
6294
|
function registerModelCommand(program2) {
|
|
5751
6295
|
const model = program2.command("model").description("Manage AI models");
|
|
5752
|
-
model.command("list <providerId>").description("List models for a provider").option("-L, --limit <n>", "Maximum number of items", "50").option("--enabled", "Only show enabled models").option(
|
|
6296
|
+
model.command("list <providerId>").description("List models for a provider").option("-L, --limit <n>", "Maximum number of items", "50").option("--enabled", "Only show enabled models").option(
|
|
6297
|
+
"--type <type>",
|
|
6298
|
+
"Filter by model type (chat|embedding|tts|stt|image|video|text2music|realtime)"
|
|
6299
|
+
).option("--json [fields]", "Output JSON, optionally specify fields (comma-separated)").action(
|
|
5753
6300
|
async (providerId, options) => {
|
|
5754
6301
|
const client = await getTrpcClient();
|
|
5755
6302
|
const input = { id: providerId };
|
|
5756
6303
|
if (options.limit) input.limit = Number.parseInt(options.limit, 10);
|
|
5757
6304
|
if (options.enabled) input.enabled = true;
|
|
6305
|
+
if (options.type) input.type = options.type;
|
|
5758
6306
|
const result = await client.aiModel.getAiProviderModelList.query(input);
|
|
5759
|
-
|
|
6307
|
+
let items = Array.isArray(result) ? result : result.items ?? [];
|
|
6308
|
+
if (options.type) {
|
|
6309
|
+
items = items.filter((m) => m.type === options.type);
|
|
6310
|
+
}
|
|
5760
6311
|
if (options.json !== void 0) {
|
|
5761
6312
|
const fields = typeof options.json === "string" ? options.json : void 0;
|
|
5762
6313
|
outputJson(items, fields);
|
|
@@ -5769,7 +6320,7 @@ function registerModelCommand(program2) {
|
|
|
5769
6320
|
const rows = items.map((m) => [
|
|
5770
6321
|
m.id || "",
|
|
5771
6322
|
truncate(m.displayName || m.id || "", 40),
|
|
5772
|
-
m.enabled ?
|
|
6323
|
+
m.enabled ? pc16.green("\u2713") : pc16.dim("\u2717"),
|
|
5773
6324
|
m.type || ""
|
|
5774
6325
|
]);
|
|
5775
6326
|
printTable(rows, ["ID", "NAME", "ENABLED", "TYPE"]);
|
|
@@ -5789,13 +6340,48 @@ function registerModelCommand(program2) {
|
|
|
5789
6340
|
return;
|
|
5790
6341
|
}
|
|
5791
6342
|
const r = result;
|
|
5792
|
-
console.log(
|
|
6343
|
+
console.log(pc16.bold(r.displayName || r.id || "Unknown"));
|
|
5793
6344
|
const meta = [];
|
|
5794
6345
|
if (r.providerId) meta.push(`Provider: ${r.providerId}`);
|
|
5795
6346
|
if (r.type) meta.push(`Type: ${r.type}`);
|
|
5796
6347
|
if (r.enabled !== void 0) meta.push(r.enabled ? "Enabled" : "Disabled");
|
|
5797
|
-
if (meta.length > 0) console.log(
|
|
6348
|
+
if (meta.length > 0) console.log(pc16.dim(meta.join(" \xB7 ")));
|
|
5798
6349
|
});
|
|
6350
|
+
model.command("create").description("Create a new model").requiredOption("--id <id>", "Model ID").requiredOption("--provider <providerId>", "Provider ID").option("--display-name <name>", "Display name").option(
|
|
6351
|
+
"--type <type>",
|
|
6352
|
+
"Model type (chat|embedding|tts|stt|image|video|text2music|realtime)",
|
|
6353
|
+
"chat"
|
|
6354
|
+
).action(
|
|
6355
|
+
async (options) => {
|
|
6356
|
+
const client = await getTrpcClient();
|
|
6357
|
+
const input = {
|
|
6358
|
+
id: options.id,
|
|
6359
|
+
providerId: options.provider,
|
|
6360
|
+
type: options.type || "chat"
|
|
6361
|
+
};
|
|
6362
|
+
if (options.displayName) input.displayName = options.displayName;
|
|
6363
|
+
const resultId = await client.aiModel.createAiModel.mutate(input);
|
|
6364
|
+
console.log(`${pc16.green("\u2713")} Created model ${pc16.bold(resultId || options.id)}`);
|
|
6365
|
+
}
|
|
6366
|
+
);
|
|
6367
|
+
model.command("edit <id>").description("Update model info").requiredOption("--provider <providerId>", "Provider ID").option("--display-name <name>", "Display name").option("--type <type>", "Model type (chat|embedding|tts|stt|image|video|text2music|realtime)").action(
|
|
6368
|
+
async (id, options) => {
|
|
6369
|
+
if (!options.displayName && !options.type) {
|
|
6370
|
+
log.error("No changes specified. Use --display-name or --type.");
|
|
6371
|
+
process.exit(1);
|
|
6372
|
+
}
|
|
6373
|
+
const client = await getTrpcClient();
|
|
6374
|
+
const value = {};
|
|
6375
|
+
if (options.displayName) value.displayName = options.displayName;
|
|
6376
|
+
if (options.type) value.type = options.type;
|
|
6377
|
+
await client.aiModel.updateAiModel.mutate({
|
|
6378
|
+
id,
|
|
6379
|
+
providerId: options.provider,
|
|
6380
|
+
value
|
|
6381
|
+
});
|
|
6382
|
+
console.log(`${pc16.green("\u2713")} Updated model ${pc16.bold(id)}`);
|
|
6383
|
+
}
|
|
6384
|
+
);
|
|
5799
6385
|
model.command("toggle <id>").description("Enable or disable a model").requiredOption("--provider <providerId>", "Provider ID").option("--enable", "Enable the model").option("--disable", "Disable the model").action(
|
|
5800
6386
|
async (id, options) => {
|
|
5801
6387
|
if (options.enable === void 0 && options.disable === void 0) {
|
|
@@ -5809,7 +6395,7 @@ function registerModelCommand(program2) {
|
|
|
5809
6395
|
id,
|
|
5810
6396
|
providerId: options.provider
|
|
5811
6397
|
});
|
|
5812
|
-
console.log(`${
|
|
6398
|
+
console.log(`${pc16.green("\u2713")} Model ${pc16.bold(id)} ${enabled ? "enabled" : "disabled"}`);
|
|
5813
6399
|
}
|
|
5814
6400
|
);
|
|
5815
6401
|
model.command("delete <id>").description("Delete a model").requiredOption("--provider <providerId>", "Provider ID").option("--yes", "Skip confirmation prompt").action(async (id, options) => {
|
|
@@ -5822,12 +6408,49 @@ function registerModelCommand(program2) {
|
|
|
5822
6408
|
}
|
|
5823
6409
|
const client = await getTrpcClient();
|
|
5824
6410
|
await client.aiModel.removeAiModel.mutate({ id, providerId: options.provider });
|
|
5825
|
-
console.log(`${
|
|
6411
|
+
console.log(`${pc16.green("\u2713")} Deleted model ${pc16.bold(id)}`);
|
|
6412
|
+
});
|
|
6413
|
+
model.command("batch-toggle <ids...>").description("Enable or disable multiple models at once").requiredOption("--provider <providerId>", "Provider ID").option("--enable", "Enable the models").option("--disable", "Disable the models").action(
|
|
6414
|
+
async (ids, options) => {
|
|
6415
|
+
if (options.enable === void 0 && options.disable === void 0) {
|
|
6416
|
+
log.error("Specify --enable or --disable.");
|
|
6417
|
+
process.exit(1);
|
|
6418
|
+
}
|
|
6419
|
+
const client = await getTrpcClient();
|
|
6420
|
+
const enabled = options.enable === true;
|
|
6421
|
+
await client.aiModel.batchToggleAiModels.mutate({
|
|
6422
|
+
enabled,
|
|
6423
|
+
id: options.provider,
|
|
6424
|
+
models: ids
|
|
6425
|
+
});
|
|
6426
|
+
console.log(
|
|
6427
|
+
`${pc16.green("\u2713")} ${enabled ? "Enabled" : "Disabled"} ${ids.length} model(s) for provider ${pc16.bold(options.provider)}`
|
|
6428
|
+
);
|
|
6429
|
+
}
|
|
6430
|
+
);
|
|
6431
|
+
model.command("clear").description("Clear models for a provider").requiredOption("--provider <providerId>", "Provider ID").option("--remote", "Only clear remote/fetched models").option("--yes", "Skip confirmation prompt").action(async (options) => {
|
|
6432
|
+
const label = options.remote ? "remote models" : "all models";
|
|
6433
|
+
if (!options.yes) {
|
|
6434
|
+
const confirmed = await confirm(
|
|
6435
|
+
`Are you sure you want to clear ${label} for provider ${options.provider}?`
|
|
6436
|
+
);
|
|
6437
|
+
if (!confirmed) {
|
|
6438
|
+
console.log("Cancelled.");
|
|
6439
|
+
return;
|
|
6440
|
+
}
|
|
6441
|
+
}
|
|
6442
|
+
const client = await getTrpcClient();
|
|
6443
|
+
if (options.remote) {
|
|
6444
|
+
await client.aiModel.clearRemoteModels.mutate({ providerId: options.provider });
|
|
6445
|
+
} else {
|
|
6446
|
+
await client.aiModel.clearModelsByProvider.mutate({ providerId: options.provider });
|
|
6447
|
+
}
|
|
6448
|
+
console.log(`${pc16.green("\u2713")} Cleared ${label} for provider ${pc16.bold(options.provider)}`);
|
|
5826
6449
|
});
|
|
5827
6450
|
}
|
|
5828
6451
|
|
|
5829
6452
|
// src/commands/plugin.ts
|
|
5830
|
-
import
|
|
6453
|
+
import pc17 from "picocolors";
|
|
5831
6454
|
function registerPluginCommand(program2) {
|
|
5832
6455
|
const plugin = program2.command("plugin").description("Manage plugins");
|
|
5833
6456
|
plugin.command("list").description("List installed plugins").option("--json [fields]", "Output JSON, optionally specify fields (comma-separated)").action(async (options) => {
|
|
@@ -5877,7 +6500,7 @@ function registerPluginCommand(program2) {
|
|
|
5877
6500
|
settings,
|
|
5878
6501
|
type: options.type
|
|
5879
6502
|
});
|
|
5880
|
-
console.log(`${
|
|
6503
|
+
console.log(`${pc17.green("\u2713")} Installed plugin ${pc17.bold(options.identifier)}`);
|
|
5881
6504
|
}
|
|
5882
6505
|
);
|
|
5883
6506
|
plugin.command("uninstall <id>").description("Uninstall a plugin").option("--yes", "Skip confirmation prompt").action(async (id, options) => {
|
|
@@ -5890,7 +6513,7 @@ function registerPluginCommand(program2) {
|
|
|
5890
6513
|
}
|
|
5891
6514
|
const client = await getTrpcClient();
|
|
5892
6515
|
await client.plugin.removePlugin.mutate({ id });
|
|
5893
|
-
console.log(`${
|
|
6516
|
+
console.log(`${pc17.green("\u2713")} Uninstalled plugin ${pc17.bold(id)}`);
|
|
5894
6517
|
});
|
|
5895
6518
|
plugin.command("update <id>").description("Update plugin settings or manifest").option("--manifest <json>", "New manifest JSON").option("--settings <json>", "New settings JSON").action(async (id, options) => {
|
|
5896
6519
|
const input = { id };
|
|
@@ -5916,12 +6539,12 @@ function registerPluginCommand(program2) {
|
|
|
5916
6539
|
}
|
|
5917
6540
|
const client = await getTrpcClient();
|
|
5918
6541
|
await client.plugin.updatePlugin.mutate(input);
|
|
5919
|
-
console.log(`${
|
|
6542
|
+
console.log(`${pc17.green("\u2713")} Updated plugin ${pc17.bold(id)}`);
|
|
5920
6543
|
});
|
|
5921
6544
|
}
|
|
5922
6545
|
|
|
5923
6546
|
// src/commands/provider.ts
|
|
5924
|
-
import
|
|
6547
|
+
import pc18 from "picocolors";
|
|
5925
6548
|
function registerProviderCommand(program2) {
|
|
5926
6549
|
const provider = program2.command("provider").description("Manage AI providers");
|
|
5927
6550
|
provider.command("list").description("List AI providers").option("--json [fields]", "Output JSON, optionally specify fields (comma-separated)").action(async (options) => {
|
|
@@ -5940,7 +6563,7 @@ function registerProviderCommand(program2) {
|
|
|
5940
6563
|
const rows = items.map((p) => [
|
|
5941
6564
|
p.id || "",
|
|
5942
6565
|
truncate(p.name || p.id || "", 30),
|
|
5943
|
-
p.enabled ?
|
|
6566
|
+
p.enabled ? pc18.green("\u2713") : pc18.dim("\u2717"),
|
|
5944
6567
|
p.source || ""
|
|
5945
6568
|
]);
|
|
5946
6569
|
printTable(rows, ["ID", "NAME", "ENABLED", "SOURCE"]);
|
|
@@ -5948,7 +6571,7 @@ function registerProviderCommand(program2) {
|
|
|
5948
6571
|
provider.command("view <id>").description("View provider details").option("--json [fields]", "Output JSON, optionally specify fields (comma-separated)").action(async (id, options) => {
|
|
5949
6572
|
const client = await getTrpcClient();
|
|
5950
6573
|
const result = await client.aiProvider.getAiProviderById.query({ id });
|
|
5951
|
-
if (!result) {
|
|
6574
|
+
if (!result || !result.id) {
|
|
5952
6575
|
log.error(`Provider not found: ${id}`);
|
|
5953
6576
|
process.exit(1);
|
|
5954
6577
|
return;
|
|
@@ -5959,11 +6582,124 @@ function registerProviderCommand(program2) {
|
|
|
5959
6582
|
return;
|
|
5960
6583
|
}
|
|
5961
6584
|
const r = result;
|
|
5962
|
-
console.log(
|
|
6585
|
+
console.log(pc18.bold(r.name || r.id));
|
|
5963
6586
|
const meta = [];
|
|
5964
6587
|
if (r.enabled !== void 0) meta.push(r.enabled ? "Enabled" : "Disabled");
|
|
5965
6588
|
if (r.source) meta.push(`Source: ${r.source}`);
|
|
5966
|
-
if (meta.length > 0) console.log(
|
|
6589
|
+
if (meta.length > 0) console.log(pc18.dim(meta.join(" \xB7 ")));
|
|
6590
|
+
});
|
|
6591
|
+
provider.command("create").description("Create a new AI provider").requiredOption("--id <id>", "Provider ID").requiredOption("-n, --name <name>", "Provider name").option("-s, --source <source>", "Source type (builtin|custom)", "custom").option("-d, --description <desc>", "Provider description").option("--logo <logo>", "Provider logo URL").option("--sdk-type <sdkType>", "SDK type (openai|anthropic|azure|bedrock|...)").action(
|
|
6592
|
+
async (options) => {
|
|
6593
|
+
const client = await getTrpcClient();
|
|
6594
|
+
const input = {
|
|
6595
|
+
id: options.id,
|
|
6596
|
+
name: options.name,
|
|
6597
|
+
source: options.source || "custom"
|
|
6598
|
+
};
|
|
6599
|
+
if (options.description) input.description = options.description;
|
|
6600
|
+
if (options.logo) input.logo = options.logo;
|
|
6601
|
+
if (options.sdkType) input.sdkType = options.sdkType;
|
|
6602
|
+
const resultId = await client.aiProvider.createAiProvider.mutate(input);
|
|
6603
|
+
console.log(`${pc18.green("\u2713")} Created provider ${pc18.bold(resultId || options.id)}`);
|
|
6604
|
+
}
|
|
6605
|
+
);
|
|
6606
|
+
provider.command("edit <id>").description("Update provider info").option("-n, --name <name>", "Provider name").option("-d, --description <desc>", "Provider description").option("--logo <logo>", "Provider logo URL").option("--sdk-type <sdkType>", "SDK type").action(
|
|
6607
|
+
async (id, options) => {
|
|
6608
|
+
if (!options.name && !options.description && !options.logo && !options.sdkType) {
|
|
6609
|
+
log.error("No changes specified. Use --name, --description, --logo, or --sdk-type.");
|
|
6610
|
+
process.exit(1);
|
|
6611
|
+
}
|
|
6612
|
+
const client = await getTrpcClient();
|
|
6613
|
+
const value = {};
|
|
6614
|
+
if (options.name) value.name = options.name;
|
|
6615
|
+
if (options.description !== void 0) value.description = options.description;
|
|
6616
|
+
if (options.logo !== void 0) value.logo = options.logo;
|
|
6617
|
+
if (options.sdkType) value.sdkType = options.sdkType;
|
|
6618
|
+
await client.aiProvider.updateAiProvider.mutate({ id, value });
|
|
6619
|
+
console.log(`${pc18.green("\u2713")} Updated provider ${pc18.bold(id)}`);
|
|
6620
|
+
}
|
|
6621
|
+
);
|
|
6622
|
+
provider.command("config <id>").description("Configure provider settings (API key, base URL, etc.)").option("--api-key <key>", "Set API key").option("--base-url <url>", "Set base URL").option("--check-model <model>", "Set connectivity check model").option("--enable-response-api", "Enable Response API mode (OpenAI)").option("--disable-response-api", "Disable Response API mode").option("--fetch-on-client", "Enable fetching models on client side").option("--no-fetch-on-client", "Disable fetching models on client side").option("--show", "Show current config").option("--json [fields]", "Output JSON (with --show)").action(
|
|
6623
|
+
async (id, options) => {
|
|
6624
|
+
if (id === "lobehub" && (options.apiKey !== void 0 || options.baseUrl !== void 0)) {
|
|
6625
|
+
log.error(
|
|
6626
|
+
`Provider "lobehub" is managed by the LobeHub platform. You cannot set --api-key or --base-url for it.`
|
|
6627
|
+
);
|
|
6628
|
+
process.exit(1);
|
|
6629
|
+
}
|
|
6630
|
+
const client = await getTrpcClient();
|
|
6631
|
+
if (options.show) {
|
|
6632
|
+
const detail = await client.aiProvider.getAiProviderById.query({ id });
|
|
6633
|
+
if (!detail) {
|
|
6634
|
+
log.error(`Provider not found: ${id}`);
|
|
6635
|
+
process.exit(1);
|
|
6636
|
+
return;
|
|
6637
|
+
}
|
|
6638
|
+
const config = {
|
|
6639
|
+
checkModel: detail.checkModel || "",
|
|
6640
|
+
fetchOnClient: detail.fetchOnClient ?? false,
|
|
6641
|
+
keyVaults: detail.keyVaults || {}
|
|
6642
|
+
};
|
|
6643
|
+
if (options.json !== void 0) {
|
|
6644
|
+
const fields = typeof options.json === "string" ? options.json : void 0;
|
|
6645
|
+
outputJson(config, fields);
|
|
6646
|
+
} else {
|
|
6647
|
+
console.log(pc18.bold(`Config for ${id}`));
|
|
6648
|
+
if (config.checkModel) console.log(` Check Model: ${config.checkModel}`);
|
|
6649
|
+
console.log(` Fetch on Client: ${config.fetchOnClient ? pc18.green("\u2713") : pc18.dim("\u2717")}`);
|
|
6650
|
+
const vaults = config.keyVaults;
|
|
6651
|
+
if (vaults.apiKey)
|
|
6652
|
+
console.log(` API Key: ${pc18.dim(vaults.apiKey.slice(0, 8) + "...")}`);
|
|
6653
|
+
if (vaults.baseURL) console.log(` Base URL: ${vaults.baseURL}`);
|
|
6654
|
+
}
|
|
6655
|
+
return;
|
|
6656
|
+
}
|
|
6657
|
+
const hasKeyVaults = options.apiKey !== void 0 || options.baseUrl !== void 0;
|
|
6658
|
+
const hasConfig = options.enableResponseApi || options.disableResponseApi;
|
|
6659
|
+
const hasOther = options.checkModel !== void 0 || options.fetchOnClient !== void 0;
|
|
6660
|
+
if (!hasKeyVaults && !hasConfig && !hasOther) {
|
|
6661
|
+
log.error(
|
|
6662
|
+
"No config specified. Use --api-key, --base-url, --check-model, --enable-response-api, --fetch-on-client, or --show."
|
|
6663
|
+
);
|
|
6664
|
+
process.exit(1);
|
|
6665
|
+
}
|
|
6666
|
+
const input = {};
|
|
6667
|
+
if (hasKeyVaults) {
|
|
6668
|
+
const keyVaults = {};
|
|
6669
|
+
if (options.apiKey !== void 0) keyVaults.apiKey = options.apiKey;
|
|
6670
|
+
if (options.baseUrl !== void 0) keyVaults.baseURL = options.baseUrl;
|
|
6671
|
+
input.keyVaults = keyVaults;
|
|
6672
|
+
}
|
|
6673
|
+
if (hasConfig) {
|
|
6674
|
+
input.config = { enableResponseApi: !!options.enableResponseApi };
|
|
6675
|
+
}
|
|
6676
|
+
if (options.checkModel !== void 0) input.checkModel = options.checkModel;
|
|
6677
|
+
if (options.fetchOnClient !== void 0) input.fetchOnClient = options.fetchOnClient;
|
|
6678
|
+
await client.aiProvider.updateAiProviderConfig.mutate({ id, value: input });
|
|
6679
|
+
console.log(`${pc18.green("\u2713")} Updated config for provider ${pc18.bold(id)}`);
|
|
6680
|
+
}
|
|
6681
|
+
);
|
|
6682
|
+
provider.command("test <id>").description("Test provider connectivity").option("-m, --model <model>", "Model to test with (defaults to provider checkModel)").option("--json", "Output result as JSON").action(async (id, options) => {
|
|
6683
|
+
const client = await getTrpcClient();
|
|
6684
|
+
console.log(`${pc18.yellow("\u22EF")} Testing provider ${pc18.bold(id)}...`);
|
|
6685
|
+
const result = await client.aiProvider.checkProviderConnectivity.mutate({
|
|
6686
|
+
id,
|
|
6687
|
+
model: options.model
|
|
6688
|
+
});
|
|
6689
|
+
if (options.json) {
|
|
6690
|
+
outputJson(result);
|
|
6691
|
+
return;
|
|
6692
|
+
}
|
|
6693
|
+
if (result.ok) {
|
|
6694
|
+
console.log(
|
|
6695
|
+
`${pc18.green("\u2713")} Provider ${pc18.bold(id)} is reachable (model: ${result.model})`
|
|
6696
|
+
);
|
|
6697
|
+
} else {
|
|
6698
|
+
console.log(`${pc18.red("\u2717")} Provider ${pc18.bold(id)} check failed`);
|
|
6699
|
+
if (result.model) console.log(` Model: ${result.model}`);
|
|
6700
|
+
if (result.error) console.log(` Error: ${pc18.dim(result.error)}`);
|
|
6701
|
+
process.exit(1);
|
|
6702
|
+
}
|
|
5967
6703
|
});
|
|
5968
6704
|
provider.command("toggle <id>").description("Enable or disable a provider").option("--enable", "Enable the provider").option("--disable", "Disable the provider").action(async (id, options) => {
|
|
5969
6705
|
if (options.enable === void 0 && options.disable === void 0) {
|
|
@@ -5973,7 +6709,7 @@ function registerProviderCommand(program2) {
|
|
|
5973
6709
|
const client = await getTrpcClient();
|
|
5974
6710
|
const enabled = options.enable === true;
|
|
5975
6711
|
await client.aiProvider.toggleProviderEnabled.mutate({ enabled, id });
|
|
5976
|
-
console.log(`${
|
|
6712
|
+
console.log(`${pc18.green("\u2713")} Provider ${pc18.bold(id)} ${enabled ? "enabled" : "disabled"}`);
|
|
5977
6713
|
});
|
|
5978
6714
|
provider.command("delete <id>").description("Delete a provider").option("--yes", "Skip confirmation prompt").action(async (id, options) => {
|
|
5979
6715
|
if (!options.yes) {
|
|
@@ -5985,12 +6721,12 @@ function registerProviderCommand(program2) {
|
|
|
5985
6721
|
}
|
|
5986
6722
|
const client = await getTrpcClient();
|
|
5987
6723
|
await client.aiProvider.removeAiProvider.mutate({ id });
|
|
5988
|
-
console.log(`${
|
|
6724
|
+
console.log(`${pc18.green("\u2713")} Deleted provider ${pc18.bold(id)}`);
|
|
5989
6725
|
});
|
|
5990
6726
|
}
|
|
5991
6727
|
|
|
5992
6728
|
// src/commands/search.ts
|
|
5993
|
-
import
|
|
6729
|
+
import pc19 from "picocolors";
|
|
5994
6730
|
var SEARCH_TYPES = [
|
|
5995
6731
|
"agent",
|
|
5996
6732
|
"topic",
|
|
@@ -6007,7 +6743,7 @@ var SEARCH_TYPES = [
|
|
|
6007
6743
|
function renderResultGroup(type, items) {
|
|
6008
6744
|
if (items.length === 0) return;
|
|
6009
6745
|
console.log();
|
|
6010
|
-
console.log(
|
|
6746
|
+
console.log(pc19.bold(pc19.cyan(`\u2500\u2500 ${type} (${items.length}) \u2500\u2500`)));
|
|
6011
6747
|
const rows = items.map((item) => [
|
|
6012
6748
|
item.id || "",
|
|
6013
6749
|
truncate(item.title || item.name || item.content || "Untitled", 80),
|
|
@@ -6066,7 +6802,19 @@ function registerSearchCommand(program2) {
|
|
|
6066
6802
|
}
|
|
6067
6803
|
|
|
6068
6804
|
// src/commands/skill.ts
|
|
6069
|
-
import
|
|
6805
|
+
import pc20 from "picocolors";
|
|
6806
|
+
function detectSourceType(source) {
|
|
6807
|
+
if (source.startsWith("https://github.com/") || source.startsWith("http://github.com/")) {
|
|
6808
|
+
return "github";
|
|
6809
|
+
}
|
|
6810
|
+
if (/^[\w-]+\/[\w.-]+$/.test(source)) {
|
|
6811
|
+
return "github";
|
|
6812
|
+
}
|
|
6813
|
+
if (source.startsWith("https://") || source.startsWith("http://")) {
|
|
6814
|
+
return "url";
|
|
6815
|
+
}
|
|
6816
|
+
return "market";
|
|
6817
|
+
}
|
|
6070
6818
|
function registerSkillCommand(program2) {
|
|
6071
6819
|
const skill = program2.command("skill").description("Manage agent skills");
|
|
6072
6820
|
skill.command("list").description("List skills").option("--source <source>", "Filter by source: builtin, market, user").option("--json [fields]", "Output JSON, optionally specify fields (comma-separated)").action(async (options) => {
|
|
@@ -6112,15 +6860,15 @@ function registerSkillCommand(program2) {
|
|
|
6112
6860
|
return;
|
|
6113
6861
|
}
|
|
6114
6862
|
const r = result;
|
|
6115
|
-
console.log(
|
|
6863
|
+
console.log(pc20.bold(r.name || "Untitled"));
|
|
6116
6864
|
const meta = [];
|
|
6117
6865
|
if (r.description) meta.push(r.description);
|
|
6118
6866
|
if (r.source) meta.push(`Source: ${r.source}`);
|
|
6119
6867
|
if (r.identifier) meta.push(`ID: ${r.identifier}`);
|
|
6120
|
-
if (meta.length > 0) console.log(
|
|
6868
|
+
if (meta.length > 0) console.log(pc20.dim(meta.join(" \xB7 ")));
|
|
6121
6869
|
if (r.content) {
|
|
6122
6870
|
console.log();
|
|
6123
|
-
console.log(
|
|
6871
|
+
console.log(pc20.bold("Content:"));
|
|
6124
6872
|
console.log(r.content);
|
|
6125
6873
|
}
|
|
6126
6874
|
});
|
|
@@ -6135,7 +6883,7 @@ function registerSkillCommand(program2) {
|
|
|
6135
6883
|
if (options.identifier) input.identifier = options.identifier;
|
|
6136
6884
|
const result = await client.agentSkills.create.mutate(input);
|
|
6137
6885
|
const r = result;
|
|
6138
|
-
console.log(`${
|
|
6886
|
+
console.log(`${pc20.green("\u2713")} Created skill ${pc20.bold(r.id || r)}`);
|
|
6139
6887
|
}
|
|
6140
6888
|
);
|
|
6141
6889
|
skill.command("edit <id>").description("Update a skill").option("-c, --content <content>", "New content").option("-n, --name <name>", "New name (via manifest)").option("-d, --description <desc>", "New description (via manifest)").action(
|
|
@@ -6155,7 +6903,7 @@ function registerSkillCommand(program2) {
|
|
|
6155
6903
|
input.manifest = manifest;
|
|
6156
6904
|
}
|
|
6157
6905
|
await client.agentSkills.update.mutate(input);
|
|
6158
|
-
console.log(`${
|
|
6906
|
+
console.log(`${pc20.green("\u2713")} Updated skill ${pc20.bold(id)}`);
|
|
6159
6907
|
}
|
|
6160
6908
|
);
|
|
6161
6909
|
skill.command("delete <id>").description("Delete a skill").option("--yes", "Skip confirmation prompt").action(async (id, options) => {
|
|
@@ -6168,7 +6916,7 @@ function registerSkillCommand(program2) {
|
|
|
6168
6916
|
}
|
|
6169
6917
|
const client = await getTrpcClient();
|
|
6170
6918
|
await client.agentSkills.delete.mutate({ id });
|
|
6171
|
-
console.log(`${
|
|
6919
|
+
console.log(`${pc20.green("\u2713")} Deleted skill ${pc20.bold(id)}`);
|
|
6172
6920
|
});
|
|
6173
6921
|
skill.command("search <query>").description("Search skills").option("--json [fields]", "Output JSON, optionally specify fields (comma-separated)").action(async (query, options) => {
|
|
6174
6922
|
const client = await getTrpcClient();
|
|
@@ -6190,29 +6938,31 @@ function registerSkillCommand(program2) {
|
|
|
6190
6938
|
]);
|
|
6191
6939
|
printTable(rows, ["ID", "NAME", "DESCRIPTION"]);
|
|
6192
6940
|
});
|
|
6193
|
-
skill.command("
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
if (options.branch) input.branch = options.branch;
|
|
6197
|
-
const result = await client.agentSkills.importFromGitHub.mutate(input);
|
|
6198
|
-
const r = result;
|
|
6199
|
-
console.log(`${pc19.green("\u2713")} Imported skill from GitHub ${pc19.bold(r.id || r.name || "")}`);
|
|
6200
|
-
});
|
|
6201
|
-
skill.command("import-url").description("Import a skill from a ZIP URL").requiredOption("--url <zipUrl>", "URL to skill ZIP file").action(async (options) => {
|
|
6202
|
-
const client = await getTrpcClient();
|
|
6203
|
-
const result = await client.agentSkills.importFromUrl.mutate({ url: options.url });
|
|
6204
|
-
const r = result;
|
|
6205
|
-
console.log(`${pc19.green("\u2713")} Imported skill from URL ${pc19.bold(r.id || r.name || "")}`);
|
|
6206
|
-
});
|
|
6207
|
-
skill.command("import-market").description("Install a skill from the marketplace").requiredOption("-i, --identifier <id>", "Skill identifier in marketplace").action(async (options) => {
|
|
6941
|
+
skill.command("install <source>").alias("i").description(
|
|
6942
|
+
"Install a skill (auto-detects: GitHub URL/shorthand, ZIP URL, or marketplace identifier)"
|
|
6943
|
+
).option("--branch <branch>", "Branch name (GitHub only)").action(async (source, options) => {
|
|
6208
6944
|
const client = await getTrpcClient();
|
|
6209
|
-
const
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6945
|
+
const sourceType = detectSourceType(source);
|
|
6946
|
+
if (sourceType === "github") {
|
|
6947
|
+
const gitUrl = source.startsWith("https://") ? source : `https://github.com/${source}`;
|
|
6948
|
+
const input = { gitUrl };
|
|
6949
|
+
if (options.branch) input.branch = options.branch;
|
|
6950
|
+
const result = await client.agentSkills.importFromGitHub.mutate(input);
|
|
6951
|
+
const r = result;
|
|
6952
|
+
console.log(
|
|
6953
|
+
`${pc20.green("\u2713")} Installed skill from GitHub ${pc20.bold(r.id || r.name || "")}`
|
|
6954
|
+
);
|
|
6955
|
+
} else if (sourceType === "url") {
|
|
6956
|
+
const result = await client.agentSkills.importFromUrl.mutate({ url: source });
|
|
6957
|
+
const r = result;
|
|
6958
|
+
console.log(`${pc20.green("\u2713")} Installed skill from URL ${pc20.bold(r.id || r.name || "")}`);
|
|
6959
|
+
} else {
|
|
6960
|
+
const result = await client.agentSkills.importFromMarket.mutate({ identifier: source });
|
|
6961
|
+
const r = result;
|
|
6962
|
+
console.log(
|
|
6963
|
+
`${pc20.green("\u2713")} Installed skill ${pc20.bold(source)} ${r.id ? `(${r.id})` : ""}`
|
|
6964
|
+
);
|
|
6965
|
+
}
|
|
6216
6966
|
});
|
|
6217
6967
|
skill.command("resources <id>").description("List skill resource files").option("--json [fields]", "Output JSON, optionally specify fields (comma-separated)").action(async (id, options) => {
|
|
6218
6968
|
const client = await getTrpcClient();
|
|
@@ -6234,11 +6984,11 @@ function registerSkillCommand(program2) {
|
|
|
6234
6984
|
]);
|
|
6235
6985
|
printTable(rows, ["PATH", "TYPE", "SIZE"]);
|
|
6236
6986
|
});
|
|
6237
|
-
skill.command("read-resource <id> <path>").description("Read a skill resource file").action(async (id,
|
|
6987
|
+
skill.command("read-resource <id> <path>").description("Read a skill resource file").action(async (id, path13) => {
|
|
6238
6988
|
const client = await getTrpcClient();
|
|
6239
|
-
const result = await client.agentSkills.readResource.query({ id, path:
|
|
6989
|
+
const result = await client.agentSkills.readResource.query({ id, path: path13 });
|
|
6240
6990
|
if (!result) {
|
|
6241
|
-
log.error(`Resource not found: ${
|
|
6991
|
+
log.error(`Resource not found: ${path13}`);
|
|
6242
6992
|
process.exit(1);
|
|
6243
6993
|
return;
|
|
6244
6994
|
}
|
|
@@ -6311,15 +7061,14 @@ function registerStatusCommand(program2) {
|
|
|
6311
7061
|
}
|
|
6312
7062
|
|
|
6313
7063
|
// src/commands/topic.ts
|
|
6314
|
-
import
|
|
7064
|
+
import pc21 from "picocolors";
|
|
6315
7065
|
function registerTopicCommand(program2) {
|
|
6316
7066
|
const topic = program2.command("topic").description("Manage conversation topics");
|
|
6317
|
-
topic.command("list").description("List topics").option("--agent-id <id>", "Filter by agent ID").option("
|
|
7067
|
+
topic.command("list").description("List topics").option("--agent-id <id>", "Filter by agent ID").option("-L, --limit <n>", "Page size", "30").option("--page <n>", "Page number", "1").option("--json [fields]", "Output JSON, optionally specify fields (comma-separated)").action(
|
|
6318
7068
|
async (options) => {
|
|
6319
7069
|
const client = await getTrpcClient();
|
|
6320
7070
|
const input = {};
|
|
6321
7071
|
if (options.agentId) input.agentId = options.agentId;
|
|
6322
|
-
if (options.sessionId) input.sessionId = options.sessionId;
|
|
6323
7072
|
if (options.limit) input.pageSize = Number.parseInt(options.limit, 10);
|
|
6324
7073
|
if (options.page) input.current = Number.parseInt(options.page, 10);
|
|
6325
7074
|
const result = await client.topic.getTopics.query(input);
|
|
@@ -6360,18 +7109,15 @@ function registerTopicCommand(program2) {
|
|
|
6360
7109
|
const rows = items.map((t) => [t.id || "", truncate(t.title || "Untitled", 50)]);
|
|
6361
7110
|
printTable(rows, ["ID", "TITLE"]);
|
|
6362
7111
|
});
|
|
6363
|
-
topic.command("create").description("Create a topic").requiredOption("-t, --title <title>", "Topic title").option("--agent-id <id>", "Agent ID").option("--
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
console.log(`${pc20.green("\u2713")} Created topic ${pc20.bold(r.id || r)}`);
|
|
6373
|
-
}
|
|
6374
|
-
);
|
|
7112
|
+
topic.command("create").description("Create a topic").requiredOption("-t, --title <title>", "Topic title").option("--agent-id <id>", "Agent ID").option("--favorite", "Mark as favorite").action(async (options) => {
|
|
7113
|
+
const client = await getTrpcClient();
|
|
7114
|
+
const input = { title: options.title };
|
|
7115
|
+
if (options.agentId) input.agentId = options.agentId;
|
|
7116
|
+
if (options.favorite) input.favorite = true;
|
|
7117
|
+
const result = await client.topic.createTopic.mutate(input);
|
|
7118
|
+
const r = result;
|
|
7119
|
+
console.log(`${pc21.green("\u2713")} Created topic ${pc21.bold(r.id || r)}`);
|
|
7120
|
+
});
|
|
6375
7121
|
topic.command("edit <id>").description("Update a topic").option("-t, --title <title>", "New title").option("--favorite", "Mark as favorite").option("--no-favorite", "Unmark as favorite").action(async (id, options) => {
|
|
6376
7122
|
const value = {};
|
|
6377
7123
|
if (options.title) value.title = options.title;
|
|
@@ -6382,7 +7128,7 @@ function registerTopicCommand(program2) {
|
|
|
6382
7128
|
}
|
|
6383
7129
|
const client = await getTrpcClient();
|
|
6384
7130
|
await client.topic.updateTopic.mutate({ id, value });
|
|
6385
|
-
console.log(`${
|
|
7131
|
+
console.log(`${pc21.green("\u2713")} Updated topic ${pc21.bold(id)}`);
|
|
6386
7132
|
});
|
|
6387
7133
|
topic.command("delete <ids...>").description("Delete one or more topics").option("--yes", "Skip confirmation prompt").action(async (ids, options) => {
|
|
6388
7134
|
if (!options.yes) {
|
|
@@ -6398,7 +7144,7 @@ function registerTopicCommand(program2) {
|
|
|
6398
7144
|
} else {
|
|
6399
7145
|
await client.topic.batchDelete.mutate({ ids });
|
|
6400
7146
|
}
|
|
6401
|
-
console.log(`${
|
|
7147
|
+
console.log(`${pc21.green("\u2713")} Deleted ${ids.length} topic(s)`);
|
|
6402
7148
|
});
|
|
6403
7149
|
topic.command("recent").description("List recent topics").option("-L, --limit <n>", "Number of items", "10").option("--json [fields]", "Output JSON, optionally specify fields (comma-separated)").action(async (options) => {
|
|
6404
7150
|
const client = await getTrpcClient();
|
|
@@ -6446,6 +7192,7 @@ registerModelCommand(program);
|
|
|
6446
7192
|
registerProviderCommand(program);
|
|
6447
7193
|
registerPluginCommand(program);
|
|
6448
7194
|
registerConfigCommand(program);
|
|
7195
|
+
registerEvalCommand(program);
|
|
6449
7196
|
program.parse();
|
|
6450
7197
|
/*! Bundled license information:
|
|
6451
7198
|
|