clitrigger 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/.env.example +9 -0
- package/LICENSE +21 -0
- package/README.md +186 -0
- package/bin/clitrigger.js +106 -0
- package/dist/client/assets/index-BkOCv65b.css +1 -0
- package/dist/client/assets/index-Fbf16Lh1.js +129 -0
- package/dist/client/index.html +24 -0
- package/dist/server/db/connection.d.ts +4 -0
- package/dist/server/db/connection.d.ts.map +1 -0
- package/dist/server/db/connection.js +24 -0
- package/dist/server/db/connection.js.map +1 -0
- package/dist/server/db/queries.d.ts +265 -0
- package/dist/server/db/queries.d.ts.map +1 -0
- package/dist/server/db/queries.js +836 -0
- package/dist/server/db/queries.js.map +1 -0
- package/dist/server/db/schema.d.ts +3 -0
- package/dist/server/db/schema.d.ts.map +1 -0
- package/dist/server/db/schema.js +325 -0
- package/dist/server/db/schema.js.map +1 -0
- package/dist/server/index.d.ts +5 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +207 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/middleware/auth.d.ts +5 -0
- package/dist/server/middleware/auth.d.ts.map +1 -0
- package/dist/server/middleware/auth.js +45 -0
- package/dist/server/middleware/auth.js.map +1 -0
- package/dist/server/plugins/github/index.d.ts +3 -0
- package/dist/server/plugins/github/index.d.ts.map +1 -0
- package/dist/server/plugins/github/index.js +18 -0
- package/dist/server/plugins/github/index.js.map +1 -0
- package/dist/server/plugins/github/router.d.ts +4 -0
- package/dist/server/plugins/github/router.d.ts.map +1 -0
- package/dist/server/plugins/github/router.js +250 -0
- package/dist/server/plugins/github/router.js.map +1 -0
- package/dist/server/plugins/gstack/index.d.ts +3 -0
- package/dist/server/plugins/gstack/index.d.ts.map +1 -0
- package/dist/server/plugins/gstack/index.js +36 -0
- package/dist/server/plugins/gstack/index.js.map +1 -0
- package/dist/server/plugins/jira/index.d.ts +3 -0
- package/dist/server/plugins/jira/index.d.ts.map +1 -0
- package/dist/server/plugins/jira/index.js +19 -0
- package/dist/server/plugins/jira/index.js.map +1 -0
- package/dist/server/plugins/jira/router.d.ts +4 -0
- package/dist/server/plugins/jira/router.d.ts.map +1 -0
- package/dist/server/plugins/jira/router.js +332 -0
- package/dist/server/plugins/jira/router.js.map +1 -0
- package/dist/server/plugins/notion/index.d.ts +3 -0
- package/dist/server/plugins/notion/index.d.ts.map +1 -0
- package/dist/server/plugins/notion/index.js +17 -0
- package/dist/server/plugins/notion/index.js.map +1 -0
- package/dist/server/plugins/notion/router.d.ts +4 -0
- package/dist/server/plugins/notion/router.d.ts.map +1 -0
- package/dist/server/plugins/notion/router.js +313 -0
- package/dist/server/plugins/notion/router.js.map +1 -0
- package/dist/server/plugins/registry.d.ts +8 -0
- package/dist/server/plugins/registry.d.ts.map +1 -0
- package/dist/server/plugins/registry.js +31 -0
- package/dist/server/plugins/registry.js.map +1 -0
- package/dist/server/plugins/types.d.ts +32 -0
- package/dist/server/plugins/types.d.ts.map +1 -0
- package/dist/server/plugins/types.js +2 -0
- package/dist/server/plugins/types.js.map +1 -0
- package/dist/server/resources/gstack-skills/LICENSE +21 -0
- package/dist/server/resources/gstack-skills/benchmark/SKILL.md +528 -0
- package/dist/server/resources/gstack-skills/careful/SKILL.md +59 -0
- package/dist/server/resources/gstack-skills/cso/SKILL.md +898 -0
- package/dist/server/resources/gstack-skills/investigate/SKILL.md +474 -0
- package/dist/server/resources/gstack-skills/qa/SKILL.md +1055 -0
- package/dist/server/resources/gstack-skills/qa-only/SKILL.md +672 -0
- package/dist/server/resources/gstack-skills/review/SKILL.md +1044 -0
- package/dist/server/resources/gstack-skills/skills-manifest.d.ts +9 -0
- package/dist/server/resources/gstack-skills/skills-manifest.d.ts.map +1 -0
- package/dist/server/resources/gstack-skills/skills-manifest.js +52 -0
- package/dist/server/resources/gstack-skills/skills-manifest.js.map +1 -0
- package/dist/server/resources/gstack-skills/skills-manifest.ts +59 -0
- package/dist/server/routes/auth.d.ts +3 -0
- package/dist/server/routes/auth.d.ts.map +1 -0
- package/dist/server/routes/auth.js +70 -0
- package/dist/server/routes/auth.js.map +1 -0
- package/dist/server/routes/debug-logs.d.ts +3 -0
- package/dist/server/routes/debug-logs.d.ts.map +1 -0
- package/dist/server/routes/debug-logs.js +43 -0
- package/dist/server/routes/debug-logs.js.map +1 -0
- package/dist/server/routes/discussions.d.ts +3 -0
- package/dist/server/routes/discussions.d.ts.map +1 -0
- package/dist/server/routes/discussions.js +544 -0
- package/dist/server/routes/discussions.js.map +1 -0
- package/dist/server/routes/execution.d.ts +3 -0
- package/dist/server/routes/execution.d.ts.map +1 -0
- package/dist/server/routes/execution.js +339 -0
- package/dist/server/routes/execution.js.map +1 -0
- package/dist/server/routes/github.d.ts +3 -0
- package/dist/server/routes/github.d.ts.map +1 -0
- package/dist/server/routes/github.js +251 -0
- package/dist/server/routes/github.js.map +1 -0
- package/dist/server/routes/images.d.ts +17 -0
- package/dist/server/routes/images.d.ts.map +1 -0
- package/dist/server/routes/images.js +152 -0
- package/dist/server/routes/images.js.map +1 -0
- package/dist/server/routes/jira.d.ts +3 -0
- package/dist/server/routes/jira.d.ts.map +1 -0
- package/dist/server/routes/jira.js +333 -0
- package/dist/server/routes/jira.js.map +1 -0
- package/dist/server/routes/logs.d.ts +3 -0
- package/dist/server/routes/logs.d.ts.map +1 -0
- package/dist/server/routes/logs.js +156 -0
- package/dist/server/routes/logs.js.map +1 -0
- package/dist/server/routes/models.d.ts +3 -0
- package/dist/server/routes/models.d.ts.map +1 -0
- package/dist/server/routes/models.js +65 -0
- package/dist/server/routes/models.js.map +1 -0
- package/dist/server/routes/notion.d.ts +3 -0
- package/dist/server/routes/notion.d.ts.map +1 -0
- package/dist/server/routes/notion.js +312 -0
- package/dist/server/routes/notion.js.map +1 -0
- package/dist/server/routes/pipelines.d.ts +3 -0
- package/dist/server/routes/pipelines.d.ts.map +1 -0
- package/dist/server/routes/pipelines.js +315 -0
- package/dist/server/routes/pipelines.js.map +1 -0
- package/dist/server/routes/plugins.d.ts +3 -0
- package/dist/server/routes/plugins.d.ts.map +1 -0
- package/dist/server/routes/plugins.js +71 -0
- package/dist/server/routes/plugins.js.map +1 -0
- package/dist/server/routes/projects.d.ts +3 -0
- package/dist/server/routes/projects.d.ts.map +1 -0
- package/dist/server/routes/projects.js +557 -0
- package/dist/server/routes/projects.js.map +1 -0
- package/dist/server/routes/schedules.d.ts +3 -0
- package/dist/server/routes/schedules.d.ts.map +1 -0
- package/dist/server/routes/schedules.js +247 -0
- package/dist/server/routes/schedules.js.map +1 -0
- package/dist/server/routes/todos.d.ts +3 -0
- package/dist/server/routes/todos.d.ts.map +1 -0
- package/dist/server/routes/todos.js +103 -0
- package/dist/server/routes/todos.js.map +1 -0
- package/dist/server/routes/tunnel.d.ts +3 -0
- package/dist/server/routes/tunnel.d.ts.map +1 -0
- package/dist/server/routes/tunnel.js +44 -0
- package/dist/server/routes/tunnel.js.map +1 -0
- package/dist/server/services/claude-manager.d.ts +42 -0
- package/dist/server/services/claude-manager.d.ts.map +1 -0
- package/dist/server/services/claude-manager.js +275 -0
- package/dist/server/services/claude-manager.js.map +1 -0
- package/dist/server/services/cli-adapters.d.ts +35 -0
- package/dist/server/services/cli-adapters.d.ts.map +1 -0
- package/dist/server/services/cli-adapters.js +139 -0
- package/dist/server/services/cli-adapters.js.map +1 -0
- package/dist/server/services/debug-logger.d.ts +35 -0
- package/dist/server/services/debug-logger.d.ts.map +1 -0
- package/dist/server/services/debug-logger.js +168 -0
- package/dist/server/services/debug-logger.js.map +1 -0
- package/dist/server/services/discussion-orchestrator.d.ts +47 -0
- package/dist/server/services/discussion-orchestrator.d.ts.map +1 -0
- package/dist/server/services/discussion-orchestrator.js +599 -0
- package/dist/server/services/discussion-orchestrator.js.map +1 -0
- package/dist/server/services/log-streamer.d.ts +45 -0
- package/dist/server/services/log-streamer.d.ts.map +1 -0
- package/dist/server/services/log-streamer.js +348 -0
- package/dist/server/services/log-streamer.js.map +1 -0
- package/dist/server/services/orchestrator.d.ts +69 -0
- package/dist/server/services/orchestrator.d.ts.map +1 -0
- package/dist/server/services/orchestrator.js +642 -0
- package/dist/server/services/orchestrator.js.map +1 -0
- package/dist/server/services/pipeline-orchestrator.d.ts +43 -0
- package/dist/server/services/pipeline-orchestrator.d.ts.map +1 -0
- package/dist/server/services/pipeline-orchestrator.js +503 -0
- package/dist/server/services/pipeline-orchestrator.js.map +1 -0
- package/dist/server/services/prompt-guard.d.ts +19 -0
- package/dist/server/services/prompt-guard.d.ts.map +1 -0
- package/dist/server/services/prompt-guard.js +43 -0
- package/dist/server/services/prompt-guard.js.map +1 -0
- package/dist/server/services/scheduler.d.ts +43 -0
- package/dist/server/services/scheduler.d.ts.map +1 -0
- package/dist/server/services/scheduler.js +199 -0
- package/dist/server/services/scheduler.js.map +1 -0
- package/dist/server/services/skill-injector.d.ts +17 -0
- package/dist/server/services/skill-injector.d.ts.map +1 -0
- package/dist/server/services/skill-injector.js +60 -0
- package/dist/server/services/skill-injector.js.map +1 -0
- package/dist/server/services/tunnel-manager.d.ts +42 -0
- package/dist/server/services/tunnel-manager.d.ts.map +1 -0
- package/dist/server/services/tunnel-manager.js +265 -0
- package/dist/server/services/tunnel-manager.js.map +1 -0
- package/dist/server/services/worktree-manager.d.ts +117 -0
- package/dist/server/services/worktree-manager.d.ts.map +1 -0
- package/dist/server/services/worktree-manager.js +400 -0
- package/dist/server/services/worktree-manager.js.map +1 -0
- package/dist/server/websocket/broadcaster.d.ts +12 -0
- package/dist/server/websocket/broadcaster.d.ts.map +1 -0
- package/dist/server/websocket/broadcaster.js +23 -0
- package/dist/server/websocket/broadcaster.js.map +1 -0
- package/dist/server/websocket/events.d.ts +94 -0
- package/dist/server/websocket/events.d.ts.map +1 -0
- package/dist/server/websocket/events.js +2 -0
- package/dist/server/websocket/events.js.map +1 -0
- package/dist/server/websocket/index.d.ts +3 -0
- package/dist/server/websocket/index.d.ts.map +1 -0
- package/dist/server/websocket/index.js +82 -0
- package/dist/server/websocket/index.js.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-guard.d.ts","sourceRoot":"","sources":["../../../src/server/services/prompt-guard.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,eAAO,MAAM,sBAAsB,QAAS,CAAC;AAgB7C,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,SAAS,GAAE,MAA+B,GACzC,gBAAgB,CAmBlB"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt injection defense utilities.
|
|
3
|
+
* Validates and flags suspicious content before it becomes part of AI prompts.
|
|
4
|
+
* Warning-only by design — does not block content to avoid false positives.
|
|
5
|
+
*/
|
|
6
|
+
export const MAX_TITLE_LENGTH = 500;
|
|
7
|
+
export const MAX_DESCRIPTION_LENGTH = 50_000;
|
|
8
|
+
const INJECTION_PATTERNS = [
|
|
9
|
+
{ pattern: /ignore\s+(all\s+)?previous\s+instructions/i, label: 'ignore-previous-instructions' },
|
|
10
|
+
{ pattern: /ignore\s+(all\s+)?above\s+instructions/i, label: 'ignore-above-instructions' },
|
|
11
|
+
{ pattern: /disregard\s+(all\s+)?previous/i, label: 'disregard-previous' },
|
|
12
|
+
{ pattern: /you\s+are\s+now\s+(a|an)\s+/i, label: 'role-override' },
|
|
13
|
+
{ pattern: /new\s+instructions?\s*:/i, label: 'new-instructions' },
|
|
14
|
+
{ pattern: /\bsystem\s*:\s*/i, label: 'system-prefix' },
|
|
15
|
+
{ pattern: /\[INST\]/i, label: 'inst-tag' },
|
|
16
|
+
{ pattern: /<<SYS>>/i, label: 'sys-tag' },
|
|
17
|
+
{ pattern: /<\|im_start\|>/i, label: 'im-start-tag' },
|
|
18
|
+
{ pattern: /<\|im_end\|>/i, label: 'im-end-tag' },
|
|
19
|
+
{ pattern: /```\s*system\b/i, label: 'system-code-block' },
|
|
20
|
+
];
|
|
21
|
+
/**
|
|
22
|
+
* Validate content that will be included in AI prompts.
|
|
23
|
+
* Returns warnings for logging — does NOT block content.
|
|
24
|
+
* Truncates to max length if exceeded.
|
|
25
|
+
*/
|
|
26
|
+
export function validatePromptContent(content, maxLength = MAX_DESCRIPTION_LENGTH) {
|
|
27
|
+
const warnings = [];
|
|
28
|
+
if (content.length > maxLength) {
|
|
29
|
+
warnings.push(`Content truncated from ${content.length} to ${maxLength} characters`);
|
|
30
|
+
content = content.slice(0, maxLength);
|
|
31
|
+
}
|
|
32
|
+
for (const { pattern, label } of INJECTION_PATTERNS) {
|
|
33
|
+
if (pattern.test(content)) {
|
|
34
|
+
warnings.push(`Suspicious pattern detected: ${label}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
valid: warnings.length === 0,
|
|
39
|
+
warnings,
|
|
40
|
+
sanitized: content,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=prompt-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-guard.js","sourceRoot":"","sources":["../../../src/server/services/prompt-guard.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,CAAC;AACpC,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAE7C,MAAM,kBAAkB,GAAyC;IAC/D,EAAE,OAAO,EAAE,4CAA4C,EAAE,KAAK,EAAE,8BAA8B,EAAE;IAChG,EAAE,OAAO,EAAE,yCAAyC,EAAE,KAAK,EAAE,2BAA2B,EAAE;IAC1F,EAAE,OAAO,EAAE,gCAAgC,EAAE,KAAK,EAAE,oBAAoB,EAAE;IAC1E,EAAE,OAAO,EAAE,8BAA8B,EAAE,KAAK,EAAE,eAAe,EAAE;IACnE,EAAE,OAAO,EAAE,0BAA0B,EAAE,KAAK,EAAE,kBAAkB,EAAE;IAClE,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,eAAe,EAAE;IACvD,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE;IAC3C,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE;IACzC,EAAE,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,cAAc,EAAE;IACrD,EAAE,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,YAAY,EAAE;IACjD,EAAE,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,mBAAmB,EAAE;CAC3D,CAAC;AAQF;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CACnC,OAAe,EACf,YAAoB,sBAAsB;IAE1C,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;QAC/B,QAAQ,CAAC,IAAI,CAAC,0BAA0B,OAAO,CAAC,MAAM,OAAO,SAAS,aAAa,CAAC,CAAC;QACrF,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IACxC,CAAC;IAED,KAAK,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,kBAAkB,EAAE,CAAC;QACpD,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC1B,QAAQ,CAAC,IAAI,CAAC,gCAAgC,KAAK,EAAE,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,EAAE,QAAQ,CAAC,MAAM,KAAK,CAAC;QAC5B,QAAQ;QACR,SAAS,EAAE,OAAO;KACnB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as queries from '../db/queries.js';
|
|
2
|
+
export declare class Scheduler {
|
|
3
|
+
private jobs;
|
|
4
|
+
private timers;
|
|
5
|
+
/**
|
|
6
|
+
* Initialize all active schedules on server startup.
|
|
7
|
+
*/
|
|
8
|
+
initialize(): void;
|
|
9
|
+
/**
|
|
10
|
+
* Register a cron job for a schedule.
|
|
11
|
+
*/
|
|
12
|
+
registerJob(schedule: queries.Schedule): void;
|
|
13
|
+
/**
|
|
14
|
+
* Register a one-time scheduled job using setTimeout.
|
|
15
|
+
*/
|
|
16
|
+
registerOnceJob(schedule: queries.Schedule): void;
|
|
17
|
+
/**
|
|
18
|
+
* Unregister a cron job or timer.
|
|
19
|
+
*/
|
|
20
|
+
unregisterJob(scheduleId: string): void;
|
|
21
|
+
/**
|
|
22
|
+
* Core execution logic — called by cron callback.
|
|
23
|
+
*/
|
|
24
|
+
private executeSchedule;
|
|
25
|
+
/**
|
|
26
|
+
* Manually trigger a schedule run (for testing / on-demand).
|
|
27
|
+
*/
|
|
28
|
+
triggerSchedule(scheduleId: string): Promise<queries.ScheduleRun | null>;
|
|
29
|
+
/**
|
|
30
|
+
* Activate a schedule and register its cron job.
|
|
31
|
+
*/
|
|
32
|
+
activateSchedule(scheduleId: string): queries.Schedule | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Pause a schedule and unregister its cron job.
|
|
35
|
+
*/
|
|
36
|
+
pauseSchedule(scheduleId: string): queries.Schedule | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* Stop all cron jobs (for server shutdown).
|
|
39
|
+
*/
|
|
40
|
+
stopAll(): void;
|
|
41
|
+
}
|
|
42
|
+
export declare const scheduler: Scheduler;
|
|
43
|
+
//# sourceMappingURL=scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../../src/server/services/scheduler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,OAAO,MAAM,kBAAkB,CAAC;AAI5C,qBAAa,SAAS;IACpB,OAAO,CAAC,IAAI,CAAyC;IACrD,OAAO,CAAC,MAAM,CAAyD;IAEvE;;OAEG;IACH,UAAU,IAAI,IAAI;IAclB;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,GAAG,IAAI;IAkB7C;;OAEG;IACH,eAAe,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,GAAG,IAAI;IA+BjD;;OAEG;IACH,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAavC;;OAEG;YACW,eAAe;IAmE7B;;OAEG;IACG,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAiB9E;;OAEG;IACH,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS;IAalE;;OAEG;IACH,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS;IAS/D;;OAEG;IACH,OAAO,IAAI,IAAI;CAUhB;AAED,eAAO,MAAM,SAAS,WAAkB,CAAC"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import cron from 'node-cron';
|
|
2
|
+
import * as queries from '../db/queries.js';
|
|
3
|
+
import { orchestrator } from './orchestrator.js';
|
|
4
|
+
import { broadcaster } from '../websocket/broadcaster.js';
|
|
5
|
+
export class Scheduler {
|
|
6
|
+
jobs = new Map();
|
|
7
|
+
timers = new Map();
|
|
8
|
+
/**
|
|
9
|
+
* Initialize all active schedules on server startup.
|
|
10
|
+
*/
|
|
11
|
+
initialize() {
|
|
12
|
+
const activeSchedules = queries.getActiveSchedules();
|
|
13
|
+
for (const schedule of activeSchedules) {
|
|
14
|
+
if (schedule.schedule_type === 'once') {
|
|
15
|
+
this.registerOnceJob(schedule);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
this.registerJob(schedule);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (activeSchedules.length > 0) {
|
|
22
|
+
console.log(`Scheduler initialized: ${activeSchedules.length} active schedule(s)`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Register a cron job for a schedule.
|
|
27
|
+
*/
|
|
28
|
+
registerJob(schedule) {
|
|
29
|
+
// Unregister existing job if any
|
|
30
|
+
this.unregisterJob(schedule.id);
|
|
31
|
+
if (!cron.validate(schedule.cron_expression)) {
|
|
32
|
+
console.error(`Invalid cron expression for schedule "${schedule.title}": ${schedule.cron_expression}`);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const task = cron.schedule(schedule.cron_expression, () => {
|
|
36
|
+
this.executeSchedule(schedule.id).catch((err) => {
|
|
37
|
+
console.error(`Schedule "${schedule.title}" execution error:`, err);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
this.jobs.set(schedule.id, task);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Register a one-time scheduled job using setTimeout.
|
|
44
|
+
*/
|
|
45
|
+
registerOnceJob(schedule) {
|
|
46
|
+
this.unregisterJob(schedule.id);
|
|
47
|
+
if (!schedule.run_at) {
|
|
48
|
+
console.error(`One-time schedule "${schedule.title}" has no run_at time`);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const runAtMs = new Date(schedule.run_at).getTime();
|
|
52
|
+
const delay = runAtMs - Date.now();
|
|
53
|
+
if (delay <= 0) {
|
|
54
|
+
// run_at is in the past — execute immediately
|
|
55
|
+
console.log(`One-time schedule "${schedule.title}" run_at is in the past, executing now`);
|
|
56
|
+
this.executeSchedule(schedule.id).catch((err) => {
|
|
57
|
+
console.error(`One-time schedule "${schedule.title}" execution error:`, err);
|
|
58
|
+
});
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const timer = setTimeout(() => {
|
|
62
|
+
this.timers.delete(schedule.id);
|
|
63
|
+
this.executeSchedule(schedule.id).catch((err) => {
|
|
64
|
+
console.error(`One-time schedule "${schedule.title}" execution error:`, err);
|
|
65
|
+
});
|
|
66
|
+
}, delay);
|
|
67
|
+
this.timers.set(schedule.id, timer);
|
|
68
|
+
console.log(`One-time schedule "${schedule.title}" registered, fires in ${Math.round(delay / 1000)}s`);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Unregister a cron job or timer.
|
|
72
|
+
*/
|
|
73
|
+
unregisterJob(scheduleId) {
|
|
74
|
+
const job = this.jobs.get(scheduleId);
|
|
75
|
+
if (job) {
|
|
76
|
+
job.stop();
|
|
77
|
+
this.jobs.delete(scheduleId);
|
|
78
|
+
}
|
|
79
|
+
const timer = this.timers.get(scheduleId);
|
|
80
|
+
if (timer) {
|
|
81
|
+
clearTimeout(timer);
|
|
82
|
+
this.timers.delete(scheduleId);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Core execution logic — called by cron callback.
|
|
87
|
+
*/
|
|
88
|
+
async executeSchedule(scheduleId) {
|
|
89
|
+
const schedule = queries.getScheduleById(scheduleId);
|
|
90
|
+
if (!schedule || !schedule.is_active)
|
|
91
|
+
return;
|
|
92
|
+
const now = new Date().toISOString();
|
|
93
|
+
// Check skip-if-running condition
|
|
94
|
+
if (schedule.skip_if_running) {
|
|
95
|
+
const scheduleTodos = queries.getTodosByScheduleId(scheduleId);
|
|
96
|
+
const hasRunning = scheduleTodos.some((t) => t.status === 'running');
|
|
97
|
+
if (hasRunning) {
|
|
98
|
+
const run = queries.createScheduleRun(scheduleId, null, 'skipped', 'previous_run_still_active');
|
|
99
|
+
broadcaster.broadcast({
|
|
100
|
+
type: 'schedule:run-skipped',
|
|
101
|
+
scheduleId,
|
|
102
|
+
runId: run.id,
|
|
103
|
+
reason: 'previous_run_still_active',
|
|
104
|
+
});
|
|
105
|
+
queries.updateScheduleLastRun(scheduleId, now);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// Create todo from schedule template
|
|
110
|
+
const timestamp = new Date().toLocaleString('ko-KR', { timeZone: 'Asia/Seoul' });
|
|
111
|
+
const todoTitle = `[Schedule] ${schedule.title} - ${timestamp}`;
|
|
112
|
+
const todo = queries.createTodo(schedule.project_id, todoTitle, schedule.description ?? undefined, 0, schedule.cli_tool ?? undefined, schedule.cli_model ?? undefined, scheduleId);
|
|
113
|
+
// Create run record
|
|
114
|
+
const run = queries.createScheduleRun(scheduleId, todo.id, 'triggered');
|
|
115
|
+
// Update last run
|
|
116
|
+
queries.updateScheduleLastRun(scheduleId, now);
|
|
117
|
+
// Broadcast
|
|
118
|
+
broadcaster.broadcast({
|
|
119
|
+
type: 'schedule:run-triggered',
|
|
120
|
+
scheduleId,
|
|
121
|
+
runId: run.id,
|
|
122
|
+
todoId: todo.id,
|
|
123
|
+
});
|
|
124
|
+
// Auto-deactivate one-time schedules after execution
|
|
125
|
+
if (schedule.schedule_type === 'once') {
|
|
126
|
+
queries.updateScheduleStatus(schedule.id, 0);
|
|
127
|
+
this.unregisterJob(schedule.id);
|
|
128
|
+
broadcaster.broadcast({ type: 'schedule:status-changed', scheduleId: schedule.id, isActive: false });
|
|
129
|
+
}
|
|
130
|
+
// Start the todo
|
|
131
|
+
try {
|
|
132
|
+
await orchestrator.startTodo(todo.id);
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
136
|
+
console.error(`Schedule "${schedule.title}" failed to start todo: ${message}`);
|
|
137
|
+
queries.updateScheduleRun(run.id, { status: 'failed', completed_at: new Date().toISOString() });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Manually trigger a schedule run (for testing / on-demand).
|
|
142
|
+
*/
|
|
143
|
+
async triggerSchedule(scheduleId) {
|
|
144
|
+
const schedule = queries.getScheduleById(scheduleId);
|
|
145
|
+
if (!schedule)
|
|
146
|
+
return null;
|
|
147
|
+
// Temporarily treat as active for manual trigger
|
|
148
|
+
const origActive = schedule.is_active;
|
|
149
|
+
if (!origActive) {
|
|
150
|
+
// Allow manual trigger even if paused — just don't check is_active in executeSchedule
|
|
151
|
+
}
|
|
152
|
+
await this.executeSchedule(scheduleId);
|
|
153
|
+
// Return the latest run
|
|
154
|
+
const runs = queries.getScheduleRunsByScheduleId(scheduleId, 1);
|
|
155
|
+
return runs[0] ?? null;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Activate a schedule and register its cron job.
|
|
159
|
+
*/
|
|
160
|
+
activateSchedule(scheduleId) {
|
|
161
|
+
const schedule = queries.updateScheduleStatus(scheduleId, 1);
|
|
162
|
+
if (schedule) {
|
|
163
|
+
if (schedule.schedule_type === 'once') {
|
|
164
|
+
this.registerOnceJob(schedule);
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
this.registerJob(schedule);
|
|
168
|
+
}
|
|
169
|
+
broadcaster.broadcast({ type: 'schedule:status-changed', scheduleId, isActive: true });
|
|
170
|
+
}
|
|
171
|
+
return schedule;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Pause a schedule and unregister its cron job.
|
|
175
|
+
*/
|
|
176
|
+
pauseSchedule(scheduleId) {
|
|
177
|
+
const schedule = queries.updateScheduleStatus(scheduleId, 0);
|
|
178
|
+
if (schedule) {
|
|
179
|
+
this.unregisterJob(scheduleId);
|
|
180
|
+
broadcaster.broadcast({ type: 'schedule:status-changed', scheduleId, isActive: false });
|
|
181
|
+
}
|
|
182
|
+
return schedule;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Stop all cron jobs (for server shutdown).
|
|
186
|
+
*/
|
|
187
|
+
stopAll() {
|
|
188
|
+
for (const [, job] of this.jobs) {
|
|
189
|
+
job.stop();
|
|
190
|
+
}
|
|
191
|
+
this.jobs.clear();
|
|
192
|
+
for (const [, timer] of this.timers) {
|
|
193
|
+
clearTimeout(timer);
|
|
194
|
+
}
|
|
195
|
+
this.timers.clear();
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
export const scheduler = new Scheduler();
|
|
199
|
+
//# sourceMappingURL=scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../../src/server/services/scheduler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type GstackSkillMeta } from '../resources/gstack-skills/skills-manifest.js';
|
|
2
|
+
/**
|
|
3
|
+
* Returns the list of all available gstack skills.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getAvailableSkills(): GstackSkillMeta[];
|
|
6
|
+
/**
|
|
7
|
+
* Parse the JSON-encoded skill IDs from DB column.
|
|
8
|
+
* Returns empty array for null/invalid input.
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseSkillConfig(json: string | null): string[];
|
|
11
|
+
/**
|
|
12
|
+
* Inject selected gstack skill files into a target directory.
|
|
13
|
+
* Creates .claude/skills/gstack-{id}/SKILL.md for each selected skill.
|
|
14
|
+
* Also copies the gstack LICENSE file.
|
|
15
|
+
*/
|
|
16
|
+
export declare function injectSkills(targetDir: string, skillIds: string[]): Promise<void>;
|
|
17
|
+
//# sourceMappingURL=skill-injector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-injector.d.ts","sourceRoot":"","sources":["../../../src/server/services/skill-injector.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,+CAA+C,CAAC;AAMpG;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,eAAe,EAAE,CAEtD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,EAAE,CAS9D;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BvF"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { GSTACK_SKILLS } from '../resources/gstack-skills/skills-manifest.js';
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = path.dirname(__filename);
|
|
7
|
+
const RESOURCES_DIR = path.resolve(__dirname, '../resources/gstack-skills');
|
|
8
|
+
/**
|
|
9
|
+
* Returns the list of all available gstack skills.
|
|
10
|
+
*/
|
|
11
|
+
export function getAvailableSkills() {
|
|
12
|
+
return GSTACK_SKILLS;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Parse the JSON-encoded skill IDs from DB column.
|
|
16
|
+
* Returns empty array for null/invalid input.
|
|
17
|
+
*/
|
|
18
|
+
export function parseSkillConfig(json) {
|
|
19
|
+
if (!json)
|
|
20
|
+
return [];
|
|
21
|
+
try {
|
|
22
|
+
const parsed = JSON.parse(json);
|
|
23
|
+
if (!Array.isArray(parsed))
|
|
24
|
+
return [];
|
|
25
|
+
return parsed.filter((id) => typeof id === 'string');
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Inject selected gstack skill files into a target directory.
|
|
33
|
+
* Creates .claude/skills/gstack-{id}/SKILL.md for each selected skill.
|
|
34
|
+
* Also copies the gstack LICENSE file.
|
|
35
|
+
*/
|
|
36
|
+
export async function injectSkills(targetDir, skillIds) {
|
|
37
|
+
if (skillIds.length === 0)
|
|
38
|
+
return;
|
|
39
|
+
const validIds = skillIds.filter((id) => GSTACK_SKILLS.some((s) => s.id === id));
|
|
40
|
+
if (validIds.length === 0)
|
|
41
|
+
return;
|
|
42
|
+
const skillsDir = path.join(targetDir, '.claude', 'skills');
|
|
43
|
+
fs.mkdirSync(skillsDir, { recursive: true });
|
|
44
|
+
// Copy LICENSE
|
|
45
|
+
const licenseSrc = path.join(RESOURCES_DIR, 'LICENSE');
|
|
46
|
+
const licenseDest = path.join(skillsDir, 'gstack-LICENSE');
|
|
47
|
+
if (fs.existsSync(licenseSrc)) {
|
|
48
|
+
fs.copyFileSync(licenseSrc, licenseDest);
|
|
49
|
+
}
|
|
50
|
+
// Copy each selected skill
|
|
51
|
+
for (const id of validIds) {
|
|
52
|
+
const srcFile = path.join(RESOURCES_DIR, id, 'SKILL.md');
|
|
53
|
+
if (!fs.existsSync(srcFile))
|
|
54
|
+
continue;
|
|
55
|
+
const destDir = path.join(skillsDir, `gstack-${id}`);
|
|
56
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
57
|
+
fs.copyFileSync(srcFile, path.join(destDir, 'SKILL.md'));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=skill-injector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-injector.js","sourceRoot":"","sources":["../../../src/server/services/skill-injector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,aAAa,EAAwB,MAAM,+CAA+C,CAAC;AAEpG,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAC3C,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,4BAA4B,CAAC,CAAC;AAE5E;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO,aAAa,CAAC;AACvB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAmB;IAClD,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,EAAE,CAAC;QACtC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,EAAW,EAAE,EAAE,CAAC,OAAO,EAAE,KAAK,QAAQ,CAAC,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,SAAiB,EAAE,QAAkB;IACtE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAElC,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CACtC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CACvC,CAAC;IACF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAElC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC5D,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE7C,eAAe;IACf,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;IACvD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAC3D,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;IAC3C,CAAC;IAED,2BAA2B;IAC3B,KAAK,MAAM,EAAE,IAAI,QAAQ,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,EAAE,UAAU,CAAC,CAAC;QACzD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;YAAE,SAAS;QAEtC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;QACrD,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3C,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
export declare class TunnelManager extends EventEmitter {
|
|
3
|
+
private process;
|
|
4
|
+
private url;
|
|
5
|
+
private status;
|
|
6
|
+
private cloudflaredPath;
|
|
7
|
+
/**
|
|
8
|
+
* Start a quick (unnamed) cloudflared tunnel.
|
|
9
|
+
* Runs: cloudflared tunnel --url http://localhost:<port>
|
|
10
|
+
* Parses stderr for the generated trycloudflare.com URL.
|
|
11
|
+
*/
|
|
12
|
+
startTunnel(port: number): Promise<string>;
|
|
13
|
+
/**
|
|
14
|
+
* Start a named cloudflared tunnel.
|
|
15
|
+
* Runs: cloudflared tunnel run <tunnelName>
|
|
16
|
+
* The URL comes from the tunnel's DNS configuration (not parsed from output).
|
|
17
|
+
*/
|
|
18
|
+
startNamedTunnel(tunnelName: string, port: number): Promise<string>;
|
|
19
|
+
/**
|
|
20
|
+
* Stop the running cloudflared tunnel process.
|
|
21
|
+
*/
|
|
22
|
+
stopTunnel(): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Get the current tunnel status and URL.
|
|
25
|
+
*/
|
|
26
|
+
getTunnelStatus(): {
|
|
27
|
+
status: string;
|
|
28
|
+
url: string | null;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Resolve the full path to cloudflared, checking PATH first,
|
|
32
|
+
* then common Windows installation locations (winget, Program Files).
|
|
33
|
+
*/
|
|
34
|
+
private resolveCloudflaredPath;
|
|
35
|
+
/**
|
|
36
|
+
* Check if cloudflared is installed by running 'cloudflared --version'.
|
|
37
|
+
* Falls back to known installation paths on Windows if not found in PATH.
|
|
38
|
+
*/
|
|
39
|
+
isCloudflaredInstalled(): Promise<boolean>;
|
|
40
|
+
}
|
|
41
|
+
export declare const tunnelManager: TunnelManager;
|
|
42
|
+
//# sourceMappingURL=tunnel-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tunnel-manager.d.ts","sourceRoot":"","sources":["../../../src/server/services/tunnel-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAItC,qBAAa,aAAc,SAAQ,YAAY;IAC7C,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,GAAG,CAAuB;IAClC,OAAO,CAAC,MAAM,CAA2D;IACzE,OAAO,CAAC,eAAe,CAAyB;IAEhD;;;;OAIG;IACG,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAiFhD;;;;OAIG;IACG,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAqFzE;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAuCjC;;OAEG;IACH,eAAe,IAAI;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE;IAIzD;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IA4B9B;;;OAGG;IACG,sBAAsB,IAAI,OAAO,CAAC,OAAO,CAAC;CA6BjD;AAED,eAAO,MAAM,aAAa,eAAsB,CAAC"}
|