musonda 1.0.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 (196) hide show
  1. package/IMPLEMENTATION.md +432 -0
  2. package/README.md +119 -0
  3. package/dist/agent/harness.d.ts +25 -0
  4. package/dist/agent/harness.js +215 -0
  5. package/dist/agent/harness.js.map +1 -0
  6. package/dist/agent/openaiResponsesClient.d.ts +35 -0
  7. package/dist/agent/openaiResponsesClient.js +250 -0
  8. package/dist/agent/openaiResponsesClient.js.map +1 -0
  9. package/dist/agent/systemPrompt.d.ts +9 -0
  10. package/dist/agent/systemPrompt.js +100 -0
  11. package/dist/agent/systemPrompt.js.map +1 -0
  12. package/dist/agent/types.d.ts +53 -0
  13. package/dist/agent/types.js +2 -0
  14. package/dist/agent/types.js.map +1 -0
  15. package/dist/cli/commands/chat.d.ts +6 -0
  16. package/dist/cli/commands/chat.js +8 -0
  17. package/dist/cli/commands/chat.js.map +1 -0
  18. package/dist/cli/commands/doctor.d.ts +4 -0
  19. package/dist/cli/commands/doctor.js +336 -0
  20. package/dist/cli/commands/doctor.js.map +1 -0
  21. package/dist/cli/commands/gateway.d.ts +20 -0
  22. package/dist/cli/commands/gateway.js +135 -0
  23. package/dist/cli/commands/gateway.js.map +1 -0
  24. package/dist/cli/commands/help.d.ts +4 -0
  25. package/dist/cli/commands/help.js +159 -0
  26. package/dist/cli/commands/help.js.map +1 -0
  27. package/dist/cli/commands/plugins.d.ts +18 -0
  28. package/dist/cli/commands/plugins.js +250 -0
  29. package/dist/cli/commands/plugins.js.map +1 -0
  30. package/dist/cli/commands/service.d.ts +16 -0
  31. package/dist/cli/commands/service.js +136 -0
  32. package/dist/cli/commands/service.js.map +1 -0
  33. package/dist/cli/commands/setup.d.ts +4 -0
  34. package/dist/cli/commands/setup.js +8 -0
  35. package/dist/cli/commands/setup.js.map +1 -0
  36. package/dist/cli/commands/status.d.ts +4 -0
  37. package/dist/cli/commands/status.js +73 -0
  38. package/dist/cli/commands/status.js.map +1 -0
  39. package/dist/cli/commands/update.d.ts +22 -0
  40. package/dist/cli/commands/update.js +226 -0
  41. package/dist/cli/commands/update.js.map +1 -0
  42. package/dist/cli/daemon.d.ts +33 -0
  43. package/dist/cli/daemon.js +208 -0
  44. package/dist/cli/daemon.js.map +1 -0
  45. package/dist/cli/interactiveMenu.d.ts +5 -0
  46. package/dist/cli/interactiveMenu.js +225 -0
  47. package/dist/cli/interactiveMenu.js.map +1 -0
  48. package/dist/cli/musondaCli.d.ts +30 -0
  49. package/dist/cli/musondaCli.js +269 -0
  50. package/dist/cli/musondaCli.js.map +1 -0
  51. package/dist/cli/ui.d.ts +49 -0
  52. package/dist/cli/ui.js +90 -0
  53. package/dist/cli/ui.js.map +1 -0
  54. package/dist/cli.d.ts +9 -0
  55. package/dist/cli.js +315 -0
  56. package/dist/cli.js.map +1 -0
  57. package/dist/config/loader.d.ts +12 -0
  58. package/dist/config/loader.js +217 -0
  59. package/dist/config/loader.js.map +1 -0
  60. package/dist/config/paths.d.ts +11 -0
  61. package/dist/config/paths.js +18 -0
  62. package/dist/config/paths.js.map +1 -0
  63. package/dist/config/types.d.ts +246 -0
  64. package/dist/config/types.js +155 -0
  65. package/dist/config/types.js.map +1 -0
  66. package/dist/gateway/channels/cli.d.ts +37 -0
  67. package/dist/gateway/channels/cli.js +298 -0
  68. package/dist/gateway/channels/cli.js.map +1 -0
  69. package/dist/gateway/channels/discord.d.ts +18 -0
  70. package/dist/gateway/channels/discord.js +419 -0
  71. package/dist/gateway/channels/discord.js.map +1 -0
  72. package/dist/gateway/channels/slack.d.ts +26 -0
  73. package/dist/gateway/channels/slack.js +470 -0
  74. package/dist/gateway/channels/slack.js.map +1 -0
  75. package/dist/gateway/channels/webhook.d.ts +18 -0
  76. package/dist/gateway/channels/webhook.js +49 -0
  77. package/dist/gateway/channels/webhook.js.map +1 -0
  78. package/dist/gateway/http.d.ts +33 -0
  79. package/dist/gateway/http.js +605 -0
  80. package/dist/gateway/http.js.map +1 -0
  81. package/dist/gateway/server.d.ts +38 -0
  82. package/dist/gateway/server.js +233 -0
  83. package/dist/gateway/server.js.map +1 -0
  84. package/dist/gateway/types.d.ts +28 -0
  85. package/dist/gateway/types.js +2 -0
  86. package/dist/gateway/types.js.map +1 -0
  87. package/dist/index.d.ts +17 -0
  88. package/dist/index.js +32 -0
  89. package/dist/index.js.map +1 -0
  90. package/dist/memory/memoryManager.d.ts +22 -0
  91. package/dist/memory/memoryManager.js +200 -0
  92. package/dist/memory/memoryManager.js.map +1 -0
  93. package/dist/memory/storage.d.ts +24 -0
  94. package/dist/memory/storage.js +187 -0
  95. package/dist/memory/storage.js.map +1 -0
  96. package/dist/memory/types.d.ts +43 -0
  97. package/dist/memory/types.js +2 -0
  98. package/dist/memory/types.js.map +1 -0
  99. package/dist/plugins/manifest.d.ts +23 -0
  100. package/dist/plugins/manifest.js +185 -0
  101. package/dist/plugins/manifest.js.map +1 -0
  102. package/dist/plugins/mcp/mcpBridge.d.ts +31 -0
  103. package/dist/plugins/mcp/mcpBridge.js +115 -0
  104. package/dist/plugins/mcp/mcpBridge.js.map +1 -0
  105. package/dist/plugins/mcp/mcpClient.d.ts +43 -0
  106. package/dist/plugins/mcp/mcpClient.js +309 -0
  107. package/dist/plugins/mcp/mcpClient.js.map +1 -0
  108. package/dist/plugins/mcp/mcpConfig.d.ts +34 -0
  109. package/dist/plugins/mcp/mcpConfig.js +326 -0
  110. package/dist/plugins/mcp/mcpConfig.js.map +1 -0
  111. package/dist/plugins/mcp/types.d.ts +48 -0
  112. package/dist/plugins/mcp/types.js +2 -0
  113. package/dist/plugins/mcp/types.js.map +1 -0
  114. package/dist/plugins/pluginManager.d.ts +164 -0
  115. package/dist/plugins/pluginManager.js +1016 -0
  116. package/dist/plugins/pluginManager.js.map +1 -0
  117. package/dist/plugins/skills/frontmatterParser.d.ts +28 -0
  118. package/dist/plugins/skills/frontmatterParser.js +189 -0
  119. package/dist/plugins/skills/frontmatterParser.js.map +1 -0
  120. package/dist/plugins/skills/skillDiscovery.d.ts +15 -0
  121. package/dist/plugins/skills/skillDiscovery.js +148 -0
  122. package/dist/plugins/skills/skillDiscovery.js.map +1 -0
  123. package/dist/plugins/skills/skillTools.d.ts +8 -0
  124. package/dist/plugins/skills/skillTools.js +195 -0
  125. package/dist/plugins/skills/skillTools.js.map +1 -0
  126. package/dist/plugins/skills/types.d.ts +25 -0
  127. package/dist/plugins/skills/types.js +2 -0
  128. package/dist/plugins/skills/types.js.map +1 -0
  129. package/dist/plugins/types.d.ts +30 -0
  130. package/dist/plugins/types.js +2 -0
  131. package/dist/plugins/types.js.map +1 -0
  132. package/dist/scheduler/scheduler.d.ts +25 -0
  133. package/dist/scheduler/scheduler.js +239 -0
  134. package/dist/scheduler/scheduler.js.map +1 -0
  135. package/dist/scheduler/types.d.ts +39 -0
  136. package/dist/scheduler/types.js +2 -0
  137. package/dist/scheduler/types.js.map +1 -0
  138. package/dist/security/childProcessEnv.d.ts +5 -0
  139. package/dist/security/childProcessEnv.js +42 -0
  140. package/dist/security/childProcessEnv.js.map +1 -0
  141. package/dist/security/fileSandbox.d.ts +153 -0
  142. package/dist/security/fileSandbox.js +779 -0
  143. package/dist/security/fileSandbox.js.map +1 -0
  144. package/dist/service/index.d.ts +30 -0
  145. package/dist/service/index.js +41 -0
  146. package/dist/service/index.js.map +1 -0
  147. package/dist/service/systemd.d.ts +36 -0
  148. package/dist/service/systemd.js +409 -0
  149. package/dist/service/systemd.js.map +1 -0
  150. package/dist/service/types.d.ts +118 -0
  151. package/dist/service/types.js +6 -0
  152. package/dist/service/types.js.map +1 -0
  153. package/dist/tools/builtin/calcTools.d.ts +2 -0
  154. package/dist/tools/builtin/calcTools.js +51 -0
  155. package/dist/tools/builtin/calcTools.js.map +1 -0
  156. package/dist/tools/builtin/fileTools.d.ts +11 -0
  157. package/dist/tools/builtin/fileTools.js +352 -0
  158. package/dist/tools/builtin/fileTools.js.map +1 -0
  159. package/dist/tools/builtin/memoryTools.d.ts +4 -0
  160. package/dist/tools/builtin/memoryTools.js +123 -0
  161. package/dist/tools/builtin/memoryTools.js.map +1 -0
  162. package/dist/tools/builtin/noteTools.d.ts +4 -0
  163. package/dist/tools/builtin/noteTools.js +91 -0
  164. package/dist/tools/builtin/noteTools.js.map +1 -0
  165. package/dist/tools/builtin/pluginTools.d.ts +29 -0
  166. package/dist/tools/builtin/pluginTools.js +406 -0
  167. package/dist/tools/builtin/pluginTools.js.map +1 -0
  168. package/dist/tools/builtin/scheduleTools.d.ts +4 -0
  169. package/dist/tools/builtin/scheduleTools.js +156 -0
  170. package/dist/tools/builtin/scheduleTools.js.map +1 -0
  171. package/dist/tools/builtin/timeTools.d.ts +2 -0
  172. package/dist/tools/builtin/timeTools.js +41 -0
  173. package/dist/tools/builtin/timeTools.js.map +1 -0
  174. package/dist/tools/builtin/webTools.d.ts +12 -0
  175. package/dist/tools/builtin/webTools.js +325 -0
  176. package/dist/tools/builtin/webTools.js.map +1 -0
  177. package/dist/tools/registry.d.ts +15 -0
  178. package/dist/tools/registry.js +111 -0
  179. package/dist/tools/registry.js.map +1 -0
  180. package/dist/tools/types.d.ts +41 -0
  181. package/dist/tools/types.js +2 -0
  182. package/dist/tools/types.js.map +1 -0
  183. package/dist/utils/logger.d.ts +29 -0
  184. package/dist/utils/logger.js +124 -0
  185. package/dist/utils/logger.js.map +1 -0
  186. package/dist/wizard/onboarding.d.ts +3 -0
  187. package/dist/wizard/onboarding.js +408 -0
  188. package/dist/wizard/onboarding.js.map +1 -0
  189. package/package.json +69 -0
  190. package/plugins/example-calc/mcp.json +11 -0
  191. package/plugins/example-calc/plugin.json +12 -0
  192. package/plugins/example-calc/server.mjs +92 -0
  193. package/plugins/example-calc/skills/math-assistant/SKILL.md +15 -0
  194. package/plugins/plugin-builder/plugin.json +12 -0
  195. package/plugins/plugin-builder/skills/create-plugin/SKILL.md +149 -0
  196. package/plugins/plugin-builder/skills/manage-plugins/SKILL.md +157 -0
@@ -0,0 +1,195 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { execFile } from 'node:child_process';
4
+ import { logger } from '../../utils/logger.js';
5
+ import { createSanitizedChildEnv } from '../../security/childProcessEnv.js';
6
+ export class SkillToolFactory {
7
+ /**
8
+ * Creates the built-in skill tools bound to a getter that returns current active skills.
9
+ */
10
+ static createTools(getSkills) {
11
+ const listTool = {
12
+ name: 'skill_list',
13
+ description: 'List all available Agent Skills installed via plugins. Returns skill names, descriptions, and capabilities.',
14
+ parameters: {
15
+ type: 'object',
16
+ properties: {},
17
+ required: [],
18
+ },
19
+ execute: async () => {
20
+ const skills = getSkills();
21
+ if (skills.length === 0) {
22
+ return {
23
+ skillsCount: 0,
24
+ skills: [],
25
+ message: 'No plugin skills currently loaded.',
26
+ };
27
+ }
28
+ return {
29
+ skillsCount: skills.length,
30
+ skills: skills.map((s) => ({
31
+ name: s.name,
32
+ description: s.description,
33
+ plugin: s.pluginName,
34
+ scripts: s.scripts,
35
+ references: s.references,
36
+ assets: s.assets,
37
+ })),
38
+ };
39
+ },
40
+ };
41
+ const readTool = {
42
+ name: 'skill_read',
43
+ description: 'Read the full instructions and documentation for a specific Agent Skill. Use this when you need detailed procedures to perform a skill task.',
44
+ parameters: {
45
+ type: 'object',
46
+ properties: {
47
+ skill_name: {
48
+ type: 'string',
49
+ description: 'The name of the skill to read.',
50
+ },
51
+ include_reference: {
52
+ type: 'string',
53
+ description: 'Optional name of a reference file inside the skill (e.g. "REFERENCE.md").',
54
+ },
55
+ },
56
+ required: ['skill_name'],
57
+ },
58
+ execute: async (args) => {
59
+ const skills = getSkills();
60
+ const skill = skills.find((s) => s.name === args.skill_name);
61
+ if (!skill) {
62
+ return {
63
+ error: `Skill "${args.skill_name}" not found. Use "skill_list" to see available skills.`,
64
+ };
65
+ }
66
+ const response = {
67
+ name: skill.name,
68
+ plugin: skill.pluginName,
69
+ description: skill.description,
70
+ frontmatter: skill.frontmatter,
71
+ instructions: skill.body,
72
+ scripts: skill.scripts,
73
+ references: skill.references,
74
+ };
75
+ if (args.include_reference) {
76
+ const refPath = path.join(skill.skillDir, 'references', args.include_reference);
77
+ const resolved = path.resolve(refPath);
78
+ if (resolved.startsWith(skill.skillDir) && fs.existsSync(resolved)) {
79
+ try {
80
+ response.referenceContent = fs.readFileSync(resolved, 'utf8');
81
+ }
82
+ catch (err) {
83
+ response.referenceError = `Could not read reference: ${err.message}`;
84
+ }
85
+ }
86
+ else {
87
+ response.referenceError = `Reference file "${args.include_reference}" not found or escapes skill boundary.`;
88
+ }
89
+ }
90
+ return response;
91
+ },
92
+ };
93
+ const runScriptTool = {
94
+ name: 'skill_run_script',
95
+ description: 'Run an executable script bundled with an Agent Skill from its scripts/ directory.',
96
+ parameters: {
97
+ type: 'object',
98
+ properties: {
99
+ skill_name: {
100
+ type: 'string',
101
+ description: 'The name of the skill containing the script.',
102
+ },
103
+ script_name: {
104
+ type: 'string',
105
+ description: 'The file name of the script in the skill\'s scripts/ folder.',
106
+ },
107
+ args: {
108
+ type: 'array',
109
+ items: { type: 'string' },
110
+ description: 'Optional command line arguments to pass to the script.',
111
+ },
112
+ },
113
+ required: ['skill_name', 'script_name'],
114
+ },
115
+ execute: async (args, context) => {
116
+ const skills = getSkills();
117
+ const skill = skills.find((s) => s.name === args.skill_name);
118
+ if (!skill) {
119
+ return {
120
+ error: `Skill "${args.skill_name}" not found.`,
121
+ };
122
+ }
123
+ const scriptsDir = path.join(skill.skillDir, 'scripts');
124
+ const scriptPath = path.join(scriptsDir, args.script_name);
125
+ const resolvedScript = path.resolve(scriptPath);
126
+ // Enforce lexical and canonical containment, including symlink escapes.
127
+ const scriptsRoot = path.resolve(scriptsDir);
128
+ const relativeScript = path.relative(scriptsRoot, resolvedScript);
129
+ if (relativeScript.startsWith('..') || path.isAbsolute(relativeScript) || !fs.existsSync(resolvedScript)) {
130
+ return {
131
+ error: `Script "${args.script_name}" not found in skill "${args.skill_name}".`,
132
+ };
133
+ }
134
+ let canonicalScript;
135
+ try {
136
+ const canonicalRoot = fs.realpathSync(scriptsRoot);
137
+ canonicalScript = fs.realpathSync(resolvedScript);
138
+ const canonicalRelative = path.relative(canonicalRoot, canonicalScript);
139
+ if (canonicalRelative.startsWith('..') || path.isAbsolute(canonicalRelative) || !fs.statSync(canonicalScript).isFile()) {
140
+ return { error: `Script "${args.script_name}" escapes skill "${args.skill_name}" or is not a file.` };
141
+ }
142
+ }
143
+ catch {
144
+ return { error: `Script "${args.script_name}" could not be safely resolved.` };
145
+ }
146
+ const scriptArgs = args.args || [];
147
+ const isWindows = process.platform === 'win32';
148
+ // Select runner
149
+ let command = canonicalScript;
150
+ let finalArgs = scriptArgs;
151
+ if (canonicalScript.endsWith('.js') || canonicalScript.endsWith('.mjs') || canonicalScript.endsWith('.cjs')) {
152
+ command = process.execPath;
153
+ finalArgs = [canonicalScript, ...scriptArgs];
154
+ }
155
+ else if (canonicalScript.endsWith('.py')) {
156
+ command = isWindows ? 'python' : 'python3';
157
+ finalArgs = [canonicalScript, ...scriptArgs];
158
+ }
159
+ else if (canonicalScript.endsWith('.sh')) {
160
+ command = 'bash';
161
+ finalArgs = [canonicalScript, ...scriptArgs];
162
+ }
163
+ logger.info(`[Skill: ${args.skill_name}] Running script "${path.basename(canonicalScript)}" with ${scriptArgs.length} argument(s).`);
164
+ return new Promise((resolve) => {
165
+ execFile(command, finalArgs, {
166
+ cwd: skill.skillDir,
167
+ timeout: 30000,
168
+ maxBuffer: 2 * 1024 * 1024,
169
+ env: createSanitizedChildEnv(process.env, {
170
+ SKILL_NAME: skill.name,
171
+ SKILL_DIR: skill.skillDir,
172
+ }),
173
+ }, (err, stdout, stderr) => {
174
+ if (err) {
175
+ resolve({
176
+ error: `Script execution error: ${err.message}`,
177
+ stdout: stdout ? stdout.trim() : '',
178
+ stderr: stderr ? stderr.trim() : '',
179
+ });
180
+ }
181
+ else {
182
+ resolve({
183
+ stdout: stdout ? stdout.trim() : '',
184
+ stderr: stderr ? stderr.trim() : '',
185
+ exitCode: 0,
186
+ });
187
+ }
188
+ });
189
+ });
190
+ },
191
+ };
192
+ return [listTool, readTool, runScriptTool];
193
+ }
194
+ }
195
+ //# sourceMappingURL=skillTools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skillTools.js","sourceRoot":"","sources":["../../../src/plugins/skills/skillTools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ export interface SkillFrontmatter {
2
+ name: string;
3
+ description: string;
4
+ license?: string;
5
+ compatibility?: string;
6
+ metadata?: Record<string, string>;
7
+ 'allowed-tools'?: string;
8
+ }
9
+ export interface AgentSkill {
10
+ name: string;
11
+ description: string;
12
+ pluginName: string;
13
+ skillDir: string;
14
+ skillFile: string;
15
+ frontmatter: SkillFrontmatter;
16
+ body: string;
17
+ scripts: string[];
18
+ references: string[];
19
+ assets: string[];
20
+ }
21
+ export interface SkillValidationResult {
22
+ valid: boolean;
23
+ skill?: AgentSkill;
24
+ errors: string[];
25
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/plugins/skills/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,30 @@
1
+ export interface PluginAuthor {
2
+ name?: string;
3
+ email?: string;
4
+ url?: string;
5
+ }
6
+ export interface PluginManifest {
7
+ $schema: string;
8
+ name: string;
9
+ version?: string;
10
+ description?: string;
11
+ author?: PluginAuthor;
12
+ homepage?: string;
13
+ repository?: string;
14
+ license?: string;
15
+ keywords?: string[];
16
+ extensions?: Record<string, any>;
17
+ [key: string]: any;
18
+ }
19
+ export interface ManifestValidationResult {
20
+ valid: boolean;
21
+ manifest?: PluginManifest;
22
+ errors: string[];
23
+ warnings: string[];
24
+ }
25
+ export interface PluginPackage {
26
+ name: string;
27
+ rootDir: string;
28
+ dataDir: string;
29
+ manifest: PluginManifest;
30
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/plugins/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,25 @@
1
+ import { ScheduleJob, CreateScheduleInput } from './types.js';
2
+ export type JobTriggerCallback = (job: ScheduleJob) => Promise<void>;
3
+ export declare class MusondaScheduler {
4
+ private storage;
5
+ private cronInstances;
6
+ private triggerCallback?;
7
+ private running;
8
+ private defaultTimezone;
9
+ constructor(dataDir: string, defaultTimezone?: string);
10
+ onTrigger(callback: JobTriggerCallback): void;
11
+ isRunning(): boolean;
12
+ start(): Promise<void>;
13
+ stop(): Promise<void>;
14
+ listJobs(filter?: {
15
+ status?: string;
16
+ channel?: string;
17
+ }): ScheduleJob[];
18
+ getJob(id: string): ScheduleJob | undefined;
19
+ createJob(input: CreateScheduleInput): ScheduleJob;
20
+ cancelJob(id: string): boolean;
21
+ deleteJob(id: string): boolean;
22
+ private scheduleCronInstance;
23
+ private executeJob;
24
+ private updateJobInStorage;
25
+ }
@@ -0,0 +1,239 @@
1
+ import path from 'node:path';
2
+ import crypto from 'node:crypto';
3
+ import { Cron } from 'croner';
4
+ import { JsonStorage } from '../memory/storage.js';
5
+ import { logger } from '../utils/logger.js';
6
+ export class MusondaScheduler {
7
+ storage;
8
+ cronInstances = new Map();
9
+ triggerCallback;
10
+ running = false;
11
+ defaultTimezone;
12
+ constructor(dataDir, defaultTimezone = 'UTC') {
13
+ const schedulesDir = path.join(dataDir, 'schedules');
14
+ this.storage = new JsonStorage(path.join(schedulesDir, 'jobs.json'));
15
+ this.defaultTimezone = defaultTimezone;
16
+ }
17
+ onTrigger(callback) {
18
+ this.triggerCallback = callback;
19
+ }
20
+ isRunning() {
21
+ return this.running;
22
+ }
23
+ async start() {
24
+ if (this.running)
25
+ return;
26
+ this.running = true;
27
+ const jobs = this.storage.read([]);
28
+ let scheduledCount = 0;
29
+ for (const job of jobs) {
30
+ if (job.status === 'active') {
31
+ const scheduled = this.scheduleCronInstance(job);
32
+ if (scheduled)
33
+ scheduledCount++;
34
+ }
35
+ }
36
+ logger.info(`Scheduler started. Loaded ${jobs.length} job(s), ${scheduledCount} active.`);
37
+ }
38
+ async stop() {
39
+ this.running = false;
40
+ for (const [id, cron] of this.cronInstances.entries()) {
41
+ cron.stop();
42
+ }
43
+ this.cronInstances.clear();
44
+ logger.info('Scheduler stopped.');
45
+ }
46
+ listJobs(filter) {
47
+ const jobs = this.storage.read([]);
48
+ return jobs.filter((job) => {
49
+ if (filter?.status && job.status !== filter.status)
50
+ return false;
51
+ if (filter?.channel && job.target.channel !== filter.channel)
52
+ return false;
53
+ return true;
54
+ });
55
+ }
56
+ getJob(id) {
57
+ const jobs = this.storage.read([]);
58
+ return jobs.find((j) => j.id === id);
59
+ }
60
+ createJob(input) {
61
+ const jobs = this.storage.read([]);
62
+ const now = new Date();
63
+ let jobType = input.type || 'cron';
64
+ let targetPattern = input.pattern.trim();
65
+ let maxRuns = input.maxRuns;
66
+ // Handle relative duration syntax (e.g. "+30m", "+2h", "+1d", "+45s")
67
+ const relativeMatch = targetPattern.match(/^\+(\d+)\s*(s|m|h|d|sec|min|hour|day)s?$/i);
68
+ if (relativeMatch) {
69
+ const amount = parseInt(relativeMatch[1], 10);
70
+ const unit = relativeMatch[2].toLowerCase();
71
+ let ms = 0;
72
+ if (unit.startsWith('s'))
73
+ ms = amount * 1000;
74
+ else if (unit.startsWith('m'))
75
+ ms = amount * 60 * 1000;
76
+ else if (unit.startsWith('h'))
77
+ ms = amount * 3600 * 1000;
78
+ else if (unit.startsWith('d'))
79
+ ms = amount * 86400 * 1000;
80
+ const runDate = new Date(now.getTime() + ms);
81
+ targetPattern = runDate.toISOString();
82
+ jobType = 'once';
83
+ maxRuns = 1;
84
+ }
85
+ else if (!isNaN(Date.parse(targetPattern)) && !targetPattern.includes('*')) {
86
+ // Looks like an ISO date or timestamp
87
+ jobType = 'once';
88
+ maxRuns = 1;
89
+ }
90
+ const timezone = input.timezone || this.defaultTimezone;
91
+ const id = `job_${crypto.randomBytes(4).toString('hex')}`;
92
+ const newJob = {
93
+ id,
94
+ title: input.title,
95
+ type: jobType,
96
+ pattern: targetPattern,
97
+ timezone,
98
+ target: input.target,
99
+ action: input.action,
100
+ createdAt: now.toISOString(),
101
+ runCount: 0,
102
+ maxRuns,
103
+ status: 'active',
104
+ };
105
+ // Attempt to calculate nextRunAt
106
+ try {
107
+ const testCron = new Cron(newJob.pattern, {
108
+ timezone: newJob.timezone,
109
+ maxRuns: newJob.maxRuns,
110
+ });
111
+ const nextDate = testCron.nextRun();
112
+ newJob.nextRunAt = nextDate ? nextDate.toISOString() : undefined;
113
+ testCron.stop();
114
+ }
115
+ catch (err) {
116
+ throw new Error(`Invalid schedule pattern or cron expression "${input.pattern}": ${err.message}`);
117
+ }
118
+ jobs.push(newJob);
119
+ this.storage.write(jobs);
120
+ if (this.running) {
121
+ this.scheduleCronInstance(newJob);
122
+ }
123
+ logger.info(`Created schedule "${newJob.title}" [${newJob.type}] next run: ${newJob.nextRunAt || 'none'}`);
124
+ return newJob;
125
+ }
126
+ cancelJob(id) {
127
+ const jobs = this.storage.read([]);
128
+ const jobIndex = jobs.findIndex((j) => j.id === id);
129
+ if (jobIndex === -1)
130
+ return false;
131
+ // Stop runtime instance
132
+ const cron = this.cronInstances.get(id);
133
+ if (cron) {
134
+ cron.stop();
135
+ this.cronInstances.delete(id);
136
+ }
137
+ jobs[jobIndex].status = 'completed';
138
+ jobs[jobIndex].nextRunAt = undefined;
139
+ this.storage.write(jobs);
140
+ logger.info(`Cancelled schedule job id: ${id}`);
141
+ return true;
142
+ }
143
+ deleteJob(id) {
144
+ const jobs = this.storage.read([]);
145
+ const initialLen = jobs.length;
146
+ const filtered = jobs.filter((j) => j.id !== id);
147
+ if (filtered.length === initialLen)
148
+ return false;
149
+ const cron = this.cronInstances.get(id);
150
+ if (cron) {
151
+ cron.stop();
152
+ this.cronInstances.delete(id);
153
+ }
154
+ this.storage.write(filtered);
155
+ logger.info(`Deleted schedule job id: ${id}`);
156
+ return true;
157
+ }
158
+ scheduleCronInstance(job) {
159
+ if (job.status !== 'active')
160
+ return false;
161
+ // Stop existing if any
162
+ const existing = this.cronInstances.get(job.id);
163
+ if (existing) {
164
+ existing.stop();
165
+ this.cronInstances.delete(job.id);
166
+ }
167
+ try {
168
+ const cron = new Cron(job.pattern, {
169
+ timezone: job.timezone,
170
+ maxRuns: job.maxRuns ? job.maxRuns - job.runCount : undefined,
171
+ }, async () => {
172
+ await this.executeJob(job.id);
173
+ });
174
+ const nextDate = cron.nextRun();
175
+ if (!nextDate) {
176
+ // No future runs remaining
177
+ job.status = 'completed';
178
+ job.nextRunAt = undefined;
179
+ this.updateJobInStorage(job);
180
+ return false;
181
+ }
182
+ job.nextRunAt = nextDate.toISOString();
183
+ this.updateJobInStorage(job);
184
+ this.cronInstances.set(job.id, cron);
185
+ return true;
186
+ }
187
+ catch (err) {
188
+ logger.error(`Failed to schedule job "${job.title}" (${job.id}):`, err.message);
189
+ job.status = 'error';
190
+ job.lastError = err.message;
191
+ this.updateJobInStorage(job);
192
+ return false;
193
+ }
194
+ }
195
+ async executeJob(jobId) {
196
+ const job = this.getJob(jobId);
197
+ if (!job || job.status !== 'active')
198
+ return;
199
+ logger.info(`⏰ Triggering schedule: "${job.title}" (type: ${job.type})`);
200
+ const now = new Date();
201
+ job.lastRunAt = now.toISOString();
202
+ job.runCount += 1;
203
+ try {
204
+ if (this.triggerCallback) {
205
+ await this.triggerCallback(job);
206
+ }
207
+ // Check if job completed
208
+ const cron = this.cronInstances.get(job.id);
209
+ const nextDate = cron?.nextRun();
210
+ if (!nextDate || (job.maxRuns && job.runCount >= job.maxRuns) || job.type === 'once') {
211
+ job.status = 'completed';
212
+ job.nextRunAt = undefined;
213
+ if (cron) {
214
+ cron.stop();
215
+ this.cronInstances.delete(job.id);
216
+ }
217
+ }
218
+ else {
219
+ job.nextRunAt = nextDate.toISOString();
220
+ }
221
+ }
222
+ catch (err) {
223
+ logger.error(`Error executing schedule job "${job.title}":`, err);
224
+ job.lastError = err.message || 'Execution error';
225
+ }
226
+ finally {
227
+ this.updateJobInStorage(job);
228
+ }
229
+ }
230
+ updateJobInStorage(updatedJob) {
231
+ const jobs = this.storage.read([]);
232
+ const idx = jobs.findIndex((j) => j.id === updatedJob.id);
233
+ if (idx !== -1) {
234
+ jobs[idx] = updatedJob;
235
+ this.storage.write(jobs);
236
+ }
237
+ }
238
+ }
239
+ //# sourceMappingURL=scheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/scheduler/scheduler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ export type ScheduleType = 'cron' | 'once';
2
+ export type ScheduleStatus = 'active' | 'completed' | 'paused' | 'error';
3
+ export type ScheduleActionType = 'prompt' | 'reminder';
4
+ export interface ScheduleTarget {
5
+ channel: 'discord' | 'slack' | 'webhook' | 'cli';
6
+ channelId: string;
7
+ userId: string;
8
+ userName?: string;
9
+ threadTs?: string;
10
+ }
11
+ export interface ScheduleAction {
12
+ type: ScheduleActionType;
13
+ content: string;
14
+ }
15
+ export interface ScheduleJob {
16
+ id: string;
17
+ title: string;
18
+ type: ScheduleType;
19
+ pattern: string;
20
+ timezone: string;
21
+ target: ScheduleTarget;
22
+ action: ScheduleAction;
23
+ createdAt: string;
24
+ lastRunAt?: string;
25
+ nextRunAt?: string;
26
+ runCount: number;
27
+ maxRuns?: number;
28
+ status: ScheduleStatus;
29
+ lastError?: string;
30
+ }
31
+ export interface CreateScheduleInput {
32
+ title: string;
33
+ type?: ScheduleType;
34
+ pattern: string;
35
+ timezone?: string;
36
+ target: ScheduleTarget;
37
+ action: ScheduleAction;
38
+ maxRuns?: number;
39
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/scheduler/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Builds a minimal environment for untrusted plugin child processes.
3
+ * Extra values are explicit capabilities granted by the caller.
4
+ */
5
+ export declare function createSanitizedChildEnv(source?: NodeJS.ProcessEnv, extra?: Record<string, string>): Record<string, string>;
@@ -0,0 +1,42 @@
1
+ const SAFE_SYSTEM_ENV_KEYS = new Set([
2
+ 'PATH',
3
+ 'PATHEXT',
4
+ 'SYSTEMROOT',
5
+ 'WINDIR',
6
+ 'COMSPEC',
7
+ 'TEMP',
8
+ 'TMP',
9
+ 'HOME',
10
+ 'HOMEPATH',
11
+ 'HOMEDRIVE',
12
+ 'USERPROFILE',
13
+ 'APPDATA',
14
+ 'LOCALAPPDATA',
15
+ 'LANG',
16
+ 'LANGUAGE',
17
+ 'LC_ALL',
18
+ 'LC_CTYPE',
19
+ 'SHELL',
20
+ 'TERM',
21
+ 'NODE_PATH',
22
+ 'NODE_ENV',
23
+ ]);
24
+ const SECRET_NAME_FRAGMENTS = ['KEY', 'TOKEN', 'SECRET', 'PASSWORD', 'CREDENTIAL'];
25
+ /**
26
+ * Builds a minimal environment for untrusted plugin child processes.
27
+ * Extra values are explicit capabilities granted by the caller.
28
+ */
29
+ export function createSanitizedChildEnv(source = process.env, extra = {}) {
30
+ const sanitized = {};
31
+ for (const [key, value] of Object.entries(source)) {
32
+ if (!value)
33
+ continue;
34
+ const upperKey = key.toUpperCase();
35
+ if (SECRET_NAME_FRAGMENTS.some((fragment) => upperKey.includes(fragment)))
36
+ continue;
37
+ if (SAFE_SYSTEM_ENV_KEYS.has(upperKey))
38
+ sanitized[key] = value;
39
+ }
40
+ return { ...sanitized, ...extra };
41
+ }
42
+ //# sourceMappingURL=childProcessEnv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"childProcessEnv.js","sourceRoot":"","sources":["../../src/security/childProcessEnv.ts"],"names":[],"mappings":"AAAA,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC;IACnC,MAAM;IACN,SAAS;IACT,YAAY;IACZ,QAAQ;IACR,SAAS;IACT,MAAM;IACN,KAAK;IACL,MAAM;IACN,UAAU;IACV,WAAW;IACX,aAAa;IACb,SAAS;IACT,cAAc;IACd,MAAM;IACN,UAAU;IACV,QAAQ;IACR,UAAU;IACV,OAAO;IACP,MAAM;IACN,WAAW;IACX,UAAU;CACX,CAAC,CAAC;AAEH,MAAM,qBAAqB,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;AAEnF;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CACrC,MAAM,GAAsB,OAAO,CAAC,GAAG,EACvC,KAAK,GAA2B,EAAE;IAElC,MAAM,SAAS,GAA2B,EAAE,CAAC;IAE7C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;QACnC,IAAI,qBAAqB,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAAE,SAAS;QACpF,IAAI,oBAAoB,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,SAAS,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACjE,CAAC;IAED,OAAO,EAAE,GAAG,SAAS,EAAE,GAAG,KAAK,EAAE,CAAC;AACpC,CAAC"}