@action-llama/action-llama 0.17.7 → 0.18.1
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/agent-docs/AGENTS.md +5 -5
- package/dist/agents/bash-prefix.d.ts +9 -0
- package/dist/agents/bash-prefix.d.ts.map +1 -0
- package/dist/agents/bash-prefix.js +15 -0
- package/dist/agents/bash-prefix.js.map +1 -0
- package/dist/agents/chat-entry.d.ts +9 -0
- package/dist/agents/chat-entry.d.ts.map +1 -0
- package/dist/agents/chat-entry.js +165 -0
- package/dist/agents/chat-entry.js.map +1 -0
- package/dist/agents/container-entry.d.ts.map +1 -1
- package/dist/agents/container-entry.js +11 -148
- package/dist/agents/container-entry.js.map +1 -1
- package/dist/agents/container-runner.d.ts +1 -1
- package/dist/agents/container-runner.d.ts.map +1 -1
- package/dist/agents/container-runner.js.map +1 -1
- package/dist/agents/credential-setup.d.ts +21 -0
- package/dist/agents/credential-setup.d.ts.map +1 -0
- package/dist/agents/credential-setup.js +160 -0
- package/dist/agents/credential-setup.js.map +1 -0
- package/dist/agents/prompt.d.ts +2 -1
- package/dist/agents/prompt.d.ts.map +1 -1
- package/dist/agents/prompt.js +8 -2
- package/dist/agents/prompt.js.map +1 -1
- package/dist/agents/runner.d.ts +1 -1
- package/dist/agents/runner.d.ts.map +1 -1
- package/dist/agents/runner.js.map +1 -1
- package/dist/agents/session-factory.d.ts.map +1 -1
- package/dist/agents/session-factory.js +2 -1
- package/dist/agents/session-factory.js.map +1 -1
- package/dist/build-info.json +1 -1
- package/dist/chat/container-launcher.d.ts +33 -0
- package/dist/chat/container-launcher.d.ts.map +1 -0
- package/dist/chat/container-launcher.js +82 -0
- package/dist/chat/container-launcher.js.map +1 -0
- package/dist/chat/event-mapper.d.ts +27 -0
- package/dist/chat/event-mapper.d.ts.map +1 -0
- package/dist/chat/event-mapper.js +56 -0
- package/dist/chat/event-mapper.js.map +1 -0
- package/dist/chat/ink-adapter.d.ts +9 -0
- package/dist/chat/ink-adapter.d.ts.map +1 -0
- package/dist/chat/ink-adapter.js +120 -0
- package/dist/chat/ink-adapter.js.map +1 -0
- package/dist/chat/local-transport.d.ts +28 -0
- package/dist/chat/local-transport.d.ts.map +1 -0
- package/dist/chat/local-transport.js +68 -0
- package/dist/chat/local-transport.js.map +1 -0
- package/dist/chat/remote-transport.d.ts +30 -0
- package/dist/chat/remote-transport.d.ts.map +1 -0
- package/dist/chat/remote-transport.js +110 -0
- package/dist/chat/remote-transport.js.map +1 -0
- package/dist/chat/routes.d.ts +10 -0
- package/dist/chat/routes.d.ts.map +1 -0
- package/dist/chat/routes.js +58 -0
- package/dist/chat/routes.js.map +1 -0
- package/dist/chat/session-manager.d.ts +20 -0
- package/dist/chat/session-manager.d.ts.map +1 -0
- package/dist/chat/session-manager.js +64 -0
- package/dist/chat/session-manager.js.map +1 -0
- package/dist/chat/transport.d.ts +15 -0
- package/dist/chat/transport.d.ts.map +1 -0
- package/dist/chat/transport.js +5 -0
- package/dist/chat/transport.js.map +1 -0
- package/dist/chat/types.d.ts +50 -0
- package/dist/chat/types.d.ts.map +1 -0
- package/dist/chat/types.js +7 -0
- package/dist/chat/types.js.map +1 -0
- package/dist/chat/validation.d.ts +30 -0
- package/dist/chat/validation.d.ts.map +1 -0
- package/dist/chat/validation.js +79 -0
- package/dist/chat/validation.js.map +1 -0
- package/dist/chat/ws-handler.d.ts +31 -0
- package/dist/chat/ws-handler.d.ts.map +1 -0
- package/dist/chat/ws-handler.js +247 -0
- package/dist/chat/ws-handler.js.map +1 -0
- package/dist/cli/commands/add.d.ts +14 -0
- package/dist/cli/commands/add.d.ts.map +1 -0
- package/dist/cli/commands/add.js +188 -0
- package/dist/cli/commands/add.js.map +1 -0
- package/dist/cli/commands/agent.d.ts.map +1 -1
- package/dist/cli/commands/agent.js +93 -41
- package/dist/cli/commands/agent.js.map +1 -1
- package/dist/cli/commands/chat.d.ts.map +1 -1
- package/dist/cli/commands/chat.js +38 -2
- package/dist/cli/commands/chat.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/doctor.js +26 -13
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/run.d.ts +1 -1
- package/dist/cli/commands/run.d.ts.map +1 -1
- package/dist/cli/commands/run.js +2 -1
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/update.d.ts +14 -0
- package/dist/cli/commands/update.d.ts.map +1 -0
- package/dist/cli/commands/update.js +191 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/cli/commands/webhook.js +9 -10
- package/dist/cli/commands/webhook.js.map +1 -1
- package/dist/cli/main.js +32 -2
- package/dist/cli/main.js.map +1 -1
- package/dist/control/routes/control.d.ts +1 -1
- package/dist/control/routes/control.d.ts.map +1 -1
- package/dist/control/routes/control.js +12 -2
- package/dist/control/routes/control.js.map +1 -1
- package/dist/control/routes/dashboard.d.ts.map +1 -1
- package/dist/control/routes/dashboard.js +11 -1
- package/dist/control/routes/dashboard.js.map +1 -1
- package/dist/execution/execution.d.ts +5 -2
- package/dist/execution/execution.d.ts.map +1 -1
- package/dist/execution/execution.js +22 -7
- package/dist/execution/execution.js.map +1 -1
- package/dist/execution/runner-pool.d.ts +1 -1
- package/dist/execution/runner-pool.d.ts.map +1 -1
- package/dist/execution/runner-setup.d.ts.map +1 -1
- package/dist/execution/runner-setup.js +15 -2
- package/dist/execution/runner-setup.js.map +1 -1
- package/dist/frontend/assets/index-Cb_hkpne.js +13 -0
- package/dist/frontend/assets/index-ClYf0bqf.css +2 -0
- package/dist/frontend/index.html +2 -2
- package/dist/gateway/index.d.ts +11 -0
- package/dist/gateway/index.d.ts.map +1 -1
- package/dist/gateway/index.js +32 -1
- package/dist/gateway/index.js.map +1 -1
- package/dist/remote/push.js +1 -4
- package/dist/remote/push.js.map +1 -1
- package/dist/scheduler/gateway-setup.d.ts +3 -0
- package/dist/scheduler/gateway-setup.d.ts.map +1 -1
- package/dist/scheduler/gateway-setup.js +47 -7
- package/dist/scheduler/gateway-setup.js.map +1 -1
- package/dist/scheduler/index.d.ts.map +1 -1
- package/dist/scheduler/index.js +4 -1
- package/dist/scheduler/index.js.map +1 -1
- package/dist/setup/scaffold.d.ts.map +1 -1
- package/dist/setup/scaffold.js +21 -21
- package/dist/setup/scaffold.js.map +1 -1
- package/dist/shared/config.d.ts +29 -5
- package/dist/shared/config.d.ts.map +1 -1
- package/dist/shared/config.js +50 -37
- package/dist/shared/config.js.map +1 -1
- package/dist/shared/environment.d.ts +0 -7
- package/dist/shared/environment.d.ts.map +1 -1
- package/dist/shared/environment.js +0 -29
- package/dist/shared/environment.js.map +1 -1
- package/dist/shared/validation.d.ts +9 -2
- package/dist/shared/validation.d.ts.map +1 -1
- package/dist/shared/validation.js +39 -20
- package/dist/shared/validation.js.map +1 -1
- package/dist/tui/App.js +2 -2
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/status-tracker.d.ts +8 -0
- package/dist/tui/status-tracker.d.ts.map +1 -1
- package/dist/tui/status-tracker.js +27 -0
- package/dist/tui/status-tracker.js.map +1 -1
- package/dist/webhooks/providers/index.js +4 -4
- package/dist/webhooks/providers/index.js.map +1 -1
- package/package.json +3 -1
- package/dist/frontend/assets/index-heXAA4Ev.js +0 -13
- package/dist/frontend/assets/index-tjVM5-7N.css +0 -2
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chat protocol types for bidirectional real-time agent communication.
|
|
3
|
+
*
|
|
4
|
+
* Used by both browser WebSocket connections and container-side chat entries.
|
|
5
|
+
*/
|
|
6
|
+
export interface UserMessage {
|
|
7
|
+
type: "user_message";
|
|
8
|
+
text: string;
|
|
9
|
+
}
|
|
10
|
+
export interface CancelMessage {
|
|
11
|
+
type: "cancel";
|
|
12
|
+
}
|
|
13
|
+
export interface ShutdownMessage {
|
|
14
|
+
type: "shutdown";
|
|
15
|
+
}
|
|
16
|
+
export type ChatInbound = UserMessage | CancelMessage | ShutdownMessage;
|
|
17
|
+
export interface AssistantMessage {
|
|
18
|
+
type: "assistant_message";
|
|
19
|
+
text: string;
|
|
20
|
+
done: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface ToolStart {
|
|
23
|
+
type: "tool_start";
|
|
24
|
+
toolCallId: string;
|
|
25
|
+
tool: string;
|
|
26
|
+
input: string;
|
|
27
|
+
}
|
|
28
|
+
export interface ToolResult {
|
|
29
|
+
type: "tool_result";
|
|
30
|
+
toolCallId: string;
|
|
31
|
+
tool: string;
|
|
32
|
+
output: string;
|
|
33
|
+
error?: boolean;
|
|
34
|
+
}
|
|
35
|
+
export interface ChatError {
|
|
36
|
+
type: "error";
|
|
37
|
+
message: string;
|
|
38
|
+
}
|
|
39
|
+
export interface Heartbeat {
|
|
40
|
+
type: "heartbeat";
|
|
41
|
+
}
|
|
42
|
+
export type ChatOutbound = AssistantMessage | ToolStart | ToolResult | ChatError | Heartbeat;
|
|
43
|
+
export interface ChatSession {
|
|
44
|
+
sessionId: string;
|
|
45
|
+
agentName: string;
|
|
46
|
+
containerName?: string;
|
|
47
|
+
createdAt: Date;
|
|
48
|
+
lastActivityAt: Date;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/chat/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,cAAc,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,UAAU,CAAC;CAClB;AAED,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,aAAa,GAAG,eAAe,CAAC;AAIxE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,mBAAmB,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,YAAY,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,aAAa,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,WAAW,CAAC;CACnB;AAED,MAAM,MAAM,YAAY,GACpB,gBAAgB,GAChB,SAAS,GACT,UAAU,GACV,SAAS,GACT,SAAS,CAAC;AAId,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,IAAI,CAAC;IAChB,cAAc,EAAE,IAAI,CAAC;CACtB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/chat/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message validation and rate limiting for the chat protocol.
|
|
3
|
+
*/
|
|
4
|
+
export interface ValidationResult {
|
|
5
|
+
valid: boolean;
|
|
6
|
+
error?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Validate an inbound chat message.
|
|
10
|
+
*/
|
|
11
|
+
export declare function validateInbound(raw: string): ValidationResult;
|
|
12
|
+
/**
|
|
13
|
+
* Validate an outbound chat message.
|
|
14
|
+
*/
|
|
15
|
+
export declare function validateOutbound(raw: string): ValidationResult;
|
|
16
|
+
/**
|
|
17
|
+
* Token bucket rate limiter for chat messages.
|
|
18
|
+
*/
|
|
19
|
+
export declare class RateLimiter {
|
|
20
|
+
private tokens;
|
|
21
|
+
private lastRefill;
|
|
22
|
+
private readonly maxTokens;
|
|
23
|
+
private readonly refillRate;
|
|
24
|
+
constructor(maxTokens?: number, refillRatePerSecond?: number);
|
|
25
|
+
/**
|
|
26
|
+
* Try to consume a token. Returns true if allowed, false if rate-limited.
|
|
27
|
+
*/
|
|
28
|
+
consume(): boolean;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/chat/validation.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAuB7D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAiB9D;AAED;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAExB,SAAS,SAAK,EAAE,mBAAmB,SAAK;IAOpD;;OAEG;IACH,OAAO,IAAI,OAAO;CAYnB"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message validation and rate limiting for the chat protocol.
|
|
3
|
+
*/
|
|
4
|
+
const MAX_MESSAGE_SIZE = 64 * 1024; // 64KB
|
|
5
|
+
const INBOUND_TYPES = new Set(["user_message", "cancel", "shutdown"]);
|
|
6
|
+
const OUTBOUND_TYPES = new Set(["assistant_message", "tool_start", "tool_result", "error", "heartbeat"]);
|
|
7
|
+
/**
|
|
8
|
+
* Validate an inbound chat message.
|
|
9
|
+
*/
|
|
10
|
+
export function validateInbound(raw) {
|
|
11
|
+
if (raw.length > MAX_MESSAGE_SIZE) {
|
|
12
|
+
return { valid: false, error: `Message exceeds ${MAX_MESSAGE_SIZE} byte limit` };
|
|
13
|
+
}
|
|
14
|
+
let msg;
|
|
15
|
+
try {
|
|
16
|
+
msg = JSON.parse(raw);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return { valid: false, error: "Invalid JSON" };
|
|
20
|
+
}
|
|
21
|
+
if (!msg || typeof msg !== "object" || !INBOUND_TYPES.has(msg.type)) {
|
|
22
|
+
return { valid: false, error: `Invalid message type: ${msg?.type}` };
|
|
23
|
+
}
|
|
24
|
+
if (msg.type === "user_message") {
|
|
25
|
+
if (typeof msg.text !== "string" || msg.text.length === 0) {
|
|
26
|
+
return { valid: false, error: "user_message requires non-empty text" };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return { valid: true };
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Validate an outbound chat message.
|
|
33
|
+
*/
|
|
34
|
+
export function validateOutbound(raw) {
|
|
35
|
+
if (raw.length > MAX_MESSAGE_SIZE) {
|
|
36
|
+
return { valid: false, error: `Message exceeds ${MAX_MESSAGE_SIZE} byte limit` };
|
|
37
|
+
}
|
|
38
|
+
let msg;
|
|
39
|
+
try {
|
|
40
|
+
msg = JSON.parse(raw);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return { valid: false, error: "Invalid JSON" };
|
|
44
|
+
}
|
|
45
|
+
if (!msg || typeof msg !== "object" || !OUTBOUND_TYPES.has(msg.type)) {
|
|
46
|
+
return { valid: false, error: `Invalid message type: ${msg?.type}` };
|
|
47
|
+
}
|
|
48
|
+
return { valid: true };
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Token bucket rate limiter for chat messages.
|
|
52
|
+
*/
|
|
53
|
+
export class RateLimiter {
|
|
54
|
+
tokens;
|
|
55
|
+
lastRefill;
|
|
56
|
+
maxTokens;
|
|
57
|
+
refillRate;
|
|
58
|
+
constructor(maxTokens = 10, refillRatePerSecond = 10) {
|
|
59
|
+
this.maxTokens = maxTokens;
|
|
60
|
+
this.tokens = maxTokens;
|
|
61
|
+
this.refillRate = refillRatePerSecond;
|
|
62
|
+
this.lastRefill = Date.now();
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Try to consume a token. Returns true if allowed, false if rate-limited.
|
|
66
|
+
*/
|
|
67
|
+
consume() {
|
|
68
|
+
const now = Date.now();
|
|
69
|
+
const elapsed = (now - this.lastRefill) / 1000;
|
|
70
|
+
this.tokens = Math.min(this.maxTokens, this.tokens + elapsed * this.refillRate);
|
|
71
|
+
this.lastRefill = now;
|
|
72
|
+
if (this.tokens >= 1) {
|
|
73
|
+
this.tokens -= 1;
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/chat/validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocket handler for chat — bridges browser ↔ container per session.
|
|
3
|
+
*
|
|
4
|
+
* Two WS paths:
|
|
5
|
+
* /chat/ws/:sessionId — browser connects here (auth via header/cookie)
|
|
6
|
+
* /chat/container/:sessionId — container connects here (auth via first-message token)
|
|
7
|
+
*/
|
|
8
|
+
import type { Server } from "http";
|
|
9
|
+
import { WebSocket } from "ws";
|
|
10
|
+
import type { ChatSessionManager } from "./session-manager.js";
|
|
11
|
+
import { RateLimiter } from "./validation.js";
|
|
12
|
+
import type { SessionStore } from "../control/session-store.js";
|
|
13
|
+
import type { Logger } from "../shared/logger.js";
|
|
14
|
+
interface BrowserConnection {
|
|
15
|
+
ws: WebSocket;
|
|
16
|
+
rateLimiter: RateLimiter;
|
|
17
|
+
}
|
|
18
|
+
interface ContainerConnection {
|
|
19
|
+
ws: WebSocket;
|
|
20
|
+
authenticated: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface ChatWebSocketState {
|
|
23
|
+
browserConnections: Map<string, BrowserConnection>;
|
|
24
|
+
containerConnections: Map<string, ContainerConnection>;
|
|
25
|
+
cleanupInterval: ReturnType<typeof setInterval>;
|
|
26
|
+
/** Callback to stop a chat container by session. */
|
|
27
|
+
stopContainer?: (sessionId: string) => Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
export declare function attachChatWebSocket(server: Server, sessionManager: ChatSessionManager, apiKey: string, sessionStore?: SessionStore, logger?: Logger): ChatWebSocketState;
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=ws-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws-handler.d.ts","sourceRoot":"","sources":["../../src/chat/ws-handler.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,OAAO,EAAmB,SAAS,EAAgB,MAAM,IAAI,CAAC;AAE9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAqC,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACjF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,UAAU,iBAAiB;IACzB,EAAE,EAAE,SAAS,CAAC;IACd,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED,UAAU,mBAAmB;IAC3B,EAAE,EAAE,SAAS,CAAC;IACd,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACnD,oBAAoB,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IACvD,eAAe,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;IAChD,oDAAoD;IACpD,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtD;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,kBAAkB,EAClC,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,YAAY,EAC3B,MAAM,CAAC,EAAE,MAAM,GACd,kBAAkB,CA2OpB"}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocket handler for chat — bridges browser ↔ container per session.
|
|
3
|
+
*
|
|
4
|
+
* Two WS paths:
|
|
5
|
+
* /chat/ws/:sessionId — browser connects here (auth via header/cookie)
|
|
6
|
+
* /chat/container/:sessionId — container connects here (auth via first-message token)
|
|
7
|
+
*/
|
|
8
|
+
import { WebSocketServer, WebSocket } from "ws";
|
|
9
|
+
import { safeCompare } from "../control/auth.js";
|
|
10
|
+
import { validateInbound, validateOutbound, RateLimiter } from "./validation.js";
|
|
11
|
+
export function attachChatWebSocket(server, sessionManager, apiKey, sessionStore, logger) {
|
|
12
|
+
const browserConnections = new Map();
|
|
13
|
+
const containerConnections = new Map();
|
|
14
|
+
// Browser-facing WS server
|
|
15
|
+
const browserWss = new WebSocketServer({ noServer: true });
|
|
16
|
+
// Container-facing WS server
|
|
17
|
+
const containerWss = new WebSocketServer({ noServer: true });
|
|
18
|
+
// Disconnection grace periods: track when browser disconnected
|
|
19
|
+
const browserDisconnectTimers = new Map();
|
|
20
|
+
server.on("upgrade", async (req, socket, head) => {
|
|
21
|
+
const url = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
|
|
22
|
+
const pathname = url.pathname;
|
|
23
|
+
// Browser path: /chat/ws/:sessionId
|
|
24
|
+
const browserMatch = pathname.match(/^\/chat\/ws\/([^/]+)$/);
|
|
25
|
+
if (browserMatch) {
|
|
26
|
+
const sessionId = browserMatch[1];
|
|
27
|
+
const session = sessionManager.getSession(sessionId);
|
|
28
|
+
if (!session) {
|
|
29
|
+
socket.write("HTTP/1.1 404 Not Found\r\n\r\n");
|
|
30
|
+
socket.destroy();
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
// Authenticate via Authorization header or cookie
|
|
34
|
+
const authenticated = await authenticateBrowser(req, apiKey, sessionStore);
|
|
35
|
+
if (!authenticated) {
|
|
36
|
+
socket.write("HTTP/1.1 401 Unauthorized\r\n\r\n");
|
|
37
|
+
socket.destroy();
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
browserWss.handleUpgrade(req, socket, head, (ws) => {
|
|
41
|
+
handleBrowserConnection(ws, sessionId);
|
|
42
|
+
});
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
// Container path: /chat/container/:sessionId
|
|
46
|
+
const containerMatch = pathname.match(/^\/chat\/container\/([^/]+)$/);
|
|
47
|
+
if (containerMatch) {
|
|
48
|
+
const sessionId = containerMatch[1];
|
|
49
|
+
const session = sessionManager.getSession(sessionId);
|
|
50
|
+
if (!session) {
|
|
51
|
+
socket.write("HTTP/1.1 404 Not Found\r\n\r\n");
|
|
52
|
+
socket.destroy();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
containerWss.handleUpgrade(req, socket, head, (ws) => {
|
|
56
|
+
handleContainerConnection(ws, sessionId);
|
|
57
|
+
});
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
// Not a chat path — let other upgrade handlers deal with it
|
|
61
|
+
});
|
|
62
|
+
function handleBrowserConnection(ws, sessionId) {
|
|
63
|
+
logger?.debug({ sessionId }, "browser WebSocket connected");
|
|
64
|
+
// Clear any grace-period timer from a prior disconnect
|
|
65
|
+
const timer = browserDisconnectTimers.get(sessionId);
|
|
66
|
+
if (timer) {
|
|
67
|
+
clearTimeout(timer);
|
|
68
|
+
browserDisconnectTimers.delete(sessionId);
|
|
69
|
+
}
|
|
70
|
+
const conn = { ws, rateLimiter: new RateLimiter() };
|
|
71
|
+
browserConnections.set(sessionId, conn);
|
|
72
|
+
ws.on("message", (data) => {
|
|
73
|
+
const raw = data.toString();
|
|
74
|
+
sessionManager.touchSession(sessionId);
|
|
75
|
+
if (!conn.rateLimiter.consume()) {
|
|
76
|
+
ws.send(JSON.stringify({ type: "error", message: "Rate limited" }));
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const validation = validateInbound(raw);
|
|
80
|
+
if (!validation.valid) {
|
|
81
|
+
ws.send(JSON.stringify({ type: "error", message: validation.error }));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
// Forward to container
|
|
85
|
+
const containerConn = containerConnections.get(sessionId);
|
|
86
|
+
if (containerConn?.authenticated && containerConn.ws.readyState === WebSocket.OPEN) {
|
|
87
|
+
containerConn.ws.send(raw);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
ws.send(JSON.stringify({ type: "error", message: "Agent container not connected" }));
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
ws.on("close", () => {
|
|
94
|
+
logger?.debug({ sessionId }, "browser WebSocket disconnected");
|
|
95
|
+
browserConnections.delete(sessionId);
|
|
96
|
+
// Grace period: wait 60s before shutting down the container
|
|
97
|
+
const gracePeriod = setTimeout(() => {
|
|
98
|
+
browserDisconnectTimers.delete(sessionId);
|
|
99
|
+
logger?.info({ sessionId }, "browser grace period expired, shutting down container");
|
|
100
|
+
shutdownSession(sessionId);
|
|
101
|
+
}, 60_000);
|
|
102
|
+
browserDisconnectTimers.set(sessionId, gracePeriod);
|
|
103
|
+
});
|
|
104
|
+
ws.on("error", (err) => {
|
|
105
|
+
logger?.warn({ sessionId, err: err.message }, "browser WebSocket error");
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
function handleContainerConnection(ws, sessionId) {
|
|
109
|
+
logger?.debug({ sessionId }, "container WebSocket connected");
|
|
110
|
+
const conn = { ws, authenticated: false };
|
|
111
|
+
containerConnections.set(sessionId, conn);
|
|
112
|
+
// Container must authenticate with session token in first message within 5s
|
|
113
|
+
const authTimeout = setTimeout(() => {
|
|
114
|
+
if (!conn.authenticated) {
|
|
115
|
+
logger?.warn({ sessionId }, "container auth timeout");
|
|
116
|
+
ws.close(4001, "Auth timeout");
|
|
117
|
+
containerConnections.delete(sessionId);
|
|
118
|
+
}
|
|
119
|
+
}, 5000);
|
|
120
|
+
ws.on("message", (data) => {
|
|
121
|
+
const raw = data.toString();
|
|
122
|
+
// First message must be auth token
|
|
123
|
+
if (!conn.authenticated) {
|
|
124
|
+
try {
|
|
125
|
+
const msg = JSON.parse(raw);
|
|
126
|
+
if (msg.type === "auth" && typeof msg.token === "string") {
|
|
127
|
+
const session = sessionManager.getSession(sessionId);
|
|
128
|
+
if (session && safeCompare(msg.token, sessionId)) {
|
|
129
|
+
conn.authenticated = true;
|
|
130
|
+
clearTimeout(authTimeout);
|
|
131
|
+
ws.send(JSON.stringify({ type: "auth_ok" }));
|
|
132
|
+
logger?.info({ sessionId }, "container authenticated");
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
catch { /* invalid JSON */ }
|
|
138
|
+
ws.close(4003, "Auth failed");
|
|
139
|
+
containerConnections.delete(sessionId);
|
|
140
|
+
clearTimeout(authTimeout);
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
sessionManager.touchSession(sessionId);
|
|
144
|
+
// Validate outbound message from container
|
|
145
|
+
const validation = validateOutbound(raw);
|
|
146
|
+
if (!validation.valid) {
|
|
147
|
+
logger?.warn({ sessionId, error: validation.error }, "invalid outbound from container");
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// Forward to browser
|
|
151
|
+
const browserConn = browserConnections.get(sessionId);
|
|
152
|
+
if (browserConn && browserConn.ws.readyState === WebSocket.OPEN) {
|
|
153
|
+
browserConn.ws.send(raw);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
ws.on("close", () => {
|
|
157
|
+
logger?.debug({ sessionId }, "container WebSocket disconnected");
|
|
158
|
+
containerConnections.delete(sessionId);
|
|
159
|
+
// Notify browser
|
|
160
|
+
const browserConn = browserConnections.get(sessionId);
|
|
161
|
+
if (browserConn && browserConn.ws.readyState === WebSocket.OPEN) {
|
|
162
|
+
browserConn.ws.send(JSON.stringify({ type: "error", message: "Agent container disconnected" }));
|
|
163
|
+
}
|
|
164
|
+
sessionManager.removeSession(sessionId);
|
|
165
|
+
});
|
|
166
|
+
ws.on("error", (err) => {
|
|
167
|
+
logger?.warn({ sessionId, err: err.message }, "container WebSocket error");
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
async function shutdownSession(sessionId) {
|
|
171
|
+
// Send shutdown to container
|
|
172
|
+
const containerConn = containerConnections.get(sessionId);
|
|
173
|
+
if (containerConn?.authenticated && containerConn.ws.readyState === WebSocket.OPEN) {
|
|
174
|
+
containerConn.ws.send(JSON.stringify({ type: "shutdown" }));
|
|
175
|
+
containerConn.ws.close();
|
|
176
|
+
}
|
|
177
|
+
containerConnections.delete(sessionId);
|
|
178
|
+
// Close browser connection
|
|
179
|
+
const browserConn = browserConnections.get(sessionId);
|
|
180
|
+
if (browserConn && browserConn.ws.readyState === WebSocket.OPEN) {
|
|
181
|
+
browserConn.ws.close();
|
|
182
|
+
}
|
|
183
|
+
browserConnections.delete(sessionId);
|
|
184
|
+
// Stop container via callback
|
|
185
|
+
if (state.stopContainer) {
|
|
186
|
+
try {
|
|
187
|
+
await state.stopContainer(sessionId);
|
|
188
|
+
}
|
|
189
|
+
catch (err) {
|
|
190
|
+
logger?.warn({ sessionId, err: err.message }, "failed to stop chat container");
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
sessionManager.removeSession(sessionId);
|
|
194
|
+
}
|
|
195
|
+
// Idle session cleanup interval (Phase 8)
|
|
196
|
+
const IDLE_TIMEOUT_MS = 15 * 60 * 1000; // 15 minutes
|
|
197
|
+
const cleanupInterval = setInterval(() => {
|
|
198
|
+
const idle = sessionManager.getIdleSessions(IDLE_TIMEOUT_MS);
|
|
199
|
+
for (const session of idle) {
|
|
200
|
+
logger?.info({ sessionId: session.sessionId, agentName: session.agentName }, "cleaning up idle chat session");
|
|
201
|
+
shutdownSession(session.sessionId);
|
|
202
|
+
}
|
|
203
|
+
}, 60_000);
|
|
204
|
+
cleanupInterval.unref();
|
|
205
|
+
const state = {
|
|
206
|
+
browserConnections,
|
|
207
|
+
containerConnections,
|
|
208
|
+
cleanupInterval,
|
|
209
|
+
};
|
|
210
|
+
return state;
|
|
211
|
+
}
|
|
212
|
+
// --- Auth helpers ---
|
|
213
|
+
async function authenticateBrowser(req, apiKey, sessionStore) {
|
|
214
|
+
// Check Authorization header
|
|
215
|
+
const authHeader = req.headers.authorization;
|
|
216
|
+
if (authHeader?.startsWith("Bearer ")) {
|
|
217
|
+
const token = authHeader.slice(7);
|
|
218
|
+
if (safeCompare(token, apiKey))
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
// Check al_session cookie
|
|
222
|
+
const cookieHeader = req.headers.cookie || "";
|
|
223
|
+
const sessionToken = parseCookie(cookieHeader)["al_session"];
|
|
224
|
+
if (sessionToken) {
|
|
225
|
+
if (sessionStore) {
|
|
226
|
+
const session = await sessionStore.getSession(sessionToken);
|
|
227
|
+
if (session)
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
if (safeCompare(sessionToken, apiKey))
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
function parseCookie(header) {
|
|
238
|
+
const result = {};
|
|
239
|
+
for (const part of header.split(";")) {
|
|
240
|
+
const eq = part.indexOf("=");
|
|
241
|
+
if (eq === -1)
|
|
242
|
+
continue;
|
|
243
|
+
result[part.slice(0, eq).trim()] = part.slice(eq + 1).trim();
|
|
244
|
+
}
|
|
245
|
+
return result;
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=ws-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws-handler.js","sourceRoot":"","sources":["../../src/chat/ws-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* al add — install a skill from a git repository.
|
|
3
|
+
*
|
|
4
|
+
* 1. Fetch repo (shallow clone to temp dir)
|
|
5
|
+
* 2. Discover SKILL.md files (root or skills/star/)
|
|
6
|
+
* 3. If multiple and no --skill, prompt user to pick
|
|
7
|
+
* 4. Copy SKILL.md + config.toml into agents dir
|
|
8
|
+
* 5. Run al config for interactive gap-filling
|
|
9
|
+
*/
|
|
10
|
+
export declare function execute(repo: string, opts: {
|
|
11
|
+
skill?: string;
|
|
12
|
+
project: string;
|
|
13
|
+
}): Promise<void>;
|
|
14
|
+
//# sourceMappingURL=add.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/add.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAmFH,wBAAsB,OAAO,CAC3B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACxC,OAAO,CAAC,IAAI,CAAC,CAiHf"}
|