kagent-ts 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.
Files changed (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +395 -0
  3. package/dist/compression/interface.d.ts +26 -0
  4. package/dist/compression/interface.d.ts.map +1 -0
  5. package/dist/compression/interface.js +3 -0
  6. package/dist/compression/interface.js.map +1 -0
  7. package/dist/compression/sliding-window.d.ts +21 -0
  8. package/dist/compression/sliding-window.d.ts.map +1 -0
  9. package/dist/compression/sliding-window.js +55 -0
  10. package/dist/compression/sliding-window.js.map +1 -0
  11. package/dist/compression/types.d.ts +12 -0
  12. package/dist/compression/types.d.ts.map +1 -0
  13. package/dist/compression/types.js +3 -0
  14. package/dist/compression/types.js.map +1 -0
  15. package/dist/context/context-manager.d.ts +76 -0
  16. package/dist/context/context-manager.d.ts.map +1 -0
  17. package/dist/context/context-manager.js +132 -0
  18. package/dist/context/context-manager.js.map +1 -0
  19. package/dist/context/types.d.ts +35 -0
  20. package/dist/context/types.d.ts.map +1 -0
  21. package/dist/context/types.js +3 -0
  22. package/dist/context/types.js.map +1 -0
  23. package/dist/core/agent.d.ts +288 -0
  24. package/dist/core/agent.d.ts.map +1 -0
  25. package/dist/core/agent.js +398 -0
  26. package/dist/core/agent.js.map +1 -0
  27. package/dist/core/hooks.d.ts +34 -0
  28. package/dist/core/hooks.d.ts.map +1 -0
  29. package/dist/core/hooks.js +3 -0
  30. package/dist/core/hooks.js.map +1 -0
  31. package/dist/core/plan-solve-agent.d.ts +114 -0
  32. package/dist/core/plan-solve-agent.d.ts.map +1 -0
  33. package/dist/core/plan-solve-agent.js +450 -0
  34. package/dist/core/plan-solve-agent.js.map +1 -0
  35. package/dist/core/react-agent.d.ts +52 -0
  36. package/dist/core/react-agent.d.ts.map +1 -0
  37. package/dist/core/react-agent.js +266 -0
  38. package/dist/core/react-agent.js.map +1 -0
  39. package/dist/core/response-schema.d.ts +91 -0
  40. package/dist/core/response-schema.d.ts.map +1 -0
  41. package/dist/core/response-schema.js +292 -0
  42. package/dist/core/response-schema.js.map +1 -0
  43. package/dist/core/types.d.ts +6 -0
  44. package/dist/core/types.d.ts.map +1 -0
  45. package/dist/core/types.js +3 -0
  46. package/dist/core/types.js.map +1 -0
  47. package/dist/index.d.ts +39 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +67 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/llm/interface.d.ts +87 -0
  52. package/dist/llm/interface.d.ts.map +1 -0
  53. package/dist/llm/interface.js +3 -0
  54. package/dist/llm/interface.js.map +1 -0
  55. package/dist/llm/openai-provider.d.ts +92 -0
  56. package/dist/llm/openai-provider.d.ts.map +1 -0
  57. package/dist/llm/openai-provider.js +262 -0
  58. package/dist/llm/openai-provider.js.map +1 -0
  59. package/dist/messages/message.d.ts +50 -0
  60. package/dist/messages/message.d.ts.map +1 -0
  61. package/dist/messages/message.js +87 -0
  62. package/dist/messages/message.js.map +1 -0
  63. package/dist/messages/types.d.ts +31 -0
  64. package/dist/messages/types.d.ts.map +1 -0
  65. package/dist/messages/types.js +14 -0
  66. package/dist/messages/types.js.map +1 -0
  67. package/dist/preferences/preference-manager.d.ts +88 -0
  68. package/dist/preferences/preference-manager.d.ts.map +1 -0
  69. package/dist/preferences/preference-manager.js +196 -0
  70. package/dist/preferences/preference-manager.js.map +1 -0
  71. package/dist/preferences/types.d.ts +27 -0
  72. package/dist/preferences/types.d.ts.map +1 -0
  73. package/dist/preferences/types.js +3 -0
  74. package/dist/preferences/types.js.map +1 -0
  75. package/dist/session/session-manager.d.ts +56 -0
  76. package/dist/session/session-manager.d.ts.map +1 -0
  77. package/dist/session/session-manager.js +156 -0
  78. package/dist/session/session-manager.js.map +1 -0
  79. package/dist/session/session-types.d.ts +51 -0
  80. package/dist/session/session-types.d.ts.map +1 -0
  81. package/dist/session/session-types.js +3 -0
  82. package/dist/session/session-types.js.map +1 -0
  83. package/dist/skills/file-skill-loader.d.ts +88 -0
  84. package/dist/skills/file-skill-loader.d.ts.map +1 -0
  85. package/dist/skills/file-skill-loader.js +365 -0
  86. package/dist/skills/file-skill-loader.js.map +1 -0
  87. package/dist/skills/index.d.ts +4 -0
  88. package/dist/skills/index.d.ts.map +1 -0
  89. package/dist/skills/index.js +10 -0
  90. package/dist/skills/index.js.map +1 -0
  91. package/dist/skills/skill-manager.d.ts +133 -0
  92. package/dist/skills/skill-manager.d.ts.map +1 -0
  93. package/dist/skills/skill-manager.js +310 -0
  94. package/dist/skills/skill-manager.js.map +1 -0
  95. package/dist/skills/types.d.ts +42 -0
  96. package/dist/skills/types.d.ts.map +1 -0
  97. package/dist/skills/types.js +3 -0
  98. package/dist/skills/types.js.map +1 -0
  99. package/dist/tools/builtin/edit-file.d.ts +12 -0
  100. package/dist/tools/builtin/edit-file.d.ts.map +1 -0
  101. package/dist/tools/builtin/edit-file.js +123 -0
  102. package/dist/tools/builtin/edit-file.js.map +1 -0
  103. package/dist/tools/builtin/glob-search.d.ts +11 -0
  104. package/dist/tools/builtin/glob-search.d.ts.map +1 -0
  105. package/dist/tools/builtin/glob-search.js +264 -0
  106. package/dist/tools/builtin/glob-search.js.map +1 -0
  107. package/dist/tools/builtin/grep-search.d.ts +14 -0
  108. package/dist/tools/builtin/grep-search.d.ts.map +1 -0
  109. package/dist/tools/builtin/grep-search.js +264 -0
  110. package/dist/tools/builtin/grep-search.js.map +1 -0
  111. package/dist/tools/builtin/index.d.ts +21 -0
  112. package/dist/tools/builtin/index.d.ts.map +1 -0
  113. package/dist/tools/builtin/index.js +53 -0
  114. package/dist/tools/builtin/index.js.map +1 -0
  115. package/dist/tools/builtin/read-file.d.ts +11 -0
  116. package/dist/tools/builtin/read-file.d.ts.map +1 -0
  117. package/dist/tools/builtin/read-file.js +122 -0
  118. package/dist/tools/builtin/read-file.js.map +1 -0
  119. package/dist/tools/builtin/write-file.d.ts +10 -0
  120. package/dist/tools/builtin/write-file.d.ts.map +1 -0
  121. package/dist/tools/builtin/write-file.js +89 -0
  122. package/dist/tools/builtin/write-file.js.map +1 -0
  123. package/dist/tools/circuit-breaker.d.ts +77 -0
  124. package/dist/tools/circuit-breaker.d.ts.map +1 -0
  125. package/dist/tools/circuit-breaker.js +102 -0
  126. package/dist/tools/circuit-breaker.js.map +1 -0
  127. package/dist/tools/error-tracker.d.ts +116 -0
  128. package/dist/tools/error-tracker.d.ts.map +1 -0
  129. package/dist/tools/error-tracker.js +484 -0
  130. package/dist/tools/error-tracker.js.map +1 -0
  131. package/dist/tools/tool-registry.d.ts +87 -0
  132. package/dist/tools/tool-registry.d.ts.map +1 -0
  133. package/dist/tools/tool-registry.js +188 -0
  134. package/dist/tools/tool-registry.js.map +1 -0
  135. package/dist/tools/types.d.ts +95 -0
  136. package/dist/tools/types.d.ts.map +1 -0
  137. package/dist/tools/types.js +14 -0
  138. package/dist/tools/types.js.map +1 -0
  139. package/dist/utils/token-counter.d.ts +31 -0
  140. package/dist/utils/token-counter.d.ts.map +1 -0
  141. package/dist/utils/token-counter.js +105 -0
  142. package/dist/utils/token-counter.js.map +1 -0
  143. package/package.json +56 -0
@@ -0,0 +1,156 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.SessionManager = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ /**
40
+ * Manages session state persistence to disk.
41
+ *
42
+ * Each session is stored as a single JSON file in the configured directory.
43
+ * Sessions are self-contained (messages are inline) so they survive any
44
+ * memory/component lifecycle and can be resumed after process restarts.
45
+ */
46
+ class SessionManager {
47
+ sessionId;
48
+ sessionDir;
49
+ constructor(config) {
50
+ this.sessionId =
51
+ config?.sessionId ?? `session-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
52
+ this.sessionDir = path.resolve(config?.sessionDir ?? ".kagent-sessions");
53
+ fs.mkdirSync(this.sessionDir, { recursive: true });
54
+ }
55
+ // ─── Identity ──────────────────────────────────────────────────────────
56
+ getSessionId() {
57
+ return this.sessionId;
58
+ }
59
+ getSessionDir() {
60
+ return this.sessionDir;
61
+ }
62
+ /**
63
+ * Set the session ID (used during resume to match the restored session).
64
+ */
65
+ setSessionId(id) {
66
+ this.sessionId = id;
67
+ }
68
+ // ─── Persistence ───────────────────────────────────────────────────────
69
+ /**
70
+ * Get the file path for the current session.
71
+ */
72
+ filePath() {
73
+ return path.join(this.sessionDir, `${this.sessionId}.json`);
74
+ }
75
+ /**
76
+ * Save a session checkpoint to disk.
77
+ *
78
+ * Preserves the original `createdAt` timestamp so resuming a session
79
+ * retains the original creation time. Updates `updatedAt` to now.
80
+ */
81
+ saveCheckpoint(state) {
82
+ // Preserve the original createdAt (don't overwrite with a later timestamp)
83
+ const existing = this.loadSession(this.sessionId);
84
+ const stateToSave = {
85
+ ...state,
86
+ createdAt: existing?.createdAt ?? state.createdAt,
87
+ updatedAt: new Date().toISOString(),
88
+ };
89
+ fs.writeFileSync(this.filePath(), JSON.stringify(stateToSave, null, 2), "utf-8");
90
+ }
91
+ /**
92
+ * Load a session by ID. Returns null if the file is missing or corrupt.
93
+ */
94
+ loadSession(sessionId) {
95
+ const filePath = path.join(this.sessionDir, `${sessionId}.json`);
96
+ try {
97
+ const raw = fs.readFileSync(filePath, "utf-8");
98
+ const parsed = JSON.parse(raw);
99
+ // Basic structural validation
100
+ if (!parsed.sessionId || !parsed.agentType || !parsed.messages) {
101
+ return null;
102
+ }
103
+ return parsed;
104
+ }
105
+ catch {
106
+ return null;
107
+ }
108
+ }
109
+ /**
110
+ * Return all persisted session states, sorted by `updatedAt` descending.
111
+ */
112
+ listSessions() {
113
+ const sessions = [];
114
+ try {
115
+ const files = fs.readdirSync(this.sessionDir);
116
+ for (const file of files) {
117
+ if (!file.endsWith(".json"))
118
+ continue;
119
+ const sessionId = file.slice(0, -".json".length);
120
+ const state = this.loadSession(sessionId);
121
+ if (state)
122
+ sessions.push(state);
123
+ }
124
+ }
125
+ catch {
126
+ // Directory doesn't exist or can't be read
127
+ }
128
+ sessions.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
129
+ return sessions;
130
+ }
131
+ /**
132
+ * Delete a session file from disk.
133
+ */
134
+ deleteSession(sessionId) {
135
+ const filePath = path.join(this.sessionDir, `${sessionId}.json`);
136
+ try {
137
+ fs.unlinkSync(filePath);
138
+ }
139
+ catch {
140
+ // File doesn't exist — that's fine
141
+ }
142
+ }
143
+ /**
144
+ * Update the status and timestamp of a session in-place.
145
+ */
146
+ markStatus(sessionId, status) {
147
+ const state = this.loadSession(sessionId);
148
+ if (state) {
149
+ state.status = status;
150
+ state.updatedAt = new Date().toISOString();
151
+ this.saveCheckpoint(state);
152
+ }
153
+ }
154
+ }
155
+ exports.SessionManager = SessionManager;
156
+ //# sourceMappingURL=session-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-manager.js","sourceRoot":"","sources":["../../src/session/session-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import { MessageData } from "../messages/types";
2
+ /**
3
+ * Which agent paradigm the session belongs to.
4
+ */
5
+ export type AgentType = "react" | "plan-solve";
6
+ /**
7
+ * Lifecycle status of a persisted session.
8
+ * - "active": Session is in progress, checkpoint was saved mid-run.
9
+ * - "interrupted": Session was interrupted by a network error, ready for resume.
10
+ * - "completed": Session finished normally.
11
+ */
12
+ export type SessionStatus = "active" | "interrupted" | "completed";
13
+ /**
14
+ * Serializable plan state for PlanSolveAgent sessions.
15
+ */
16
+ export interface PlanSolveSessionState {
17
+ currentPlan: string[];
18
+ hasPlan: boolean;
19
+ completedSteps: number;
20
+ consecutiveFailures: number;
21
+ }
22
+ /**
23
+ * Full session state snapshot.
24
+ *
25
+ * This is the serialised form of everything needed to reconstruct an agent
26
+ * and resume execution after an interruption (e.g. network outage).
27
+ *
28
+ * Messages are stored inline — not referenced via MediumTermMemory — so the
29
+ * checkpoint is self-contained regardless of memory configuration.
30
+ */
31
+ export interface SessionState {
32
+ /** Unique identifier for this session (e.g. "session-1748234567890"). */
33
+ sessionId: string;
34
+ /** Which agent type created this session. */
35
+ agentType: AgentType;
36
+ /** The core system prompt used by the agent. */
37
+ systemPrompt: string;
38
+ /** Full message history at checkpoint time. */
39
+ messages: MessageData[];
40
+ /** Plan-Solve specific state (only present for plan-solve agents). */
41
+ planState?: PlanSolveSessionState;
42
+ /** ISO-8601 timestamp of session creation (stable across saves). */
43
+ createdAt: string;
44
+ /** ISO-8601 timestamp of last checkpoint save. */
45
+ updatedAt: string;
46
+ /** Current lifecycle status. */
47
+ status: SessionStatus;
48
+ /** Optional metadata (model name, token counts, etc.). */
49
+ metadata?: Record<string, unknown>;
50
+ }
51
+ //# sourceMappingURL=session-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-types.d.ts","sourceRoot":"","sources":["../../src/session/session-types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,YAAY,CAAC;AAE/C;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,aAAa,GAAG,WAAW,CAAC;AAEnE;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B,yEAAyE;IACzE,SAAS,EAAE,MAAM,CAAC;IAElB,6CAA6C;IAC7C,SAAS,EAAE,SAAS,CAAC;IAErB,gDAAgD;IAChD,YAAY,EAAE,MAAM,CAAC;IAErB,+CAA+C;IAC/C,QAAQ,EAAE,WAAW,EAAE,CAAC;IAExB,sEAAsE;IACtE,SAAS,CAAC,EAAE,qBAAqB,CAAC;IAElC,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAElB,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAC;IAElB,gCAAgC;IAChC,MAAM,EAAE,aAAa,CAAC;IAEtB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=session-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-types.js","sourceRoot":"","sources":["../../src/session/session-types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,88 @@
1
+ import { Skill } from "./types";
2
+ import { Tool } from "../tools/types";
3
+ /**
4
+ * Parse YAML-like frontmatter from a Markdown file.
5
+ *
6
+ * Expects content between `---` delimiters at the start of the file:
7
+ * ```
8
+ * ---
9
+ * key: value
10
+ * ---
11
+ * body content...
12
+ * ```
13
+ *
14
+ * Lines starting with `#` inside frontmatter are treated as comments.
15
+ * Returns empty frontmatter and full content as body when no `---` markers
16
+ * are found.
17
+ */
18
+ export declare function parseFrontmatter(raw: string): {
19
+ frontmatter: Record<string, string>;
20
+ body: string;
21
+ };
22
+ /**
23
+ * Parse a comma-separated keywords string into an array.
24
+ * Returns `undefined` when the input is empty or absent.
25
+ */
26
+ export declare function parseKeywords(raw?: string): string[] | undefined;
27
+ /**
28
+ * Loads skill definitions from a directory on disk.
29
+ *
30
+ * Expected directory structure:
31
+ * ```
32
+ * skills/
33
+ * ├── <skill-name>/
34
+ * │ ├── SKILL.md # Frontmatter (metadata) + body (system prompt)
35
+ * │ ├── reference/ # Optional reference docs (*.md, *.txt)
36
+ * │ └── scripts/ # Optional executable scripts
37
+ * ├── <another-skill>/
38
+ * │ └── ...
39
+ * ```
40
+ *
41
+ * Loading is two-phase:
42
+ * 1. `scan()` — reads only frontmatter, returns metadata-only `Skill[]`
43
+ * 2. `loadSystemPrompt()` / `loadScriptsAsTools()` — full content, called
44
+ * lazily on activation.
45
+ */
46
+ export declare class FileSkillLoader {
47
+ private directory;
48
+ /**
49
+ * @param directory Path to the skills root directory (default: `./skills`).
50
+ */
51
+ constructor(directory?: string);
52
+ /**
53
+ * Get the root directory path.
54
+ */
55
+ getDirectory(): string;
56
+ /**
57
+ * Get the absolute path to a named skill's subdirectory.
58
+ */
59
+ getSkillDir(name: string): string;
60
+ /**
61
+ * Scan the skills directory and return metadata-only Skill objects.
62
+ *
63
+ * Reads only the frontmatter from each SKILL.md — the body (systemPrompt)
64
+ * and scripts are NOT loaded at this stage. They are loaded lazily when
65
+ * the skill is activated.
66
+ *
67
+ * Subdirectories without a valid SKILL.md (or without a `name` in
68
+ * frontmatter) are skipped with a warning.
69
+ */
70
+ scan(): Skill[];
71
+ /**
72
+ * Fully load the system prompt for a skill:
73
+ * 1. SKILL.md body (the content after frontmatter)
74
+ * 2. All reference/*.md and reference/*.txt files (concatenated with headers)
75
+ *
76
+ * Throws if the skill directory does not exist.
77
+ */
78
+ loadSystemPrompt(name: string): string;
79
+ /**
80
+ * Create Tool objects from scripts in the scripts/ subdirectory.
81
+ *
82
+ * Each recognized script file becomes a Tool named `{skillName}_{scriptName}`.
83
+ *
84
+ * Returns an empty array if the scripts/ directory is missing or empty.
85
+ */
86
+ loadScriptsAsTools(name: string): Tool[];
87
+ }
88
+ //# sourceMappingURL=file-skill-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-skill-loader.d.ts","sourceRoot":"","sources":["../../src/skills/file-skill-loader.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAItC;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG;IAC7C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC;CACd,CAkBA;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAOhE;AAiFD;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,SAAS,CAAS;IAE1B;;OAEG;gBACS,SAAS,CAAC,EAAE,MAAM;IAI9B;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIjC;;;;;;;;;OASG;IACH,IAAI,IAAI,KAAK,EAAE;IAmDf;;;;;;OAMG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAsCtC;;;;;;OAMG;IACH,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE;CAgFzC"}
@@ -0,0 +1,365 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.FileSkillLoader = void 0;
37
+ exports.parseFrontmatter = parseFrontmatter;
38
+ exports.parseKeywords = parseKeywords;
39
+ const fs = __importStar(require("fs"));
40
+ const path = __importStar(require("path"));
41
+ const child_process_1 = require("child_process");
42
+ // ─── Frontmatter Parsing ───────────────────────────────────────────────────
43
+ /**
44
+ * Parse YAML-like frontmatter from a Markdown file.
45
+ *
46
+ * Expects content between `---` delimiters at the start of the file:
47
+ * ```
48
+ * ---
49
+ * key: value
50
+ * ---
51
+ * body content...
52
+ * ```
53
+ *
54
+ * Lines starting with `#` inside frontmatter are treated as comments.
55
+ * Returns empty frontmatter and full content as body when no `---` markers
56
+ * are found.
57
+ */
58
+ function parseFrontmatter(raw) {
59
+ const match = raw.match(/^---\s*\n([\s\S]*?)\n---\s*\n?([\s\S]*)$/);
60
+ if (!match) {
61
+ return { frontmatter: {}, body: raw.trim() };
62
+ }
63
+ const frontmatter = {};
64
+ for (const line of match[1].split("\n")) {
65
+ const trimmed = line.trim();
66
+ if (!trimmed || trimmed.startsWith("#"))
67
+ continue;
68
+ const colonIdx = trimmed.indexOf(":");
69
+ if (colonIdx <= 0)
70
+ continue;
71
+ const key = trimmed.slice(0, colonIdx).trim();
72
+ const value = trimmed.slice(colonIdx + 1).trim();
73
+ if (key)
74
+ frontmatter[key] = value;
75
+ }
76
+ return { frontmatter, body: match[2].trim() };
77
+ }
78
+ /**
79
+ * Parse a comma-separated keywords string into an array.
80
+ * Returns `undefined` when the input is empty or absent.
81
+ */
82
+ function parseKeywords(raw) {
83
+ if (!raw)
84
+ return undefined;
85
+ const keywords = raw
86
+ .split(",")
87
+ .map((k) => k.trim())
88
+ .filter(Boolean);
89
+ return keywords.length > 0 ? keywords : undefined;
90
+ }
91
+ // ─── Script Execution ──────────────────────────────────────────────────────
92
+ const SUPPORTED_SCRIPT_EXTENSIONS = new Set([
93
+ ".sh",
94
+ ".bat",
95
+ ".cmd",
96
+ ".ps1",
97
+ ".js",
98
+ ".py",
99
+ ]);
100
+ const REFERENCE_EXTENSIONS = new Set([".md", ".txt"]);
101
+ /**
102
+ * Determine the interpreter and arguments needed to run a script file.
103
+ * Returns `null` if the file extension is not supported.
104
+ */
105
+ function getInterpreter(filePath) {
106
+ const ext = path.extname(filePath).toLowerCase();
107
+ switch (ext) {
108
+ case ".sh":
109
+ return ["bash", filePath];
110
+ case ".bat":
111
+ case ".cmd":
112
+ return ["cmd.exe", "/c", filePath];
113
+ case ".ps1":
114
+ return ["powershell.exe", "-File", filePath];
115
+ case ".js":
116
+ return ["node", filePath];
117
+ case ".py":
118
+ // Try python3 first, fall back to python
119
+ try {
120
+ (0, child_process_1.execFileSync)("python3", ["--version"], { timeout: 5000, stdio: "ignore" });
121
+ return ["python3", filePath];
122
+ }
123
+ catch {
124
+ return ["python", filePath];
125
+ }
126
+ default:
127
+ return null;
128
+ }
129
+ }
130
+ /**
131
+ * Extract a description for a script tool from the first comment/line
132
+ * of the file, or fall back to a generic description.
133
+ */
134
+ function getScriptDescription(filePath) {
135
+ try {
136
+ const content = fs.readFileSync(filePath, "utf-8");
137
+ const firstLine = content.split("\n")[0]?.trim();
138
+ if (firstLine) {
139
+ // Strip common comment markers and shebang
140
+ const clean = firstLine
141
+ .replace(/^#!\s*/, "")
142
+ .replace(/^#\s*/, "")
143
+ .replace(/^\/\/\s*/, "")
144
+ .replace(/^--\s*/, "")
145
+ .trim();
146
+ if (clean && !clean.startsWith("/"))
147
+ return clean;
148
+ }
149
+ }
150
+ catch {
151
+ // Ignore read errors
152
+ }
153
+ return `Execute the ${path.basename(filePath)} script`;
154
+ }
155
+ /**
156
+ * Sanitize a string for use as a tool name (alphanumeric + underscores only).
157
+ */
158
+ function sanitizeToolName(name) {
159
+ return name
160
+ .toLowerCase()
161
+ .replace(/[^a-z0-9_]/g, "_")
162
+ .replace(/_+/g, "_")
163
+ .replace(/^_|_$/g, "");
164
+ }
165
+ // ─── FileSkillLoader ───────────────────────────────────────────────────────
166
+ /**
167
+ * Loads skill definitions from a directory on disk.
168
+ *
169
+ * Expected directory structure:
170
+ * ```
171
+ * skills/
172
+ * ├── <skill-name>/
173
+ * │ ├── SKILL.md # Frontmatter (metadata) + body (system prompt)
174
+ * │ ├── reference/ # Optional reference docs (*.md, *.txt)
175
+ * │ └── scripts/ # Optional executable scripts
176
+ * ├── <another-skill>/
177
+ * │ └── ...
178
+ * ```
179
+ *
180
+ * Loading is two-phase:
181
+ * 1. `scan()` — reads only frontmatter, returns metadata-only `Skill[]`
182
+ * 2. `loadSystemPrompt()` / `loadScriptsAsTools()` — full content, called
183
+ * lazily on activation.
184
+ */
185
+ class FileSkillLoader {
186
+ directory;
187
+ /**
188
+ * @param directory Path to the skills root directory (default: `./skills`).
189
+ */
190
+ constructor(directory) {
191
+ this.directory = path.resolve(directory || "./skills");
192
+ }
193
+ /**
194
+ * Get the root directory path.
195
+ */
196
+ getDirectory() {
197
+ return this.directory;
198
+ }
199
+ /**
200
+ * Get the absolute path to a named skill's subdirectory.
201
+ */
202
+ getSkillDir(name) {
203
+ return path.join(this.directory, name);
204
+ }
205
+ /**
206
+ * Scan the skills directory and return metadata-only Skill objects.
207
+ *
208
+ * Reads only the frontmatter from each SKILL.md — the body (systemPrompt)
209
+ * and scripts are NOT loaded at this stage. They are loaded lazily when
210
+ * the skill is activated.
211
+ *
212
+ * Subdirectories without a valid SKILL.md (or without a `name` in
213
+ * frontmatter) are skipped with a warning.
214
+ */
215
+ scan() {
216
+ const skills = [];
217
+ let entries;
218
+ try {
219
+ entries = fs.readdirSync(this.directory, { withFileTypes: true });
220
+ }
221
+ catch {
222
+ // Directory doesn't exist or can't be read — return empty
223
+ return [];
224
+ }
225
+ for (const entry of entries) {
226
+ // Skip non-directories, dotfiles, and symlinks
227
+ if (!entry.isDirectory())
228
+ continue;
229
+ if (entry.name.startsWith("."))
230
+ continue;
231
+ const skillPath = path.join(this.directory, entry.name);
232
+ const skillMdPath = path.join(skillPath, "SKILL.md");
233
+ let raw;
234
+ try {
235
+ raw = fs.readFileSync(skillMdPath, "utf-8");
236
+ }
237
+ catch {
238
+ console.warn(`[Skills] Skipping "${entry.name}": no SKILL.md found in ${skillPath}`);
239
+ continue;
240
+ }
241
+ const { frontmatter, body } = parseFrontmatter(raw);
242
+ const name = frontmatter.name?.trim();
243
+ if (!name) {
244
+ console.warn(`[Skills] Skipping "${entry.name}": SKILL.md has no "name" in frontmatter`);
245
+ continue;
246
+ }
247
+ skills.push({
248
+ name,
249
+ description: frontmatter.description?.trim() ?? "",
250
+ systemPrompt: "", // Loaded lazily on activation
251
+ keywords: parseKeywords(frontmatter.keywords),
252
+ tools: [], // Loaded lazily on activation
253
+ });
254
+ }
255
+ return skills;
256
+ }
257
+ /**
258
+ * Fully load the system prompt for a skill:
259
+ * 1. SKILL.md body (the content after frontmatter)
260
+ * 2. All reference/*.md and reference/*.txt files (concatenated with headers)
261
+ *
262
+ * Throws if the skill directory does not exist.
263
+ */
264
+ loadSystemPrompt(name) {
265
+ const skillDir = this.getSkillDir(name);
266
+ const skillMdPath = path.join(skillDir, "SKILL.md");
267
+ // Read SKILL.md body
268
+ const raw = fs.readFileSync(skillMdPath, "utf-8");
269
+ const { body } = parseFrontmatter(raw);
270
+ const parts = [body];
271
+ // Append reference docs
272
+ const refDir = path.join(skillDir, "reference");
273
+ try {
274
+ const refFiles = fs
275
+ .readdirSync(refDir, { withFileTypes: true })
276
+ .filter((f) => f.isFile() &&
277
+ REFERENCE_EXTENSIONS.has(path.extname(f.name).toLowerCase()))
278
+ .sort((a, b) => a.name.localeCompare(b.name));
279
+ if (refFiles.length > 0) {
280
+ parts.push("\n\n---\n### Reference Documents\n");
281
+ for (const ref of refFiles) {
282
+ const refContent = fs.readFileSync(path.join(refDir, ref.name), "utf-8");
283
+ parts.push(`\n**${ref.name}**\n${refContent.trim()}\n`);
284
+ }
285
+ }
286
+ }
287
+ catch {
288
+ // No reference/ directory — skip silently
289
+ }
290
+ return parts.join("").trim();
291
+ }
292
+ /**
293
+ * Create Tool objects from scripts in the scripts/ subdirectory.
294
+ *
295
+ * Each recognized script file becomes a Tool named `{skillName}_{scriptName}`.
296
+ *
297
+ * Returns an empty array if the scripts/ directory is missing or empty.
298
+ */
299
+ loadScriptsAsTools(name) {
300
+ const scriptsDir = path.join(this.getSkillDir(name), "scripts");
301
+ const tools = [];
302
+ let entries;
303
+ try {
304
+ entries = fs.readdirSync(scriptsDir, { withFileTypes: true });
305
+ }
306
+ catch {
307
+ // No scripts/ directory — return empty
308
+ return [];
309
+ }
310
+ for (const entry of entries) {
311
+ if (!entry.isFile())
312
+ continue;
313
+ const ext = path.extname(entry.name).toLowerCase();
314
+ if (!SUPPORTED_SCRIPT_EXTENSIONS.has(ext))
315
+ continue;
316
+ const scriptPath = path.join(scriptsDir, entry.name);
317
+ const scriptName = path.basename(entry.name, ext);
318
+ const toolName = sanitizeToolName(`${name}_${scriptName}`);
319
+ const toolDescription = getScriptDescription(scriptPath);
320
+ const tool = {
321
+ name: toolName,
322
+ description: toolDescription,
323
+ parameters: {
324
+ type: "object",
325
+ properties: {
326
+ args: {
327
+ type: "string",
328
+ description: `Arguments to pass to the ${entry.name} script. ` +
329
+ `Use shell-style syntax (space-separated).`,
330
+ },
331
+ },
332
+ required: ["args"],
333
+ },
334
+ async execute(params) {
335
+ const argsStr = String(params.args ?? "");
336
+ const interpreter = getInterpreter(scriptPath);
337
+ if (!interpreter) {
338
+ return `Error: Unsupported script type "${ext}" for ${entry.name}`;
339
+ }
340
+ const [cmd, ...cmdArgs] = interpreter;
341
+ // Append the script argument after the interpreter args
342
+ const allArgs = argsStr
343
+ ? [...cmdArgs, ...argsStr.split(/\s+/).filter(Boolean)]
344
+ : cmdArgs;
345
+ return new Promise((resolve) => {
346
+ const child = (0, child_process_1.execFile)(cmd, allArgs, { timeout: 30000, maxBuffer: 1024 * 1024 }, (err, stdout, stderr) => {
347
+ if (err) {
348
+ const details = stderr
349
+ ? `\nstderr:\n${stderr.trim()}`
350
+ : "";
351
+ resolve(`Error executing ${entry.name}: ${err.message}${details}`);
352
+ return;
353
+ }
354
+ resolve(stdout.trim() || "(no output)");
355
+ });
356
+ });
357
+ },
358
+ };
359
+ tools.push(tool);
360
+ }
361
+ return tools;
362
+ }
363
+ }
364
+ exports.FileSkillLoader = FileSkillLoader;
365
+ //# sourceMappingURL=file-skill-loader.js.map