@archznn/crewloop-skills 0.3.0 → 0.4.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/package.json +2 -1
- package/servers/dashboard/README.md +87 -0
- package/servers/dashboard/bin/crewloop-dashboard.js +5 -0
- package/servers/dashboard/config-examples/codex-hooks.json +14 -0
- package/servers/dashboard/config-examples/kimi-code-config.toml +6 -0
- package/servers/dashboard/config-examples/opencode-plugin/crewloop-dashboard.js +64 -0
- package/servers/dashboard/package.json +46 -0
- package/servers/dashboard/public/app.js +447 -0
- package/servers/dashboard/public/index.html +96 -0
- package/servers/dashboard/public/styles.css +664 -0
- package/servers/dashboard/src/adapters/codex.ts +50 -0
- package/servers/dashboard/src/adapters/kimi.ts +40 -0
- package/servers/dashboard/src/adapters/opencode.ts +36 -0
- package/servers/dashboard/src/adapters/shim.test.ts +74 -0
- package/servers/dashboard/src/adapters/shim.ts +120 -0
- package/servers/dashboard/src/api/event.ts +70 -0
- package/servers/dashboard/src/api/skills.ts +11 -0
- package/servers/dashboard/src/config.ts +66 -0
- package/servers/dashboard/src/filters/sanitize.test.ts +94 -0
- package/servers/dashboard/src/filters/sanitize.ts +78 -0
- package/servers/dashboard/src/index.ts +24 -0
- package/servers/dashboard/src/presenter.test.ts +69 -0
- package/servers/dashboard/src/presenter.ts +56 -0
- package/servers/dashboard/src/server.test.ts +123 -0
- package/servers/dashboard/src/server.ts +191 -0
- package/servers/dashboard/src/skills/infer.test.ts +86 -0
- package/servers/dashboard/src/skills/infer.ts +53 -0
- package/servers/dashboard/src/skills/mapping.ts +26 -0
- package/servers/dashboard/src/skills/registry.ts +60 -0
- package/servers/dashboard/src/state.test.ts +88 -0
- package/servers/dashboard/src/state.ts +115 -0
- package/servers/dashboard/src/types.ts +110 -0
- package/servers/dashboard/tsconfig.json +19 -0
- package/skills/orchestrator/SKILL.md +1 -1
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type { DashboardEvent, Session, DashboardState, AgentSource, EventStatus } from './types';
|
|
2
|
+
|
|
3
|
+
export interface StateStoreOptions {
|
|
4
|
+
maxEventsPerSession: number;
|
|
5
|
+
sessionMaxAgeMs: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class StateStore {
|
|
9
|
+
private sessions: Map<string, Session> = new Map();
|
|
10
|
+
private options: StateStoreOptions;
|
|
11
|
+
|
|
12
|
+
constructor(options: StateStoreOptions) {
|
|
13
|
+
this.options = options;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
applyEvent(event: DashboardEvent): Session {
|
|
17
|
+
let session = this.sessions.get(event.session_id);
|
|
18
|
+
|
|
19
|
+
if (!session) {
|
|
20
|
+
session = this.createSession(event.session_id, event.source);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
session.source = event.source;
|
|
24
|
+
session.last_event_at = event.timestamp;
|
|
25
|
+
session.events.unshift(event);
|
|
26
|
+
|
|
27
|
+
if (session.events.length > this.options.maxEventsPerSession) {
|
|
28
|
+
session.events.length = this.options.maxEventsPerSession;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (event.tool) {
|
|
32
|
+
session.tool_counts[event.tool] = (session.tool_counts[event.tool] || 0) + 1;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (event.skill) {
|
|
36
|
+
session.active_skill = event.skill;
|
|
37
|
+
session.active_confidence = event.event_type === 'skill_change' ? 'explicit' : 'heuristic';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
session.status = deriveSessionStatus(event);
|
|
41
|
+
|
|
42
|
+
this.sessions.set(event.session_id, session);
|
|
43
|
+
return session;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
setActiveSkill(
|
|
47
|
+
sessionId: string,
|
|
48
|
+
skill: string | undefined,
|
|
49
|
+
confidence: 'explicit' | 'heuristic' | 'unknown'
|
|
50
|
+
): Session | undefined {
|
|
51
|
+
const session = this.sessions.get(sessionId);
|
|
52
|
+
if (!session) {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
session.active_skill = skill;
|
|
56
|
+
session.active_confidence = confidence;
|
|
57
|
+
return session;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
getSession(id: string): Session | undefined {
|
|
61
|
+
return this.sessions.get(id);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
getAllSessions(): Session[] {
|
|
65
|
+
return Array.from(this.sessions.values()).sort(
|
|
66
|
+
(a, b) => b.last_event_at - a.last_event_at
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
getState(): DashboardState {
|
|
71
|
+
return {
|
|
72
|
+
sessions: Object.fromEntries(this.sessions),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
pruneInactive(now: number = Date.now()): number {
|
|
77
|
+
let removed = 0;
|
|
78
|
+
for (const [id, session] of this.sessions) {
|
|
79
|
+
if (now - session.last_event_at > this.options.sessionMaxAgeMs) {
|
|
80
|
+
this.sessions.delete(id);
|
|
81
|
+
removed++;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return removed;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private createSession(id: string, source: AgentSource): Session {
|
|
88
|
+
const now = Date.now();
|
|
89
|
+
const session: Session = {
|
|
90
|
+
id,
|
|
91
|
+
source,
|
|
92
|
+
events: [],
|
|
93
|
+
tool_counts: {},
|
|
94
|
+
started_at: now,
|
|
95
|
+
last_event_at: now,
|
|
96
|
+
};
|
|
97
|
+
this.sessions.set(id, session);
|
|
98
|
+
return session;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function deriveSessionStatus(event: DashboardEvent): EventStatus | undefined {
|
|
103
|
+
switch (event.event_type) {
|
|
104
|
+
case 'session_start':
|
|
105
|
+
case 'tool_start':
|
|
106
|
+
case 'skill_change':
|
|
107
|
+
return 'running';
|
|
108
|
+
case 'tool_end':
|
|
109
|
+
return event.status || 'success';
|
|
110
|
+
case 'session_end':
|
|
111
|
+
return 'success';
|
|
112
|
+
default:
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
export type AgentSource = 'kimi' | 'codex' | 'opencode' | 'log-watcher';
|
|
2
|
+
|
|
3
|
+
export type EventType =
|
|
4
|
+
| 'session_start'
|
|
5
|
+
| 'session_end'
|
|
6
|
+
| 'tool_start'
|
|
7
|
+
| 'tool_end'
|
|
8
|
+
| 'skill_change';
|
|
9
|
+
|
|
10
|
+
export type EventStatus = 'running' | 'success' | 'error';
|
|
11
|
+
|
|
12
|
+
export interface DashboardEvent {
|
|
13
|
+
id: string;
|
|
14
|
+
timestamp: number;
|
|
15
|
+
source: AgentSource;
|
|
16
|
+
session_id: string;
|
|
17
|
+
event_type: EventType;
|
|
18
|
+
skill?: string;
|
|
19
|
+
tool?: string;
|
|
20
|
+
detail?: string;
|
|
21
|
+
status?: EventStatus;
|
|
22
|
+
duration_ms?: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface Session {
|
|
26
|
+
id: string;
|
|
27
|
+
source: AgentSource;
|
|
28
|
+
active_skill?: string;
|
|
29
|
+
active_confidence?: 'explicit' | 'heuristic' | 'unknown';
|
|
30
|
+
status?: EventStatus;
|
|
31
|
+
events: DashboardEvent[];
|
|
32
|
+
tool_counts: Record<string, number>;
|
|
33
|
+
started_at: number;
|
|
34
|
+
last_event_at: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface DashboardState {
|
|
38
|
+
sessions: Record<string, Session>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface ClientActiveSkill {
|
|
42
|
+
name: string;
|
|
43
|
+
confidence: 'explicit' | 'heuristic' | 'unknown';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ClientEvent {
|
|
47
|
+
id: string;
|
|
48
|
+
timestamp: number;
|
|
49
|
+
event_type: EventType;
|
|
50
|
+
tool?: string;
|
|
51
|
+
detail?: string;
|
|
52
|
+
status?: EventStatus;
|
|
53
|
+
duration_ms?: number;
|
|
54
|
+
skill?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface ClientSession {
|
|
58
|
+
id: string;
|
|
59
|
+
source: AgentSource;
|
|
60
|
+
skill?: string;
|
|
61
|
+
activeSkill?: ClientActiveSkill;
|
|
62
|
+
status?: EventStatus;
|
|
63
|
+
events: ClientEvent[];
|
|
64
|
+
startTime: number;
|
|
65
|
+
lastActivity: number;
|
|
66
|
+
toolCounts: Record<string, number>;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface ClientSnapshotMessage {
|
|
70
|
+
type: 'snapshot';
|
|
71
|
+
sessions: ClientSession[];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface ClientUpdateMessage {
|
|
75
|
+
type: 'update';
|
|
76
|
+
session: ClientSession;
|
|
77
|
+
isActive: boolean;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface ClientPongMessage {
|
|
81
|
+
type: 'pong';
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export type ClientWebSocketMessage =
|
|
85
|
+
| ClientSnapshotMessage
|
|
86
|
+
| ClientUpdateMessage
|
|
87
|
+
| ClientPongMessage;
|
|
88
|
+
|
|
89
|
+
export interface SkillMeta {
|
|
90
|
+
name: string;
|
|
91
|
+
description: string;
|
|
92
|
+
icon: string;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export type ToolToSkillMap = Record<string, string | undefined>;
|
|
96
|
+
|
|
97
|
+
export interface SkillInferenceResult {
|
|
98
|
+
skill: string | undefined;
|
|
99
|
+
confidence: 'explicit' | 'heuristic' | 'unknown';
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export interface ServerConfig {
|
|
103
|
+
port: number;
|
|
104
|
+
host: string;
|
|
105
|
+
packageRoot: string;
|
|
106
|
+
maxEventsPerSession: number;
|
|
107
|
+
sessionMaxAgeMs: number;
|
|
108
|
+
pruneIntervalMs: number;
|
|
109
|
+
}
|
|
110
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "CommonJS",
|
|
5
|
+
"moduleResolution": "node",
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"rootDir": "./src",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"declarationMap": true,
|
|
14
|
+
"sourceMap": true,
|
|
15
|
+
"resolveJsonModule": true
|
|
16
|
+
},
|
|
17
|
+
"include": ["src/**/*"],
|
|
18
|
+
"exclude": ["node_modules", "dist", "public", "bin"]
|
|
19
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: orchestrator
|
|
3
|
-
description: Context discovery orchestrator for software tasks. Run FIRST for build, create, modify, fix, refactor, design, or implement requests. Gathers context and routes to architect for specs. Trigger: build, create, fix, refactor, design, implement, UI, frontend, dashboard, landing page, or code changes.
|
|
3
|
+
description: "Context discovery orchestrator for software tasks. Run FIRST for build, create, modify, fix, refactor, design, or implement requests. Gathers context and routes to architect for specs. Trigger: build, create, fix, refactor, design, implement, UI, frontend, dashboard, landing page, or code changes."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Orchestrator — Context Discovery & Requirement Gathering
|