@jcheesepkg/nanobot 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +139 -0
- package/dist/_virtual/_rolldown/runtime.mjs +40 -0
- package/dist/agent/context.d.mts +44 -0
- package/dist/agent/context.d.mts.map +1 -0
- package/dist/agent/context.mjs +153 -0
- package/dist/agent/context.mjs.map +1 -0
- package/dist/agent/loop.d.mts +56 -0
- package/dist/agent/loop.d.mts.map +1 -0
- package/dist/agent/loop.mjs +232 -0
- package/dist/agent/loop.mjs.map +1 -0
- package/dist/agent/memory.d.mts +30 -0
- package/dist/agent/memory.d.mts.map +1 -0
- package/dist/agent/memory.mjs +77 -0
- package/dist/agent/memory.mjs.map +1 -0
- package/dist/agent/skills.d.mts +43 -0
- package/dist/agent/skills.d.mts.map +1 -0
- package/dist/agent/skills.mjs +159 -0
- package/dist/agent/skills.mjs.map +1 -0
- package/dist/agent/subagent.d.mts +39 -0
- package/dist/agent/subagent.d.mts.map +1 -0
- package/dist/agent/subagent.mjs +167 -0
- package/dist/agent/subagent.mjs.map +1 -0
- package/dist/agent/tools/base.d.mts +16 -0
- package/dist/agent/tools/base.d.mts.map +1 -0
- package/dist/agent/tools/base.mjs +19 -0
- package/dist/agent/tools/base.mjs.map +1 -0
- package/dist/agent/tools/cron.d.mts +49 -0
- package/dist/agent/tools/cron.d.mts.map +1 -0
- package/dist/agent/tools/cron.mjs +101 -0
- package/dist/agent/tools/cron.mjs.map +1 -0
- package/dist/agent/tools/filesystem.d.mts +87 -0
- package/dist/agent/tools/filesystem.d.mts.map +1 -0
- package/dist/agent/tools/filesystem.mjs +145 -0
- package/dist/agent/tools/filesystem.mjs.map +1 -0
- package/dist/agent/tools/message.d.mts +44 -0
- package/dist/agent/tools/message.d.mts.map +1 -0
- package/dist/agent/tools/message.mjs +68 -0
- package/dist/agent/tools/message.mjs.map +1 -0
- package/dist/agent/tools/registry.d.mts +29 -0
- package/dist/agent/tools/registry.d.mts.map +1 -0
- package/dist/agent/tools/registry.mjs +49 -0
- package/dist/agent/tools/registry.mjs.map +1 -0
- package/dist/agent/tools/shell.d.mts +36 -0
- package/dist/agent/tools/shell.d.mts.map +1 -0
- package/dist/agent/tools/shell.mjs +73 -0
- package/dist/agent/tools/shell.mjs.map +1 -0
- package/dist/agent/tools/spawn.d.mts +35 -0
- package/dist/agent/tools/spawn.d.mts.map +1 -0
- package/dist/agent/tools/spawn.mjs +50 -0
- package/dist/agent/tools/spawn.mjs.map +1 -0
- package/dist/agent/tools/web.d.mts +63 -0
- package/dist/agent/tools/web.d.mts.map +1 -0
- package/dist/agent/tools/web.mjs +195 -0
- package/dist/agent/tools/web.mjs.map +1 -0
- package/dist/bus/events.d.mts +29 -0
- package/dist/bus/events.d.mts.map +1 -0
- package/dist/bus/events.mjs +30 -0
- package/dist/bus/events.mjs.map +1 -0
- package/dist/bus/queue.d.mts +38 -0
- package/dist/bus/queue.d.mts.map +1 -0
- package/dist/bus/queue.mjs +90 -0
- package/dist/bus/queue.mjs.map +1 -0
- package/dist/channels/base.d.mts +31 -0
- package/dist/channels/base.d.mts.map +1 -0
- package/dist/channels/base.mjs +49 -0
- package/dist/channels/base.mjs.map +1 -0
- package/dist/channels/manager.d.mts +30 -0
- package/dist/channels/manager.d.mts.map +1 -0
- package/dist/channels/manager.mjs +100 -0
- package/dist/channels/manager.mjs.map +1 -0
- package/dist/channels/telegram.d.mts +23 -0
- package/dist/channels/telegram.d.mts.map +1 -0
- package/dist/channels/telegram.mjs +161 -0
- package/dist/channels/telegram.mjs.map +1 -0
- package/dist/cli/index.d.mts +1 -0
- package/dist/cli/index.mjs +337 -0
- package/dist/cli/index.mjs.map +1 -0
- package/dist/config/loader.d.mts +14 -0
- package/dist/config/loader.d.mts.map +1 -0
- package/dist/config/loader.mjs +40 -0
- package/dist/config/loader.mjs.map +1 -0
- package/dist/config/schema.d.mts +724 -0
- package/dist/config/schema.d.mts.map +1 -0
- package/dist/config/schema.mjs +123 -0
- package/dist/config/schema.mjs.map +1 -0
- package/dist/cron/service.d.mts +42 -0
- package/dist/cron/service.d.mts.map +1 -0
- package/dist/cron/service.mjs +256 -0
- package/dist/cron/service.mjs.map +1 -0
- package/dist/cron/types.d.mts +55 -0
- package/dist/cron/types.d.mts.map +1 -0
- package/dist/cron/types.mjs +30 -0
- package/dist/cron/types.mjs.map +1 -0
- package/dist/heartbeat/service.d.mts +29 -0
- package/dist/heartbeat/service.d.mts.map +1 -0
- package/dist/heartbeat/service.mjs +96 -0
- package/dist/heartbeat/service.mjs.map +1 -0
- package/dist/index.d.mts +23 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +23 -0
- package/dist/index.mjs.map +1 -0
- package/dist/providers/base.d.mts +65 -0
- package/dist/providers/base.d.mts.map +1 -0
- package/dist/providers/base.mjs +1 -0
- package/dist/providers/openai-provider.d.mts +27 -0
- package/dist/providers/openai-provider.d.mts.map +1 -0
- package/dist/providers/openai-provider.mjs +67 -0
- package/dist/providers/openai-provider.mjs.map +1 -0
- package/dist/providers/transcription.d.mts +14 -0
- package/dist/providers/transcription.d.mts.map +1 -0
- package/dist/providers/transcription.mjs +46 -0
- package/dist/providers/transcription.mjs.map +1 -0
- package/dist/session/manager.d.mts +56 -0
- package/dist/session/manager.d.mts.map +1 -0
- package/dist/session/manager.mjs +144 -0
- package/dist/session/manager.mjs.map +1 -0
- package/dist/utils/helpers.d.mts +26 -0
- package/dist/utils/helpers.d.mts.map +1 -0
- package/dist/utils/helpers.mjs +60 -0
- package/dist/utils/helpers.mjs.map +1 -0
- package/dist/utils/which.d.mts +6 -0
- package/dist/utils/which.d.mts.map +1 -0
- package/dist/utils/which.mjs +20 -0
- package/dist/utils/which.mjs.map +1 -0
- package/package.json +45 -0
- package/skills/cron/SKILL.md +40 -0
- package/skills/github/SKILL.md +48 -0
- package/skills/skill-creator/SKILL.md +73 -0
- package/skills/summarize/SKILL.md +47 -0
- package/skills/weather/SKILL.md +43 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//#region src/utils/helpers.d.ts
|
|
2
|
+
/** Ensure a directory exists, creating it if necessary. */
|
|
3
|
+
declare function ensureDir(dirPath: string): string;
|
|
4
|
+
/** Get the nanobot data directory (~/.nanobot). */
|
|
5
|
+
declare function getDataPath(): string;
|
|
6
|
+
/** Get the workspace path. Defaults to ~/.nanobot/workspace. */
|
|
7
|
+
declare function getWorkspacePath(workspace?: string): string;
|
|
8
|
+
/** Get the sessions storage directory. */
|
|
9
|
+
declare function getSessionsPath(): string;
|
|
10
|
+
/** Get the memory directory within the workspace. */
|
|
11
|
+
declare function getMemoryPath(workspace?: string): string;
|
|
12
|
+
/** Get the skills directory within the workspace. */
|
|
13
|
+
declare function getSkillsPath(workspace?: string): string;
|
|
14
|
+
/** Get today's date in YYYY-MM-DD format. */
|
|
15
|
+
declare function todayDate(): string;
|
|
16
|
+
/** Get current timestamp in ISO format. */
|
|
17
|
+
declare function timestamp(): string;
|
|
18
|
+
/** Truncate a string to max length, adding suffix if truncated. */
|
|
19
|
+
declare function truncateString(s: string, maxLen?: number, suffix?: string): string;
|
|
20
|
+
/** Convert a string to a safe filename. */
|
|
21
|
+
declare function safeFilename(name: string): string;
|
|
22
|
+
/** Parse a session key into channel and chat_id. */
|
|
23
|
+
declare function parseSessionKey(key: string): [string, string];
|
|
24
|
+
//#endregion
|
|
25
|
+
export { ensureDir, getDataPath, getMemoryPath, getSessionsPath, getSkillsPath, getWorkspacePath, parseSessionKey, safeFilename, timestamp, todayDate, truncateString };
|
|
26
|
+
//# sourceMappingURL=helpers.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.mts","names":[],"sources":["../../src/utils/helpers.ts"],"mappings":";;iBAKgB,SAAA,CAAU,OAAA;;iBAQV,WAAA,CAAA;;iBAKA,gBAAA,CAAiB,SAAA;AALjC;AAAA,iBAagB,eAAA,CAAA;;iBAKA,aAAA,CAAc,SAAA;;iBAMd,aAAA,CAAc,SAAA;;iBAMd,SAAA,CAAA;;iBAKA,SAAA,CAAA;AAtBhB;AAAA,iBA2BgB,cAAA,CACd,CAAA,UACA,MAAA,WACA,MAAA;;iBAOc,YAAA,CAAa,IAAA;;iBAUb,eAAA,CAAgB,GAAA"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
|
|
5
|
+
//#region src/utils/helpers.ts
|
|
6
|
+
/** Ensure a directory exists, creating it if necessary. */
|
|
7
|
+
function ensureDir(dirPath) {
|
|
8
|
+
if (!existsSync(dirPath)) mkdirSync(dirPath, { recursive: true });
|
|
9
|
+
return dirPath;
|
|
10
|
+
}
|
|
11
|
+
/** Get the nanobot data directory (~/.nanobot). */
|
|
12
|
+
function getDataPath() {
|
|
13
|
+
return ensureDir(join(homedir(), ".nanobot"));
|
|
14
|
+
}
|
|
15
|
+
/** Get the workspace path. Defaults to ~/.nanobot/workspace. */
|
|
16
|
+
function getWorkspacePath(workspace) {
|
|
17
|
+
return ensureDir(workspace ? workspace.replace(/^~/, homedir()) : join(homedir(), ".nanobot", "workspace"));
|
|
18
|
+
}
|
|
19
|
+
/** Get the sessions storage directory. */
|
|
20
|
+
function getSessionsPath() {
|
|
21
|
+
return ensureDir(join(getDataPath(), "sessions"));
|
|
22
|
+
}
|
|
23
|
+
/** Get the memory directory within the workspace. */
|
|
24
|
+
function getMemoryPath(workspace) {
|
|
25
|
+
return ensureDir(join(workspace ?? getWorkspacePath(), "memory"));
|
|
26
|
+
}
|
|
27
|
+
/** Get the skills directory within the workspace. */
|
|
28
|
+
function getSkillsPath(workspace) {
|
|
29
|
+
return ensureDir(join(workspace ?? getWorkspacePath(), "skills"));
|
|
30
|
+
}
|
|
31
|
+
/** Get today's date in YYYY-MM-DD format. */
|
|
32
|
+
function todayDate() {
|
|
33
|
+
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
34
|
+
}
|
|
35
|
+
/** Get current timestamp in ISO format. */
|
|
36
|
+
function timestamp() {
|
|
37
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
38
|
+
}
|
|
39
|
+
/** Truncate a string to max length, adding suffix if truncated. */
|
|
40
|
+
function truncateString(s, maxLen = 100, suffix = "...") {
|
|
41
|
+
if (s.length <= maxLen) return s;
|
|
42
|
+
return s.slice(0, maxLen - suffix.length) + suffix;
|
|
43
|
+
}
|
|
44
|
+
/** Convert a string to a safe filename. */
|
|
45
|
+
function safeFilename(name) {
|
|
46
|
+
const unsafe = "<>:\"/\\|?*";
|
|
47
|
+
let result = name;
|
|
48
|
+
for (const char of unsafe) result = result.replaceAll(char, "_");
|
|
49
|
+
return result.trim();
|
|
50
|
+
}
|
|
51
|
+
/** Parse a session key into channel and chat_id. */
|
|
52
|
+
function parseSessionKey(key) {
|
|
53
|
+
const idx = key.indexOf(":");
|
|
54
|
+
if (idx === -1) throw new Error(`Invalid session key: ${key}`);
|
|
55
|
+
return [key.slice(0, idx), key.slice(idx + 1)];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
//#endregion
|
|
59
|
+
export { ensureDir, getDataPath, getMemoryPath, getSessionsPath, getSkillsPath, getWorkspacePath, parseSessionKey, safeFilename, timestamp, todayDate, truncateString };
|
|
60
|
+
//# sourceMappingURL=helpers.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.mjs","names":[],"sources":["../../src/utils/helpers.ts"],"sourcesContent":["import { mkdirSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\n/** Ensure a directory exists, creating it if necessary. */\nexport function ensureDir(dirPath: string): string {\n if (!existsSync(dirPath)) {\n mkdirSync(dirPath, { recursive: true });\n }\n return dirPath;\n}\n\n/** Get the nanobot data directory (~/.nanobot). */\nexport function getDataPath(): string {\n return ensureDir(join(homedir(), \".nanobot\"));\n}\n\n/** Get the workspace path. Defaults to ~/.nanobot/workspace. */\nexport function getWorkspacePath(workspace?: string): string {\n const resolved = workspace\n ? workspace.replace(/^~/, homedir())\n : join(homedir(), \".nanobot\", \"workspace\");\n return ensureDir(resolved);\n}\n\n/** Get the sessions storage directory. */\nexport function getSessionsPath(): string {\n return ensureDir(join(getDataPath(), \"sessions\"));\n}\n\n/** Get the memory directory within the workspace. */\nexport function getMemoryPath(workspace?: string): string {\n const ws = workspace ?? getWorkspacePath();\n return ensureDir(join(ws, \"memory\"));\n}\n\n/** Get the skills directory within the workspace. */\nexport function getSkillsPath(workspace?: string): string {\n const ws = workspace ?? getWorkspacePath();\n return ensureDir(join(ws, \"skills\"));\n}\n\n/** Get today's date in YYYY-MM-DD format. */\nexport function todayDate(): string {\n return new Date().toISOString().slice(0, 10);\n}\n\n/** Get current timestamp in ISO format. */\nexport function timestamp(): string {\n return new Date().toISOString();\n}\n\n/** Truncate a string to max length, adding suffix if truncated. */\nexport function truncateString(\n s: string,\n maxLen = 100,\n suffix = \"...\",\n): string {\n if (s.length <= maxLen) return s;\n return s.slice(0, maxLen - suffix.length) + suffix;\n}\n\n/** Convert a string to a safe filename. */\nexport function safeFilename(name: string): string {\n const unsafe = '<>:\"/\\\\|?*';\n let result = name;\n for (const char of unsafe) {\n result = result.replaceAll(char, \"_\");\n }\n return result.trim();\n}\n\n/** Parse a session key into channel and chat_id. */\nexport function parseSessionKey(key: string): [string, string] {\n const idx = key.indexOf(\":\");\n if (idx === -1) {\n throw new Error(`Invalid session key: ${key}`);\n }\n return [key.slice(0, idx), key.slice(idx + 1)];\n}\n"],"mappings":";;;;;;AAKA,SAAgB,UAAU,SAAyB;AACjD,KAAI,CAAC,WAAW,QAAQ,CACtB,WAAU,SAAS,EAAE,WAAW,MAAM,CAAC;AAEzC,QAAO;;;AAIT,SAAgB,cAAsB;AACpC,QAAO,UAAU,KAAK,SAAS,EAAE,WAAW,CAAC;;;AAI/C,SAAgB,iBAAiB,WAA4B;AAI3D,QAAO,UAHU,YACb,UAAU,QAAQ,MAAM,SAAS,CAAC,GAClC,KAAK,SAAS,EAAE,YAAY,YAAY,CAClB;;;AAI5B,SAAgB,kBAA0B;AACxC,QAAO,UAAU,KAAK,aAAa,EAAE,WAAW,CAAC;;;AAInD,SAAgB,cAAc,WAA4B;AAExD,QAAO,UAAU,KADN,aAAa,kBAAkB,EAChB,SAAS,CAAC;;;AAItC,SAAgB,cAAc,WAA4B;AAExD,QAAO,UAAU,KADN,aAAa,kBAAkB,EAChB,SAAS,CAAC;;;AAItC,SAAgB,YAAoB;AAClC,yBAAO,IAAI,MAAM,EAAC,aAAa,CAAC,MAAM,GAAG,GAAG;;;AAI9C,SAAgB,YAAoB;AAClC,yBAAO,IAAI,MAAM,EAAC,aAAa;;;AAIjC,SAAgB,eACd,GACA,SAAS,KACT,SAAS,OACD;AACR,KAAI,EAAE,UAAU,OAAQ,QAAO;AAC/B,QAAO,EAAE,MAAM,GAAG,SAAS,OAAO,OAAO,GAAG;;;AAI9C,SAAgB,aAAa,MAAsB;CACjD,MAAM,SAAS;CACf,IAAI,SAAS;AACb,MAAK,MAAM,QAAQ,OACjB,UAAS,OAAO,WAAW,MAAM,IAAI;AAEvC,QAAO,OAAO,MAAM;;;AAItB,SAAgB,gBAAgB,KAA+B;CAC7D,MAAM,MAAM,IAAI,QAAQ,IAAI;AAC5B,KAAI,QAAQ,GACV,OAAM,IAAI,MAAM,wBAAwB,MAAM;AAEhD,QAAO,CAAC,IAAI,MAAM,GAAG,IAAI,EAAE,IAAI,MAAM,MAAM,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"which.d.mts","names":[],"sources":["../../src/utils/which.ts"],"mappings":";;iBAIgB,KAAA,CAAM,IAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { accessSync, constants } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
//#region src/utils/which.ts
|
|
5
|
+
/** Simple `which` implementation - find a binary in PATH. */
|
|
6
|
+
function which(name) {
|
|
7
|
+
const pathDirs = (process.env.PATH ?? "").split(":");
|
|
8
|
+
for (const dir of pathDirs) {
|
|
9
|
+
const fullPath = join(dir, name);
|
|
10
|
+
try {
|
|
11
|
+
accessSync(fullPath, constants.X_OK);
|
|
12
|
+
return fullPath;
|
|
13
|
+
} catch {}
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
export { which };
|
|
20
|
+
//# sourceMappingURL=which.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"which.mjs","names":[],"sources":["../../src/utils/which.ts"],"sourcesContent":["import { existsSync, accessSync, constants } from \"node:fs\";\nimport { join } from \"node:path\";\n\n/** Simple `which` implementation - find a binary in PATH. */\nexport function which(name: string): string | null {\n const pathDirs = (process.env.PATH ?? \"\").split(\":\");\n for (const dir of pathDirs) {\n const fullPath = join(dir, name);\n try {\n accessSync(fullPath, constants.X_OK);\n return fullPath;\n } catch {\n // not found in this dir\n }\n }\n return null;\n}\n"],"mappings":";;;;;AAIA,SAAgB,MAAM,MAA6B;CACjD,MAAM,YAAY,QAAQ,IAAI,QAAQ,IAAI,MAAM,IAAI;AACpD,MAAK,MAAM,OAAO,UAAU;EAC1B,MAAM,WAAW,KAAK,KAAK,KAAK;AAChC,MAAI;AACF,cAAW,UAAU,UAAU,KAAK;AACpC,UAAO;UACD;;AAIV,QAAO"}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jcheesepkg/nanobot",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Lightweight AI assistant - TypeScript port",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.mts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"nanobot": "dist/cli/index.mjs"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.mts",
|
|
14
|
+
"import": "./dist/index.mjs"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsdown",
|
|
19
|
+
"dev": "tsx src/cli/index.ts",
|
|
20
|
+
"start": "node dist/cli/index.mjs",
|
|
21
|
+
"typecheck": "tsc --noEmit"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"commander": "^12.1.0",
|
|
25
|
+
"cron-parser": "^4.9.0",
|
|
26
|
+
"grammy": "^1.30.0",
|
|
27
|
+
"openai": "^4.73.0",
|
|
28
|
+
"zod": "^3.23.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/node": "^22.0.0",
|
|
32
|
+
"tsdown": "^0.20.3",
|
|
33
|
+
"tsx": "^4.19.0",
|
|
34
|
+
"typescript": "^5.6.0"
|
|
35
|
+
},
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=18.0.0"
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"dist",
|
|
41
|
+
"skills",
|
|
42
|
+
"workspace"
|
|
43
|
+
],
|
|
44
|
+
"license": "MIT"
|
|
45
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cron
|
|
3
|
+
description: Schedule reminders and recurring tasks.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Cron
|
|
7
|
+
|
|
8
|
+
Use the `cron` tool to schedule reminders or recurring tasks.
|
|
9
|
+
|
|
10
|
+
## Two Modes
|
|
11
|
+
|
|
12
|
+
1. **Reminder** - message is sent directly to user
|
|
13
|
+
2. **Task** - message is a task description, agent executes and sends result
|
|
14
|
+
|
|
15
|
+
## Examples
|
|
16
|
+
|
|
17
|
+
Fixed reminder:
|
|
18
|
+
```
|
|
19
|
+
cron(action="add", message="Time to take a break!", every_seconds=1200)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Dynamic task (agent executes each time):
|
|
23
|
+
```
|
|
24
|
+
cron(action="add", message="Check HKUDS/nanobot GitHub stars and report", every_seconds=600)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
List/remove:
|
|
28
|
+
```
|
|
29
|
+
cron(action="list")
|
|
30
|
+
cron(action="remove", job_id="abc123")
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Time Expressions
|
|
34
|
+
|
|
35
|
+
| User says | Parameters |
|
|
36
|
+
|-----------|------------|
|
|
37
|
+
| every 20 minutes | every_seconds: 1200 |
|
|
38
|
+
| every hour | every_seconds: 3600 |
|
|
39
|
+
| every day at 8am | cron_expr: "0 8 * * *" |
|
|
40
|
+
| weekdays at 5pm | cron_expr: "0 17 * * 1-5" |
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: github
|
|
3
|
+
description: "Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries."
|
|
4
|
+
metadata: {"nanobot":{"emoji":"octopus","requires":{"bins":["gh"]}}}
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# GitHub Skill
|
|
8
|
+
|
|
9
|
+
Use the `gh` CLI to interact with GitHub. Always specify `--repo owner/repo` when not in a git directory, or use URLs directly.
|
|
10
|
+
|
|
11
|
+
## Pull Requests
|
|
12
|
+
|
|
13
|
+
Check CI status on a PR:
|
|
14
|
+
```bash
|
|
15
|
+
gh pr checks 55 --repo owner/repo
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
List recent workflow runs:
|
|
19
|
+
```bash
|
|
20
|
+
gh run list --repo owner/repo --limit 10
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
View a run and see which steps failed:
|
|
24
|
+
```bash
|
|
25
|
+
gh run view <run-id> --repo owner/repo
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
View logs for failed steps only:
|
|
29
|
+
```bash
|
|
30
|
+
gh run view <run-id> --repo owner/repo --log-failed
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## API for Advanced Queries
|
|
34
|
+
|
|
35
|
+
The `gh api` command is useful for accessing data not available through other subcommands.
|
|
36
|
+
|
|
37
|
+
Get PR with specific fields:
|
|
38
|
+
```bash
|
|
39
|
+
gh api repos/owner/repo/pulls/55 --jq '.title, .state, .user.login'
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## JSON Output
|
|
43
|
+
|
|
44
|
+
Most commands support `--json` for structured output. You can use `--jq` to filter:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
gh issue list --repo owner/repo --json number,title --jq '.[] | "\(.number): \(.title)"'
|
|
48
|
+
```
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: skill-creator
|
|
3
|
+
description: Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Skill Creator
|
|
7
|
+
|
|
8
|
+
This skill provides guidance for creating effective skills.
|
|
9
|
+
|
|
10
|
+
## About Skills
|
|
11
|
+
|
|
12
|
+
Skills are modular, self-contained packages that extend the agent's capabilities by providing
|
|
13
|
+
specialized knowledge, workflows, and tools. They transform the agent from a general-purpose
|
|
14
|
+
assistant into a specialized one equipped with procedural knowledge.
|
|
15
|
+
|
|
16
|
+
### What Skills Provide
|
|
17
|
+
|
|
18
|
+
1. Specialized workflows - Multi-step procedures for specific domains
|
|
19
|
+
2. Tool integrations - Instructions for working with specific file formats or APIs
|
|
20
|
+
3. Domain expertise - Company-specific knowledge, schemas, business logic
|
|
21
|
+
4. Bundled resources - Scripts, references, and assets for complex tasks
|
|
22
|
+
|
|
23
|
+
## Core Principles
|
|
24
|
+
|
|
25
|
+
### Concise is Key
|
|
26
|
+
|
|
27
|
+
The context window is a shared resource. Only add context the agent doesn't already have. Prefer concise examples over verbose explanations.
|
|
28
|
+
|
|
29
|
+
### Anatomy of a Skill
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
skill-name/
|
|
33
|
+
SKILL.md (required)
|
|
34
|
+
- YAML frontmatter: name, description
|
|
35
|
+
- Markdown instructions
|
|
36
|
+
scripts/ (optional) - Executable code
|
|
37
|
+
references/ (optional) - Documentation for context
|
|
38
|
+
assets/ (optional) - Files used in output
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
#### SKILL.md
|
|
42
|
+
|
|
43
|
+
- **Frontmatter** (YAML): `name` and `description` fields. Description is the primary triggering mechanism.
|
|
44
|
+
- **Body** (Markdown): Instructions loaded after the skill triggers.
|
|
45
|
+
|
|
46
|
+
### Progressive Disclosure
|
|
47
|
+
|
|
48
|
+
Skills use three-level loading:
|
|
49
|
+
|
|
50
|
+
1. **Metadata (name + description)** - Always in context (~100 words)
|
|
51
|
+
2. **SKILL.md body** - When skill triggers (<5k words)
|
|
52
|
+
3. **Bundled resources** - As needed (unlimited)
|
|
53
|
+
|
|
54
|
+
## Skill Creation Process
|
|
55
|
+
|
|
56
|
+
1. Understand the skill with concrete examples
|
|
57
|
+
2. Plan reusable contents (scripts, references, assets)
|
|
58
|
+
3. Create SKILL.md with proper frontmatter
|
|
59
|
+
4. Implement resources and instructions
|
|
60
|
+
5. Test and iterate based on real usage
|
|
61
|
+
|
|
62
|
+
### Naming
|
|
63
|
+
|
|
64
|
+
- Lowercase, digits, hyphens only
|
|
65
|
+
- Under 64 characters
|
|
66
|
+
- Prefer short, verb-led phrases
|
|
67
|
+
- Namespace by tool when helpful (e.g., `gh-address-comments`)
|
|
68
|
+
|
|
69
|
+
### Frontmatter Guidelines
|
|
70
|
+
|
|
71
|
+
- `name`: The skill name
|
|
72
|
+
- `description`: What the skill does AND when to use it. Include trigger contexts.
|
|
73
|
+
All "when to use" info goes here since the body only loads after triggering.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: summarize
|
|
3
|
+
description: Summarize or extract text/transcripts from URLs, podcasts, and local files (great fallback for "transcribe this YouTube/video").
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Summarize
|
|
7
|
+
|
|
8
|
+
Fast CLI to summarize URLs, local files, and YouTube links.
|
|
9
|
+
|
|
10
|
+
## When to use (trigger phrases)
|
|
11
|
+
|
|
12
|
+
Use this skill immediately when the user asks any of:
|
|
13
|
+
- "what's this link/video about?"
|
|
14
|
+
- "summarize this URL/article"
|
|
15
|
+
- "transcribe this YouTube/video" (best-effort transcript extraction)
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
summarize "https://example.com" --model google/gemini-3-flash-preview
|
|
21
|
+
summarize "/path/to/file.pdf" --model google/gemini-3-flash-preview
|
|
22
|
+
summarize "https://youtu.be/dQw4w9WgXcQ" --youtube auto
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## YouTube: summary vs transcript
|
|
26
|
+
|
|
27
|
+
Best-effort transcript (URLs only):
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
summarize "https://youtu.be/dQw4w9WgXcQ" --youtube auto --extract-only
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
If the user asked for a transcript but it's huge, return a tight summary first, then ask which section/time range to expand.
|
|
34
|
+
|
|
35
|
+
## Model + keys
|
|
36
|
+
|
|
37
|
+
Set the API key for your chosen provider:
|
|
38
|
+
- OpenAI: `OPENAI_API_KEY`
|
|
39
|
+
- Anthropic: `ANTHROPIC_API_KEY`
|
|
40
|
+
- Google: `GEMINI_API_KEY`
|
|
41
|
+
|
|
42
|
+
## Useful flags
|
|
43
|
+
|
|
44
|
+
- `--length short|medium|long|xl|xxl|<chars>`
|
|
45
|
+
- `--max-output-tokens <count>`
|
|
46
|
+
- `--extract-only` (URLs only)
|
|
47
|
+
- `--json` (machine readable)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: weather
|
|
3
|
+
description: Get current weather and forecasts (no API key required).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Weather
|
|
7
|
+
|
|
8
|
+
Two free services, no API keys needed.
|
|
9
|
+
|
|
10
|
+
## wttr.in (primary)
|
|
11
|
+
|
|
12
|
+
Quick one-liner:
|
|
13
|
+
```bash
|
|
14
|
+
curl -s "wttr.in/London?format=3"
|
|
15
|
+
# Output: London: +8C
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Compact format:
|
|
19
|
+
```bash
|
|
20
|
+
curl -s "wttr.in/London?format=%l:+%c+%t+%h+%w"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Full forecast:
|
|
24
|
+
```bash
|
|
25
|
+
curl -s "wttr.in/London?T"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Format codes: `%c` condition, `%t` temp, `%h` humidity, `%w` wind, `%l` location, `%m` moon
|
|
29
|
+
|
|
30
|
+
Tips:
|
|
31
|
+
- URL-encode spaces: `wttr.in/New+York`
|
|
32
|
+
- Airport codes: `wttr.in/JFK`
|
|
33
|
+
- Units: `?m` (metric) `?u` (USCS)
|
|
34
|
+
- Today only: `?1` / Current only: `?0`
|
|
35
|
+
|
|
36
|
+
## Open-Meteo (fallback, JSON)
|
|
37
|
+
|
|
38
|
+
Free, no key, good for programmatic use:
|
|
39
|
+
```bash
|
|
40
|
+
curl -s "https://api.open-meteo.com/v1/forecast?latitude=51.5&longitude=-0.12¤t_weather=true"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Find coordinates for a city, then query. Returns JSON with temp, windspeed, weathercode.
|