@stzhu/skills 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bash-complete.mjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as app, t as buildContext } from "./context-
|
|
2
|
+
import { n as app, t as buildContext } from "./context-BQaSQqU1.mjs";
|
|
3
3
|
import { proposeCompletions } from "@stricli/core";
|
|
4
|
-
|
|
5
4
|
//#region src/bin/bash-complete.ts
|
|
6
5
|
const inputs = process.argv.slice(3);
|
|
7
6
|
if (process.env["COMP_LINE"]?.endsWith(" ")) inputs.push("");
|
|
@@ -9,6 +8,5 @@ await proposeCompletions(app, inputs, buildContext(process));
|
|
|
9
8
|
try {
|
|
10
9
|
for (const { completion } of await proposeCompletions(app, inputs, buildContext(process))) process.stdout.write(`${completion}\n`);
|
|
11
10
|
} catch {}
|
|
12
|
-
|
|
13
11
|
//#endregion
|
|
14
|
-
export {
|
|
12
|
+
export {};
|
package/dist/cli.mjs
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as app, t as buildContext } from "./context-
|
|
2
|
+
import { n as app, t as buildContext } from "./context-BQaSQqU1.mjs";
|
|
3
3
|
import { run } from "@stricli/core";
|
|
4
|
-
|
|
5
4
|
//#region src/bin/cli.ts
|
|
6
5
|
await run(app, process.argv.slice(2), buildContext(process));
|
|
7
|
-
|
|
8
6
|
//#endregion
|
|
9
|
-
export {
|
|
7
|
+
export {};
|
|
@@ -4,64 +4,52 @@ import fs from "node:fs";
|
|
|
4
4
|
import os from "node:os";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { findWorkspacesRoot } from "find-workspaces";
|
|
7
|
-
|
|
8
7
|
//#region package.json
|
|
9
|
-
var version = "0.1.
|
|
8
|
+
var version = "0.1.2";
|
|
10
9
|
var description = "Skills CLI";
|
|
11
|
-
var bin = {
|
|
12
|
-
"__stz-skills_bash_complete": "dist/bash-complete.mjs",
|
|
13
|
-
"stz-skills": "dist/cli.mjs"
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
//#endregion
|
|
17
|
-
//#region src/commands/agent-logbook/commands.ts
|
|
18
|
-
const statsCommand = buildCommand({
|
|
19
|
-
loader: async () => {
|
|
20
|
-
const { stats } = await import("./stats-RlcmzM9e.mjs");
|
|
21
|
-
return stats;
|
|
22
|
-
},
|
|
23
|
-
parameters: {
|
|
24
|
-
flags: { agent: {
|
|
25
|
-
kind: "enum",
|
|
26
|
-
brief: "The agent to get stats for",
|
|
27
|
-
values: ["claudecode", "geminicli"]
|
|
28
|
-
} },
|
|
29
|
-
positional: {
|
|
30
|
-
kind: "tuple",
|
|
31
|
-
parameters: [{
|
|
32
|
-
parse: String,
|
|
33
|
-
brief: "The session ID to get stats for"
|
|
34
|
-
}]
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
docs: { brief: "Agent logbook stats command" }
|
|
38
|
-
});
|
|
39
|
-
const validateCommand = buildCommand({
|
|
40
|
-
loader: async () => {
|
|
41
|
-
const { validate } = await import("./validate-D3AdsB3Q.mjs");
|
|
42
|
-
return validate;
|
|
43
|
-
},
|
|
44
|
-
parameters: { positional: {
|
|
45
|
-
kind: "tuple",
|
|
46
|
-
parameters: [{
|
|
47
|
-
parse: String,
|
|
48
|
-
brief: "The target file or directory to validate frontmatter for",
|
|
49
|
-
optional: true
|
|
50
|
-
}]
|
|
51
|
-
} },
|
|
52
|
-
docs: { brief: "Agent logbook validate command" }
|
|
53
|
-
});
|
|
10
|
+
var bin = { "stz-skills": "dist/cli.mjs" };
|
|
54
11
|
const agentLogbookRoutes = buildRouteMap({
|
|
55
12
|
routes: {
|
|
56
|
-
stats:
|
|
57
|
-
|
|
13
|
+
stats: buildCommand({
|
|
14
|
+
loader: async () => {
|
|
15
|
+
const { stats } = await import("./stats-Bq8rF7sI.mjs");
|
|
16
|
+
return stats;
|
|
17
|
+
},
|
|
18
|
+
parameters: {
|
|
19
|
+
flags: { agent: {
|
|
20
|
+
kind: "enum",
|
|
21
|
+
brief: "The agent to get stats for",
|
|
22
|
+
values: ["claudecode", "geminicli"]
|
|
23
|
+
} },
|
|
24
|
+
positional: {
|
|
25
|
+
kind: "tuple",
|
|
26
|
+
parameters: [{
|
|
27
|
+
parse: String,
|
|
28
|
+
brief: "The session ID to get stats for"
|
|
29
|
+
}]
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
docs: { brief: "Agent logbook stats command" }
|
|
33
|
+
}),
|
|
34
|
+
validate: buildCommand({
|
|
35
|
+
loader: async () => {
|
|
36
|
+
const { validate } = await import("./validate-CMKdK9Xg.mjs");
|
|
37
|
+
return validate;
|
|
38
|
+
},
|
|
39
|
+
parameters: { positional: {
|
|
40
|
+
kind: "tuple",
|
|
41
|
+
parameters: [{
|
|
42
|
+
parse: String,
|
|
43
|
+
brief: "The target file or directory to validate frontmatter for",
|
|
44
|
+
optional: true
|
|
45
|
+
}]
|
|
46
|
+
} },
|
|
47
|
+
docs: { brief: "Agent logbook validate command" }
|
|
48
|
+
})
|
|
58
49
|
},
|
|
59
50
|
docs: { brief: "Agent logbook commands" }
|
|
60
51
|
});
|
|
61
|
-
|
|
62
|
-
//#endregion
|
|
63
|
-
//#region src/app.ts
|
|
64
|
-
const routes = buildRouteMap({
|
|
52
|
+
const app = buildApplication(buildRouteMap({
|
|
65
53
|
routes: {
|
|
66
54
|
"agent-logbook": agentLogbookRoutes,
|
|
67
55
|
install: buildInstallCommand("stz-skills", { bash: "__stz-skills_bash_complete" }),
|
|
@@ -74,8 +62,7 @@ const routes = buildRouteMap({
|
|
|
74
62
|
uninstall: true
|
|
75
63
|
}
|
|
76
64
|
}
|
|
77
|
-
})
|
|
78
|
-
const app = buildApplication(routes, {
|
|
65
|
+
}), {
|
|
79
66
|
name: (() => {
|
|
80
67
|
const name = Object.keys(bin).find((key) => !key.startsWith("__"));
|
|
81
68
|
if (!name) throw new Error("Name not found");
|
|
@@ -83,7 +70,6 @@ const app = buildApplication(routes, {
|
|
|
83
70
|
})(),
|
|
84
71
|
versionInfo: { currentVersion: version }
|
|
85
72
|
});
|
|
86
|
-
|
|
87
73
|
//#endregion
|
|
88
74
|
//#region src/context.ts
|
|
89
75
|
function buildContext(process) {
|
|
@@ -97,6 +83,5 @@ function buildContext(process) {
|
|
|
97
83
|
workspacesRoot: workspacesRoot.location
|
|
98
84
|
};
|
|
99
85
|
}
|
|
100
|
-
|
|
101
86
|
//#endregion
|
|
102
|
-
export { app as n, buildContext as t };
|
|
87
|
+
export { app as n, buildContext as t };
|
|
@@ -2,7 +2,6 @@ import fs from "node:fs";
|
|
|
2
2
|
import os from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import readline from "node:readline";
|
|
5
|
-
|
|
6
5
|
//#region src/util/defineCommandFunction.ts
|
|
7
6
|
/**
|
|
8
7
|
* Identity wrapper for strongly typed command implementations.
|
|
@@ -13,7 +12,6 @@ import readline from "node:readline";
|
|
|
13
12
|
function defineCommandFunction(impl) {
|
|
14
13
|
return impl;
|
|
15
14
|
}
|
|
16
|
-
|
|
17
15
|
//#endregion
|
|
18
16
|
//#region src/commands/agent-logbook/stats/formatSessionStatsOutput.ts
|
|
19
17
|
/**
|
|
@@ -60,7 +58,6 @@ function formatSessionStatsOutput(agentName, sessionId, result) {
|
|
|
60
58
|
lines.push("");
|
|
61
59
|
return lines.join("\n");
|
|
62
60
|
}
|
|
63
|
-
|
|
64
61
|
//#endregion
|
|
65
62
|
//#region src/commands/agent-logbook/stats/defineSessionStatsPlugin.ts
|
|
66
63
|
/**
|
|
@@ -72,7 +69,6 @@ function formatSessionStatsOutput(agentName, sessionId, result) {
|
|
|
72
69
|
function defineSessionStatsPlugin(plugin) {
|
|
73
70
|
return plugin;
|
|
74
71
|
}
|
|
75
|
-
|
|
76
72
|
//#endregion
|
|
77
73
|
//#region src/commands/agent-logbook/stats/plugins/claudecode.ts
|
|
78
74
|
/** Base directory where Claude Code stores project and session metadata. */
|
|
@@ -216,7 +212,6 @@ const claudecodePlugin = defineSessionStatsPlugin({
|
|
|
216
212
|
};
|
|
217
213
|
}
|
|
218
214
|
});
|
|
219
|
-
|
|
220
215
|
//#endregion
|
|
221
216
|
//#region src/commands/agent-logbook/stats/plugins/geminicli.ts
|
|
222
217
|
/** Base directory where Gemini CLI stores its temporary session data. */
|
|
@@ -229,88 +224,82 @@ async function readJsonFile(filePath) {
|
|
|
229
224
|
const content = await fs.promises.readFile(filePath, "utf8");
|
|
230
225
|
return JSON.parse(content);
|
|
231
226
|
}
|
|
232
|
-
/**
|
|
233
|
-
* The GeminiCLI-specific stats plugin.
|
|
234
|
-
* Handles parsing GeminiCLI session JSON files found in ~/.gemini/tmp.
|
|
235
|
-
*/
|
|
236
|
-
const geminicliPlugin = defineSessionStatsPlugin({
|
|
237
|
-
name: "geminicli",
|
|
238
|
-
async findSession(sessionId) {
|
|
239
|
-
const matchingFiles = [];
|
|
240
|
-
try {
|
|
241
|
-
const projectDirs = await fs.promises.readdir(GEMINICLI_TMP_DIR);
|
|
242
|
-
const dirResults = await Promise.all(projectDirs.map(async (projectDir) => {
|
|
243
|
-
const chatsDir = path.join(GEMINICLI_TMP_DIR, projectDir, "chats");
|
|
244
|
-
try {
|
|
245
|
-
const jsonFiles = (await fs.promises.readdir(chatsDir)).filter((f) => f.endsWith(".json")).map((f) => path.join(chatsDir, f));
|
|
246
|
-
return (await Promise.all(jsonFiles.map(async (filePath) => {
|
|
247
|
-
return (await readJsonFile(filePath)).sessionId === sessionId ? filePath : null;
|
|
248
|
-
}))).filter((f) => f !== null);
|
|
249
|
-
} catch {
|
|
250
|
-
return [];
|
|
251
|
-
}
|
|
252
|
-
}));
|
|
253
|
-
matchingFiles.push(...dirResults.flat());
|
|
254
|
-
} catch (error) {
|
|
255
|
-
console.error("Error searching gemini tmp directory:", error.message);
|
|
256
|
-
}
|
|
257
|
-
return matchingFiles.length > 0 ? matchingFiles : null;
|
|
258
|
-
},
|
|
259
|
-
async aggregateStats(sessionFiles) {
|
|
260
|
-
const stats = {
|
|
261
|
-
input: 0,
|
|
262
|
-
output: 0,
|
|
263
|
-
cached: 0,
|
|
264
|
-
thoughts: 0,
|
|
265
|
-
tool: 0,
|
|
266
|
-
total: 0,
|
|
267
|
-
models: /* @__PURE__ */ new Set()
|
|
268
|
-
};
|
|
269
|
-
const results = await Promise.all(sessionFiles.map(async (filePath) => {
|
|
270
|
-
try {
|
|
271
|
-
return await readJsonFile(filePath);
|
|
272
|
-
} catch (error) {
|
|
273
|
-
console.error(`Error processing file ${filePath}:`, error.message);
|
|
274
|
-
return null;
|
|
275
|
-
}
|
|
276
|
-
}));
|
|
277
|
-
for (const data of results) {
|
|
278
|
-
if (!data?.messages || !Array.isArray(data.messages)) continue;
|
|
279
|
-
for (const msg of data.messages) if (msg.type === "gemini" && msg.tokens) {
|
|
280
|
-
stats.input += msg.tokens.input || 0;
|
|
281
|
-
stats.output += msg.tokens.output || 0;
|
|
282
|
-
stats.cached += msg.tokens.cached || 0;
|
|
283
|
-
stats.thoughts += msg.tokens.thoughts || 0;
|
|
284
|
-
stats.tool += msg.tokens.tool || 0;
|
|
285
|
-
stats.total += msg.tokens.total || 0;
|
|
286
|
-
if (msg.model) stats.models.add(msg.model);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
return {
|
|
290
|
-
models: Array.from(stats.models),
|
|
291
|
-
meta: [["Files Found", sessionFiles.length]],
|
|
292
|
-
sections: [{
|
|
293
|
-
label: "TOKEN USAGE",
|
|
294
|
-
entries: [
|
|
295
|
-
["Input Tokens", stats.input - stats.cached],
|
|
296
|
-
["Output Tokens", stats.output],
|
|
297
|
-
["Cached Tokens", stats.cached],
|
|
298
|
-
["Thoughts Tokens", stats.thoughts],
|
|
299
|
-
["Tool Tokens", stats.tool]
|
|
300
|
-
]
|
|
301
|
-
}],
|
|
302
|
-
summary: null,
|
|
303
|
-
grandTotal: stats.total
|
|
304
|
-
};
|
|
305
|
-
}
|
|
306
|
-
});
|
|
307
|
-
|
|
308
227
|
//#endregion
|
|
309
228
|
//#region src/commands/agent-logbook/stats/index.ts
|
|
310
229
|
/** Mapping of agent names to their respective stats plugins. */
|
|
311
230
|
const plugins = {
|
|
312
231
|
claudecode: claudecodePlugin,
|
|
313
|
-
geminicli:
|
|
232
|
+
geminicli: defineSessionStatsPlugin({
|
|
233
|
+
name: "geminicli",
|
|
234
|
+
async findSession(sessionId) {
|
|
235
|
+
const matchingFiles = [];
|
|
236
|
+
try {
|
|
237
|
+
const projectDirs = await fs.promises.readdir(GEMINICLI_TMP_DIR);
|
|
238
|
+
const dirResults = await Promise.all(projectDirs.map(async (projectDir) => {
|
|
239
|
+
const chatsDir = path.join(GEMINICLI_TMP_DIR, projectDir, "chats");
|
|
240
|
+
try {
|
|
241
|
+
const jsonFiles = (await fs.promises.readdir(chatsDir)).filter((f) => f.endsWith(".json")).map((f) => path.join(chatsDir, f));
|
|
242
|
+
return (await Promise.all(jsonFiles.map(async (filePath) => {
|
|
243
|
+
return (await readJsonFile(filePath)).sessionId === sessionId ? filePath : null;
|
|
244
|
+
}))).filter((f) => f !== null);
|
|
245
|
+
} catch {
|
|
246
|
+
return [];
|
|
247
|
+
}
|
|
248
|
+
}));
|
|
249
|
+
matchingFiles.push(...dirResults.flat());
|
|
250
|
+
} catch (error) {
|
|
251
|
+
console.error("Error searching gemini tmp directory:", error.message);
|
|
252
|
+
}
|
|
253
|
+
return matchingFiles.length > 0 ? matchingFiles : null;
|
|
254
|
+
},
|
|
255
|
+
async aggregateStats(sessionFiles) {
|
|
256
|
+
const stats = {
|
|
257
|
+
input: 0,
|
|
258
|
+
output: 0,
|
|
259
|
+
cached: 0,
|
|
260
|
+
thoughts: 0,
|
|
261
|
+
tool: 0,
|
|
262
|
+
total: 0,
|
|
263
|
+
models: /* @__PURE__ */ new Set()
|
|
264
|
+
};
|
|
265
|
+
const results = await Promise.all(sessionFiles.map(async (filePath) => {
|
|
266
|
+
try {
|
|
267
|
+
return await readJsonFile(filePath);
|
|
268
|
+
} catch (error) {
|
|
269
|
+
console.error(`Error processing file ${filePath}:`, error.message);
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
}));
|
|
273
|
+
for (const data of results) {
|
|
274
|
+
if (!data?.messages || !Array.isArray(data.messages)) continue;
|
|
275
|
+
for (const msg of data.messages) if (msg.type === "gemini" && msg.tokens) {
|
|
276
|
+
stats.input += msg.tokens.input || 0;
|
|
277
|
+
stats.output += msg.tokens.output || 0;
|
|
278
|
+
stats.cached += msg.tokens.cached || 0;
|
|
279
|
+
stats.thoughts += msg.tokens.thoughts || 0;
|
|
280
|
+
stats.tool += msg.tokens.tool || 0;
|
|
281
|
+
stats.total += msg.tokens.total || 0;
|
|
282
|
+
if (msg.model) stats.models.add(msg.model);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return {
|
|
286
|
+
models: Array.from(stats.models),
|
|
287
|
+
meta: [["Files Found", sessionFiles.length]],
|
|
288
|
+
sections: [{
|
|
289
|
+
label: "TOKEN USAGE",
|
|
290
|
+
entries: [
|
|
291
|
+
["Input Tokens", stats.input - stats.cached],
|
|
292
|
+
["Output Tokens", stats.output],
|
|
293
|
+
["Cached Tokens", stats.cached],
|
|
294
|
+
["Thoughts Tokens", stats.thoughts],
|
|
295
|
+
["Tool Tokens", stats.tool]
|
|
296
|
+
]
|
|
297
|
+
}],
|
|
298
|
+
summary: null,
|
|
299
|
+
grandTotal: stats.total
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
})
|
|
314
303
|
};
|
|
315
304
|
/**
|
|
316
305
|
* The 'stats' command implementation.
|
|
@@ -336,6 +325,5 @@ const stats = defineCommandFunction(async function stats({ agent }, sessionId) {
|
|
|
336
325
|
const result = await plugin.aggregateStats(sessionData);
|
|
337
326
|
console.log(formatSessionStatsOutput(plugin.name, sessionId, result));
|
|
338
327
|
});
|
|
339
|
-
|
|
340
328
|
//#endregion
|
|
341
|
-
export { stats };
|
|
329
|
+
export { stats };
|
|
@@ -4,7 +4,6 @@ import matter from "gray-matter";
|
|
|
4
4
|
import { Compile } from "typebox/compile";
|
|
5
5
|
import yaml from "yaml";
|
|
6
6
|
import { Type } from "typebox";
|
|
7
|
-
|
|
8
7
|
//#region src/commands/agent-logbook/validate/frontmatterSchema.ts
|
|
9
8
|
const IsoDate = Type.Codec(Type.String({ format: "date-time" })).Decode((value) => new Date(value)).Encode((value) => value.toISOString());
|
|
10
9
|
/**
|
|
@@ -37,7 +36,6 @@ const FrontmatterSchema = Type.Object({
|
|
|
37
36
|
relatedPlan: Type.Optional(Type.String()),
|
|
38
37
|
migrated: Type.Optional(Type.Boolean())
|
|
39
38
|
}, { additionalProperties: false });
|
|
40
|
-
|
|
41
39
|
//#endregion
|
|
42
40
|
//#region src/commands/agent-logbook/validate/index.ts
|
|
43
41
|
/**
|
|
@@ -99,6 +97,5 @@ async function validate(_flags, targetPath = ".agent-logbook") {
|
|
|
99
97
|
if (failed > 0) return process.exit(1);
|
|
100
98
|
console.log("All files validated successfully");
|
|
101
99
|
}
|
|
102
|
-
|
|
103
100
|
//#endregion
|
|
104
|
-
export { validate };
|
|
101
|
+
export { validate };
|
package/package.json
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stzhu/skills",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Skills CLI",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"skills"
|
|
7
7
|
],
|
|
8
8
|
"license": "MIT",
|
|
9
9
|
"author": "Steve Zhu <4130171+stevezhu@users.noreply.github.com>",
|
|
10
|
-
"repository":
|
|
11
|
-
"type": "git",
|
|
12
|
-
"url": "git+https://github.com/stevezhu/eslint-config.git"
|
|
13
|
-
},
|
|
10
|
+
"repository": "github:stevezhu/skills",
|
|
14
11
|
"bin": {
|
|
15
|
-
"__stz-skills_bash_complete": "dist/bash-complete.mjs",
|
|
16
12
|
"stz-skills": "dist/cli.mjs"
|
|
17
13
|
},
|
|
18
14
|
"files": [
|
|
@@ -27,16 +23,16 @@
|
|
|
27
23
|
"@stricli/core": "^1.2.6",
|
|
28
24
|
"find-workspaces": "^0.3.1",
|
|
29
25
|
"gray-matter": "^4.0.3",
|
|
30
|
-
"typebox": "^1.1.
|
|
26
|
+
"typebox": "^1.1.6",
|
|
31
27
|
"yaml": "^2.8.2"
|
|
32
28
|
},
|
|
33
29
|
"devDependencies": {
|
|
34
|
-
"@stzhu/tsconfig": "^0.
|
|
35
|
-
"@types/node": "^25.
|
|
36
|
-
"oxfmt": "^0.
|
|
37
|
-
"oxlint": "^1.
|
|
30
|
+
"@stzhu/tsconfig": "^0.3.0",
|
|
31
|
+
"@types/node": "^25.4.0",
|
|
32
|
+
"oxfmt": "^0.37.0",
|
|
33
|
+
"oxlint": "^1.52.0",
|
|
38
34
|
"oxlint-tsgolint": "^0.16.0",
|
|
39
|
-
"tsdown": "^0.
|
|
35
|
+
"tsdown": "^0.21.1",
|
|
40
36
|
"tsx": "^4.21.0",
|
|
41
37
|
"typescript": "^5.9.3",
|
|
42
38
|
"vitest": "^4.0.18"
|
|
@@ -45,14 +41,11 @@
|
|
|
45
41
|
"node": ">=25"
|
|
46
42
|
},
|
|
47
43
|
"scripts": {
|
|
48
|
-
"ai:claude": "claude",
|
|
49
|
-
"ai:gemini": "SEATBELT_PROFILE=custom gemini",
|
|
50
44
|
"build": "tsdown",
|
|
51
45
|
"format": "oxfmt",
|
|
52
46
|
"format:check": "oxfmt --check",
|
|
53
47
|
"lint": "pnpm run format:check && oxlint --type-aware",
|
|
54
48
|
"lint:fix": "oxlint --type-aware --fix",
|
|
55
|
-
"postinstall": "([ ! -d \"src\" ] || pnpm run build) && node dist/cli.mjs install",
|
|
56
49
|
"pretest": "tsc --noEmit",
|
|
57
50
|
"test": "vitest"
|
|
58
51
|
}
|